Проблема связана с подразумеваемым изменением фазы, а также с изменением частоты. Короче говоря, когда вы вычисляете ответ относительно каждой точки на временной шкале, важно отметить, что фаза колебаний будет различной для каждой частоты в каждый момент времени (за исключением начальной точки, где они все одинаковы). Поэтому перемещение между частотами подобно перемещению между различными фазами. Для случая перехода между двумя отдельными частотами это можно исправить для 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()
Обратите внимание, что диапазон частоты колебаний возрастает (как вы изначально слышали). Применяя коррекцию, связанную с выше, дает:
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)
Который гораздо ближе к тому, что было задумано, я надеюсь.
Другой способ концептуализировать это, что может иметь больше смысла в контексте цикла через каждый временной шаг (как это делает 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)
Я отредактировал мое сообщение для ясности. Я использовал смелость для просмотра осциллограмм, но это было не очень полезно, потому что мы смотрим на скорость сжатия волны, а не на фактическое значение волны. Я знаю, что начальная синусоидальная волна, определяющая частоту, работает нормально, поэтому я думаю, что это концептуальная проблема. Я взял производную от моей функции, которая показала, что моя функция выборки меняет Ω (t), поэтому моя функция не только синусоидально. – twinlakes
@twinlakes: Я понимаю, что вы имеете в виду, и мой предыдущий ответ был неправильным. Я полностью переписал его, и я думаю, что сейчас это правильно. – tom10
спасибо. Я только что реализовал это, и он сработал. – twinlakes