2014-01-07 43 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版本? –