Android之 AudioTrack学习
AudioTrack主要是用來播放聲音的,AudioTrack貫穿了JAVA層,JNI層和Native層。
AudioTrack JAVA層:
framework\base\media\java\android\media\AudioTrack.java
以AudioTrack的使用方法舉例:pp]
// 得到一個滿足最小要求的緩沖區的大小 int bufsize = AudioTrack.getMinBufferSize(8000,//采樣率 = 每秒8K個點 AudioFormat.CHANNEL_CONFIGURATION_STEREO,//雙聲道 AudioFormat.ENCODING_PCM_16BIT);//采樣精度 = 一個采樣點16比特 = 2個字節 //創建AudioTrack AudioTrack trackplayer = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_ STEREO, AudioFormat.ENCODING_PCM_16BIT, bufsize, AudioTrack.MODE_STREAM);// trackplayer.play() ;//開始 trackplayer.write(bytes_pkg, 0, bytes_pkg.length) ;//往track中寫數據 //... trackplayer.stop();//停止播放 trackplayer.release();//釋放底層資源 AudioTrack Native層:
// 得到一個滿足最小要求的緩沖區的大小 int bufsize = AudioTrack.getMinBufferSize(8000,//采樣率 = 每秒8K個點 AudioFormat.CHANNEL_CONFIGURATION_STEREO,//雙聲道 AudioFormat.ENCODING_PCM_16BIT);//采樣精度 = 一個采樣點16比特 = 2個字節 getMinBufferSize實際調用了JNI通過Native代碼來實現。
framework/base/core/jni/android_media_track.cpp
static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz, jint sampleRateInHertz, jint nbChannels, jint audioFormat) {//注意我們傳入的參數是: //sampleRateInHertz = 8000 //nbChannels = 2; //audioFormat = AudioFormat.ENCODING_PCM_16BIT int afSamplingRate; int afFrameCount; uint32_t afLatency; if (AudioSystem::getOutputSamplingRate(&afSamplingRate) != NO_ERROR) { return -1; } if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) { return -1; } if (AudioSystem::getOutputLatency(&afLatency) != NO_ERROR) { return -1; } //音頻中最常見的是frame,解釋:一個frame就是1個采樣點的字節數*聲道。 // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSamplingRate); if (minBufCount < 2) minBufCount = 2; uint32_t minFrameCount = (afFrameCount*sampleRateInHertz*minBufCount)/afSamplingRate; //下面根據最小的framecount計算最小的buffersize int minBuffSize = minFrameCount * (audioFormat == javaAudioTrackFields.PCM16 ? 2 : 1) * nbChannels; return minBuffSize; }MODE_STREAM和MODE_STATIC
STREAM的意思是由用戶在應用程序通過write方式把數據一次一次得寫到audiotrack中。這個和我們在socket中發送數據一樣,應用層從某個地方獲取數據,例如通過編解碼得到PCM數據,然后write到audiotrack。這種方式的壞處就是總是在JAVA層和Native層交互,效率損失較大。
In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using one of thewrite()?methods. These are?blocking?and return when the data has been transferred from the Java layer to the native layer and queued for playback.
MODE_STREAM模式終使用Write方法,該方法是阻塞的,當數據從Java層到Native層執行播放完畢后才返回。
而STATIC的意思是一開始創建的時候,就把音頻數據放到一個固定的buffer,然后直接傳給audiotrack,后續就不用一次次得write了。AudioTrack會自己播放這個buffer中的數據。這種方法對于鈴聲等內存占用較小,延時要求較高的聲音來說很適用。
AudioTrack的構造函數
public?AudioTrack?(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)
AudioTrack的構造函數中有一個變量用來指定buffer的大小bufferSizeInBytes。?
AudioTrack在Native層會對這個變量的值進行有效性判斷。首先,它至少要等于或者大于getMinBufferSize返回的值,然后它必須是frame大小的整數倍。
舉例說明,MODE_STREAM模式下,在JAVA層構造AudioTrack時,bufferSizeInBytes的大小設定為9600,在Native層調用Write方法拷貝數據至Hardware進行回放,每次拷貝的大小為320.則需要拷貝到30次,聲卡才發出聲音。即需要將數據填滿緩沖區才進行播放。(320*30=9600)
? view plai ?copy
總結
以上是生活随笔為你收集整理的Android之 AudioTrack学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android之录音--AudioRec
- 下一篇: Android之在ubuntu过滤日志以