2015-01-23 2 views
2

Это мой первый опыт работы со звуком, и я пытаюсь объединить синусоиды произвольных (управляемых данными) частот и не могу избавиться от щелчков, вызванных разрывами между грехами.конкатенатные синусоиды различной частоты

Я читал this thread, делая частоту функцией фазы, чтобы увеличить частоту волны линейно, но не мог понять, как ее адаптировать для произвольно меняющихся частот.

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

def audio_map(data): 
p=[] 
phase = 0 
for point in data: 
    if point[0]<0: 
     f=100*np.abs(point[0]) 
    else: 
     f=100*point[0] 
#Do something with the phase to shift the sinusoid below??? 
p=np.concatenate((p,np.sin((4*np.pi*f/sampling_rate)*np.arange(sampling_rate*np.pi/(16))))) 
    phase=f*np.pi/16 

return p 

Спасибо за помощь!

ответ

3

EDIT

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

p = np.concatenate((p, np.sin((2 * np.pi * f/sampling_rate) * np.arange(total_tone_time * sampling_rate) + phase))) 
phase += 2 * np.pi * f * total_tone_time 
phase %= 2 * np.pi # strip off full cycles to avoid overflow 

Где

  • total_tone_time является длительность текущего сигнала воспроизводимого
  • sampling_rate измеряется в герцах (образцов в секунду)

Цель добавления в фазе между каждым термином является сохранение полученной сложной кривой непрерывной, которые могли бы помочь избежать каких-либо хлопков в форме волны. Если вы ничего не слышите, убедитесь, что выведенные частоты находятся в диапазоне слышимости: http://en.wikipedia.org/wiki/Audio_frequency

Я попробовал бы вышеупомянутое предложение прежде, чем попробовать, о чем я расскажу ниже, которые идут намного глубже в отверстие кролика.

/EDIT

Не эксперт, но я думаю, что вы говорите о разрыве вызывает щелчок может быть правильным. Если это так, вы можете быстро ускорить постепенное исчезновение/исчезновение амплитуды на стыке, чтобы избежать щелчка.

Вот некоторые другие возможности, о которых я могу думать.

Модель и Fit

Как вы выборки частоты? Они отбираются в определенное время, поэтому вы можете получать частоту в зависимости от времени? Если это так, вы можете попытаться совместить кривую с точками (что является нетривиальной задачей), а затем взять синус интеграла от расчетной кривой:

Sin [2 * PI * Integral [freq (time), время, 0, current_time]]

Численное интегрирование

в качестве альтернативы подгонки кривой, если частота дискретизации частота достаточно быстро, чтобы аппроксимировать гладкую кривую, вы можете использовать значения непосредственно в числовой интеграл.В приведенном ниже примере я предполагаю, что ваши данные находятся в формате [[freq0, time0], [freq1, time1], ...] и что выборки частоты равномерно распределены со временем с той же скоростью, для выборки выходного сигнала.

PI = 3.14159 
waveform = [0] * len(data) 
phase = 0 
time_delta = data[1][1] - data[0][1] 
for i, (f, t) in enumerate(data): 
    if i != 0: 
     phase += 0.5 * (f + last_f) * time_delta 
     waveform[i] = sin(2 * PI * phase) 
    last_f = f 
    phase %= 2 * PI 

Обратите внимание, что для выше я использую метод трапеции, описанные здесь: http://www.mathworks.com/help/matlab/ref/trapz.html#bua4lsr

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

Добавить Ramp

Наконец, если вы конкатенации частоты от случайной выборки, без прямой зависимости от времени, вы можете добавить частоты пандус для преодоления разрыва.

Вы можете попробовать линейные:

sin(PI * [(f2 - f1)/time_frame * t ** 2 + 2 * f1 * t]) 

или экспоненциальной:

sin(2 * PI * time_frame * f1 * exp(log(f2/f1) * t/time_frame)/log(f2/f1)) 

Где

  • time_frame является продолжительность вы хотите пандус к последнему
  • т выбрана начинаться с нуля и заканчиваться на time_frame
  • f1 является частота остаться
  • f2 является частота вводимой
+0

Большое спасибо за обстоятельный ответ !! Я многому научился со своего поста. Для других, кто читает это, после дня, когда я играю, я наконец понял, что могу просто обеспечить, чтобы мои конкатенации проходили при нулевых переходах (т. Е. /, Что целое кратное периодов объединяется для каждого синусоида), но все выше, чем у Меридиуса окажутся полезными в последующих итерациях моей работы. [например. Я использовал что-то вроде p = np.concatenate ((p, np.sin (((4 * np.pi * f/sampling_rate)) * np.arange (50 * sampling_rate/(4 * f)))))] – user1262799

+0

Потрясающие! Я рад, что мог бы помочь, это был крутой вопрос :) – Meridius