I am trying to make a keyboard in python where every note's frequency is a ratio of the previous note but my output is strangely choppy for some reason. Here's an example of what I mean.
I'm using the sounddevice module and playing the sine wave through a callback function, here's what it looks like:
def callback(indata, outdata, frames, time, status): if status: print(status) global pressed if pressed: global pitched_sine global percent_thru_sine sine_len = len(pitched_sine) starting_index = int(sine_len * percent_thru_sine) out = np.concatenate((pitched_sine[starting_index:], pitched_sine[:starting_index - sine_len])) percent_thru_sine = (frames + int(percent_thru_sine * sine_len) + sine_len) % sine_len while percent_thru_sine > 1: percent_thru_sine -= 1 out = np.resize(out,frames) out = np.reshape(out,(1,frames)) outdata[:] = out.transpose() else: outdata[:] = None
I thought the choppiness was from the sine wave not starting where the previous one left off, like the end of one buffer having an amplitude of 1.0 immediately followed by the next buffer starting with 0.0, so I save the % through the last sine wave so I can start at that point in the new sine wave.
"pitched_sine" is generated when a keyboard button is pressed by pitch shifting a precalculated sine wave since I figured that calling np.sine() for every sample might have been causing a slowdown responsible for the hiccups in the output.
I also made sure that my pitch shift function or reshaping weren't resulting in weird results by making pyplots at every stage to check for strange looking sine waves but I didn't see any. Those were all the reasons I could think of, does anyone here have any ideas?
Here's the whole script if anyone wants to run it. If you do use the "-p" flag since the other stuff isn't relevant here. You'll also need this to be in the same folder and change the generated filename to "keys", press the spacebar while the program is running to play a note without its pitch changing.
EDIT: The chops correspond to either an "input overflow" or an "output underflow" even though the size of the output is always equal to the number of frames specified to the callback. According to this page I am using too much CPU time. Is there a way to optimize this?
EDIT 2: I figured it out, posted an answer but apparently I can't accept it for two days.