【问题标题】:Unable to create Audio player via OpenSL ES无法通过 OpenSL ES 创建音频播放器
【发布时间】:2012-04-04 03:02:37
【问题描述】:

我一直在尝试通过适用于 Android 的 OpenSL ES API 创建音频播放器。但是,当我尝试运行我的代码时出现错误,这表明我向CreateAudioPlayer() 提供了错误的参数:

05-16 12:16:40.593: ERROR/libOpenSLES(2020): channelMask=0x100 numChannels=1
05-16 12:16:40.593: ERROR/AudioProcessor_Native(2020): Invalid parameter found
05-16 12:16:40.593: ERROR/AudioProcessor_Native(2020): Unable to create player object

但是,我无法找到任何错误或无效的参数。我已经检查了其中任何一个,并且在网络上没有发现任何表明我的组合无效的内容。代码如下所示:

JNIEXPORT jboolean JNICALL Java_org_test_opensl_AudioProcessor_initPlayer(JNIEnv* env, jobject thiz){
    SLresult result;
    // Configure Buffer Queue.
    SLDataLocator_AndroidSimpleBufferQueue bufferQueue;
    bufferQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
    bufferQueue.numBuffers = MAX_BUFFERS;
    // Configure data format.
    SLDataFormat_PCM pcm;
    pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
    pcm.channelMask = SL_SPEAKER_BACK_CENTER;
    pcm.containerSize = 16;
    pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
    pcm.formatType = SL_DATAFORMAT_PCM;
    pcm.numChannels = 1;
    pcm.samplesPerSec = SL_SAMPLINGRATE_8;
    // Configure Audio Source.
    SLDataSource source;
    source.pFormat = &pcm;
    source.pLocator = &bufferQueue;
    // Configure output mix.
    SLDataLocator_OutputMix outputMix;
    outputMix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    outputMix.outputMix = outputMixObject;
    // Configure Audio sink.
    SLDataSink sink;
    sink.pFormat = NULL;
    sink.pLocator = &outputMix;
    // Create Audio player.
    const SLInterfaceID ids[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
    const SLboolean req[1] = {SL_BOOLEAN_TRUE};
    result = (*engineInstance)->CreateAudioPlayer(engineInstance, &playerObject, &source,
                                                  &sink, 1, ids, req);
    if(checkError(result, "Unable to create player object") == -1){
        return JNI_FALSE;
    }
    // Realize Audio player.
    result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
    if(checkError(result, "Unable to realize player object") == -1){
        return JNI_FALSE;
    }
    // Get the Audio player interface.
    result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerInstance);
    if(checkError(result, "Unable to get player interface") == -1){
        return JNI_FALSE;
    }
    // Get the Player Buffer Queue interface.
    result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
                                           &playerBufferQueue);
    if(checkError(result, "Unable to get player buffer interface") == -1){
        return JNI_FALSE;
    }
    // Set the player's state to playing.
    result = (*playerInstance)->SetPlayState(playerInstance, SL_PLAYSTATE_PLAYING);
    if(checkError(result, "Unable to set player's state to playing") == -1){
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

其中checkError()是自定义的错误检查方法。

有人对为什么会失败有任何想法吗?正如我所说,所有参数对我来说都是有效的,并且我检查了源、输出混合或接收器对象中的无效组合,这些组合没有......

【问题讨论】:

    标签: android java-native-interface android-ndk


    【解决方案1】:

    这既不是您设置字段的顺序,也不是 containerSize 的值。我觉得您的问题已通过为 channelMask 设置适当的值得到解决。

    pcm.channelMask = SL_SPEAKER_FRONT_CENTER; 
    

    而不是

    pcm.channelMask = SL_SPEAKER_BACK_CENTER;
    

    【讨论】:

      【解决方案2】:

      我没有通过好的、足够的文档解决这个问题,更多的是靠运气。事实证明,我在SLDataFormat_PCM 对象中的 PCM 属性的顺序不正确....

      当我把它改成:

      // Configure data format.
      SLDataFormat_PCM pcm;
      pcm.formatType = SL_DATAFORMAT_PCM;
      pcm.numChannels = 1;
      pcm.samplesPerSec = SL_SAMPLINGRATE_8;
      pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
      pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
      pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
      pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
      

      它将顺利创建 AudioPlayer...

      我不知道为什么会这样,也许是因为它是一个需要以正确顺序设置的结构?我不知道...虽然我真的无法想象...除非它更像是一个或多个变量的内存映射,我可以在其中想象....

      不管怎样,我修好了... 叹息

      【讨论】:

      • 实际上,顺序根本不重要......这是导致问题的 pcm 结构的错误设置属性......这是导致问题的pcm.containerSize = 16; 行,因为这没有指定类型...如果我使用 OpenSL ES 宏 (pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;) 或将其转换为 SLuint32 (pcm.containerSize = (SLuint)16;),它也能正常工作。
      猜你喜欢
      • 2012-07-04
      • 2016-10-31
      • 2012-12-23
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      相关资源
      最近更新 更多