Androidレコーディング実装(AudioRecord)
10760 ワード
前回はMediaRecorderを使用した録音機能Android録音実装(MediaRecorder)について紹介しましたが、AudioRecordsを使用した録音機能について引き続き見ていきます.
AudioRecord
まず、Androidヘルプドキュメントの簡単な概要を見てみましょう.AndioRecordクラスの主な機能は、プラットフォームの音声を録画してハードウェアで収集した音声を入力できるように、さまざまなJavaアプリケーションがオーディオリソースを管理できるようにすることです.この機能の実現は、「pulling同期」(reading Reading)AudioRecordオブジェクトの音声データによるものである.録音の過程において、アプリケーションが必要とするのは、後の3つのクラスの方法のうちの1つによってAudioRecordオブジェクトの録音データをタイムリーに取得することである.AudioRecordクラスが提供する3つの音声データを取得する方法は、それぞれread(byte[],int,int)であり、 read(short[], int, int), read(ByteBuffer, int).いずれの方法を選択しても,ユーザの音声データを容易に格納するためのフォーマットを事前に設定しておく必要がある.
録音を開始するとき、AudioRecordは関連する音声bufferを初期化する必要があります.このbufferは主に新しい音声データを保存するために使用されます.このbufferのサイズは、オブジェクトの構築中に指定できます.これは、AudioRecordオブジェクトがまだ音声データを読み込まれていない(同期されていない)前に、どのくらいの音(すなわち、一度に録画可能な音声容量)を記録できるかを示しています.音声データは、オーディオハードウェアから読み出され、録音データ全体のサイズを超えない(複数回に分けて読み出される)、すなわちbuffer容量を初期化したデータを読み出すたびに読み出される.
収集作業は簡単で、AudioRecordオブジェクトを構築し、さまざまな構成のパラメータを入力するだけでいいです.一般的に録音の実現の簡単な流れは以下の通りである.オーディオソース:オーディオを収集するデータソースとしてマイクを使用できます. サンプリングレート:1秒の音声データのサンプリング回数、サンプリングレートが高いほど音質が良い. オーディオチャネル:シングルチャネル、デュアルチャネルなど、 オーディオフォーマット:一般的にPCMフォーマット、すなわち元のオーディオサンプルを選択する. バッファサイズ:オーディオデータ書き込みバッファの総数は、AudioRecord.getMinBufferSizeは最小のバッファを取得します.(オーディオをバッファに収集し、バッファから読み出す). コードは次のように実装されます.
AudioRecorder録音音声データはオーディオハードウェアから読み出され、符号化形式はPCM形式であるが、PCM音声データは、オーディオファイルとして保存されていればプレーヤーで再生できないため、先にコードを書いてデータ符号化および圧縮を実現しなければならない.以下、PCM音声データのWAVファイルへの移行を実現する.
まとめ:AudioRecorder録音はMediaRecorderと比較して使用すると面倒になるが、利点も明らかである.AudioRecorder録音時にハードウェアを直接操作してオーディオストリームデータを取得するプロセスはリアルタイム処理であり、コードで各種オーディオのパッケージを実現できるとともに、一時停止機能を実現できる.imhxlブロガーの共有をお勧めしますhttp://blog.csdn.net/imhxl/article/details/52190451 .
作者:DreamFishリンク:https://www.jianshu.com/p/90c4071c7768出典:簡書の著作権は作者の所有である.商業転載は著者に連絡して許可を得てください.非商業転載は出典を明記してください.
AudioRecord
まず、Androidヘルプドキュメントの簡単な概要を見てみましょう.AndioRecordクラスの主な機能は、プラットフォームの音声を録画してハードウェアで収集した音声を入力できるように、さまざまなJavaアプリケーションがオーディオリソースを管理できるようにすることです.この機能の実現は、「pulling同期」(reading Reading)AudioRecordオブジェクトの音声データによるものである.録音の過程において、アプリケーションが必要とするのは、後の3つのクラスの方法のうちの1つによってAudioRecordオブジェクトの録音データをタイムリーに取得することである.AudioRecordクラスが提供する3つの音声データを取得する方法は、それぞれread(byte[],int,int)であり、 read(short[], int, int), read(ByteBuffer, int).いずれの方法を選択しても,ユーザの音声データを容易に格納するためのフォーマットを事前に設定しておく必要がある.
録音を開始するとき、AudioRecordは関連する音声bufferを初期化する必要があります.このbufferは主に新しい音声データを保存するために使用されます.このbufferのサイズは、オブジェクトの構築中に指定できます.これは、AudioRecordオブジェクトがまだ音声データを読み込まれていない(同期されていない)前に、どのくらいの音(すなわち、一度に録画可能な音声容量)を記録できるかを示しています.音声データは、オーディオハードウェアから読み出され、録音データ全体のサイズを超えない(複数回に分けて読み出される)、すなわちbuffer容量を初期化したデータを読み出すたびに読み出される.
収集作業は簡単で、AudioRecordオブジェクトを構築し、さまざまな構成のパラメータを入力するだけでいいです.一般的に録音の実現の簡単な流れは以下の通りである.
public class AudioRecorder {
private static AudioRecorder audioRecorder;
// : -
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 = 16000;
//
private final static int AUDIO_CHANNEL = AudioFormat.CHANNEL_IN_MONO;
// :PCM
private final static int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
// :
private int bufferSizeInBytes = 0;
//
private AudioRecord audioRecord;
//
private Status status = Status.STATUS_NO_READY;
//
private String fileName;
//
private List filesName = new ArrayList<>();
private AudioRecorder() {
}
//
public static AudioRecorder getInstance() {
if (audioRecorder == null) {
audioRecorder = new AudioRecorder();
}
return audioRecorder;
}
/**
*
*/
public void createAudio(String fileName, int audioSource, int sampleRateInHz, int channelConfig, int audioFormat) {
//
bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
channelConfig, audioFormat);
audioRecord = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes);
this.fileName = fileName;
}
/**
*
* @param fileName
*/
public void createDefaultAudio(String fileName) {
mContext = ctx;
mHandler = handler;
//
bufferSizeInBytes = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE,
AUDIO_CHANNEL, AUDIO_ENCODING);
audioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING, bufferSizeInBytes);
this.fileName = fileName;
status = Status.STATUS_READY;
}
/**
*
* @param listener
*/
public void startRecord(final RecordStreamListener listener) {
if (status == Status.STATUS_NO_READY || TextUtils.isEmpty(fileName)) {
throw new IllegalStateException(" , ~");
}
if (status == Status.STATUS_START) {
throw new IllegalStateException(" ");
}
Log.d("AudioRecorder","===startRecord==="+audioRecord.getState());
audioRecord.startRecording();
new Thread(new Runnable() {
@Override
public void run() {
writeDataTOFile(listener);
}
}).start();
}
/**
*
*/
public void stopRecord() {
Log.d("AudioRecorder","===stopRecord===");
if (status == Status.STATUS_NO_READY || status == Status.STATUS_READY) {
throw new IllegalStateException(" ");
} else {
audioRecord.stop();
status = Status.STATUS_STOP;
release();
}
}
/**
*
*/
public void canel() {
filesName.clear();
fileName = null;
if (audioRecord != null) {
audioRecord.release();
audioRecord = null;
}
status = Status.STATUS_NO_READY;
}
/**
*
*/
public void release() {
Log.d("AudioRecorder","===release===");
//
try {
if (filesName.size() > 0) {
List filePaths = new ArrayList<>();
for (String fileName : filesName) {
filePaths.add(FileUtils.getPcmFileAbsolutePath(fileName));
}
//
filesName.clear();
// pcm wav
mergePCMFilesToWAVFile(filePaths);
} else {
// filesName.size 0, fileName null
// NullPointerException
// pcm wav
//Log.d("AudioRecorder", "=====makePCMFileToWAVFile======");
//makePCMFileToWAVFile();
}
} catch (IllegalStateException e) {
throw new IllegalStateException(e.getMessage());
}
if (audioRecord != null) {
audioRecord.release();
audioRecord = null;
}
status = Status.STATUS_NO_READY;
}
/**
*
* @param listener
*/
private void writeDataTOFile(RecordStreamListener listener) {
// new byte ,
byte[] audiodata = new byte[bufferSizeInBytes];
FileOutputStream fos = null;
int readsize = 0;
try {
String currentFileName = fileName;
if (status == Status.STATUS_PAUSE) {
// ,
currentFileName += filesName.size();
}
filesName.add(currentFileName);
File file = new File(FileUtils.getPcmFileAbsolutePath(currentFileName));
if (file.exists()) {
file.delete();
}
fos = new FileOutputStream(file);//
} catch (IllegalStateException e) {
Log.e("AudioRecorder", e.getMessage());
throw new IllegalStateException(e.getMessage());
} catch (FileNotFoundException e) {
Log.e("AudioRecorder", e.getMessage());
}
//
status = Status.STATUS_START;
while (status == Status.STATUS_START) {
readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes);
if (AudioRecord.ERROR_INVALID_OPERATION != readsize && fos != null) {
try {
fos.write(audiodata);
if (listener != null) {
//
listener.recordOfByte(audiodata, 0, audiodata.length);
}
} catch (IOException e) {
Log.e("AudioRecorder", e.getMessage());
}
}
}
try {
if (fos != null) {
fos.close();//
}
} catch (IOException e) {
Log.e("AudioRecorder", e.getMessage());
}
}
}
AudioRecorder録音音声データはオーディオハードウェアから読み出され、符号化形式はPCM形式であるが、PCM音声データは、オーディオファイルとして保存されていればプレーヤーで再生できないため、先にコードを書いてデータ符号化および圧縮を実現しなければならない.以下、PCM音声データのWAVファイルへの移行を実現する.
/**
* pcm wav
* @param pcmPath pcm
* @param destinationPath (wav)
* @param deletePcmFile
* @return
*/
public static boolean makePCMFileToWAVFile(String pcmPath, String destinationPath, boolean deletePcmFile) {
byte buffer[] = null;
int TOTAL_SIZE = 0;
File file = new File(pcmPath);
if (!file.exists()) {
return false;
}
TOTAL_SIZE = (int) file.length();
// , 。 16 8000 hz
WaveHeader header = new WaveHeader();
// = (TOTAL_SIZE) +
// ( 4 RIFF fileLength 4 )
header.fileLength = TOTAL_SIZE + (44 - 8);
header.FmtHdrLeth = 16;
header.BitsPerSample = 16;
header.Channels = 2;
header.FormatTag = 0x0001;
header.SamplesPerSec = 8000;
header.BlockAlign = (short) (header.Channels * header.BitsPerSample / 8);
header.AvgBytesPerSec = header.BlockAlign * header.SamplesPerSec;
header.DataHdrLeth = TOTAL_SIZE;
byte[] h = null;
try {
h = header.getHeader();
} catch (IOException e1) {
Log.e("PcmToWav", e1.getMessage());
return false;
}
if (h.length != 44) // WAV , 44 , 44
return false;
//
File destfile = new File(destinationPath);
if (destfile.exists())
destfile.delete();
// pcm ,
try {
buffer = new byte[1024 * 4]; // Length of All Files, Total Size
InputStream inStream = null;
OutputStream ouStream = null;
ouStream = new BufferedOutputStream(new FileOutputStream(
destinationPath));
ouStream.write(h, 0, h.length);
inStream = new BufferedInputStream(new FileInputStream(file));
int size = inStream.read(buffer);
while (size != -1) {
ouStream.write(buffer);
size = inStream.read(buffer);
}
inStream.close();
ouStream.close();
} catch (FileNotFoundException e) {
Log.e("PcmToWav", e.getMessage());
return false;
} catch (IOException ioe) {
Log.e("PcmToWav", ioe.getMessage());
return false;
}
if (deletePcmFile) {
file.delete();
}
Log.i("PcmToWav", "makePCMFileToWAVFile success!" + new SimpleDateFormat("yyyy-MM-dd hh:mm").format(new Date()));
return true;
}
まとめ:AudioRecorder録音はMediaRecorderと比較して使用すると面倒になるが、利点も明らかである.AudioRecorder録音時にハードウェアを直接操作してオーディオストリームデータを取得するプロセスはリアルタイム処理であり、コードで各種オーディオのパッケージを実現できるとともに、一時停止機能を実現できる.imhxlブロガーの共有をお勧めしますhttp://blog.csdn.net/imhxl/article/details/52190451 .
作者:DreamFishリンク:https://www.jianshu.com/p/90c4071c7768出典:簡書の著作権は作者の所有である.商業転載は著者に連絡して許可を得てください.非商業転載は出典を明記してください.