PyGame, PyAudio and PySoundDevice are three of the best currently maintained packages for playing audio from Python, including from Numpy arrays or streaming sources. For these examples, we will use this common sinewave-generating code in a Numpy array.
import numpy as np 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 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.
python -m pip install pygame
.whl for Mac, Linux and Windows.
import pygame from time import sleep 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
The PyAudio and PySoundDevice packages are PortAudio based.
apt install portaudio19-dev python -m pip install pyaudio
brew install portaudio python -m pip install pyaudio
- Windows: PyAudio wheels include PortAudio.
python -m pip install pyaudio
PySoundDevice has the simplest syntax of these three Python audio play/record packages.
sounddevice.play(x,fs) # releases GIL sleep(1) # NOTE: Since sound playback is async, allow sound playback to finish before Python exits
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 pyaudio # 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()
Python Numpy arrays could be played back using Octave/Matlab
python -m pip install oct2py
HOWEVER, there is currently a limitation of Octave and Oct2Py, in that Octave 4.2.1
exist() does not work for classes.
So this is a “future working” method.
from oct2py import Oct2Py with Oct2Py() as oc: a = oc.audioplayer(x,fs) oc.play(a)