android混音
❶ android 播放音樂時為什麼用不到混音線程mixerthread
MixerThread是按照音頻輸出的核心部分,所有Android的音頻都需要經過MixerThread進行混音後再輸出到音頻設備。
MixerThread的繼承關系如下:
MixerThread--->PlaybackThread--->ThreadBase--->Thread
在PlaybackThread中,重寫了Thread的threadLoop,onFirstRef等方法,因此在調用MixerThread這些方法時,實際上就是調用了PlaybackThread的方法。
1. onFirstRef
在getOutput的時候,我們創建了一個MixerThread對象,由於這個對象繼承於Thread,因此在創建對象時,會調用它的onFirstRef函數。
void AudioFlinger::PlaybackThread::onFirstRef(){ run(mName, ANDROID_PRIORITY_URGENT_AUDIO);}
在該方法內部,調用了run,即開始運行threadLoop。也就是說,其實在new MixerThread的時候就已經開始啟動PlaybackThread::threadLoop。
2. threadLoop
在分析threadLoop之前,我們先來了解MixerThread中的幾種Audio操作。
在Threads.cpp內有幾個threadLoop_xxx方法,這些方法就分別代表不同的Audio操作:
操作 方法 功能 standby threadLoop_standby 待機 mix threadLoop_mix 混音 write threadLoop_write 音頻輸出 exit threadLoop_exit 退出 drain threadLoop_drain 只有offload用到,還不清楚作用 sleep threadLoop_sleepTime 無音頻需要處理,睡眠
另外還有幾個非常重要的變數:
變數 取值 含義 tracksToRemove
需要被移除的Track,一旦所有的Track都被移除,則表明沒有音頻數據需要處理,那麼線程會進入睡眠
sleepTime
睡眠時間
standbyTime
如果持續睡眠超出standbyTime,則會進入待機
mStandby
表明當前是否為待機狀態
mActiveTracks
需要進行音頻處理的Track,如果該Track已經播放完成或者被停止,則會被移入tracksToRemove
mMixerStatus MIXER_IDLE
Mixer狀態,no active tracks,表明不需要混音,而是進入睡眠
❷ android開發中怎樣實現混音
音頻混音的原理: 量化的語音信號的疊加等價於空氣中聲波的疊加。
下面是代碼,可以參照來學習:
java">publicvoidmixAudios(File[]rawAudioFiles){
finalintfileSize=rawAudioFiles.length;
FileInputStream[]audioFileStreams=newFileInputStream[fileSize];
FileaudioFile=null;
FileInputStreaminputStream; byte[][]allAudioBytes=newbyte[fileSize][]; boolean[]streamDoneArray=newboolean[fileSize]; byte[]buffer=newbyte[512]; intoffset;
try{
for(intfileIndex=0;fileIndex<fileSize;++fileIndex){
audioFile=rawAudioFiles[fileIndex];
audioFileStreams[fileIndex]=newFileInputStream(audioFile);
} while(true){
for(intstreamIndex=0;streamIndex<fileSize;++streamIndex){
inputStream=audioFileStreams[streamIndex]; if(!streamDoneArray[streamIndex]&&(offset=inputStream.read(buffer))!=-1){
allAudioBytes[streamIndex]=Arrays.Of(buffer,buffer.length);
}else{
streamDoneArray[streamIndex]=true;
allAudioBytes[streamIndex]=newbyte[512];
}
}
byte[]mixBytes=mixRawAudioBytes(allAudioBytes);
//mixBytes就是混合後的數據
booleandone=true; for(booleanstreamEnd:streamDoneArray){ if(!streamEnd){
done=false;
}
}
if(done){ break;
}
}
}catch(IOExceptione){
e.printStackTrace(); if(mOnAudioMixListener!=null)
mOnAudioMixListener.onMixError(1);
}finally{ try{ for(FileInputStreamin:audioFileStreams){ if(in!=null)
in.close();
}
}catch(IOExceptione){
e.printStackTrace();
}
}
}/**
*每一行是一個音頻的數據
*/byte[]averageMix(byte[][]bMulRoadAudioes){
if(bMulRoadAudioes==null||bMulRoadAudioes.length==0) returnnull; byte[]realMixAudio=bMulRoadAudioes[0];
if(bMulRoadAudioes.length==1) returnrealMixAudio;
for(intrw=0;rw<bMulRoadAudioes.length;++rw){ if(bMulRoadAudioes[rw].length!=realMixAudio.length){
Log.e("app","columnoftheroadofaudio+"+rw+"isdiffrent."); returnnull;
}
}
introw=bMulRoadAudioes.length; intcoloum=realMixAudio.length/2; short[][]sMulRoadAudioes=newshort[row][coloum]; for(intr=0;r<row;++r){ for(intc=0;c<coloum;++c){
sMulRoadAudioes[r][c]=(short)((bMulRoadAudioes[r][c*2]&0xff)|(bMulRoadAudioes[r][c*2+1]&0xff)<<8);
}
} short[]sMixAudio=newshort[coloum]; intmixVal; intsr=0; for(intsc=0;sc<coloum;++sc){
mixVal=0;
sr=0; for(;sr<row;++sr){
mixVal+=sMulRoadAudioes[sr][sc];
}
sMixAudio[sc]=(short)(mixVal/row);
} for(sr=0;sr<coloum;++sr){
realMixAudio[sr*2]=(byte)(sMixAudio[sr]&0x00FF);
realMixAudio[sr*2+1]=(byte)((sMixAudio[sr]&0xFF00)>>8);
} returnrealMixAudio;
}
❸ android 應用怎樣調用tinyalsa
1.編譯tinyalsa配套工具
$ mmm external/tinyalsa/
編譯完後會產生tinyplay/tinymix/tinycap等等工具。
tinymix: 查看配置混音器
tinyplay: 播放音頻
tinycap: 錄音
2.查看當前系統的音效卡
[python] view plain
root@android:/ # cat /proc/asound/cards
0 [RKRK616 ]: RK_RK616 - RK_RK616
RK_RK616
1 [ROCKCHIPSPDIF ]: ROCKCHIP-SPDIF - ROCKCHIP-SPDIF
ROCKCHIP-SPDIF
root@android:/ #
3.tinymix查看混響器
tinymix使用方法a.不加任何參數-顯示當前配置情況 b.tinymix [ctrl id] [var]不加[var]可以查看該[ctrl id]可選選項。
[python] view plain
root@android:/ # tinymix
Number of controls: 7
ctl type num name value
0 ENUM 1 Playback Path OFF
1 ENUM 1 Capture MIC Path MIC OFF
2 ENUM 1 Voice Call Path OFF
3 ENUM 1 Voip Path OFF
4 INT 2 Speaker Playback Volume 0 0
5 INT 2 Headphone Playback Volume 0 0
6 ENUM 1 Modem Input Enable ON
root@android:/ #
4.使用tinyplay播放wav音樂
這個只是一個最基本的播放器,所以不支持播放MP3等等壓縮過格式的音樂。沒有學會使用前,網上都說很麻煩,但是現在看來一點也不麻煩,直接播放了44.1kHz/44.8kHz的wav音樂。
[python] view plain
root@android:/ # tinyplay /sdcard/0_16.wav
Playing sample: 2 ch, 44100 hz, 16 bit
root@android:/ #
註:播放之前得首先使用tinymix把通道設置好,上文中已經給出了設置到揚聲器中的例子;由於播放時使用的最大音量進行播放的,所以注意防止被嚇到。這里將測試音頻文件上傳。
5.tinycap使用
root@android:/ # tinycap /sdcard/test.wav
可以進行錄音。
目前只遇到這些,就先總結到這,可以隨時再深入。
❹ Mate10手機投屏時,手機視頻聲音與大屏微信語音信息混音
問題現象:
手機投屏時,大屏播放視頻的同時,手機播放微信或某些媒體流時,聲音也會從大屏上輸出,造成混音現象。
問題原因:
大屏播放視頻和手機播放媒體流,使用同一種媒體流,同一種流的輸出策略是一樣的,Android 目前無法做分流處理,同時輸出到同一個設備,則會出現混音。
解決方案:
為了更好的視聽體驗,建議您暫時關閉其中一個正在播放音頻的應用。
❺ Android AudioRecord有辦法做混音嗎
android開發中怎樣實現混音,實例代碼如下:
[mw_shl_code=java,true]public class MixRunnable implements Runnable {
private MixRecorder context;
/**
* AudioRecord創建參數類
*
* @author christ
*/
private static class RecorderParameter {
// 音頻獲取源
private static int audioSource = MediaRecorder.AudioSource.MIC;
// 設置音頻采樣率,44100是目前的標准,但是某些設備仍然支持22050,16000,11025
❻ 如何將 Android 將MP3伴奏文件與錄音文件合成AAC文件,要求具體的實現方式或、思路、或解決方案。
你把兩個音頻文件同時播放,要求那個文件的音量大小你具體調節。用錄音軟體進行錄音。我推薦你兩款錄音軟體<宏樂錄音棚》。《影音錄霸》。它們都是全中文操作免費版本。然後用《狸窩全能視頻轉換器》進行編輯修改合並格式轉換,這款軟體也是全中文操作免費版本。希以上回答對你有助。
❼ android開發中怎樣實現混音
android開發中怎樣實現混音,實例代碼如下:
[mw_shl_code=java,true]public class MixRunnable implements Runnable {
private MixRecorder context;
/**
* AudioRecord創建參數類
*
* @author christ
*/
private static class RecorderParameter {
// 音頻獲取源
private static int audioSource = MediaRecorder.AudioSource.MIC;
// 設置音頻采樣率,44100是目前的標准,但是某些設備仍然支持22050,16000,11025
private static final int sampleRateInHz = 44100;
// 設置音頻的錄制的聲道CHANNEL_IN_STEREO為雙聲道,CHANNEL_CONFIGURATION_MONO為單聲道
private static final int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
// 音頻數據格式:PCM 16位每個樣本。保證設備支持。PCM 8位每個樣本。不一定能得到設備支持。
private static final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
// 緩沖區位元組大小
private static int bufferSizeInBytes;
}
// 設置運行狀態
private boolean isRunning = true;
// AudioRecord對象
private static AudioRecord recorder;
// 設置MediaPlayer對象
private static MediaPlayer mediaPlayer;
// 伴奏文件
private FileInputStream accompany;
// 原唱文件
private FileInputStream original;
// 得分
private int score;
private boolean isFirst = true;
/**
* 混音評分線程的構造方法
*
* @param accompany
* :伴奏文件路徑
* @param original
* :原唱文件路徑
* @throws FileNotFoundException
*/
public MixRunnable(MixRecorder context, String accompany, String original) throws FileNotFoundException {
this.context = context;
this.accompany = new FileInputStream(accompany);
this.original = new FileInputStream(original);
creatAudioRecord();
mediaPlayer = new MediaPlayer();
}
@Override
public void run() {
try {
// MediaPlayer准備
mediaPlayer.reset();
mediaPlayer.setDataSource("/sdcard/111.wav");
// mediaPlayer.setDataSource(accompany.getFD());
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
isRunning = false;
}
});
mediaPlayer.prepare();
// 跳過頭
accompany.read(new byte[44]);
original.read(new byte[44]);
FileOutputStream fos = new FileOutputStream(new File("/sdcard/love.raw"));
// 開始讀
byte[] sourceReader = new byte[RecorderParameter.bufferSizeInBytes * 2];
short[] sourceShortArray;
short[] audioReader = new short[sourceReader.length / 4];
mediaPlayer.start();
recorder.startRecording();
while (isRunning) {
int sourceReadSize = accompany.read(sourceReader, 0, sourceReader.length);
if (sourceReadSize < 0) {
isRunning = false;
continue;
}
sourceShortArray = byteToShortArray(sourceReader, sourceReadSize / 2);
recorder.read(audioReader, 0, audioReader.length);
short[] oneSecond = mixVoice(sourceShortArray, audioReader, sourceReadSize / 2);
byte[] outStream = new byte[oneSecond.length * 2];
for (int i = 0; i < oneSecond.length; i++) {
byte[] b = shortToByteArray(oneSecond<i>);
outStream[2 * i] = b[0];
outStream[2 * i + 1] = b[1];
}
❽ 安卓系統為什麼音質不好
Android 基於Linux,我們先來了解一下Linux的特點。Linux使用ALSA作為其音頻架構,其全稱Advanced Linux Sound Architecture,即高級Linux聲音架構的意思,在2.6核心之後,ALSA成為了Linux系統默認的音頻子架構。取代了之前的OSS[Open Sound System,開放式聲音系統]。
ALSA並不太好理解,它首先是一個驅動庫,包含了大量的音效卡設備的開源驅動,並提供了核心層API與ALSA庫通信,而ALSA庫則是應用程序訪問和操控音頻硬體的中間層,這個中間層有標准介面,開發者可以無須考慮硬體差異性進行開發,它對提升開發效率是大有幫助的。ALSA可以向下兼容OSS,因為OSS已經被淘汰,其兼容的工作模式不再討論。
這個體系被繼承到了Android當中。在Android2.2[含2,2]之前,系統文件夾中能找到一個LibAudioALSA.so的文件,這就是ALSA庫文件,其他應用程序調用它,與音效卡設備進行指令和數據通信。Android音頻架構與Linux的並無本質區別。
在桌面版本的Linux當中,為了兼容各類音效卡,Linux也設置了一個SRC[Sample Rate Converter,采樣頻率轉換]的環節,當當前采樣率低於48kHz時強制SRC到48kHz輸出。這個SRC環節位於ALSA的插件模塊中的混音器部分。Android針對這個進行了改進。
什麼是SRC?SRC即Sample Rate Converter,中文意思為采樣頻率轉換。它被音效卡愛好者所關注,大部分發燒友視SRC為音質殺手。
Android增加了一個AudioFinger,這個可以簡單的理解為Android的ALSA音頻子系統的標准化的插件模塊,它包含了AudioMixer[混音器]、AudioResampler[重采樣]等子模塊,AudioResampler即我們理解的SRC,Android換了一個新名稱而已。針對SRC,Android做了改進,但改進並不是以去除SRC為目的,而是修改了默認的輸出頻率,Android的SRC目標采樣率為44.1kHz,非該值的采樣率都將SRC處理。例如播放48kHz采樣率的信號,輸出的最終是44.1kHz,這對音質將產生負面影響。
ALSA是一個針對Linux 桌面版本設計的音頻架構,它實際上是不適合智能終端設備的,起碼裡面大量的開源驅動代碼是可以去除的,對與Android來說,這些都是廢代碼。從Android2.3起,啟用了一個新的音頻架構。它放棄了一直使用的ALSA架構,因此系統文件夾中,也不再有LibAudioALSA.so這個文件。
Android2.3起,架構已經做了修改,在針對內部代碼進行了優化,去除了冗餘代碼,理論上讓系統能變得更加高效,可以將新架構理解為一個精簡的或者為智能終端設備定製的ALSA架構。遺憾的是,它同樣存在SRC嚴重劣化的問題,通過測試可以證明。
Android 3.0專門為平板電腦設計,影音體驗變得更加重要了,是不是新系統在音質方面會有新的的進步呢,測試結果依然是令人失望的。
Android系統將采樣率同一為44.1kHz輸出,這造成了諸多限制,它將無法實現96kHz、192kHz高清音頻節目的良好回放,大量視頻節目源自DVD或者藍光碟,其採用率多為48kHz,Android設備在回放這些視頻節目時,音質也將大打折扣。
理論上軟體SRC可以通過更換演算法來實現音質提升,但卻不太現實,智能終端所採用的CPU多為ARM,ARM晶元的浮點運算力有限,而SRC需要大量的浮點運算的資源,即便有了高質量的SRC演算法,其運算也是以犧牲設備性能和耗電量為代價的,實用性差。
從Android的音頻架構及流程分析,可以認為,播放44.1kHz采樣率的音樂節目時,不會引發SRC,音質因此可以獲得保證,理論上確實如此。但它同樣存在問題,不管是之前的ALSA架構還是Android2.3之後改良的架構,其驅動庫都位於核心層,也就意味著音頻設備廠商、用戶無法象PC平台那樣安裝驅動來改善音質。實際測試也表明,Android設備音質普遍偏差,Soomal有大量測試可以證明。
我們再把目光投向iOS,iOS非常封閉,我們甚至無法獲知其架構的具體構成,但iOS設備不存在硬體設備多樣性的問題,因此要實現更好音質也會更加簡單。iOS可以實現針對性的開發和改良,以實現更好的音質。實際情況也是如此,目前為止,還沒有一款Android設備的音質可以媲美任意一款iOS設備,這種差距,我們認為不是來自硬體,而是操作系統。
Android音頻架構的局限性也使得其難以成為優質的影音平台,如果你希望設計一款基於Android的高清影音播放器,那麼首先需要做的不是設計硬體,而是去修改現有架構的不足,或者乾脆設計一個專用的架構來取代Android的通用架構。從源代碼分析,Android和原生的Linux底層能支持各種采樣率,開源也使得其具有改造基礎,因此,在技術實力強勁的公司手裡,Android也可以烏雞變鳳凰。