美文网首页
第二十八节 录制音频AudioRecord、OpenSL ES

第二十八节 录制音频AudioRecord、OpenSL ES

作者: 最美下雨天 | 来源:发表于2018-12-06 14:47 被阅读13次
    image.png
    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;
    }
    
    
    
    

    相关文章

      网友评论

          本文标题:第二十八节 录制音频AudioRecord、OpenSL ES

          本文链接:https://www.haomeiwen.com/subject/ffnkqqtx.html