Как изменить высоту звука? - PullRequest
0 голосов
/ 30 марта 2020

Я использую библиотеку Oboe C ++ для воспроизведения звуков в моем приложении android. Я хочу изменить высоту звука в моих сэмплах. Итак, я начал создавать значение с плавающей запятой « mPos », чтобы удерживать текущий воспроизводимый кадр, и добавляя значение « mPitch » каждый шаг.

Похоже, что воспроизводимый звук правильно с новой высотой тона, но он вдвое больше, когда высота высока (например, 1,2) и издает странный шум, а высота звука низкая (например, 0,212).

Это мое первое звуковое программирование, Я провел много исследований, прежде чем опубликовать этот вопрос. Я даже отправляю сообщения напрямую в "Гобой", но не отвечаю. Кто-нибудь есть идеи, как правильно реализовать Pitch?

streamLength всегда 192

channelCount всегда 2

код:

void Player::renderAudio(float *stream, int32_t streamLength){

    const int32_t channelCount = mSound->getChannelCount();

    if (mIsPlaying){

        float framesToRenderFromData = streamLength ;
        float totalSourceFrames = mSound->getTotalFrames()/mPitch;
        const float *data = mSound->getData();

        // Check whether we're about to reach the end of the recording
        if (mPos + streamLength >= totalSourceFrames ){
            framesToRenderFromData = (totalSourceFrames - mPos);
            mIsPlaying = false;
        }
        for (int i = 0; i < framesToRenderFromData; ++i) {
            for (int j = 0; j < channelCount; ++j) {
                if(j % 2 == 0){
                    stream[(i*channelCount)+j] = (data[((size_t)mPos * channelCount)) + j] * mLeftVol) * mVol;
                }else{
                    stream[(i*channelCount)+j] = (data[((size_t)mPos * channelCount)) + j] * mRightVol) * mVol;
                }
            }
            mPos += mPitch;
            if(mPos >= totalSourceFrames){
                mPos = 0;
            }
        }
        if (framesToRenderFromData < streamLength){
            renderSilence(&stream[(size_t)framesToRenderFromData], streamLength * channelCount);
        }
    } else {
        renderSilence(stream, streamLength * channelCount);
    }
}

void Player::renderSilence(float *start, int32_t numSamples){
    for (int i = 0; i < numSamples; ++i) {
        start[i] = 0;
    }
}

void Player::setPitch(float pitchData){
    mPitch = pitchData;
};

1 Ответ

1 голос
/ 03 апреля 2020

Когда вы умножаете переменную с плавающей запятой (mPos) на переменную целочисленного типа (channelCount), результатом является число с плавающей запятой. Вы, по крайней мере, испортили свое чередование каналов. Вместо

(size_t)(mPos * channelCount)

try

((size_t)mPos) * channelCount

EDIT: вы намеренно зацикливаете источник при достижении конца с помощью оператора if, который приводит к mPos = 0;. Вместо этого вы можете рассчитать количество исходных выборок независимо от высоты тона, но выйти из l oop, когда исходные выборки будут исчерпаны. Кроме того, сравнение исходных и конечных сэмплов бесполезно из-за регулировки высоты тона:

    float framesToRenderFromData = streamLength ;
    float totalSourceFrames = mSound->getTotalFrames();  // Note change here
    const float *data = mSound->getData();

    // Note: Only check here is whether mPos has reached the end from
    // a previous call
    if ( mPos >= totalSourceFrames ) {
        framesToRenderFromData = 0.0f;
    }
    for (int i = 0; i < framesToRenderFromData; ++i) {
       for (int j = 0; j < channelCount; ++j) {
           if(j % 2 == 0){
                stream[(i*channelCount)+j] = (data[((size_t)mPos * channelCount)) + j] * mLeftVol) * mVol;
            }else{
                stream[(i*channelCount)+j] = (data[((size_t)mPos * channelCount)) + j] * mRightVol) * mVol;
            }
        }
        mPos += mPitch;
        if ( ((size_t)mPos) >= totalSourceFrames ) {   // Replace this 'if' and its contents
            framesToRenderFromData = (size_t)mPos;
            mPos = 0.0f;
            break;
        }
    }

Однако, для полноты, обратите внимание: Вы действительно не должны выполнять изменение высоты тона таким образом для любое серьезное приложение - качество звука будет ужасным. Существуют бесплатные библиотеки для повторной выборки аудио с произвольной целевой частотой; они преобразуют исходную выборку в большее или меньшее количество выборок и обеспечат качественные изменения высоты тона при воспроизведении с той же скоростью, что и у источника.

...