Android 使用AudioRecord錄音相關和音頻檔案的封裝

來源:互聯網
上載者:User

在Android中錄音可以用MediaRecord錄音,操作比較簡單。但是不夠專業,就是不能對音頻進行處理。如果要進行音訊即時的處理或者音訊一些封裝

就可以用AudioRecord來進行錄音了。

這裡給出一段代碼。實現了AudioRecord的錄音和WAV格式音訊封裝。

用AudioTrack和AudioTrack類可以進行邊錄邊播,可以參考:http://blog.sina.com.cn/s/blog_6309e1ed0100j1rw.html

我們這裡的代碼沒有播放。但是有封裝和詳解,如下:

package com.ppmeet;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import android.app.Activity;import android.graphics.PixelFormat;import android.media.AudioFormat;import android.media.AudioRecord;import android.media.MediaRecorder;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.view.WindowManager;import android.widget.Button;/** * class name:TestAudioRecord<BR> * class description:用AudioRecord來進行錄音<BR> * PS: <BR> *  * @version 1.00 2011/09/21 * @author CODYY)peijiangping */public class TestAudioRecord extends Activity {// 音頻擷取源private int audioSource = MediaRecorder.AudioSource.MIC;// 設定音頻採樣率,44100是目前的標準,但是某些裝置仍然支援22050,16000,11025private static int sampleRateInHz = 44100;// 設定音訊錄製的聲道CHANNEL_IN_STEREO為雙聲道,CHANNEL_CONFIGURATION_MONO為單聲道private static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;// 音頻資料格式:PCM 16位每個樣本。保證裝置支援。PCM 8位每個樣本。不一定能得到裝置支援。private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;// 緩衝區位元組大小private int bufferSizeInBytes = 0;private Button Start;private Button Stop;private AudioRecord audioRecord;private boolean isRecord = false;// 設定正在錄製的狀態//AudioName裸音頻資料檔案private static final String AudioName = "/sdcard/love.raw";//NewAudioName可播放的音頻檔案private static final String NewAudioName = "/sdcard/new.wav";public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);getWindow().setFormat(PixelFormat.TRANSLUCENT);// 讓介面橫屏requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉介面標題getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);// 重新設定介面大小setContentView(R.layout.main);init();}private void init() {Start = (Button) this.findViewById(R.id.start);Stop = (Button) this.findViewById(R.id.stop);Start.setOnClickListener(new TestAudioListener());Stop.setOnClickListener(new TestAudioListener());creatAudioRecord();}private void creatAudioRecord() {// 獲得緩衝區位元組大小bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig, audioFormat);// 建立AudioRecord對象audioRecord = new AudioRecord(audioSource, sampleRateInHz,channelConfig, audioFormat, bufferSizeInBytes);}class TestAudioListener implements OnClickListener {@Overridepublic void onClick(View v) {if (v == Start) {startRecord();}if (v == Stop) {stopRecord();}}}private void startRecord() {audioRecord.startRecording();// 讓錄製狀態為trueisRecord = true;// 開啟音頻檔案寫入線程new Thread(new AudioRecordThread()).start();}private void stopRecord() {close();}private void close() {if (audioRecord != null) {System.out.println("stopRecord");isRecord = false;//停止檔案寫入audioRecord.stop();audioRecord.release();//釋放資源audioRecord = null;}}class AudioRecordThread implements Runnable {@Overridepublic void run() {writeDateTOFile();//往檔案中寫入裸資料copyWaveFile(AudioName, NewAudioName);//給裸資料加上標頭檔}}/** * 這裡將資料寫入檔案,但是並不能播放,因為AudioRecord獲得的音頻是原始的裸音頻, * 如果需要播放就必須加入一些格式或者編碼的頭資訊。但是這樣的好處就是你可以對音訊 裸資料進行處理,比如你要做一個愛說話的TOM * 貓在這裡就進行音訊處理,然後重新封裝 所以說這樣得到的音頻比較容易做一些音訊處理。 */private void writeDateTOFile() {// new一個byte數組用來存一些位元組資料,大小為緩衝區大小byte[] audiodata = new byte[bufferSizeInBytes];FileOutputStream fos = null;int readsize = 0;try {File file = new File(AudioName);if (file.exists()) {file.delete();}fos = new FileOutputStream(file);// 建立一個可存取位元組的檔案} catch (Exception e) {e.printStackTrace();}while (isRecord == true) {readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes);if (AudioRecord.ERROR_INVALID_OPERATION != readsize) {try {fos.write(audiodata);} catch (IOException e) {e.printStackTrace();}}}try {fos.close();// 關閉寫入流} catch (IOException e) {e.printStackTrace();}}// 這裡得到可播放的音頻檔案private void copyWaveFile(String inFilename, String outFilename) {FileInputStream in = null;FileOutputStream out = null;long totalAudioLen = 0;long totalDataLen = totalAudioLen + 36;long longSampleRate = sampleRateInHz;int channels = 2;long byteRate = 16 * sampleRateInHz * channels / 8;byte[] data = new byte[bufferSizeInBytes];try {in = new FileInputStream(inFilename);out = new FileOutputStream(outFilename);totalAudioLen = in.getChannel().size();totalDataLen = totalAudioLen + 36;WriteWaveFileHeader(out, totalAudioLen, totalDataLen,longSampleRate, channels, byteRate);while (in.read(data) != -1) {out.write(data);}in.close();out.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/** * 這裡提供一個頭資訊。插入這些資訊就可以得到可以播放的檔案。 * 為我為啥插入這44個位元組,這個還真沒深入研究,不過你隨便開啟一個wav * 音訊檔案,可以發現前面的標頭檔可以說基本一樣哦。每種格式的檔案都有 * 自己特有的標頭檔。 */private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen,long totalDataLen, long longSampleRate, int channels, long byteRate)throws IOException {byte[] header = new byte[44];header[0] = 'R'; // RIFF/WAVE headerheader[1] = 'I';header[2] = 'F';header[3] = 'F';header[4] = (byte) (totalDataLen & 0xff);header[5] = (byte) ((totalDataLen >> 8) & 0xff);header[6] = (byte) ((totalDataLen >> 16) & 0xff);header[7] = (byte) ((totalDataLen >> 24) & 0xff);header[8] = 'W';header[9] = 'A';header[10] = 'V';header[11] = 'E';header[12] = 'f'; // 'fmt ' chunkheader[13] = 'm';header[14] = 't';header[15] = ' ';header[16] = 16; // 4 bytes: size of 'fmt ' chunkheader[17] = 0;header[18] = 0;header[19] = 0;header[20] = 1; // format = 1header[21] = 0;header[22] = (byte) channels;header[23] = 0;header[24] = (byte) (longSampleRate & 0xff);header[25] = (byte) ((longSampleRate >> 8) & 0xff);header[26] = (byte) ((longSampleRate >> 16) & 0xff);header[27] = (byte) ((longSampleRate >> 24) & 0xff);header[28] = (byte) (byteRate & 0xff);header[29] = (byte) ((byteRate >> 8) & 0xff);header[30] = (byte) ((byteRate >> 16) & 0xff);header[31] = (byte) ((byteRate >> 24) & 0xff);header[32] = (byte) (2 * 16 / 8); // block alignheader[33] = 0;header[34] = 16; // bits per sampleheader[35] = 0;header[36] = 'd';header[37] = 'a';header[38] = 't';header[39] = 'a';header[40] = (byte) (totalAudioLen & 0xff);header[41] = (byte) ((totalAudioLen >> 8) & 0xff);header[42] = (byte) ((totalAudioLen >> 16) & 0xff);header[43] = (byte) ((totalAudioLen >> 24) & 0xff);out.write(header, 0, 44);}@Overrideprotected void onDestroy() {close();super.onDestroy();}}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.