我试图连续播放声音,应该更改smoothley频率。例如,我的AudioTrack当前正在以100 Hz的频率播放,新频率为1000 Hz。然后我不希望频率跳跃,但是要使smoothley适应变化。我目前的代码如下:
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();
当然,这是在后台运行的。我的sampleRate自动设置为可能的最低值:
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;
}
答案 0 :(得分:1)
您可以使用low-pass filter来平滑过渡。这是另一个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处的过滤器。