image.png
AudioRecoder的使用非常简单
AudioRecordUitl.java
package com.ywl5320.audiorecord;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
public class AudioRecordUitl {
private AudioRecord audioRecord;
private int bufferSizeInBytes;
private boolean start = false;
private int readSize = 0;
private OnRecordLisener onRecordLisener;
public AudioRecordUitl() {
bufferSizeInBytes = AudioRecord.getMinBufferSize(
44100,
AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
44100,
AudioFormat.CHANNEL_IN_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSizeInBytes
);
}
public void setOnRecordLisener(OnRecordLisener onRecordLisener) {
this.onRecordLisener = onRecordLisener;
}
public void startRecord()
{
new Thread(){
@Override
public void run() {
super.run();
start = true;
audioRecord.startRecording();
byte[] audiodata = new byte[bufferSizeInBytes];
while (start)
{
readSize = audioRecord.read(audiodata, 0, bufferSizeInBytes);
if(onRecordLisener != null)
{
onRecordLisener.recordByte(audiodata, readSize);
}
}
if(audioRecord != null)
{
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
}
}.start();
}
public void stopRecord()
{
start = false;
}
public interface OnRecordLisener{
void recordByte(byte[] audioData, int readSize);
}
}
MainActivity.java
package com.ywl5320.audiorecord;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
private AudioRecordUitl audioRecordUitl = null;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=findViewById(R.id.button);
path= Environment.getExternalStorageDirectory()+"/audio.pcm";
try {
fileOutputStream=new FileOutputStream(new File(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private String path;
private FileOutputStream fileOutputStream;
public void recordaudio(View view) {
if(audioRecordUitl == null)
{
button.setText("结束录制");
audioRecordUitl = new AudioRecordUitl();
audioRecordUitl.setOnRecordLisener(new AudioRecordUitl.OnRecordLisener() {
@Override
public void recordByte(byte[] audioData, int readSize) {
Log.d("abc", "readSize is : " + readSize);
try {
fileOutputStream.write(audioData);
} catch (IOException e) {
e.printStackTrace();
}
}
});
audioRecordUitl.startRecord();
}
else
{
try {
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
button.setText("开始录制");
audioRecordUitl.stopRecord();
audioRecordUitl = null;
}
}
}
image.png
image.png
OpenSL ES既能播放音频,也能录制音频(都是对pcm数据来说的)
区别:
录制
(*engineItf)->CreateAudioRecorder(engineItf, &recordObj, &audioSrc, &audioSnk, 1, id, req);
播放
(*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slDataSource, &audioSnk, 2, ids, req);
native-lib.cpp
#include <jni.h>
#include <string>
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include "RecordBuffer.h"
#include "AndroidLog.h"
SLObjectItf slObjectEngine = NULL;
SLEngineItf engineItf = NULL;
SLObjectItf recordObj = NULL;
SLRecordItf recordItf = NULL;
SLAndroidSimpleBufferQueueItf recorderBufferQueue = NULL;
RecordBuffer *recordBuffer;
FILE *pcmFile = NULL;
bool finish = false;
void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
{
fwrite(recordBuffer->getRecordBuffer(), 1, 4096, pcmFile);
if(finish)
{
LOGE("录制完成");
(*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED);
//
(*recordObj)->Destroy(recordObj);
recordObj = NULL;
recordItf = NULL;
(*slObjectEngine)->Destroy(slObjectEngine);
slObjectEngine = NULL;
engineItf = NULL;
delete(recordBuffer);
} else{
LOGE("正在录制");
//入队,bqRecorderCallback会循环被调用
(*recorderBufferQueue)->Enqueue(recorderBufferQueue, recordBuffer->getRecordBuffer(), 4096);
}
}
extern "C"
JNIEXPORT void JNICALL
Java_com_ywl5320_openslesrecord_MainActivity_startRecord(JNIEnv *env, jobject instance,
jstring path_) {
if(finish)
{
return;
}
const char *path = env->GetStringUTFChars(path_, 0);
finish = false;
pcmFile = fopen(path, "w");
recordBuffer = new RecordBuffer(4096);
slCreateEngine(&slObjectEngine, 0, NULL, 0, NULL, NULL);
(*slObjectEngine)->Realize(slObjectEngine, SL_BOOLEAN_FALSE);
(*slObjectEngine)->GetInterface(slObjectEngine, SL_IID_ENGINE, &engineItf);
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE,
SL_IODEVICE_AUDIOINPUT,
SL_DEFAULTDEVICEID_AUDIOINPUT,
NULL};
SLDataSource audioSrc = {&loc_dev, NULL};
SLDataLocator_AndroidSimpleBufferQueue loc_bq = {
SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
2
};
SLDataFormat_PCM format_pcm = {
SL_DATAFORMAT_PCM, 2, SL_SAMPLINGRATE_44_1,
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, SL_BYTEORDER_LITTLEENDIAN
};
SLDataSink audioSnk = {&loc_bq, &format_pcm};
const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
const SLboolean req[1] = {SL_BOOLEAN_TRUE};
(*engineItf)->CreateAudioRecorder(engineItf, &recordObj, &audioSrc, &audioSnk, 1, id, req);
(*recordObj)->Realize(recordObj, SL_BOOLEAN_FALSE);
(*recordObj)->GetInterface(recordObj, SL_IID_RECORD, &recordItf);
(*recordObj)->GetInterface(recordObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue);
//入队
(*recorderBufferQueue)->Enqueue(recorderBufferQueue, recordBuffer->getRecordBuffer(), 4096);
(*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, bqRecorderCallback, NULL);
(*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING);
env->ReleaseStringUTFChars(path_, path);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_ywl5320_openslesrecord_MainActivity_stopRecord(JNIEnv *env, jobject instance) {
// TODO
finish = true;
}
RecordBuffer.cpp
课件中用了两个数组,但是感觉是没有起到什么作用的
//
// Created by yangw on 2018-9-3.
//
#include "RecordBuffer.h"
RecordBuffer::RecordBuffer(int buffersize) {
buffer = new short *[1];
buffer[0] = new short[buffersize];
}
short *RecordBuffer::getRecordBuffer() {
return buffer[0];
}
RecordBuffer::~RecordBuffer() {
delete buffer[0];
delete buffer;
}
网友评论