синусоида глиссандо от одного шага до другого в Numpy - PullRequest
4 голосов
/ 22 июня 2010

Я работал над программой, в которой мне нужно медленно и плавно изменять высоту синусоидальной волны с одной высоты на другую. Я могу получить массив частоты, на которой высота звука должна быть в любой данный момент (например, [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 ...]). Этот метод работает, однако он заставляет частоту превышать ожидаемую частоту, а затем снижаться. Я очень долго работал над этой проблемой и не смог добиться какого-либо прогресса в поиске более подходящего метода. Любой совет? Я был достаточно ясен в выражении моей дилеммы?

Спасибо.

Ответы [ 2 ]

7 голосов
/ 22 июня 2010

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

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

Вот полученная цифра с кодом ниже. Верхний показатель - это частота, в которой середина не имеет фазовой коррекции, а нижняя имеет непрерывно корректируемую фазу.

enter image description here

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()
0 голосов
/ 22 июня 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, я все еще изучаю язык.

...