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

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

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. Может кто-нибудь объяснить, что здесь происходит?


person Naveen    schedule 16.03.2016    source источник
comment
Если вы заинтересованы в XCode, вам нужно сообщить нам, к какому типу относятся разные переменные. Это может что-то показать. Как бы то ни было, я вижу только тип temp.   -  person Peter K.    schedule 23.03.2016
comment
Привет, Питер, PI объявлен как двойной, а тета - с плавающей запятой. Я изменил theta на double, и код генерирует сигнал 8K без искажений. Спасибо!   -  person Naveen    schedule 23.03.2016
comment
Рад слышать. Однако я собираюсь закрыть этот вопрос как не по теме и перенести его на SO.   -  person Peter K.    schedule 23.03.2016


Ответы (3)


Я считаю, что расчет должен быть (2,0 * PI) * частота/частота дискретизации

Это даст вам следующее приращение фазы в радианах. затем это значение может быть передано в функцию Sin для расчета фазы. Обратите внимание, что вам необходимо накапливать значения в радианах.

Технически ваше первое утверждение неверно в своей формулировке. FS/2 — значение Найквиста. Вы можете создавать частоты выше этого, но они будут накладываться.

С точки зрения переноса фаз существуют разные способы управления этим.

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

С удовольствием поправлю более знающие люди.

person cixelsyd    schedule 16.03.2016

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

theta = phase * 2 * PI;  

Я думаю, что Xcode изменит результат на целое число. Вы можете попробовать:

theta = phase * 2.0 * PI;  

вместо этого и убедитесь, что ваша переменная PI является double.

Все это делает эту тему не относящейся к теме DSP.SE. :-)

person Peter K.    schedule 23.03.2016

@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
}

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

person Scott Stensland    schedule 20.09.2017