編輯:關於Android編程
說到音頻應用,首先想到的就是音樂播放器。有些播放器可以播放流媒體,有些可以播放本地音樂文件。隨著Android平台的演變,需要更多高級的音頻API。好在谷歌新增了這方面的API,支持低延遲的音頻流媒體和錄制。
Android音頻API提供了一些高級的功能,開發者可以把它們集成到自己的應用中。有了這些API,現在可以更容易地實現VoIP應用程序,構建定制的流媒體音樂客戶端,實現低延遲的游戲音效。此外,還有提供文本到語音轉換以及語音識別的API,用戶可以直接使用音頻和應用交互,而不需要使用用戶界面或者觸控技術。
Android有四個用來播放音頻的API(算上MIDI的話一共五個)和三個用來錄音的API。接下來會簡要的介紹這些API,以及一些高級用法示例。
音樂播放默認使用MediaPlayer。該類適合播放音樂或者視頻,既能播放流式資源,還可以播放本地文件。每個MediaPlayer都有一個關聯的狀態機,需要在應用程序中跟蹤這些狀態。開發者可以使用MediaPlayer類的API在自己應用中嵌入音樂或者視頻播放功能,而無需額外處理或者考慮延遲要求。
第二個選擇是SoundPool類,它提供了低延遲支持,適合播放音效和其他比較短的音頻,比如可以使用SoundPool播放游戲聲音。但是,它不支持音頻流,所以不適合那些需要實時音頻流處理的應用,如VoIP。
第三個選擇是AudioTrack類,它允許把音頻流緩沖到硬件中,支持低延遲播放,甚至適合流媒體場景。AudioTrack類通常提供足夠低的延遲,可在VoIP或類似應用中使用。
下面的代碼展示了如何在VoIP應用中使用AudioTrack:
public class AudioTrackDemo { private final int mMinBufferSize; private final AudioTrack mAudioTrack; public AudioTrackDemo() { this.mMinBufferSize = AudioTrack.getMinBufferSize(16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); this.mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, this.mMinBufferSize*2, AudioTrack.MODE_STREAM); } public void playPcmPacket(byte[] pcmData) { if (this.mAudioTrack != null && this.mAudioTrack.getState() == AudioTrack.STATE_INITIALIZED) { if (this.mAudioTrack.getPlaybackRate() != AudioTrack.PLAYSTATE_PLAYING) { this.mAudioTrack.play(); } this.mAudioTrack.write(pcmData, 0, pcmData.length); } } public void stopPlayback() { if (this.mAudioTrack != null) { this.mAudioTrack.stop(); this.mAudioTrack.release(); } } }
首先,確定音頻流的最小緩沖區大小。要做到這一點,需要知道采樣率,數據是單聲道還是立體聲,以及是否使用8位或者16位PCM編碼。然後以采樣率和采樣大小作為參數調用AudioTrack.getMinBufferSize(),該方法會以字節形式返回AudioTrack實例的最小緩沖區大小。
接下來,根據需要使用正確參數創建AudioTrack實例。第一個參數為音頻的類型,不同的應用使用不同的值。對VoIP應用來說,使用STREAM_VOICE_CALL,而對於流媒體音樂應用則使用STREAM_MUSIC。
具體的選擇有:
STREAM_ALARM:手機鬧鈴的聲音
STREAM_MUSIC:手機音樂的聲音
STREAM_DTMF:DTMF音調的聲音
STREAM_RING:電話鈴聲的聲音
STREAM_NOTFICATION:系統提示的聲音
STREAM_SYSTEM:系統的聲音
STREAM_VOICE_CALL:語音電話聲音
第二,第三,第四個參數根據使用場景會有所不同。這些參數分別表示采樣率,立體聲或者單聲道,以及采樣大小。一般而言,一個VoIP應用會使用16KHZ的16位單聲道,而常規的音樂CD可能采用44.1KHZ的16位立體聲。16位立體聲高采樣率需要更大的緩沖區以及更多的數據傳輸,但是音質會更好。所有的Android設備都支持PCM以8KHZ,16KHZ,44.1KHZ的采樣率播放8或者16位立體聲。
緩沖區大小參數應該是最小緩沖區的倍數,實際取決於具體的需求,有時網絡延遲等因素也會影響緩沖區大小。
任何時候都應該避免使用空的緩沖區,因為可能導致播放出現故障。
最後一個參數決定只發送一次音頻數據(MODE_STATIC)還是連續發送數據流(MODE_STREAM)。第一種情況需要一次發送整個音頻剪輯。對於持續發送音頻流的情況,可以發送任大小塊的PCM數據,處理流媒體音樂或者VoIP通話可以會使用這種方式。
談到錄制音頻,首先要考慮的API是MediaRecorder。和MediaPlayer類似,需要在應用代碼中跟蹤MediaRecorder類的內部狀態。由於MediaRecorder只能把錄音保存到文件中,所以它不適合錄制流媒體。
如果需要錄制流媒體,可以使用AudioRecord,和剛才展示的代碼非常類似。
下面的示例顯示了如何創建AudioRecord實例錄制16位單聲道16KHZ的音頻采樣:
public class AudioRecordDemo { private final AudioRecord mAudioRecord; private final int mMinBufferSize; private boolean mDoRecord = false; public AudioRecordDemo() { this.mMinBufferSize = AudioTrack.getMinBufferSize(16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); this.mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, this.mMinBufferSize * 2); } public void writeAudioToStream(OutputStream stream){ this.mDoRecord=true; this.mAudioRecord.startRecording(); byte[] buffer=new byte[this.mMinBufferSize*2]; while(this.mDoRecord){ int byteWritten=this.mAudioRecord.read(buffer,0,buffer.length); try{ stream.write(buffer,0,byteWritten); }catch(IOException e){ this.mDoRecord=false; } } this.mAudioRecord.stop(); this.mAudioRecord.release(); } public void stopRecording(){ this.mDoRecord=false; } }
因為和AudioTrack的創建過程非常類似,在使用VoIP或者類似應用時可以很方便地把它們結合起來。
相信學過多媒體的人對采樣率等這些東西並不陌生,如果缺乏這方面的知識,可以適當的補充後在來看這段代碼。
如果看的認真的人會發現本文只介紹了三個播放API和兩個錄制API,說好的四個的三個呢?其實最後一個不是一兩句就能說清楚,還需要單獨列出一篇文章講解——OpenSL ES請關注本博客後續會講解到。
今天是Android學習第四天,上午簡單的學習了數據的存儲與使用,在這裡把上午的總結一下 數據存儲分為四大類: * 文件 * Sharedpreference(參數) *
面對一個項目,對於Android應用開發框架的選擇,我想過三種方案:1.使用Loader + HttpClient + GreenDao + Gson + Fragmen
其實很早之前也寫了一篇Gradle的基礎博客,但是時間很久了,現在Gradle已經更新了很多,所以暫且結合Stduio 1.0正式版與最新的Gradle語法來詳細講解下,
Android現在實現Tab類型的界面方式越來越多,今天就把常見的實現方式給大家來個總結。目前寫了:1、傳統的ViewPager實現2、FragmentManager+F