我正在使用 Oboe C++库在我的android应用程序中播放声音。
我想更改音频样本的音高。
因此,我开始创建“ mPos ”浮点值以保存当前播放的帧,并在每个步骤中添加“ mPitch ”值。

似乎新的Pitch可以正确播放音频,但是当Pitch高(例如1.2)并发出奇怪的噪音,而Pitch低(例如0.212)时,它是自身的两倍。

这是我的第一次音频编程,
发布此问题之前,我做了很多研究。我什至直接向“Oboe”支持发送消息,但没有响应。
有谁知道如何正确实现Pitch?

流长度始终 192

channel 计数总是 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;
};

最佳答案

当您将浮点型变量(mPos)乘以整数类型的变量(channelCount)时,结果就是浮点型。至少,您正在弄乱 channel 的交错。代替

(size_t)(mPos * channelCount)

尝试
((size_t)mPos) * channelCount

编辑:
您将在到达末尾时故意使用源语句循环源代码,该语句导致mPos = 0;。替代此操作,您可以独立于音高来计算源样本的数量,但是当源样本用尽时会跳出循环。另外,由于音调调整,对源样本和目标样本的比较也没有用:
    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;
        }
    }

但是,为了完整起见,请注意以下事项:对于任何严肃的应用,您实际上都不应该以这种方式完成音高变化-声音质量会很糟糕。有免费的库,可以将音频重采样到任意目标速率。这些将把您的源样本转换为更多或更少的样本,并在以与源相同的速率重放时提供高质量的音高变化。

关于android - 如何改变音调?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60935204/

10-10 14:47