AudioRecord實作錄音功能
- 簡介
- 實作步驟及決議
- 測驗
簡介
AudioRecord類管理Java應用程式的音瞥澩,以便從平臺的音頻輸入硬體錄制音頻,
AudioRecord錄制的是PCM格式的音頻檔案,需要用AudioTrack來播放(下一期介紹),AudioTrack比MediaRecorder更接近底層、更專業,
實作步驟及決議
1、添加權限

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
分別是錄音權限;讀、寫外部存盤器權限
2、撰寫基于AudioRecord的錄音工具類
AudioRecordTool.java
package com.audioandvideo.two.Tool;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 基于AudioRecord的錄音工具類
*/
public class AudioRecordTool{
private AudioRecord audioRecord;
private int recordBufSize = 0;
private byte data[];
private PcmToWavTool tool;
private boolean isRecording = false;
//錄音得到的檔案 的儲存位置及檔案名
private final String pcmFileName = Environment.getExternalStorageDirectory() + "/Download/record.pcm";
//轉換成wav檔案后新檔案的存盤位置及檔案名
private final String wavFileName = Environment.getExternalStorageDirectory() + "/Download/record1.wav";
// 音頻源:音頻輸入-麥克風
private final static int AUDIO_INPUT = MediaRecorder.AudioSource.MIC;
// 采樣率:音頻的采樣頻率,每秒鐘能夠采樣的次數,采樣率越高,音質越高
// 44100是目前的標準,但是某些設備仍然支持22050,16000,11025
// 采樣頻率一般共分為22.05KHz、44.1KHz、48KHz三個等級
private final static int AUDIO_SAMPLE_RATE = 44100;
// 聲道設定:android支持雙聲道立體聲和單聲道,MONO單聲道,STEREO立體聲
private final static int AUDIO_CHANNEL = AudioFormat.CHANNEL_IN_MONO;
// 編碼制式和采樣大小:采集來的資料當然使用PCM編碼
// (脈沖代碼調制編碼,即PCM編碼,PCM通過抽樣、量化、編碼三個步驟將連續變化的模擬信號轉換為數字編碼,)
// android支持的采樣大小16bit 或者8bit,當然采樣大小越大,那么資訊量越多,音質也越高,現在主流的采樣
// 大小都是16bit,在低質量的語音傳輸的時候8bit 足夠了,
private final static int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
//初始化
public void createAudioRecord() {
recordBufSize = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING); //audioRecord能接受的最小的buffer大小
//構造方法,傳入的引數上面在有決議
audioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING, recordBufSize);
data = new byte[recordBufSize];
tool = new PcmToWavTool(AUDIO_SAMPLE_RATE,AUDIO_CHANNEL,AUDIO_ENCODING);
}
//開始錄音
public void start(){
Log.i("AUDIO","開始錄音");
isRecording = true;
//呼叫startRecording()方法開始錄制
audioRecord.startRecording();
MyThread myThread = new MyThread();
myThread.start();
}
//停止錄音
public void stop(){
isRecording = false;
if (audioRecord != null){
Log.i("AUDIO","停止錄音");
//呼叫stop()方法停止錄制
audioRecord.stop();
//呼叫release() 釋放本機錄音資源,
audioRecord.release();
audioRecord = null;
}
//利用自定義工具類將pcm格式的檔案轉換為wav格式檔案才能進行播放
tool.pcmToWav(pcmFileName,wavFileName);
}
private class MyThread extends Thread{
@Override
public void run() {
super.run();
FileOutputStream os = null;
try {
//如果檔案不存在,就創建檔案
if(!new File(pcmFileName).exists()){
new File(pcmFileName).createNewFile();
}
os = new FileOutputStream(pcmFileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (null != os) {
while (isRecording) {
//呼叫read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes)方法
// 從音頻硬體讀取音頻資料,以便記錄到位元組陣列中,
int read = audioRecord.read(data, 0, recordBufSize);
// 如果讀取音頻資料沒有出現錯誤,就將資料寫入到檔案
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
try {
os.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
//關閉檔案
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3、撰寫pcm格式轉化為wav格式的工具類,播放器才能進行播放
PcmToWavTool .java
package com.audioandvideo.two.Tool;
import android.media.AudioFormat;
import android.media.AudioRecord;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**pcm格式轉化為wav格式的工具類
* PCM編碼是直接存盤聲波采樣被量化后所產生的非壓縮資料,故被視為單純的無損耗編碼格式,其優點是可獲得高質量的音頻信號
* WAV是最常見的聲音檔案格式之一
*/
public class PcmToWavTool {
/**
* 快取的音頻大小
*/
private int mBufferSize;
/**
* 采樣率
*/
private int mSampleRate;
/**
* 聲道數
*/
private int mChannel;
/**
* @param sampleRate sample rate、采樣率
* @param channel channel、聲道
* @param encoding Audio data format、音頻格式
*/
PcmToWavTool(int sampleRate, int channel, int encoding) {
this.mSampleRate = sampleRate;
this.mChannel = channel;
this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannel, encoding);
}
/**
* pcm檔案轉wav檔案
*
* @param inFilename 源檔案路徑
* @param outFilename 目標檔案路徑
*/
public void pcmToWav(String inFilename, String outFilename) {
FileInputStream in;
FileOutputStream out;
long totalAudioLen;
long totalDataLen;
long longSampleRate = mSampleRate;
int channels = mChannel == AudioFormat.CHANNEL_IN_MONO ? 1 : 2;
long byteRate = 16 * mSampleRate * channels / 8;
byte[] data = new byte[mBufferSize];
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 (IOException e) {
e.printStackTrace();
}
}
/**
* 加入wav檔案頭
*/
private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen,
long totalDataLen, long longSampleRate, int channels, long byteRate)
throws IOException {
byte[] header = new byte[44];
// RIFF/WAVE header
header[0] = 'R';
header[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);
//WAVE
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
// 'fmt ' chunk
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
// 4 bytes: size of 'fmt ' chunk
header[16] = 16;
header[17] = 0;
header[18] = 0;
header[19] = 0;
// format = 1
header[20] = 1;
header[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);
// block align
header[32] = (byte) (2 * 16 / 8);
header[33] = 0;
// bits per sample
header[34] = 16;
header[35] = 0;
//data
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);
}
}
4、撰寫Activity
AudioRecordActivity.java
package com.audioandvideo.two.Activity;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.audioandvideo.R;
import com.audioandvideo.two.Tool.AudioRecordTool;
/**
* 錄音Activity
*/
public class AudioRecordActivity extends AppCompatActivity implements View.OnClickListener{
private Button btnStart;
private Button btnStop;
private AudioRecordTool audioRecordTool;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_record);
btnStart = findViewById(R.id.btn_start);
btnStop = findViewById(R.id.btn_stop);
audioRecordTool = new AudioRecordTool();
//初始化
audioRecordTool.createAudioRecord();
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_start:
audioRecordTool.start();
break;
case R.id.btn_stop:
audioRecordTool.stop();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
audioRecordTool.stop();
}
}
頁面只有2個按鈕,一個開始錄音按鈕,一個停止錄音按鈕

測驗
手機有檔案,能播放,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/263716.html
標籤:其他
上一篇:2021涅普冬令營_wp_(二)
下一篇:ipad1安裝xbmc及配置教程
