android pcm


 

Android.media package里包含聲音錄放的兩個類AudioRecord和AudioTrack。前者用來錄制,后者用來播放。
配置 pcm:
1 int channel = AudioFormat.CHANNEL_IN_MONO ;
2 int format = AudioFormat.ENCODING_PCM_16BIT;
3 int sampleRate = 8000 ; 
4 int minBufferSize = AudioRecord.getMinBufferSize ( sampleRate, channel , format  ) * 4;
聲明:
1 AudioRecord audioRecord = new AudioRecord (MediaRecoder.AudioResource.DEFAULT, sampleRate, AudioFormat.CHANNEL_IN_STEROE, AudioFormat.ENCODING_PCM_16BIT, minBufferSize);

裝pcm和MP3的buffer:

1 short[] buffer = new short[sampleRate * (16 / 8) * 2 * 5];
2 byte[] mp3buffer = new byte[(int) (7200 + buffer.length * 2 * 1.25)];

轉碼器初始化:

1 MP3Recorder.init(sampleRate, 2, sampleRate, 192);

這是轉碼:

1 // MP3 轉碼
2 int encResult = MP3Recorder.encode(buffer, buffer, readSize, mp3buffer);

 

兩個接口:

 AudioRecord 的構造函數:public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)

第一個參數是音源,可以是從MicroPhone( MediaRecorder.AudioSource.MIC),也可以是通話的話音( MediaRecorder.AudioSource.VOICE_CALL,MediaRecorder.AudioSource.VOICE_DOWNLINK即對方聲音,MediaRecorder.AudioSource.VOICE_UPLINK即本方聲音 )

第二個參數是期望錄音的采樣頻率,比如8000,16000,44100等

第三個參數是期望錄音的聲道數,可以是AudioFormat.CHANNEL_IN_MONO 和 AudioFormat.CHANNEL_STEREO.

第四個參數是期望錄音的比特數,可以是AudioFormat.ENCODING_PCM_16BIT和AudioFormat.ENCODING_PCM_8BIT.

第五個參數是期望錄音時系統為其提供的緩沖區大小,必須大於使用AudioRecord.getMinBufferSize() 得出的大小,這個參數指定的數值愈大,可以有更長的緩沖時間,也就是可以間隔較長的時間調用AudioRecord.read 函數從底層取得數據也不會溢出。

關於第一參數指定錄制電話通話時,有的手機可以,有的手機不行。不行的原因是因為平台沒有實現這個功能。

startRecording()之后就可以不斷調用 read函數取得聲音數據。這個函數是阻塞試的,下層沒有足夠的數據會停在它里面。

一般來說,在一個獨立線程里處理錄音的數據采集比較好。

AudioTrack的構造函數

AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)

第一個參數 是選擇流的種類,一般來說從喇叭放音選擇 STREAM_MUSIC

最后一個參數是表示一次性把數據傳給 AudioTrack還是連續不斷地使用  write 函數傳數據。我這里選擇 MODE_STREAM

還有幾個函數要在這里說一下。

write也是阻塞式的,下面的數據滿了的話,會在它里面等待。

getHeadPosition()返回值表示當前已經播放了多少幀(1幀就是采樣一次的意思,比如采樣率是8000的話,那么1秒鍾就是8000幀)

AudioTrack.OnPlaybackPositionUpdateListener 聲明兩個方法:

onMarkerReached(AudioTrack track )

onPeriodicNotification(AudioTrack track )

這兩個方法由客戶實現,通過 setPlaybackPositionUpdateListener 把該接口的實現類設進去。

通過 setNotificationMarkerPosition 設定一個marker位置,當聲音播放到這個位置時,就啟動onMarkerReached 方法。

通過 setPositionNotificationPeriod 設定一個周期,然后每播放了這個周期的聲音時,就會啟動 onPeriodicNotification 的周期。

getHeadPosition  , onMarkerReached , onPeriodicNotification 可以方便的取得聲音播放的時間,了解聲音的節奏,可以用來和視頻和字幕同步。 

 

e.g.

 1 錄制: 
 2 int minBuffSize = AudioRecord.getMinBufferSize(8000, 
 3 AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT); 
 4   AudioRecord mAudioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, 
 5           AudioFormat.CHANNEL_CONFIGURATION_MONO, 
 6           AudioFormat.ENCODING_PCM_16BIT, minBuffSize*3); 
 7 //開始錄音 
 8 mAudioRecorder.startRecording(); 
 9 
10 byte[] mBuffer = new byte[minBuffSize*3]; 
11 //從MIC獲取音頻數據到mBuffer中 
12 
13 int len = mAudioRecorder.read(mBuffer, 0, 1200); 

 

 1 播放: 
 2 int iMinBufSize = AudioTrack.getMinBufferSize(8000,  
 3 AudioFormat.CHANNEL_CONFIGURATION_STEREO, 
 4             AudioFormat.ENCODING_PCM_16BIT); 
 5 AudioTrack audioTrack=new AudioTrack(AudioManager.STREAM_MUSIC, 8000, 
 6 AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT, 
 7 iMinBufSize, AudioTrack.MODE_STREAM) ; 
 8 
 9 audioTrack.play(); 
10 audioTrack.write(data, 0, data.length);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM