无法通过OpenSL ES创建音频播放器

时间:2011-05-16 10:31:24

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

我一直在尝试通过适用于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()是一种自定义的错误检查方法。

任何人都知道为什么会失败?正如我所说,所有参数对我来说都是有效的,我已经检查了source,outputmix或sink对象中的无效组合,但没有......

2 个答案:

答案 0 :(得分:4)

既不是你设置字段的顺序,也不是容器的大小,而是产生差异。我觉得通过为channelMask设置适当的值来解决您的问题。

pcm.channelMask = SL_SPEAKER_FRONT_CENTER; 

而不是

pcm.channelMask = SL_SPEAKER_BACK_CENTER;

答案 1 :(得分:0)

我已经通过良好,充足的文档解决了这个问题,但更多的是运气。事实证明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 ......

我不知道为什么会发生这种情况,也许是因为它是一个需要按正确顺序设置的结构?我不知道......虽然我不能想象它...除非它更像是一个或多个变量的记忆图,我可以想象......

无论如何,我修好了...... 叹息