pythonaudiosimpleaudioengine

How do I stop Simpleaudio from playing a file twice simulaneously?


I am using simpleaudio in a text-based adventure game. I am using Python 3. In my main loop, I want to achieve this: play a short audio clip, and once it finishes, start playing the same audio clip again. My problem is, that I cannot figure out how to make Simpleaudio do this.

I have read all of the API documentation to no avail. I have tried many different things regarding loops, and none of them work.

import simpleaudio as sa

def audio(audiofile):
    filename = "/Users/*********/Desktop/Programming/Python Files/Adventure Game/Audio Files/" + audiofile
    wave_obj = sa.WaveObject.from_wave_file(filename)
    play_obj = wave_obj.play()

A = True
while True:
audio("openingtune.wav")
clear_screen()
firstinput = input("> ")
user_input1(firstinput)

# I didn't include the other functions because they're not relevant to this. 

Note: the "while true" loop refreshes every so often (after input has been taken, and output has been given). I have no idea how to do this: once the song has finished playing one time, it should start over at the same point.


Solution

  • Contrary to the suggestions, simpleaudio doesn't play the audio on the main thread. Per the docs..

    The module implements an asynchronous interface, meaning that program execution continues immediately after audio playback is started and a background thread takes care of the rest. This makes it easy to incorporate audio playback into GUI-driven applications that need to remain responsive.

    The while loop should simply check if the thread has completed and play the audio again if it has.

    import simpleaudio as sa
    
    
    class AudioPlayer:
        def __init__(self):
            self.play_obj = None
    
        def play(audiofile):
            filename = "/Users/*********/Desktop/Programming/Python 
                        Files/Adventure Game/Audio Files/" + audiofile
            wave_obj = sa.WaveObject.from_wave_file(filename)
            self.play_obj = wave_obj.play()
        
        def is_done():
            if self.play_obj:
                return not self.play_obj.is_playing()
            return True
    
    player = AudioPlayer()
    while True:
        clear_screen()
        if player.is_done():
            player.play("openingtune.wav")
        ...
    

    If you're continuously playing the same file you might want to consider just passing the file string to constructor once and for all. Strings are immutable, so the string in the player.play() call is created and passed by copy on every iteration of the loop, which is nuts if it's always the same string.