Я пишу базовую звуковую лабораторию, чтобы экспериментировать с генерацией звука с использованием цифровых осцилляторов.
Мой генератор отлично работает для фиксированной частоты. Тем не менее, в моей программе у меня есть ползунок для изменения частоты в прогоне. Тем не менее, частота меняется, я слышу небольшой сбой при каждом переключении частоты. Вероятно, это связано с резким изменением частоты.
Я написал управляющий код, чтобы постепенно менять частоту, пока она не достигнет желаемой частоты, но что-то не работает правильно, и я не могу понять, что.
Каждый раз, когда устанавливается новая частота, я определяю разницу между фактической частотой и новой. Затем я разделяю эту разницу на 44100, которая является моей частотой дискретизации, чтобы иметь вторую. Я использую секунду, чтобы понять прогресс изменения частоты.
Случается, что я слышу, как частота увеличивается, но когда она достигает целевой частоты, слышимая частота, похоже, немного падает. Это действительно неудобно, потому что, если я вывожу значение частоты, которая отправляется на вычисление синусоиды, все просто отлично, никаких неожиданных шагов не генерируется.
Это код класса осциллятора. Этот процесс управления изменениями частоты работает только с увеличением частоты прямо сейчас:
Oscillator::Oscillator(int freq, int sr):
sampleIndex(0),
chaseTargetFrequency(false),
frequencyChanged(false)
{
currentFrequency=freq;
frequency=freq;
sampleRate=sr;
}
void Oscillator::process(unsigned char* out)
{
float t = qreal(sampleIndex % sampleRate) / sampleRate;
if (frequencyChanged)
{
frequency+=inc;
if (frequency>=currentFrequency)
{
frequencyChanged = false;
}
}
qreal x = 0;
// SINEWAVE
x = 0.5f * qSin(2.f * M_PI * frequency * t);
qint16 value = static_cast<qint16>(x * 32767);
qToLittleEndian<qint16>(value, out);
sampleIndex++;
}
void Oscillator::setFrequency(int value)
{
if (frequencyChanged)
return;
currentFrequency = value;
inc = (currentFrequency-frequency)/44000.f;
frequencyChanged = true;
}
Кто-нибудь знает, почему это работает не так, как ожидалось? Надеюсь, мой язык достаточно ясен во время объяснения проблемы.
Заранее спасибо,
С моими наилучшими пожеланиями,
Nuno Santos
Сбой состоит в том, что выходное значение изменяется мгновенно, потому что входное значение sin
изменяется мгновенно при изменении частоты.
Чтобы этого избежать, убедитесь, что ваш генератор является непрерывной фазой. Вместо sin(2.pi.ft)
do sin(phi)
, где phi += 2.pi.f.dt
(где dt
- изменение шага во времени).