当使用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");
}