I'm trying to create a simple controllable and non-blocking looping wavplayer. The following class created using simpleaudio works, however, there is a brief pause and noticeable popping/snapping noise between each loop of the audio. I'm honestly not sure what's causing it and I'm not sure how I could fix it either than using a different audio module entirely. Any suggestions?
import simpleaudio as sa
from threading import Thread
class WavPlayer(Thread):
def __init__(self,filepath,loop=False):
self.loop = loop
self.wav_obj = sa.WaveObject.from_wave_file(filepath)
self.play_obj = None
Thread.__init__(self)
def run(self):
self.play_obj = self.wav_obj.play() #initialize play buffer and play once
while self.loop is True:
if not self.play_obj.is_playing():
print("played again")
self.play_obj = self.wav_obj.play()
def terminate(self):
print("music terminated")
self.play_obj.stop()
self.loop = False
self.join()
main_loop = WavPlayer("main_loop.wav",True)
menu_loop = WavPlayer("menu.wav",True)
main_loop.start()
z = input("Enter to end theme looping")
main_loop.loop = False
z = input("Enter to terminate music")
main_loop.terminate()
print("playing next song")
menu_loop.start()
cont = ''
while cont != 'n':
cont = input("continue testing non-blocking? enter n to stop: ")
menu_loop.terminate()
I encounterded the same problem while programming a tuner that generates an infinitely long note from a limited number of samples (I used pyaudio
, and a tuning note is a very simple sound, which makes the pops very obvious, but the remedy much easier).
If you loop a wave object like:
** **
* * *
* * *
* * *
** **
... you'll hear a pop because of the large difference between the last and the first samples. Dropping a few samples until the last and the first sample match will eliminate the pops (simpleaudio
allows you to read the samples into numpy
arrays which you then can truncate (slightly) until the first and last samples match).
Cutting at zero crossings is a special case of this, see this discussion. Of course, some sound libraries may already truncate your samples at zero crossings.
Before you take the trouble to extend your program to convert your samples to numpy
arrays and truncating them, you first could try using a sound editor like Audacity and do it by hand, and then listen to the result.