2014-01-07 46 views
1

我使用NDK创建了一个音频乐器,为了获得低延迟性能,我选择了OpenSL来播放音乐文件。但是我未能更改播放音乐的播放速度。 这里是捕捉代码:Android OpenSL不支持SL_IID_PLAYBACKRATE?

int OpenSLSoundPool::createOggAudioPlayer(const char *filename, int rate){ 
    SLresult result; 
    AAsset* asset = AAssetManager_open(mMgr, filename, AASSET_MODE_UNKNOWN); 
    if (NULL == asset) { 
     return JNI_FALSE; 
    } 

    // open asset as file descriptor 
    off_t start, length; 
    int fd = AAsset_openFileDescriptor(asset, &start, &length); 
    assert(0 <= fd); 
    AAsset_close(asset); 

    // configure audio source 
    SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length}; 
    SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; 
    SLDataSource audioSrc = {&loc_fd, &format_mime}; 

    // configure audio sink 
    SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; 
    SLDataSink audioSnk = {&loc_outmix, NULL}; 

    // create audio player 
    const SLInterfaceID ids[4] = {SL_IID_SEEK, SL_IID_MUTESOLO, SL_IID_VOLUME, SL_IID_PLAYBACKRATE}; 
    const SLboolean req[4] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 
    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &fdPlayerObject, &audioSrc, &audioSnk, 
      4, ids, req); 
    assert(SL_RESULT_SUCCESS == result); 
    (void)result; 

    // realize the player 
    result = (*fdPlayerObject)->Realize(fdPlayerObject, SL_BOOLEAN_FALSE); 
    assert(SL_RESULT_SUCCESS == result); 
    (void)result; 

    // get the play interface 
    result = (*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_PLAY, &fdPlayerPlay); 
    assert(SL_RESULT_SUCCESS == result); 
    (void)result; 

    // get the seek interface 
    result = (*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_SEEK, &fdPlayerSeek); 
    assert(SL_RESULT_SUCCESS == result); 
    (void)result; 

    // get the mute/solo interface 
    result = (*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_MUTESOLO, &fdPlayerMuteSolo); 
    assert(SL_RESULT_SUCCESS == result); 
    (void)result; 

    // get the volume interface 
    result = (*fdPlayerObject)->GetInterface(fdPlayerObject, SL_IID_VOLUME, &fdPlayerVolume); 
    assert(SL_RESULT_SUCCESS == result); 
    (void)result; 

    // get playback rate interface 
    result = (*fdPlayerObject)->GetInterface(fdPlayerObject, 
      SL_IID_PLAYBACKRATE, &fdPlayerRate); 
    assert(SL_RESULT_SUCCESS == result); 


    SLuint32 capa; 
    result = (*fdPlayerRate)->GetRateRange(fdPlayerRate, 0, 
       &playbackMinRate, &playbackMaxRate, &playbackRateStepSize, &capa); 
    assert(SL_RESULT_SUCCESS == result); 

    result = (*fdPlayerRate)->SetRate(fdPlayerRate, playbackMaxRate); 
    assert(SL_RESULT_SUCCESS == result); 

    SLpermille SLrate; 
    result = (*fdPlayerRate)->GetRate(fdPlayerRate, &SLrate); 
    assert(SL_RESULT_SUCCESS == result); 

    // enable whole file looping 
    result = (*fdPlayerSeek)->SetLoop(fdPlayerSeek, SL_BOOLEAN_FALSE, 0, SL_TIME_UNKNOWN); 
    assert(SL_RESULT_SUCCESS == result); 
    (void)result; 

    return JNI_TRUE; 
} 

的关键点是:

result = (*fdPlayerRate)->SetRate(fdPlayerRate, playbackMaxRate); 
assert(SL_RESULT_SUCCESS == result); 

我试着playbackMaxRate和playbackMinRate之间设定值(在我的S3手机,playbackMaxRate是2000年,playbackMinRate为500)。但没有效果,android NDK doc说它支持SL_IID_PLAYBACKRATE。 我的代码有什么问题吗? 非常感谢。

+0

哪个android版本是您的测试手机? –

+0

我的测试手机是三星s3 android 4.1 –

回答

2

您可能尝试将当前速率属性约束设置为SL_RATEPROP_PITCHCORAUDIO。默认的音频属性是SL_RATEPROP_NOPITCHCORAUDIO。像这样:

SLuint32 capa; 
result = (*fdPlayerRate)->GetRateRange(fdPlayerRate, 0, 
      &playbackMinRate, &playbackMaxRate, &playbackRateStepSize, &capa); 
assert(SL_RESULT_SUCCESS == result); 

result = (*fdPlayerRate)->SetPropertyConstraints(fdPlayerRate, 
        SL_RATEPROP_PITCHCORAUDIO); 

if (SL_RESULT_PARAMETER_INVALID == result) { 
    LOGD("Parameter Invalid"); 
} 
if (SL_RESULT_FEATURE_UNSUPPORTED == result) { 
    LOGD("Feature Unsupported"); 
} 
if (SL_RESULT_SUCCESS == result) { 
    assert(SL_RESULT_SUCCESS == result); 
    LOGD("Success"); 
} 

result = (*fdPlayerRate)->SetRate(fdPlayerRate, playbackMaxRate); 
assert(SL_RESULT_SUCCESS == result); 

这可能因平台版本和实现而异。它适用于我的Moto G.希望这有助于。

+0

非常感谢。我添加SetPropertyConstraints代码,但也没有效果。我播放的是mp3文件和midi文件,你在Moto G上播放哪种文件? –

+0

MP3和WAV文件格式 –

+0

我试过samsung s3 4.1.2,asus-nexus_7 4.2.1和samsung note 2 4.3,它们都没有效果,并打印出“Feature Unsupported”。摩托G应该是Android 4.3版本? –