Генерация синусоидальной волны с использованием фазы

Я генерирую синусоидальную волну, используя следующий метод -

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.:-)

Другие вопросы по тегам