0

First of all I'm pretty new to this library and I don't really understand everything. With the help of the internet I managed to get this code snippet working. This code basically plays an audio file(.wav to be specific). The problem is that it only plays once; I want the audio file to loop until I set the is_looping variable to False.

import pyaudio
import wave


class AudioFile:
    chunk = 1024

    def __init__(self, file_dir):
        """ Init audio stream """
        self.wf = wave.open(file_dir, 'rb')
        self.p = pyaudio.PyAudio()
        self.stream = self.p.open(
            format=self.p.get_format_from_width(self.wf.getsampwidth()),
            channels=self.wf.getnchannels(),
            rate=self.wf.getframerate(),
            output=True
        )

    def play(self):
        """ Play entire file """
        data = self.wf.readframes(self.chunk)
        while data != '':
            self.stream.write(data)
            data = self.wf.readframes(self.chunk)

    def close(self):
        """ Graceful shutdown """
        self.stream.close()
        self.p.terminate()

is_looping = True
audio = AudioFile("___.wav")
audio.play()
audio.close()

I tried doing something like this, but it still didn't work:

is_looping = True
audio = AudioFile("___.wav")
while is_looping:
    audio.play()
audio.close()
CozyCode
  • 484
  • 4
  • 13
  • Does this answer your question? [How to loop-play an audio with pyaudio?](https://stackoverflow.com/questions/47513950/how-to-loop-play-an-audio-with-pyaudio) – Tomerikoo Apr 11 '21 at 14:12
  • I saw that question too, but I still couldn't figure it out, – CozyCode Apr 11 '21 at 14:14
  • What's wrong with a simple `while is_looping: audio.play()`? – Tomerikoo Apr 11 '21 at 14:16
  • @Tomerikoo it doesn't work for some reason – CozyCode Apr 11 '21 at 14:27
  • So please [edit] the question to include your best attempt as a [mre] and explain what's wrong with it – Tomerikoo Apr 11 '21 at 14:54
  • When you reach the end of your input file, you have to reset the file pointer back to the beginning if you want to repeat. At the start or end of your `play` method, do a `self.wf.rewind()` – RufusVS Apr 11 '21 at 16:33

1 Answers1

0

I couldn't find a way to loop the audio using my code, but I found a code in the internet that does exactly what I wanted it to do. Here's the link: https://gist.github.com/THeK3nger/3624478

And here is the code from that link:

import os
import wave
import threading
import sys

# PyAudio Library
import pyaudio

class WavePlayerLoop(threading.Thread):
    CHUNK = 1024

    def __init__(self, filepath, loop=True):
        """
        Initialize `WavePlayerLoop` class.
        PARAM:
            -- filepath (String) : File Path to wave file.
            -- loop (boolean)    : True if you want loop playback.
                                   False otherwise.
        """
        super(WavePlayerLoop, self).__init__()
        self.filepath = os.path.abspath(filepath)
        self.loop = loop

    def run(self):
        # Open Wave File and start play!
        wf = wave.open(self.filepath, 'rb')
        player = pyaudio.PyAudio()

        # Open Output Stream (based on PyAudio tutorial)
        stream = player.open(format=player.get_format_from_width(wf.getsampwidth()),
                             channels=wf.getnchannels(),
                             rate=wf.getframerate(),
                             output=True)

        # PLAYBACK LOOP
        data = wf.readframes(self.CHUNK)
        while self.loop:
            stream.write(data)
            data = wf.readframes(self.CHUNK)
            if data == b'':  # If file is over then rewind.
                wf.rewind()
                data = wf.readframes(self.CHUNK)

        stream.close()
        player.terminate()

    def play(self):
        """
        Just another name for self.start()
        """
        self.start()

    def stop(self):
        """
        Stop playback.
        """
        self.loop = False

You just need to add something like this outside the class and it should work:

player = WavePlayerLoop("sounds/1.wav")
player.play()
CozyCode
  • 484
  • 4
  • 13
  • If you read my comment to your original question, you would see that I mentioned the `rewind` method, which is the important difference between this code and yours. – RufusVS Apr 11 '21 at 17:37
  • Oh ok now I get what you meant. Yeah you're right. – CozyCode Apr 12 '21 at 12:28