下面列出了android.media.AudioRecord#read ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void initRecorder() {
final int bufferSize = 2 * AudioRecord.getMinBufferSize(RECORDER_SAMPLE_RATE,
RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, RECORDER_SAMPLE_RATE,
RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING, bufferSize);
AudioUtil.initProcessor(RECORDER_SAMPLE_RATE, RECORDER_CHANNELS, RECORDER_ENCODING_BIT);
recordingThread = new Thread("recorder") {
@Override
public void run() {
super.run();
buffer = new byte[bufferSize];
Looper.prepare();
audioRecord.setRecordPositionUpdateListener(recordPositionUpdateListener, new Handler(Looper.myLooper()));
int bytePerSample = RECORDER_ENCODING_BIT / 8;
float samplesToDraw = bufferSize / bytePerSample;
audioRecord.setPositionNotificationPeriod((int) samplesToDraw);
//We need to read first chunk to motivate recordPositionUpdateListener.
//Mostly, for lower versions - https://code.google.com/p/android/issues/detail?id=53996
audioRecord.read(buffer, 0, bufferSize);
Looper.loop();
}
};
}
private void initRecorder() {
final int bufferSize = 2 * AudioRecord.getMinBufferSize(RECORDER_SAMPLE_RATE,
RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, RECORDER_SAMPLE_RATE,
RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING, bufferSize);
AudioUtil.initProcessor(RECORDER_SAMPLE_RATE, RECORDER_CHANNELS, RECORDER_ENCODING_BIT);
recordingThread = new Thread("recorder") {
@Override
public void run() {
super.run();
buffer = new byte[bufferSize];
Looper.prepare();
audioRecord.setRecordPositionUpdateListener(recordPositionUpdateListener, new Handler(Looper.myLooper()));
int bytePerSample = RECORDER_ENCODING_BIT / 8;
float samplesToDraw = bufferSize / bytePerSample;
audioRecord.setPositionNotificationPeriod((int) samplesToDraw);
//We need to read first chunk to motivate recordPositionUpdateListener.
//Mostly, for lower versions - https://code.google.com/p/android/issues/detail?id=53996
audioRecord.read(buffer, 0, bufferSize);
Looper.loop();
}
};
}
@Override
public void run() {
FileOutputStream out = prepareWriting();
if (out == null) { return; }
AudioRecord record = new AudioRecord(AudioSource.VOICE_RECOGNITION, /*AudioSource.MIC*/
SAMPLING_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize);
record.startRecording();
int read = 0;
while (isRecording) {
read = record.read(audioBuffer, 0, bufferSize);
if ((read == AudioRecord.ERROR_INVALID_OPERATION) ||
(read == AudioRecord.ERROR_BAD_VALUE) ||
(read <= 0)) {
continue;
}
proceed();
write(out);
}
record.stop();
record.release();
finishWriting(out);
convertRawToWav();
}
private void handleCodecInput(AudioRecord audioRecord, byte[] audioRecordData,
MediaCodec mediaCodec, ByteBuffer[] codecInputBuffers,
boolean running) {
int length = audioRecord.read(audioRecordData, 0, audioRecordData.length);
int codecInputBufferIndex = mediaCodec.dequeueInputBuffer(10 * 1000);
if (codecInputBufferIndex >= 0) {
ByteBuffer codecBuffer = codecInputBuffers[codecInputBufferIndex];
codecBuffer.clear();
codecBuffer.put(audioRecordData);
mediaCodec.queueInputBuffer(codecInputBufferIndex, 0, length, 0, running ? 0 : MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
}
private void startRecord(){
File file = new File(Environment.getExternalStorageDirectory(), "record.pcm");
int sampleFreq = (Integer)spFrequency.getSelectedItem();
try{
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
int minBufferedSize = AudioRecord.getMinBufferSize(sampleFreq, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
short[] audioData = new short[minBufferedSize];
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleFreq, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferedSize);
audioRecord.startRecording();
while (recording) {
int numberOfShort = audioRecord.read(audioData, 0, minBufferedSize);
for(int i = 0; i < numberOfShort; i++){
dataOutputStream.writeShort(audioData[i]);
}
}
audioRecord.stop();
dataOutputStream.close();
} catch(Exception ex){
ex.printStackTrace();
}
}
private void handleCodecInput(AudioRecord audioRecord, byte[] audioRecordData,
MediaCodec mediaCodec, ByteBuffer[] codecInputBuffers,
boolean running)
{
int length = audioRecord.read(audioRecordData, 0, audioRecordData.length);
int codecInputBufferIndex = mediaCodec.dequeueInputBuffer(10 * 1000);
if (codecInputBufferIndex >= 0) {
ByteBuffer codecBuffer = codecInputBuffers[codecInputBufferIndex];
codecBuffer.clear();
codecBuffer.put(audioRecordData);
mediaCodec.queueInputBuffer(codecInputBufferIndex, 0, length, 0, running ? 0 : MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
}
public void start() {
if (STATE_STOP == mState) {
mState = STATE_START;
switch (mChannel) {
case CHANNEL_1:
mChannelConfig = AudioFormat.CHANNEL_IN_MONO;
break;
case CHANNEL_2:
mChannelConfig = AudioFormat.CHANNEL_IN_STEREO;
break;
}
switch (mBits) {
case BITS_8:
mAudioEncoding = AudioFormat.ENCODING_PCM_8BIT;
break;
case BITS_16:
mAudioEncoding = AudioFormat.ENCODING_PCM_16BIT;
break;
}
int minBufferSize = AudioRecord.getMinBufferSize(mFrequence, mChannelConfig, mAudioEncoding);
LogHelper.d(TAG, "minBufferSize:" + minBufferSize);
AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, mFrequence, mChannelConfig, mAudioEncoding, mBufferSize);
record.startRecording();
LogHelper.d(TAG, "record start");
if (null != mCallback) {
if (null != mListener) {
mListener.onStartRecord();
}
while (STATE_START == mState) {
BufferData data = mCallback.getRecordBuffer();
if (null != data) {
if (null != data.byteData) {
int bufferReadResult = record.read(data.byteData, 0, mBufferSize);
data.setFilledSize(bufferReadResult);
mCallback.freeRecordBuffer(data);
} else {
// end of input
LogHelper.d(TAG, "get end input data, so stop");
break;
}
} else {
LogHelper.d(TAG, "get null data");
break;
}
}
if (null != mListener) {
mListener.onStopRecord();
}
}
record.stop();
record.release();
LogHelper.d(TAG, "record stop");
}
}
@Override
@SuppressLint({ "InlinedApi", "NewApi" })
protected void encodeWithMediaCodec() throws IOException {
final int bufferSize = AudioRecord.getMinBufferSize(mQuality.samplingRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT)*2;
((AACLATMPacketizer)mPacketizer).setSamplingRate(mQuality.samplingRate);
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, mQuality.samplingRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
mMediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_BIT_RATE, mQuality.bitRate);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mQuality.samplingRate);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mAudioRecord.startRecording();
mMediaCodec.start();
final MediaCodecInputStream inputStream = new MediaCodecInputStream(mMediaCodec);
final ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers();
mThread = new Thread(new Runnable() {
@Override
public void run() {
int len = 0, bufferIndex = 0;
try {
while (!Thread.interrupted()) {
bufferIndex = mMediaCodec.dequeueInputBuffer(10000);
if (bufferIndex>=0) {
inputBuffers[bufferIndex].clear();
len = mAudioRecord.read(inputBuffers[bufferIndex], bufferSize);
if (len == AudioRecord.ERROR_INVALID_OPERATION || len == AudioRecord.ERROR_BAD_VALUE) {
Log.e(TAG,"An error occured with the AudioRecord API !");
} else {
//Log.v(TAG,"Pushing raw audio to the decoder: len="+len+" bs: "+inputBuffers[bufferIndex].capacity());
mMediaCodec.queueInputBuffer(bufferIndex, 0, len, System.nanoTime()/1000, 0);
}
}
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
});
mThread.start();
// The packetizer encapsulates this stream in an RTP stream and send it over the network
mPacketizer.setDestination(mDestination, mRtpPort, mRtcpPort);
mPacketizer.setInputStream(inputStream);
mPacketizer.start();
mStreaming = true;
}
/**
* 用于检测是否具有录音权限
*
* @return
*/
public static int getRecordState() {
int minBuffer = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat
.ENCODING_PCM_16BIT);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 44100, AudioFormat
.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, (minBuffer * 100));
short[] point = new short[minBuffer];
int readSize = 0;
try {
audioRecord.startRecording();//检测是否可以进入初始化状态
} catch (Exception e) {
if (audioRecord != null) {
audioRecord.release();
audioRecord = null;
}
return STATE_NO_PERMISSION;
}
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
//6.0以下机型都会返回此状态,故使用时需要判断bulid版本
//检测是否在录音中
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
Log.d("CheckAudioPermission", "录音机被占用");
}
return STATE_RECORDING;
} else {
//检测是否可以获取录音结果
readSize = audioRecord.read(point, 0, point.length);
if (readSize <= 0) {
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
Log.d("CheckAudioPermission", "录音的结果为空");
return STATE_NO_PERMISSION;
} else {
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
return STATE_SUCCESS;
}
}
}
/**
* 用于检测是否具有录音权限
*
* @return
*/
public static int getRecordState() {
int minBuffer = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat
.ENCODING_PCM_16BIT);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 44100, AudioFormat
.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, (minBuffer * 100));
short[] point = new short[minBuffer];
int readSize = 0;
try {
audioRecord.startRecording();//检测是否可以进入初始化状态
} catch (Exception e) {
if (audioRecord != null) {
audioRecord.release();
audioRecord = null;
}
return STATE_NO_PERMISSION;
}
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
//6.0以下机型都会返回此状态,故使用时需要判断bulid版本
//检测是否在录音中
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
Log.d("CheckAudioPermission", "录音机被占用");
}
return STATE_RECORDING;
} else {
//检测是否可以获取录音结果
readSize = audioRecord.read(point, 0, point.length);
if (readSize <= 0) {
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
Log.d("CheckAudioPermission", "录音的结果为空");
return STATE_NO_PERMISSION;
} else {
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
return STATE_SUCCESS;
}
}
}
/**
* 判断是是否有录音权限
*/
public static boolean isHasAudioPermission(final Context context){
int bufferSizeInBytes = 0;
bufferSizeInBytes = AudioRecord.getMinBufferSize(44100,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes);
//开始录制音频
//开始录制音频
try{
// 防止某些手机崩溃,例如联想
audioRecord.startRecording();
}catch (IllegalStateException e){
e.printStackTrace();
// AVLogUtils.e(TAG, Log.getStackTraceString(e));
}
/**
* 根据开始录音判断是否有录音权限
*/
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING
&& audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_STOPPED) {
// AVLogUtils.e(TAG, "audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING : " + audioRecord.getRecordingState());
return false;
}
if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_STOPPED) {
//如果短时间内频繁检测,会造成audioRecord还未销毁完成,此时检测会返回RECORDSTATE_STOPPED状态,再去read,会读到0的size,可以更具自己的需求返回true或者false
return false;
}
byte[] bytes = new byte[1024];
int readSize = audioRecord.read(bytes, 0, 1024);
if (readSize == AudioRecord.ERROR_INVALID_OPERATION || readSize <= 0) {
// AVLogUtils.e(TAG, "readSize illegal : " + readSize);
return false;
}
audioRecord.stop();
audioRecord.release();
audioRecord = null;
return true;
}
@Override
public void run() {
try {
//初始化音频
int bufferSizeInBytes = AudioRecord
.getMinBufferSize(audioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
final AudioRecord
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, audioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes);
if(audioRecord == null){
mOnAudioRecorderListener.onNotPermission();
return ;
}
audioRecord.startRecording();
/**
* 根据开始录音判断是否有录音权限
*/
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING
&& audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_STOPPED) {
// AVLogUtils.e(TAG, "audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING : " + audioRecord.getRecordingState());
isAudioPermission = false;
}
if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_STOPPED) {
//如果短时间内频繁检测,会造成audioRecord还未销毁完成,此时检测会返回RECORDSTATE_STOPPED状态,再去read,会读到0的size,可以更具自己的需求返回true或者false
isAudioPermission = false;
}
if(!isAudioPermission){
mOnAudioRecorderListener.onNotPermission();
return ;
}
mOnAudioRecorderListener.onCanRecord(isAudioPermission);
byte[] data = new byte[2048];
while(isRecord){
if(audioRecord == null){
return ;
}
int offset = 0;
while(offset < 2048) {
int readSize = audioRecord.read(data, offset, data.length-offset);
offset+=readSize;
}
if(isAudioRecordWrite){//写入文件
HeyhouRecorder.getInstance().recordAudioNHW(data,audioSampleRate,HeyhouRecorder.FORMAT_S16,1024);
}
}
audioRecord.stop();
audioRecord.release();
}catch (Exception e) {
e.printStackTrace();
mOnAudioRecorderListener.onRecordError("录音失败");
}
}
@Override
protected void recordingLoop() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
try {
final int min_buffer_size = AudioRecord.getMinBufferSize(
mSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
int buffer_size = SAMPLES_PER_FRAME * FRAMES_PER_BUFFER;
if (buffer_size < min_buffer_size)
buffer_size = ((min_buffer_size / SAMPLES_PER_FRAME) + 1) * SAMPLES_PER_FRAME * 2;
final AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, mSampleRate,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, buffer_size);
try {
if ((audioRecord.getState() == AudioRecord.STATE_INITIALIZED) && (mIsRunning)) {
if (DEBUG) Log.v(TAG, "AudioThread:start_from_encoder audio recording");
final ByteBuffer buf = ByteBuffer.allocateDirect(SAMPLES_PER_FRAME);
int readBytes;
audioRecord.startRecording();
try {
while (mIsRunning && isRecording()) {
// read audio data from internal mic
buf.clear();
readBytes = audioRecord.read(buf, SAMPLES_PER_FRAME);
if (readBytes > 0) {
// set audio data to encoder
encode(buf, readBytes, getPTSUs());
frameAvailableSoon();
}
}
frameAvailableSoon();
} finally {
audioRecord.stop();
}
}
} finally {
audioRecord.release();
}
} catch (Exception e) {
Log.e(TAG, "AudioThread#run", e);
} finally {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_DEFAULT);
}
}
private void doTask()
{
// http://stackoverflow.com/questions/10655703/what-does-androids-getmaxamplitude-function-for-the-mediarecorder-actually-gi
int bufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT);
// making the buffer bigger....
bufferSize = bufferSize * 4;
// AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
AudioRecord recorder = findAudioRecord();
if(recorder == null) {
Activity main = ActivityController.getInstance().get("MainActivity");
if(main != null) {
Utils.makeToast2(main, R.string.sensor_microphone_error, Toast.LENGTH_SHORT);
}
return;
}
short data[] = new short[bufferSize];
double average = 0.0;
recorder.startRecording();
// recording data;
recorder.read(data, 0, bufferSize);
recorder.stop();
for(short s : data) {
if(s > 0) {
average += Math.abs(s);
} else {
bufferSize--;
}
}
// x=max;
double x = average / bufferSize;
recorder.release();
double db;
if(x == 0) {
Log.w("TAG", "Warning no sound captured!");
return;
}
// calculating the pascal pressure based on the idea that the max
// amplitude (between 0 and 32767) is
// relative to the pressure
double pressure = x / 51805.5336; // the value 51805.5336 can be derived
// from asuming that x=32767=0.6325
// Pa and x=1 = 0.00002 Pa (the
// reference value)
db = (20 * Math.log10(pressure / 0.00002));
if(db < 0) {
return;
}
// if( mRecorder == null )
// return;
// float maxVolume = (float)(20 * Math.log10(mRecorder.getMaxAmplitude()
// / 2700.0));
long time = System.currentTimeMillis();
ContentValues newValues = new ContentValues();
newValues.put(valueNames[0], db);
newValues.put(valueNames[1], time);
if(db == Double.NEGATIVE_INFINITY || db == Double.POSITIVE_INFINITY || db == Double.NaN) {
return;
}
String deviceID = DeviceID.get(SensorDataCollectorService.getInstance());
MicrophoneCollector.updateLivePlotter(deviceID, new float[]{ (float) db });
MicrophoneCollector.writeDBStorage(deviceID, newValues);
}
@Override
@SuppressLint({ "InlinedApi", "NewApi" })
protected void encodeWithMediaCodec() throws IOException {
final int bufferSize = AudioRecord.getMinBufferSize(mQuality.samplingRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT)*2;
((AACLATMPacketizer)mPacketizer).setSamplingRate(mQuality.samplingRate);
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, mQuality.samplingRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
mMediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_BIT_RATE, mQuality.bitRate);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mQuality.samplingRate);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mAudioRecord.startRecording();
mMediaCodec.start();
final MediaCodecInputStream inputStream = new MediaCodecInputStream(mMediaCodec);
final ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers();
mThread = new Thread(new Runnable() {
@Override
public void run() {
int len = 0, bufferIndex = 0;
try {
while (!Thread.interrupted()) {
bufferIndex = mMediaCodec.dequeueInputBuffer(10000);
if (bufferIndex>=0) {
inputBuffers[bufferIndex].clear();
len = mAudioRecord.read(inputBuffers[bufferIndex], bufferSize);
if (len == AudioRecord.ERROR_INVALID_OPERATION || len == AudioRecord.ERROR_BAD_VALUE) {
Log.e(TAG,"An error occured with the AudioRecord API !");
} else {
//Log.v(TAG,"Pushing raw audio to the decoder: len="+len+" bs: "+inputBuffers[bufferIndex].capacity());
mMediaCodec.queueInputBuffer(bufferIndex, 0, len, System.nanoTime()/1000, 0);
}
}
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
});
mThread.start();
// The packetizer encapsulates this stream in an RTP stream and send it over the network
mPacketizer.setInputStream(inputStream);
mPacketizer.start();
mStreaming = true;
}
private void RecordAudio() {
if (mProgressListener == null) {
// A progress listener is mandatory here, as it will let us know when to stop recording.
return;
}
mInputFile = null;
mFileType = "raw";
mFileSize = 0;
mSampleRate = 44100;
mChannels = 1; // record mono audio.
short[] buffer = new short[1024]; // buffer contains 1 mono frame of 1024 16 bits samples
int minBufferSize = AudioRecord.getMinBufferSize(
mSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
// make sure minBufferSize can contain at least 1 second of audio (16 bits sample).
if (minBufferSize < mSampleRate * 2) {
minBufferSize = mSampleRate * 2;
}
AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.DEFAULT,
mSampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minBufferSize
);
// Allocate memory for 20 seconds first. Reallocate later if more is needed.
mDecodedBytes = ByteBuffer.allocate(20 * mSampleRate * 2);
mDecodedBytes.order(ByteOrder.LITTLE_ENDIAN);
mDecodedSamples = mDecodedBytes.asShortBuffer();
audioRecord.startRecording();
while (true) {
// check if mDecodedSamples can contain 1024 additional samples.
if (mDecodedSamples.remaining() < 1024) {
// Try to allocate memory for 10 additional seconds.
int newCapacity = mDecodedBytes.capacity() + 10 * mSampleRate * 2;
ByteBuffer newDecodedBytes = null;
try {
newDecodedBytes = ByteBuffer.allocate(newCapacity);
} catch (OutOfMemoryError oome) {
break;
}
int position = mDecodedSamples.position();
mDecodedBytes.rewind();
newDecodedBytes.put(mDecodedBytes);
mDecodedBytes = newDecodedBytes;
mDecodedBytes.order(ByteOrder.LITTLE_ENDIAN);
mDecodedBytes.rewind();
mDecodedSamples = mDecodedBytes.asShortBuffer();
mDecodedSamples.position(position);
}
// TODO(nfaralli): maybe use the read method that takes a direct ByteBuffer argument.
audioRecord.read(buffer, 0, buffer.length);
mDecodedSamples.put(buffer);
// Let the progress listener know how many seconds have been recorded.
// The returned value tells us if we should keep recording or stop.
if (!mProgressListener.reportProgress(
(float)(mDecodedSamples.position()) / mSampleRate)) {
break;
}
}
audioRecord.stop();
audioRecord.release();
mNumSamples = mDecodedSamples.position();
mDecodedSamples.rewind();
mDecodedBytes.rewind();
mAvgBitRate = mSampleRate * 16 / 1000;
// Temporary hack to make it work with the old version.
mNumFrames = mNumSamples / getSamplesPerFrame();
if (mNumSamples % getSamplesPerFrame() != 0){
mNumFrames++;
}
mFrameGains = new int[mNumFrames];
mFrameLens = null; // not needed for recorded audio
mFrameOffsets = null; // not needed for recorded audio
int i, j;
int gain, value;
for (i=0; i<mNumFrames; i++){
gain = -1;
for(j=0; j<getSamplesPerFrame(); j++) {
if (mDecodedSamples.remaining() > 0) {
value = java.lang.Math.abs(mDecodedSamples.get());
} else {
value = 0;
}
if (gain < value) {
gain = value;
}
}
mFrameGains[i] = (int)Math.sqrt(gain); // here gain = sqrt(max value of 1st channel)...
}
mDecodedSamples.rewind();
// DumpSamples(); // Uncomment this line to dump the samples in a TSV file.
}
private void serviceConnection(Socket socket) throws IOException
{
MonitorActivity.this.runOnUiThread(new Runnable()
{
@Override
public void run()
{
final TextView statusText = (TextView) findViewById(R.id.textStatus);
statusText.setText(R.string.streaming);
}
});
final int frequency = 11025;
final int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
final int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
final AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
frequency, channelConfiguration,
audioEncoding, bufferSize);
final int byteBufferSize = bufferSize*2;
final byte[] buffer = new byte[byteBufferSize];
try
{
audioRecord.startRecording();
final OutputStream out = socket.getOutputStream();
socket.setSendBufferSize(byteBufferSize);
Log.d(TAG, "Socket send buffer size: " + socket.getSendBufferSize());
while (socket.isConnected() && Thread.currentThread().isInterrupted() == false)
{
final int read = audioRecord.read(buffer, 0, bufferSize);
out.write(buffer, 0, read);
}
}
finally
{
audioRecord.stop();
}
}
/**
* 用于检测是否具有录音权限
*
* @return
*/
public static int getRecordState() {
int minBuffer = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat
.ENCODING_PCM_16BIT);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 44100, AudioFormat
.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, (minBuffer * 100));
short[] point = new short[minBuffer];
int readSize = 0;
try {
audioRecord.startRecording();//检测是否可以进入初始化状态
} catch (Exception e) {
if (audioRecord != null) {
audioRecord.release();
audioRecord = null;
}
return STATE_NO_PERMISSION;
}
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
//6.0以下机型都会返回此状态,故使用时需要判断bulid版本
//检测是否在录音中
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
return STATE_RECORDING;
} else {
//检测是否可以获取录音结果
readSize = audioRecord.read(point, 0, point.length);
if (readSize <= 0) {
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
return STATE_NO_PERMISSION;
} else {
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
return STATE_SUCCESS;
}
}
}
/**
* 音声をレコードして、MediaCodec に渡します.
*/
private void recordAudio() throws NativeInterfaceException {
int samplingRate = mSamplingRate.getValue();
int channels = mChannels == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int bufferSize = AudioRecord.getMinBufferSize(samplingRate, channels, audioFormat) * 4;
int oneFrameDataCount = mSamplingRate.getValue() / mFrameSize.getFps();
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
samplingRate,
channels,
audioFormat,
bufferSize);
if (mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
if (mAudioRecordCallback != null) {
mAudioRecordCallback.onEncoderError();
}
return;
}
if (mUseAEC && AcousticEchoCanceler.isAvailable()) {
// ノイズキャンセラー
mEchoCanceler = AcousticEchoCanceler.create(mAudioRecord.getAudioSessionId());
if (mEchoCanceler != null) {
int ret = mEchoCanceler.setEnabled(true);
if (ret != AudioEffect.SUCCESS) {
if (DEBUG) {
Log.w(TAG, "AcousticEchoCanceler is not supported.");
}
}
}
}
OpusEncoder opusEncoder = null;
try {
opusEncoder = new OpusEncoder(mSamplingRate, mChannels, mFrameSize, mBitRate, mApplication);
mAudioRecord.startRecording();
short[] emptyBuffer = new short[oneFrameDataCount];
short[] pcmBuffer = new short[oneFrameDataCount];
byte[] opusFrameBuffer = opusEncoder.bufferAllocate();
while (!mStopFlag) {
int readSize = mAudioRecord.read(pcmBuffer, 0, oneFrameDataCount);
if (readSize > 0) {
int opusFrameBufferLength;
if (isMute()) {
opusFrameBufferLength = opusEncoder.encode(emptyBuffer, readSize, opusFrameBuffer);
} else {
opusFrameBufferLength = opusEncoder.encode(pcmBuffer, readSize, opusFrameBuffer);
}
if (opusFrameBufferLength > 0 && mAudioRecordCallback != null) {
mAudioRecordCallback.onPeriodicNotification(opusFrameBuffer, opusFrameBufferLength);
}
} else if (readSize == AudioRecord.ERROR_INVALID_OPERATION) {
if (DEBUG) {
Log.e(TAG, "Invalid operation error.");
}
break;
} else if (readSize == AudioRecord.ERROR_BAD_VALUE) {
if (DEBUG) {
Log.e(TAG, "Bad value error.");
}
break;
} else if (readSize == AudioRecord.ERROR) {
if (DEBUG) {
Log.e(TAG, "Unknown error.");
}
break;
}
}
} finally {
if (mEchoCanceler != null) {
mEchoCanceler.release();
mEchoCanceler = null;
}
if (opusEncoder != null) {
opusEncoder.release();
}
}
}
@Override
protected void encode() throws IOException {
// 获取音频数据,并对其进行编码,之后传递给packetizer进行打包发送
// 或者采用设置编码器的方式?
final int bufferSize = AudioRecord.getMinBufferSize(8000/*mQuality.samplingRate*/, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT)*2;
((AACLATMPacketizer)mPacketizer).setSamplingRate(8000/*mQuality.samplingRate*/);
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000/*mQuality.samplingRate*/, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
mMediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_BIT_RATE,32000 /*mQuality.bitRate*/);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000/*mQuality.samplingRate*/);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mAudioRecord.startRecording();
mMediaCodec.start();
final MediaCodecInputStream inputStream = new MediaCodecInputStream(mMediaCodec);
final ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers();
mThread = new Thread(new Runnable() {
@Override
public void run() {
int len = 0, bufferIndex = 0;
try {
while (!Thread.interrupted()) {
bufferIndex = mMediaCodec.dequeueInputBuffer(10000);
if (bufferIndex>=0) {
inputBuffers[bufferIndex].clear();
len = mAudioRecord.read(inputBuffers[bufferIndex], bufferSize);
if (len == AudioRecord.ERROR_INVALID_OPERATION || len == AudioRecord.ERROR_BAD_VALUE) {
L.e("An error occured with the AudioRecord API !");
} else {
//Log.v(TAG,"Pushing raw audio to the decoder: len="+len+" bs: "+inputBuffers[bufferIndex].capacity());
mMediaCodec.queueInputBuffer(bufferIndex, 0, len, System.nanoTime()/1000, 0);
}
}
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
});
mThread.start();
// 设置 packetizer 的发送地址
mPacketizer.setDestination(mDestination, mRtpPort, mRtcpPort);
// 设置 packetizer 的接收流,使其能够打包发送编码后的数据
mPacketizer.setInputStream(inputStream);
// 开始循环获取inputStream的数据
mPacketizer.start();
mStreaming = true;
}