Генерация синусоидальной волны с использованием фазы
Я генерирую синусоидальную волну, используя следующий метод -
sampling rate = 22050;
theta = 0;
for (i = 0; i < N; i++)
{
theta = phase * 2 * PI;
signal[i] = amplitude * sin(theta);
phase = phase + frequency/sampling rate;
}
Когда я генерирую сигнал с частотой 8000 Гц, на выходе возникают искажения. Частоты ниже этой (например, 6000 Гц) генерируются правильно. Сигнал 8000 Гц генерируется правильно, если я проверю фазу следующим образом:
if (phase > 1)
{
float temp = phase - 1;
phase = temp;
}
Я думаю, что это как-то связано с функцией синуса в XCode, возможно, диапазон значений, которые он может принять? Один и тот же код с фазовым переносом и без него не имеет разницы в Matlab. Может кто-нибудь объяснить, что здесь происходит?
3 ответа
Я считаю, что расчет должен быть (2,0 * PI) * Частота / Частота выборки
Это даст вам следующий шаг фазы в радианах. это значение затем может быть введено в функцию Sin для расчета фазы. Обратите внимание, что вам нужно накапливать значения радиан.
Технически, ваше первое утверждение неверно, так как оно сформулировано. FS/2 - это значение Найквиста. Вы можете производить частоты выше этого, но они будут псевдонимами.
С точки зрения обтекания фаз существуют разные способы управления этим.
Мое понимание радиан состоит в том, что это "линейное" представление фазы, которое не повторяется, пока фаза вращается вокруг значений 2 пи. Таким образом, у вас может не быть проблемы с переносом, если вы управляете фазой, управляя радианами.
Рад, что поправил более знающих людей.
@cixelsyd имеет правильную формулу... вот код для создания набора выборок заданной частоты на основе частоты выборки
incr_theta := (2.0 * math.Pi * given_freq) / samples_per_second
phase := -1.74 // given phase ... typically 0 note its a constant
theta := 0.0
for curr_sample := 0; curr_sample < number_of_samples; curr_sample++ {
source_buffer[curr_sample] = math.Sin(theta + phase)
theta += incr_theta
}
для эффективности лучше всего переместить вычисление дельта-тета за пределы цикла... фаза уведомления является константой, поскольку она просто дает нам начальное смещение
Я не уверен, но я считаю, что проблема может быть:
theta = phase * 2 * PI;
Я думаю, что Xcode изменит результат на целое число. Вы можете попробовать:
theta = phase * 2.0 * PI;
вместо этого, и убедитесь, что ваш PI
переменная является double
,
Все это делает это не по теме для DSP.SE.:-)