2015-01-28 2 views
0

Я пытаюсь создать вибрато, колеблюсь между двумя 430 Гц и 450 Гц, сохраняя 16-разрядный образец в списке wav. Однако слышимая частота, по-видимому, увеличивает диапазон колебаний по всему клипу. Кто-нибудь знает, почему?Генерация вибрационной синусоидальной волны

редактировать: переписал код, чтобы быть более ясным/кратким

# vibrato.py 

maxamp = 2**15 - 1 # max signed short 
wav = [] 
(t, dt) = (0, 1/44100) 
while t < 6.0: 
    f = 440 + 10 * math.sin(2 * math.pi * 6 * t) 
    samp = maxamp * math.sin(2 * math.pi * f * t) 
    wav.append(samp) 
    t += dt 

-

Update: потому что ответ использует NumPy, я буду обновлять свой код для простого Python3

# vibrato.py 

maxamp = 2**15 - 1 # max signed short 
wav = [] 
(t, dt) = (0, 1/44100) 
phase = 0 
while t < 6.0: 
    f = 440 + 10 * math.sin(2 * math.pi * 6 * t) 
    phase += 2 * math.pi * f * t 
    samp = maxamp * math.sin(phase) 
    wav.append(samp) 
    t += dt 

ответ

2

Проблема связана с подразумеваемым изменением фазы, а также с изменением частоты. Короче говоря, когда вы вычисляете ответ относительно каждой точки на временной шкале, важно отметить, что фаза колебаний будет различной для каждой частоты в каждый момент времени (за исключением начальной точки, где они все одинаковы). Поэтому перемещение между частотами подобно перемещению между различными фазами. Для случая перехода между двумя отдельными частотами это можно исправить для post hoc путем настройки общих фаз сигнала на основе изменения частоты. Я объяснил это in another answer, поэтому не буду объяснять это снова здесь, но здесь просто покажите начальный сюжет, который освещает проблему и как решить проблему. Здесь главное - важность хорошего диагностического сюжета, а правильный график для этого - спектрограмма.

Вот пример:

import numpy as np 

dt = 1./44100 
time = np.arange(0., 6., dt) 
frequency = 440. - 10*np.sin(2*math.pi*time*1.) # a 1Hz oscillation 
waveform = np.sin(2*math.pi*time*frequency) 

Pxx, freqs, bins, im = plt.specgram(waveform, NFFT=4*1024, Fs=44100, noverlap=90, cmap=plt.cm.gist_heat) 
plt.show() 

enter image description here

Обратите внимание, что диапазон частоты колебаний возрастает (как вы изначально слышали). Применяя коррекцию, связанную с выше, дает:

dt = 1./defaults['framerate'] 
time = np.arange(0., 6., dt) 
frequency = 440. - 10*np.sin(2*math.pi*time*1.) # a 1Hz oscillation 
phase_correction = np.add.accumulate(time*np.concatenate((np.zeros(1), 2*np.pi*(frequency[:-1]-frequency[1:])))) 
waveform = np.sin(2*math.pi*time*frequency + phase_correction) 

enter image description here Который гораздо ближе к тому, что было задумано, я надеюсь.

Другой способ концептуализировать это, что может иметь больше смысла в контексте цикла через каждый временной шаг (как это делает OP) и, как ближе к физической модели, заключается в отслеживании фазы на каждом этапе и определить новую амплитуду, учитывая как амплитуду, так и фазу от предыдущего шага, и объединить их с новой частотой. У меня нет терпения, чтобы этот запуск выполнялся в чистом Python, но в numpy решение выглядит так и получается аналогичным образом:

dt = 1./44100 
time = np.arange(0., 6., dt) 
f = 440. - 10*np.sin(2*math.pi*time*1.) # a 1Hz oscillation 
delta_phase = 2 * math.pi * f * dt 
phase = np.cumsum(delta_phase) # add up the phase differences along timeline (same as np.add.accumulate) 
wav = np.sin(phase) 
+0

Я отредактировал мое сообщение для ясности. Я использовал смелость для просмотра осциллограмм, но это было не очень полезно, потому что мы смотрим на скорость сжатия волны, а не на фактическое значение волны. Я знаю, что начальная синусоидальная волна, определяющая частоту, работает нормально, поэтому я думаю, что это концептуальная проблема. Я взял производную от моей функции, которая показала, что моя функция выборки меняет Ω (t), поэтому моя функция не только синусоидально. – twinlakes

+0

@twinlakes: Я понимаю, что вы имеете в виду, и мой предыдущий ответ был неправильным. Я полностью переписал его, и я думаю, что сейчас это правильно. – tom10

+0

спасибо. Я только что реализовал это, и он сработал. – twinlakes

Смежные вопросы