Android OpenSL ES - .wav文件采样频率为44.1Khz的问题



我正在尝试将我的一些OpenAL代码转换为OpenSL ES,以便在Genymotion上使用Android(Kitkat 4.4.4),并遇到了以44.1Khz采样.wav文件的问题。我的应用程序是本机应用程序(胶水)。

我遵循了优秀书籍 Android NDK 初学者指南中的 Android NDK 示例和片段的 /native-audio 示例,因此我的代码在大多数 wav/PCM 数据上的行为正确,除了那些以 44.1Khz 采样的数据。我的具体代码是这样的:

引擎初始化

  // create OpenSL ES engine
  SLEngineOption EngineOption[] = {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE};
  const SLInterfaceID lEngineMixIIDs[] = {SL_IID_ENGINE};
  const SLboolean lEngineMixReqs[] = {SL_BOOLEAN_TRUE};
  SLresult res = slCreateEngine(&mEngineObj, 1, EngineOption, 1, lEngineMixIIDs, lEngineMixReqs);
  res = (*mEngineObj)->Realize(mEngineObj, SL_BOOLEAN_FALSE);
  res = (*mEngineObj)->GetInterface(mEngineObj, SL_IID_ENGINE, &mEngine);   // get 'engine' interface
  // create output mix (AKA playback; this represents speakers, headset etc.)
  res = (*mEngine)->CreateOutputMix(mEngine, &mOutputMixObj, 0,NULL, NULL);
  res = (*mOutputMixObj)->Realize(mOutputMixObj, SL_BOOLEAN_FALSE);

播放器初始化

  SLresult lRes;
  // Set-up sound audio source.
  SLDataLocator_AndroidSimpleBufferQueue lDataLocatorIn;
  lDataLocatorIn.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
  lDataLocatorIn.numBuffers = 1;   // 1 buffer for a one-time load
  // analyze and set correct PCM format
  SLDataFormat_PCM lDataFormat;
  lDataFormat.formatType = SL_DATAFORMAT_PCM;
  lDataFormat.numChannels = audio->wav.channels;     // etc. 1,2
  lDataFormat.samplesPerSec = audio->wav.sampleRate * 1000;   // etc. 44100 * 1000
  lDataFormat.bitsPerSample = audio->wav.bitsPerSample;   // etc. 16
  lDataFormat.containerSize = audio->wav.bitsPerSample;
  lDataFormat.channelMask = SL_SPEAKER_FRONT_CENTER;
  lDataFormat.endianness = SL_BYTEORDER_LITTLEENDIAN;
  SLDataSource lDataSource;
  lDataSource.pLocator = &lDataLocatorIn;
  lDataSource.pFormat = &lDataFormat;
  SLDataLocator_OutputMix lDataLocatorOut;
  lDataLocatorOut.locatorType = SL_DATALOCATOR_OUTPUTMIX;
  lDataLocatorOut.outputMix = mOutputMixObj;
  SLDataSink lDataSink;
  lDataSink.pLocator = &lDataLocatorOut;
  lDataSink.pFormat = NULL;
  const SLInterfaceID lSoundPlayerIIDs[] = { SL_IID_PLAY, SL_IID_ANDROIDSIMPLEBUFFERQUEUE };
  const SLboolean lSoundPlayerReqs[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
  lRes = (*mEngine)->CreateAudioPlayer(mEngine, &mPlayerObj, &lDataSource, &lDataSink, 2, lSoundPlayerIIDs, lSoundPlayerReqs);
  if (lRes != SL_RESULT_SUCCESS) { return; }
  lRes = (*mPlayerObj)->Realize(mPlayerObj, SL_BOOLEAN_FALSE);
  if (lRes != SL_RESULT_SUCCESS) { return; }
  lRes = (*mPlayerObj)->GetInterface(mPlayerObj, SL_IID_PLAY, &mPlayer);
  if (lRes != SL_RESULT_SUCCESS) { return; }
  lRes = (*mPlayerObj)->GetInterface(mPlayerObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &mPlayerQueue);
  if (lRes != SL_RESULT_SUCCESS) { return; }
  // register callback on the buffer queue
  lRes = (*mPlayerQueue)->RegisterCallback(mPlayerQueue, bqPlayerQueueCallback, NULL);
  if (lRes != SL_RESULT_SUCCESS) { return; }
  lRes = (*mPlayer)->SetCallbackEventsMask(mPlayer, SL_PLAYEVENT_HEADATEND);
  if (lRes != SL_RESULT_SUCCESS) { return; }
  // ..fetch the data in 'audio->data' from opened FILE* stream and set 'datasize'
  // feed the buffer with data
  lRes = (*mPlayerQueue)->Clear(mPlayerQueue);   // remove any sound from buffer
  lRes = (*mPlayerQueue)->Enqueue(mPlayerQueue, audio->data, datasize);

上述方法适用于 8000、2205032000 个样本/秒,但在 41100个样本上,5 次中有 4 次会在第一次播放时重复大量时间。这就像有一个敲门的声音效果,实际上在一个->SetPlayState(..SL_PLAYSTATE_PLAYING);和速度上循环了很多次(大约 50 次)。我的代码上有什么明显的错误吗?这些采样的多线程问题?还有人有这种问题吗?我应该在 41.1Khz 的情况下降低采样率吗?会不会是基因问题?德克萨斯州

我通过将 44Khz 缩减采样到 22Khz 来解决这个问题。有趣的是,这只发生在包含 1 个通道和 44,100 个样本的声音上;在所有其他情况下,都没有问题。

相关内容

  • 没有找到相关文章

最新更新