Thursday, October 22, 2015

Play a list of WAV files with PyAudio

By Vasudev Ram




While looking at various Python libraries, I remembered PyAudio, which I had blogged about here earlier:

PyAudio and PortAudio - like ODBC for sound

This time I thought of using it to play a list of WAV files. So I wrote a small Python program for that, adapting one of the PyAudio examples. Here it is, in the file pyaudio_play_wav.py:
'''
Module to play WAV files using PyAudio.
Author: Vasudev Ram - http://jugad2.blogspot.com
Adapted from the example at:
https://people.csail.mit.edu/hubert/pyaudio/#docs
PyAudio Example: Play a wave file.
'''

import pyaudio
import wave
import sys
import os.path
import time

CHUNK_SIZE = 1024

def play_wav(wav_filename, chunk_size=CHUNK_SIZE):
    '''
    Play (on the attached system sound device) the WAV file
    named wav_filename.
    '''

    try:
        print 'Trying to play file ' + wav_filename
        wf = wave.open(wav_filename, 'rb')
    except IOError as ioe:
        sys.stderr.write('IOError on file ' + wav_filename + '\n' + \
        str(ioe) + '. Skipping.\n')
        return
    except EOFError as eofe:
        sys.stderr.write('EOFError on file ' + wav_filename + '\n' + \
        str(eofe) + '. Skipping.\n')
        return

    # Instantiate PyAudio.
    p = pyaudio.PyAudio()

    # Open stream.
    stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
        channels=wf.getnchannels(),
        rate=wf.getframerate(),
                    output=True)

    data = wf.readframes(chunk_size)
    while len(data) > 0:
        stream.write(data)
        data = wf.readframes(chunk_size)

    # Stop stream.
    stream.stop_stream()
    stream.close()

    # Close PyAudio.
    p.terminate()

def usage():
    prog_name = os.path.basename(sys.argv[0])
    print "Usage: {} filename.wav".format(prog_name)
    print "or: {} -f wav_file_list.txt".format(prog_name)

def main():
    lsa = len(sys.argv)
    if lsa < 2:
        usage()
        sys.exit(1)
    elif lsa == 2:
        play_wav(sys.argv[1])
    else:
        if sys.argv[1] != '-f':
            usage()
            sys.exit(1)
        with open(sys.argv[2]) as wav_list_fil:
            for wav_filename in wav_list_fil:
                # Remove trailing newline.
                if wav_filename[-1] == '\n':
                    wav_filename = wav_filename[:-1]
                play_wav(wav_filename)
                time.sleep(3)

if __name__ == '__main__':
    main()
Then I ran it as follows:

$ python pyaudio_play_wav.py chimes.wav

$ python pyaudio_play_wav.py chord.wav

$ python pyaudio_play_wav.py -f wav_file_list.txt

where wav_file_list.txt contained these two lines:

chimes.wav
chord.wav
Worked okay and played the specified WAV files. I also ran it a few times with test cases that should trigger errors - the error cases that the current code handles. This worked okay too. You can use one or more WAV files to try out the program. Other than modules in the Python stdlib, the only dependency is PyAudio, which you can install with pip. - Enjoy.

- Vasudev Ram - Online Python training and programming

Signup to hear about new products and services I create.

Posts about Python  Posts about xtopdf

My ActiveState recipes

No comments: