Android音視頻(二)音頻AudioRecord和AudioTrack

Android音視頻(一) Camera2 API采集數(shù)據(jù)

AudioRecord和AudioTrack是Android系統(tǒng)提供的用于實現(xiàn)錄音、播放音頻的功能類,使用這兩個類做音頻的采集與播放還是非常簡單的。

AudioRecord

private void startRecorder() {
        try {
            // 1、輸出pcm文件
            mAudioFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/RecorderTest/" +
                    System.currentTimeMillis() + ".pcm");
            mAudioFile.getParentFile().mkdirs();
            mAudioFile.createNewFile();
            mFileOutputStream = new FileOutputStream(mAudioFile);

            // 2、配置AudioRecord
              // 聲音來源
            int audioSource = MediaRecorder.AudioSource.MIC;
              // 采樣率 Hz
            int sampleRate = 44100;
              // 音頻通道的配置 MONO 單聲道
            int channelConfig = AudioFormat.CHANNEL_IN_MONO;
              // 返回音頻數(shù)據(jù)的格式 
            int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
              //AudioRecord能接受的最小的buffer大小
            int minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
            mAudioRecorder = new AudioRecord(audioSource, sampleRate, channelConfig,
                    audioFormat, Math.max(minBufferSize, 2048));
            
            // 3、開始錄音
            mAudioRecorder.startRecording();

            
            // 4匾荆、一邊從AudioRecord中讀取聲音數(shù)據(jù)到初始化的buffer,一邊將buffer中數(shù)據(jù)導(dǎo)入數(shù)據(jù)流杆烁,寫入文件中
            while (mIsRecording) { // 標(biāo)志位牙丽,是否停止錄音
                int read = mAudioRecorder.read(mBuffer, 0, 2048);
                if (read > 0) {
                    mFileOutputStream.write(mBuffer, 0, read);
                    // 也可以在這里對音頻數(shù)據(jù)進行處理,壓縮兔魂、直播等
                } 
            }
            
            // 5烤芦、停止錄音,釋放資源
            mAudioRecorder.stop();
            mAudioRecorder.release();
            mAudioRecorder = null;
            mFileOutputStream.close();

        } catch (IOException | RuntimeException e) {
            e.printStackTrace();
        } finally {
            if (mAudioRecorder != null) {
                mAudioRecorder.release();
                mAudioRecorder = null;
            }
        }
    }

MediaRecorder 和 AudioRecord

Android SDK 中有兩套音頻采集的API析校,分別是:MediaRecorder 和 AudioRecord构罗。

  1. MediaRecorder是一個更加上層一點的API,它可以直接把手機麥克風(fēng)錄入的音頻數(shù)據(jù)進行編碼壓縮(如AMR智玻、MP3等)并存成文件

  2. AudioRecord則更接近底層遂唧,能夠更加自由靈活地控制,可以得到原始的一幀幀PCM音頻數(shù)據(jù)吊奢。

如果只是想簡單地做一個錄音機盖彭,錄制音頻文件,就使用 MediaRecorder事甜,而如果需要對音頻做進一步的算法處理谬泌、或者采用第三方的編碼庫進行壓縮、以及網(wǎng)絡(luò)傳輸逻谦、直播等應(yīng)用,則建議使用 AudioRecord陪蜻。

AudioTrack

