Play, Record, Process live audio ↔ Numpy

PyGame and PyAudio are two of the best currently maintained packages for playing audio from Python, including from Numpy arrays or streaming sources.

PyGame

PyGame is for building games and does much more than audio. I find PyGame to be very robust across a wide variety of systems (including embedded systems) to play audio from Python.

pip install pygame

uses pre-compiled .whl for Mac, Linux and Windows.

import numpy as np
import pygame
from time import sleep

fs = 8000 # Hz
T = 1. # second, arbitrary length of tone

# 1 kHz sine wave, 1 second long, sampled at 8 kHz
t = np.arange(0,T,1/fs)
x = 0.5 * np.sin(2*np.pi*1000*t)   # 0.5 is arbitrary to avoid clipping sound card DAC
x  = (x*32768).astype(np.int16)  # scale to int16 for sound card

pygame.mixer.pre_init(fs, size=-16, channels=1)
pygame.mixer.init()
sound = pygame.sndarray.make_sound(x)

sound.play()

sleep(0.01) # NOTE: Since sound playback is async, allow sound playback to start before Python exits

PyAudio

PyAudio uses PortAudio on Windows, Mac, and Linux to allow easy playback of Numpy arrays. If you find that you’re not able to install PortAudio, consider using PyGame instead of PyAudio.

import numpy as np
import pyaudio

fs = 8000 # Hz
T = 1. # second, arbitrary length of tone

# 1 kHz sine wave, 1 second long, sampled at 8 kHz
t = np.arange(0,T,1/fs)
x = 0.5 * np.sin(2*np.pi*1000*t)   # 0.5 is arbitrary to avoid clipping sound card DAC
x  = (x*32768).astype(np.int16)  # scale to int16 for sound card

# Sorry, PyAudio doesn't seem to have context manager
P = pyaudio.PyAudio()

stream = P.open(rate=fs, format=pyaudio.paInt16, channels=1, output=True)
stream.write(x.tobytes())

stream.close() # this blocks until sound finishes playing

P.terminate()

Linux

apt install portaudio19-dev
pip install pyaudio

Mac

brew install portaudio
pip install pyaudio

Windows

The Windows PyAudio wheels include PortAudio.

pip install pyaudio

Notes

Leave a Comment