使用OpenSL ES创建正弦波

时间:2019-11-26 07:30:01

标签: android-ndk opensl

当使用OpenSL ES和android NDK实现基本的正弦波振荡音时,我不明白我在做错什么。我设法使背景音乐播放器和声音效果播放器正常工作。现在,当我去弹奏它时,它似乎听起来像是正确的音调,但是它比较不稳定。当我收到一个Android TOUCH_MOVE事件时,我正在调用opensl enqueue函数来播放我的正弦波缓冲区。我正在使用int16_t缓冲区来存储PCM数据。我的设备上,每个突发的默认帧数是240。采样率为48000。请帮助,这让我发疯了。

这是我注册振荡器对象的初始化代码:

    temp->buff=new int16_t[DEFAULT_FRAMES_PER_BURST];
    temp->increment = (float)(2*M_PI) * 1000.f / 48000.f;

    SLDataLocator_AndroidSimpleBufferQueue dataLocatorIn;
    dataLocatorIn.locatorType =  SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
    dataLocatorIn.numBuffers = 1;
    SLDataFormat_PCM dataFormat;
    dataFormat.formatType = SL_DATAFORMAT_PCM;

    dataFormat.numChannels = 1;
    dataFormat.samplesPerSec = SL_SAMPLINGRATE_48;
    dataFormat.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
    dataFormat.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
    dataFormat.channelMask = SL_SPEAKER_FRONT_CENTER;          // MONO.
    dataFormat.endianness = SL_BYTEORDER_LITTLEENDIAN;

    SLDataSource dataSource;
    dataSource.pLocator = &dataLocatorIn;
    dataSource.pFormat = &dataFormat;
    SLDataLocator_OutputMix dataLocatorOut;
    dataLocatorOut.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    dataLocatorOut.outputMix = mOutputMixObj;
    SLDataSink dataSink;
    dataSink.pLocator = &dataLocatorOut;
    dataSink.pFormat = NULL;

    const SLuint32 soundPlayerIIDCount = 2;
    const SLInterfaceID soundPlayerIIDs[] = { SL_IID_PLAY, SL_IID_BUFFERQUEUE };
    const SLboolean soundPlayerReqs[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };

    result = (*mEngine)->CreateAudioPlayer(mEngine, &temp->mOscPlayerObj, &dataSource, &dataSink, soundPlayerIIDCount, soundPlayerIIDs, soundPlayerReqs);
    result = (*temp->mOscPlayerObj)->Realize(temp->mOscPlayerObj, SL_BOOLEAN_FALSE);
    result = (*temp->mOscPlayerObj)->GetInterface(temp->mOscPlayerObj, SL_IID_PLAY, &temp->mOscPlayer);
    result = (*temp->mOscPlayerObj)->GetInterface(temp->mOscPlayerObj, SL_IID_BUFFERQUEUE, &temp->mOscPlayerQueue);
    result = (*temp->mOscPlayer)->SetPlayState(temp->mOscPlayer, SL_PLAYSTATE_PLAYING);

这是我用于此振荡器对象的播放功能的代码:

    SLuint32 playerState;
    (*temp->mOscPlayerObj)->GetState(temp->mOscPlayerObj, &playerState);
    if (playerState == SL_OBJECT_STATE_REALIZED) {
       for (int i=0; i<DEFAULT_FRAMES_PER_BURST; ++i){
          int16_t output=(int16_t)((sinf(temp->angle)*(float)INT16_MAX));
          temp->buff[i]=output;
          temp->angle+=temp->increment;
   }
    result = (*temp->mOscPlayerQueue)->Enqueue(temp->mOscPlayerQueue, temp->buff, 
     DEFAULT_FRAMES_PER_BURST*2);
        if (result != SL_RESULT_SUCCESS) LOGI("OPENSL PLAY OSC ERROR");
    }

0 个答案:

没有答案