private void doPaly(File mAudioFile) {
        // 音頻流的類型
        // STREAM_ALARM:警告聲 
        // STREAM_MUSIC:音樂聲
        // STREAM_RING:鈴聲
        // STREAM_SYSTEM:系統(tǒng)聲音邦马,例如低電提示音,鎖屏音等
        // STREAM_VOCIE_CALL:通話聲
        int streamType = AudioManager.STREAM_MUSIC;
    
        // 采樣率 Hz
        int sampleRate = 44100;
        // 單聲道
        int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
        
        // 音頻數(shù)據(jù)表示的格式
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    
        // MODE_STREAM:在這種模式下宴卖,通過write一次次把音頻數(shù)據(jù)寫到AudioTrack中滋将。這和平時通過
        // write系統(tǒng)調(diào)用往文件中寫數(shù)據(jù)類似,但這種工作方式每次都需要把數(shù)據(jù)從用戶提供的Buffer中拷貝到
        // AudioTrack內(nèi)部的Buffer中症昏,這在一定程度上會使引入延時随闽。為解決這一問題,AudioTrack就引入
        // 了第二種模式肝谭。
    
        // MODE_STATIC:這種模式下掘宪,在play之前只需要把所有數(shù)據(jù)通過一次write調(diào)用傳遞到AudioTrack
        // 中的內(nèi)部緩沖區(qū)蛾扇,后續(xù)就不必再傳遞數(shù)據(jù)了。這種模式適用于像鈴聲這種內(nèi)存占用量較小魏滚,延時要求較
        // 高的文件镀首。但它也有一個缺點,就是一次write的數(shù)據(jù)不能太多鼠次,否則系統(tǒng)無法分配足夠的內(nèi)存來存儲
        // 全部數(shù)據(jù)更哄。
        int mode = AudioTrack.MODE_STREAM;

        int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);

        AudioTrack audioTrack = new AudioTrack(streamType, sampleRate, channelConfig, audioFormat, Math.max(minBufferSize, 2048), mode);

        FileInputStream mFileInputStream = null;
        try {
            mFileInputStream = new FileInputStream(mAudioFile);
            int read;
            audioTrack.play();
            while ((read = mFileInputStream.read(mBuffer)) > 0) {
                int ret = audioTrack.write(mBuffer, 0, read);
                switch (ret) {
                    case AudioTrack.ERROR_BAD_VALUE:
                    case AudioTrack.ERROR_INVALID_OPERATION:
                    case AudioManager.ERROR_DEAD_OBJECT:
                        palyFaile();
                        break;
                    default:
                        break;
                }
            }
        } catch (RuntimeException | IOException e) {
            e.printStackTrace();
            palyFaile();
        } finally {
            mIsPalying = false;
            if (mFileInputStream != null) {
                closeQuietly(mFileInputStream);
            }
            audioTrack.stop();
            audioTrack.release();
        }
    }

AudioTrack 與 MediaPlayer

在Android中播放聲音也是有兩套API:MediaPlayer和AudioTrack,兩者還是有很大的區(qū)別的腥寇。

  1. MediaPlayer可以播放多種格式的聲音文件成翩,例如MP3,AAC赦役,WAV捕传,OGG,MIDI等扩劝。MediaPlayer會在framework層創(chuàng)建對應(yīng)的音頻解碼器庸论。

  2. AudioTrack只能播放已經(jīng)解碼的PCM流,如不需要解碼的wav文件棒呛。

MediaPlayer在framework層還是會創(chuàng)建AudioTrack聂示,把解碼后的PCM數(shù)流傳遞給AudioTrack,AudioTrack再傳遞給AudioFlinger進行混音簇秒,然后才傳遞給硬件播放,所以是MediaPlayer包含了AudioTrack鱼喉。

Demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市趋观,隨后出現(xiàn)的幾起案子扛禽,更是在濱河造成了極大的恐慌,老刑警劉巖皱坛,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件编曼,死亡現(xiàn)場離奇詭異,居然都是意外死亡剩辟,警方通過查閱死者的電腦和手機掐场,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贩猎,“玉大人熊户,你說我怎么就攤上這事】苑” “怎么了嚷堡?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長艇棕。 經(jīng)常有香客問我蝌戒,道長串塑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任瓶颠,我火速辦了婚禮拟赊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘粹淋。我一直安慰自己吸祟,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布桃移。 她就那樣靜靜地躺著屋匕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪借杰。 梳的紋絲不亂的頭發(fā)上过吻,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天,我揣著相機與錄音蔗衡,去河邊找鬼纤虽。 笑死,一個胖子當(dāng)著我的面吹牛绞惦,可吹牛的內(nèi)容都是我干的逼纸。 我是一名探鬼主播,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼济蝉,長吁一口氣:“原來是場噩夢啊……” “哼杰刽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起王滤,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤贺嫂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后雁乡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體第喳,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年蔗怠,在試婚紗的時候發(fā)現(xiàn)自己被綠了墩弯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡寞射,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锌钮,到底是詐尸還是另有隱情桥温,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布梁丘,位于F島的核電站侵浸,受9級特大地震影響旺韭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掏觉,卻給世界環(huán)境...
    茶點故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一区端、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧澳腹,春花似錦织盼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至羊娃,卻和暖如春唐全,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蕊玷。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工邮利, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人垃帅。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓延届,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挺智。 傳聞我的和親對象是個殘疾皇子祷愉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,982評論 2 361

推薦閱讀更多精彩內(nèi)容