Свободное изменение частоты на основном синусоидальном генераторе

0

Я пишу базовую звуковую лабораторию, чтобы экспериментировать с генерацией звука с использованием цифровых осцилляторов.

Мой генератор отлично работает для фиксированной частоты. Тем не менее, в моей программе у меня есть ползунок для изменения частоты в прогоне. Тем не менее, частота меняется, я слышу небольшой сбой при каждом переключении частоты. Вероятно, это связано с резким изменением частоты.

Я написал управляющий код, чтобы постепенно менять частоту, пока она не достигнет желаемой частоты, но что-то не работает правильно, и я не могу понять, что.

Каждый раз, когда устанавливается новая частота, я определяю разницу между фактической частотой и новой. Затем я разделяю эту разницу на 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

Теги:
audio
signal-processing

1 ответ

3
Лучший ответ

Сбой состоит в том, что выходное значение изменяется мгновенно, потому что входное значение sin изменяется мгновенно при изменении частоты.

Чтобы этого избежать, убедитесь, что ваш генератор является непрерывной фазой. Вместо sin(2.pi.ft) do sin(phi), где phi += 2.pi.f.dt (где dt - изменение шага во времени).

  • 0
    Спасибо за ваш быстрый ответ. Должно быть dt 1/44100? Можете ли вы указать мне теорию, чтобы лучше понять этот феномен?
  • 0
    Да, это. Отлично! Спасибо

Ещё вопросы

Сообщество Overcoder
Наверх
Меню