平滑的频率变化

Smooth frequency change

我正在尝试连续播放一个声音,其频率应该平滑地改变。例如,我的 AudioTrack 当前以 100 Hz 的频率播放,新的频率为 1000 Hz。然后我不希望频率跳跃,而是平滑地适应变化。我当前的代码如下所示:

int buffSize = AudioTrack.getMinBufferSize(sampleRate,
                                           AudioFormat.CHANNEL_OUT_MONO,
                                           AudioFormat.ENCODING_PCM_16BIT);
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
                                       AudioFormat.CHANNEL_OUT_MONO,
                                       AudioFormat.ENCODING_PCM_16BIT, buffSize,
                                       AudioTrack.MODE_STREAM);
short samples[] = new short[buffSize];
int amp = 10000;
double twopi = 8. * Math.atan(1.);
double phase = 0.0;
audioTrack.play();
while (playing)
{
    double newFrequency = getFrequency();
    for (int i = 0; i < buffSize; i++)
    {
        samples[i] = (short) (amp * Math.sin(phase));
        phase += twopi * newFrequency / sampleRate;
    }
    audioTrack.write(samples, 0, buffSize);
}
audioTrack.stop();
audioTrack.release();

这当然是在后台运行。我的采样率自动设置为可能的最低值:

private int getMinSampleRate()
{
    for (int i = 1; i < 100000; i++)
        if (AudioTrack.getMinBufferSize(i, AudioFormat.CHANNEL_OUT_MONO,
                                        AudioFormat.ENCODING_PCM_16BIT) > 0)
            return i;

    return -1;
}

您可以使用 low-pass filter to smooth the transition. Here's another example.

double currentFrequency = getFrequency();
double smoothing  = 10;   // calculate based on your sample rate and desired time delta for the change
while (playing)
{
    double newFrequency = getFrequency();
    for (int i = 0; i < buffSize; i++)
    {
        // because you are filling the buffer, deltaTime will be a constant: the time between samples
        currentFrequency += deltaTime * ( newFrequency - currentFrequency ) / smoothing;
        samples[i] = (short) (amp * Math.sin(phase));
        phase += twopi * currentFrequency / sampleRate;
    }
    audioTrack.write(samples, 0, buffSize);
}

保留频率的历史记录,并根据增量使用增量步骤慢慢将其更改为您的新值。对于大增量,该值在开始时会变化得更快,然后在接近结束时变慢。 IIRC,这称为一阶过滤器,因为您无法控制变化的加速。二阶滤波器将使加速度平滑。

有很多不同的技术,请查看 Wikipedia 中的过滤器。