在Android中使用OpenSL ES录制音频时,如何监视MIC状态?

时间:2018-08-20 13:49:28

标签: android c++ audio opensl

我用OpenSL ES录制了一个非常简单的音频,但遇到了一些问题,在某些手机上它可以工作并录制,但在其他手机上,尤其是Android 8似乎在音量/增益方面存在问题。

问题是,仅当我通过蓝牙连接到设备时才进行记录,在第一次连接时它会起作用,但是当我断开与蓝牙设备的连接并再次连接时,该记录似乎不再起作用。如果将手机直接放在扬声器的顶部,似乎只能拾取音频。有什么想法会影响从蓝牙设备连接/断开连接时的音量或增益?在每个连接和断开过程中,都会调用start / stop方法,以便按相反的顺序销毁对象,然后对象应该可以重新启动,但由于某种原因未正确初始化。任何想法或建议将不胜感激

#include "Configuration.h"
#include "Trace.h"
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>

AndroidRecord::AndroidRecord() {}

int AndroidRecord::initialize(buffer_ready_cb cb_fct, void* cb_obj)
{

    clean();
    signal_proc_cb = cb_fct;
    signal_proc_obj = cb_obj;

    return kOK;
}

int AndroidRecord::startRecording()
{
    if(SL_RESULT_SUCCESS != slCreateEngine(&engine_obj, 0, nullptr, 0, nullptr, nullptr))
    {
        return error;
    }

    if(SL_RESULT_SUCCESS != (*engine_obj)->Realize(engine_obj, SL_BOOLEAN_FALSE))
    {
        return error;
    }

    if(SL_RESULT_SUCCESS != (*engine_obj)->GetInterface(engine_obj, SL_IID_ENGINE, &engine_itf))
    {
        return error;
    }

    SLAndroidDataFormat_PCM_EX pcm_format = {0};
    pcm_format.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
    pcm_format.numChannels = 1;
    pcm_format.sampleRate = config.record_sample_rate * 1000;
    pcm_format.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_32;
    pcm_format.containerSize = sizeof(recordedAudio) * 8;
    pcm_format.channelMask = SL_SPEAKER_FRONT_CENTER;
    pcm_format.endianness = SL_BYTEORDER_LITTLEENDIAN;
    pcm_format.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;

    SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
    SLDataSource audio_src = {&loc_dev, NULL};
    SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, record_buffer_count};
    SLDataSink audio_snk = {&loc_bq, &pcm_format};

    const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
    const SLboolean req[1] = {SL_BOOLEAN_TRUE};

    // create audio recorder (requires the RECORD_AUDIO permission)
    if(SL_RESULT_SUCCESS != (*engine_itf)->CreateAudioRecorder(engine_itf, &record_obj, &audio_src, &audio_snk, 1, id, req))
    {
        return error;
    }

    // realize the audio recorder
    if(SL_RESULT_SUCCESS != (*record_obj)->Realize(record_obj, SL_BOOLEAN_FALSE))
    {
        return error;
    }

    // get the record interface
    if(SL_RESULT_SUCCESS != (*record_obj)->GetInterface(record_obj, SL_IID_RECORD, &record_itf))
    {
        return error;
    }

    // get the buffer queue interface
    if(SL_RESULT_SUCCESS !=  (*record_obj)->GetInterface(record_obj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &record_buff_queue))
    {
        return error;
    }

    // register callback on the buffer queue
    if(SL_RESULT_SUCCESS != (*record_buff_queue)->RegisterCallback(record_buff_queue, opensl_record_callback, this))
    {
        return error;
    }

    SLAndroidSimpleBufferQueueState qState;
    if(SL_RESULT_SUCCESS != (*record_buff_queue)->GetState(record_buff_queue, &qState))
    {
        return error;
    }

    // Create the recording buffer
    for(int i = 0; i < record_buffer_count; i++)
    {
        record_buffers[i].reset(new recordedAudio[config.record_sample_count]);

        if (SL_RESULT_SUCCESS != (*record_buff_queue)->Enqueue(record_buff_queue, record_buffers[i].get(), record_sample_count * sizeof(AudioSample)))
        {
            return error;
        }
    }

    // Activate the recording
    if(SL_RESULT_SUCCESS != (*record_itf)->SetRecordState(record_itf, SL_RECORDSTATE_RECORDING))
    {
        return error;
    }

    return kOK;
}

int AndroidRecord::stopRecording()
{
    int result = kOK;

    // Stop the recording
    if(SL_RESULT_SUCCESS != (*record_itf)->SetRecordState(record_itf, SL_RECORDSTATE_STOPPED))
    {
        result = error;
    }

    if (SL_RESULT_SUCCESS != (*record_buff_queue)->Clear(record_buff_queue))
    {
        result = error;
    }

    cleanup();

    return result;
}

int AndroidRecord::clean()
{
    record_buff_queue = nullptr;
    record_obj = nullptr;
    record_itf = nullptr;

    record_buffer_index = 0;
    record_buffers->reset();

    engine_itf = nullptr;

    if(engine_obj != nullptr)
        (*engine_obj)->Destroy(engine_obj);
    engine_obj = nullptr;

    return kOK;
}


void AndroidRecord::opensl_record_callback(SLAndroidSimpleBufferQueueItf record_buff_queue, void *context)
{
    AndroidRecordInterface *inst = reinterpret_cast<AndroidRecordInterface *>(context);
    auto index = inst->record_buffer_index % inst->record_buffer_count;

    SLAndroidSimpleBufferQueueState qState;
    if(SL_RESULT_SUCCESS != (*inst->record_buff_queue)->GetState(inst->record_buff_queue, &qState))
    {
        return;
    }

    auto obj = reinterpret_cast<AndroidRecordInterface*>(inst->signal_proc_obj);
    (obj->*(inst->signal_proc_cb))(inst->record_buffers[index].get(), inst->record_sample_count);

    if(SL_RESULT_SUCCESS != (*record_buff_queue)->Enqueue(record_buff_queue, inst->record_buffers[index].get(), inst->record_sample_count * sizeof(AudioSample)))
    {
        return;
    }

    inst->record_buffer_index++;
}

0 个答案:

没有答案