I'm try to produce a tone that transitions linearly between a list of arbitrary frequencies with respect to time. I'm using scipy.signal to create waves that transition between pairs of frequencies, then concatenating them. When the frequencies are round numbers and relatively far from each other this works. When the numbers are close together or aren't as nice I get pops between each transition.
What is causing these pops, why only in the first case and not the other two, and what can I do to fix it? (Or if there's a better/easier way to do what I'm trying to do, what is it?)
Any thoughts would be very much appreciated.
from scipy.signal import sweep_poly
import numpy
import sounddevice
sample_rate = 44100.0
time = 1.0
amplitude = 10000
sounddevice.default.samplerate = sample_rate
freq_list = [100, 200, 100, 200]
#freq_list = [100.05,200.21,100.02,200.65,100.16]
#freq_list = [100,101,102,103]
#get samples for each segment
samples = numpy.arange(sample_rate * time) / sample_rate
#make all the different segments
wave_list = []
for i in range(len(freq_list)-1):
wave_list.append(amplitude * sweep_poly(samples, [float(freq_list[i 1])-float(freq_list[i]),float(freq_list[i])]))
#join them together
wave = numpy.concatenate(wave_list)
#convert it to wav format (16 bits)
wav_wave = numpy.array(wave, dtype=numpy.int16)
sounddevice.play(wav_wave, blocking=True)
CodePudding user response:
My comment was correct. The problem was that when I made a new wave it always started at its peak, which didn't necessarily line up with the old wave, resulting in discontinuities:
I fixed this by setting the phase offset parameter of sweep_poly to (180/math.pi)*math.acos(prev_point/amplitude)
where prev_point
was the last point in the previous sine wave.
Unfortunately since sine isn't one-to-one sometimes I got waves where the values matched, but the slopes didn't:
My fix for this was to check if the signs of the slopes matched, and if they didn't, slowly increase the offset until they did, then continue slowly increasing the offset until the discontinuity was small (<10). I'm sure this isn't the nicest or most mathematically satisfying way to solve this, but it works well enough for me. Now I have beautiful (pretty close to) continuously differentiable waves.