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