синусоидальное глиссандо от одного шага к другому в Numpy

Я работаю над программой, в которой мне нужно медленно и плавно изменять высоту синусоиды с одной высоты на другую. Я могу получить массив частоты, с которой высота звука должна быть в любой момент (например, [440, 526,5, 634,2 794,8, 880], хотя и намного, намного длиннее), но, похоже, я не могу на самом деле применить эту частоту. к волне. Моя лучшая попытка:

numpy.sin(2*math.pi*x*freq/self.sample_rate)

где «freq» — это массив частот, а x — массив перечисления ([0,1, 2, 3, 4...]). Этот метод работает, однако он заставляет частоту подниматься выше ожидаемой частоты, а затем снова падать. Я работал над этой проблемой в течение очень долгого времени и не смог добиться какого-либо прогресса в поиске более подходящего метода. Любой совет? Достаточно ли ясно я выразил свою дилемму?

Спасибо.


person user252719    schedule 22.06.2010    source источник
comment
Вы хотите линейную развертку или логарифмическую развертку?   -  person endolith    schedule 19.03.2012


Ответы (2)


Проблема в том, что при переходе через частоты каждая частота фактически имеет различную фазу для данного времени. Когда вы прокручиваете эти фазы быстро и непрерывно, они управляют синусоидой с более высокой частотой (или более низкой также возможно).

Представьте, например, что вы изменили частоту мгновенно — для этого вам нужно было бы ввести фазовую коррекцию p_1 = p_0 + 2*pi*t*(f_0-f_1), чтобы фазы совпали в момент времени t. Поскольку вы делаете это маленькими шагами, вы также должны делать аналогичную фазовую коррекцию, причем каждая фазовая коррекция добавляется к предыдущей.

Вот получившийся рисунок с приведенным ниже кодом. Верхняя цифра — частота, средняя — без фазовой коррекции, нижняя — с непрерывно корректируемой фазой.

введите здесь описание изображения

from pylab import *

sample_rate = .001
f0, f1 = 10, 20
t_change = 2

times = arange(0, 4, sample_rate)

ramp = 1./(1+exp(-6.*(times-t_change)))
freq = f0*(1-ramp)+f1*ramp
phase_correction = add.accumulate(times*concatenate((zeros(1), 2*pi*(freq[:-1]-freq[1:]))))

figure()
subplot(311)
plot(times, freq)
subplot(312)
plot(times, sin(2*pi*freq*times))
subplot(313)
plot(times, sin(2*pi*freq*times+phase_correction))

show()
person tom10    schedule 22.06.2010
comment
Здорово. Я рад, что теперь он делает то, что вы хотите... и это был интересный вопрос. - person tom10; 23.06.2010

Мне нравится думать о частоте как о скорости, с которой вы проходите через свой звуковой образец - в данном случае это синусоида. Вот попытка кода Python сделать то, что вы хотите. Мы предполагаем, что метод freq() дает частоту как функцию времени. Для ваших целей это будет какая-то экспонента. Мы пытаемся заполнить предварительно выделенный список под названием wave.

index = 0
t = 0
while t < len(wave):
  wave[t] = math.sin(2*math.pi*index/sample_rate)
  t = t+1
  index = index + freq(t/sample_rate)

Извините за мой Python, я все еще изучаю язык.

person brainjam    schedule 22.06.2010