使用 Superpowered Audio Kit 在音轨之间正确转换

Proper transition between audio tracks using Superpowered Audio Kit

我成功实现了音频播放,但经常出现一个问题,即从 JAVA 单击 "next song" 时会出现尖锐的听觉故障。这个声音故障大约过去了。大约 100 毫秒。并且在下一首歌曲开始播放之前更频繁地出现。

请务必注意: 我在每次播放结束时对每个变量 class 和 "free" 立体缓冲区 (setdestroyallthreads) 调用 "delete",然后在每次播放开始前调用 "process"(process) 方法。

从 Java 开始,过渡序列如下所示;

PlayerClass.setDestroyAllThreads( );
PlayerClass.open("new_path", sampleRate, bufferSize );
PlayerClass.play( );

这是我的片段;

    static void playerEventCallbackA(void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void * __unused value) {
    if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadSuccess) {
        SuperpoweredAdvancedAudioPlayer *player = *((SuperpoweredAdvancedAudioPlayer **)clientData);

    }else if (event == SuperpoweredAdvancedAudioPlayerEvent_EOF) {

        playerBass->pause();
        playerB->pause();

        finishedPlaying = true;

    }else if (event == SuperpoweredAdvancedAudioPlayerEvent_LoadError) {

    };
}


static bool audioProcessing(void *clientdata, short int *audioIO, int numberOfSamples, int __unused samplerate) {
    return ((Eve *)clientdata)->process(audioIO, (unsigned int)numberOfSamples);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
Eve::Eve(const char *path,unsigned int samplerate,unsigned int buffersize) : activeFx(0), crossValue(0.0f), volBass(1.0f * headroom), volB(1.0f * headroom) {
    stereoBuffer = (float *)memalign(16,(buffersize + 16) * sizeof(float) * 2);

    playerBass = new SuperpoweredAdvancedAudioPlayer(&playerBass , playerEventCallbackA, samplerate, 0);
    playerB = new SuperpoweredAdvancedAudioPlayer(&playerB, playerEventCallbackB, samplerate, 0);
    filterb = new SuperpoweredFilter(SuperpoweredFilter_Resonant_Lowpass, samplerate*0.98);
    spatializer = new SuperpoweredSpatializer(samplerate);

    playerBass->open(path);
    playerB->open(path);

    finishedPlaying = false;

    playerBass->syncMode = playerB->syncMode = SuperpoweredAdvancedAudioPlayerSyncMode_TempoAndBeat;
    audioSystem = new SuperpoweredAndroidAudioIO(samplerate, buffersize, false, true, audioProcessing, this, -1, SL_ANDROID_STREAM_MEDIA, buffersize * 2);
}


Eve::~Eve() {
    delete playerBass;
    delete playerB;
    delete spatializer;
    delete filterb;
    delete audioSystem;

    finishedPlaying = false, playingNow = false, pausedNow = false, processed = false, hd = false;
}

void Eve::onPlay() {

    playerBass->play(false);
    playerB->play(false);
    playingNow = true;

}

void Eve::setBassValue(int bass) {


    filterb->setResonantParameters(floatToFrequency(0.2f),ebass);
    filterb->enable(true);

}

void Eve::setDestroyAllThreads(){

    delete playerBass;
    delete playerB;
    delete spatializer;
    delete filterb;
    delete audioSystem;

    finishedPlaying = false, playingNow = false, pausedNow = false, processed = false, hd = false;
}




bool Eve::process(short int *output, unsigned int numberOfSamples) {

    bool masterIsA = (crossValue <= 0.5f);
    double masterBpm = masterIsA ? playerBass->currentBpm : playerB->currentBpm;
    double msElapsedSinceLastBeatA = playerBass->msElapsedSinceLastBeat;

    bool silence = !playerBass->process(stereoBuffer, false, numberOfSamples*1, volBass, masterBpm, playerB->msElapsedSinceLastBeat);
    processed = true;

    filterb->process(stereoBuffer, stereoBuffer, numberOfSamples);
    if (playerB->process(stereoBuffer, !silence, numberOfSamples, volB, masterBpm, msElapsedSinceLastBeatA)) silence = false;

    spatializer->process(stereoBuffer, stereoBuffer, (float*)output, (float*)output, numberOfSamples, true);
    SuperpoweredFloatToShortInt(stereoBuffer, output, numberOfSamples);
    return !silence;
}


static Eve *eve = NULL;

extern "C" JNIEXPORT void Java_com_EvePlayer_Eve(JNIEnv *javaEnvironment, jobject self, jstring songPath, jint samplerate, jint buffersize) {

    const char *path = javaEnvironment->GetStringUTFChars(songPath, JNI_FALSE);
    eve = new Eve(path,(unsigned int)samplerate,(unsigned int)buffersize);
    javaEnvironment->ReleaseStringUTFChars(songPath, path);

}

extern "C" JNIEXPORT void Java_com_EvePlayer_SetTempFolder(JNIEnv *javaEnvironment, jobject __unused obj, jstring path) {
    const char *str = javaEnvironment->GetStringUTFChars(path, 0);
    SuperpoweredAdvancedAudioPlayer::setTempFolder(str);
    javaEnvironment->ReleaseStringUTFChars(path, str);
}

extern "C" JNIEXPORT void Java_com_EvePlayer_evePlay(JNIEnv *javaEnvironment, jobject self){
    eve->onPlay();
}

extern "C" JNIEXPORT void Java_com_EvePlayer_setDestroyAllThreads(JNIEnv *javaEnvironment, jobject self) {
    eve->setDestroyAllThreads();
}

首先销毁音频 I/O(在您的代码中为 "audioSystem")。音频I/O会周期性调用你的音频处理回调,所以需要先销毁它,否则会使用删除的对象。