Sounds in Python
Sounds in Python

Exploring Sound in Python

Python offers a plethora of possibilities for playing and recording sound. In this tutorial, we’ll guide you through various audio libraries, empowering you to explore the art of sound manipulation.

Diving into the basics, we’ll walk you through straightforward methods for both playing and recording sound. But that’s not all; we’ll also introduce you to advanced libraries that unlock additional functionalities, allowing you to wield the power of sound with just a few extra lines of code.

So, let’s embark on this exciting journey of Python audio programming, where creativity knows no bounds, and sound becomes your canvas! Get ready to immerse yourself in the world of music and audio with Python as your trusted companion. Let’s begin!

How to Play Audio Files?

In this comprehensive guide, we will explore a variety of Python libraries that cater to your audio playing needs. Whether you’re handling MP3s, WAV files, or NumPy arrays, these libraries will empower you to delve into the world of sound manipulation with ease.

Let’s kick off with the ever-simple playsound package, perfect for straightforward WAV or MP3 file playback. Its minimalist approach makes it a breeze to use for basic audio needs.

For a step up in versatility, consider simple audio. This gem not only handles WAV files and NumPy arrays but also offers convenient options to check the playback status of your files, giving you more control over your audio experience.

Windows users will find Winsound particularly useful, allowing WAV file playback and even speaker beeping, though it’s exclusive to the Windows platform.

For cross-platform capabilities, Python-sounddevice and PyAudio come to the rescue, providing bindings for the powerful PortAudio library. Both are excellent choices for playing WAV files across different operating systems.

Last but not least, we have pydub, which, when combined with Pyaudio and FFmpeg, opens the door to an extensive range of audio formats. With just a few lines of code, you can revel in the richness of audio possibilities.

Now you have a spectrum of options at your disposal, each library offering its unique strengths. So, let’s dive in.

What Is a Playsound Module?

Get ready to elevate your Python audio experience with the playsound module. This is a cross-platform module that opens the gateway to audio file playback.
playsound() is the only function that is contained in this library.
playsound harmonizes with both Python 2 and Python 3, ensuring a seamless experience across different versions. In the documentation, it is written that this library works well with mp3 and wav files, but it is also possible to use for other file formats.

The command to install playsound package

pip install playsound

playsound() function have one or two arguments and looks like this:

playsound("/filepath/song.mp3")

or

playsound("/filepath/song.mp3" , 0)

where “/filepath/song.mp3” stands for a local file path or a URL and the second argument stands for block(default True) that can also be set to False for running asynchronously.

Playsound in Python for MP3 Format

#import playsound module
from playsound import playsound

playsound("/filepath/song.mp3")

Playsound in Python for WAV Format

There is no difference between code that is used to play MP3 or WAV format.

#import playsound module
from playsound import playsound

playsound("/filepath/song.wav")

What Is a Simpleaudio Library?

Simpleaudio stands out as a versatile and cross-platform library, offering seamless playback of mono and stereo WAV files without any dependencies. Employing the provided code snippet allows users to effortlessly play a WAV file, ensuring the script waits until the file completes playback before terminating.

import simpleaudio as sa

file = 'song.wav'
wave_obj = sa.WaveObject.from_wave_file(file)
play_obj = wave_obj.play()
play_obj.wait_done()

Delving into the intricacies of WAV files, they encompass a stream of bits capturing the raw audio data alongside metadata in the RIFF (Resource Interchange File Format) format.
In the realm of CD recordings, the gold standard involves storing each audio sample, which corresponds to an individual audio datapoint relating to air pressure, as a 16-bit value at a rate of 44100 samples per second.

To optimize file size, certain recordings, such as those containing human speech, can be suitable with a lower sampling rate, for instance, 8000 samples per second. However, this does come at the cost of potentially compromised representation for higher sound frequencies.

Both bytes objects and NumPy arrays encompass a sequence of data points, facilitating sound playback at a specified sample rate. When working with bytes objects, each sample is stored as a pair of 8-bit values, while NumPy arrays employ 16-bit values to represent individual samples.

An essential distinction between these data types is their mutability: bytes objects are immutable, whereas NumPy arrays are mutable, rendering the latter ideal for generating sounds and engaging in more intricate signal processing tasks.

The brilliance of simpleaudio lies in its ability to play NumPy and Python arrays and bytes objects through the utilization of simpleaudio.play_buffer(). Before running the ensuing example, ensure the presence of NumPy on your system, and install it effortlessly by executing pip install NumPy from your console.

#import modules
import numpy as np
import simpleaudio as sa

seconds = 3 # Note duration
frequency = 440 # Note will be 440 Hz
sample_rate = 44100 # samples per second

t = np.linspace(0, seconds, int(sample_rate * seconds), False) 

# 440 Hz sine wave
wave = np.sin( 2 * np.pi * frequency * t)

# Convert to 16-bit data
audio = (wave * 32767).astype(np.int16)

# Start playback
play_obj = sa.play_buffer(audio, num_channels=1, bytes_per_sample=2, sample_rate=sample_rate)

play_obj.wait_done()

Feel free to explore the endless possibilities unlocked by simpleaudio, making audio playback and manipulation an enjoyable and seamless experience across different platforms.

Winsound Library and How It Works

Introducing winsound, a versatile module designed exclusively for Windows users, allowing playback of ‘.wav’ music files directly from your system. For those on different operating systems, fret not, as the ‘PlaySound’ module comes to the rescue.

The best part? No installation is required! Winsound module is preinstalled and readily available.

Keep in mind that Winsound is limited to playing “.wav” files only. However, if you have other file formats you’d like to play, you can turn to the PlaySound module to handle those for you.

winsound.Beep(frequency, duration) function allows you to beep your speakers.

The first parameter, “frequency,” dictates the pitch of the sound and is measured in hertz (Hz), ranging from 37 to 32,767. This gives you the flexibility to create different tones based on your needs. Next, the “duration” parameter comes into play, allowing you to control how long the sound persists in milliseconds.

For example, you can beep a 250 Hz tone for 100 milliseconds with the following code:

import winsound

#beep sound
winsound.Beep(250,100)

In addition to using the Winsound module, another method at your disposal is PlaySound(). This function also requires two arguments: the file path of the sound you wish to play and a flag that allows you to apply various conditions to the audio playback. For example, you can use SND_LOOP to create a continuous loop of the sound or SND_NOSTOP to prevent interruptions during playback.

import winsound

winsound.PlaySound("/filepath/song.wav", window.SND_LOOP)

Also, there is MessageBeep() function that allows you to play different types of beeps based on the parameter you pass. In this example, we’ll use MB_OK to play the OK sound.

Here’s an example:

import winsound

winsound.MessageBeep(winsound.MB_OK)

Do Developers Need Python-Sounddevice?

Python-sounddevice is a Python library that empowers developers to work with audio streams and devices effortlessly. Whether you want to record audio from a microphone, play sound through speakers, process real-time audio data, or simply manipulate audio files, Python-sounddevice provides an intuitive interface to accomplish these tasks with ease.

One of the key features that sets Python-sounddevice apart is its ability to access audio devices directly, bypassing the need for external programs or dependencies. This direct access to the sound hardware enables low-latency audio I/O operations, making it suitable for real-time audio applications like audio synthesis, live audio processing, and interactive audio programs.

To enable the playback of WAV files and open them as NumPy arrays, you must have NumPy and soundfile installed on your system.

import sounddevice as sd
import numpy as np

# Create a sine wave for demonstration
frequency = 440 # note frequency in Hz
seconds = 3 # seconds
t = np.linspace(0, seconds, int(duration * 44100), endpoint=False)
audio = 0.5 * np.sin(2 * np.pi * frequency * t)

# Play the audio
sd.play(audio, samplerate=44100)
sd.wait()

Pydub

While pydub has the capability to open and save WAV files independently, to experience audio playback, it’s essential to have an audio playback package installed. The preferred choice is simpleaudio, offering robust functionality, though PyAudio, FFplay, and AVPlay stand as viable alternative options.

from pydub import AudioSegment 
import pyaudio

audio = AudioSegment.from_wav('song.wav')
play(audio)

For seamless playback of various audio formats, like MP3 files, it’s essential to have either FFmpeg or Libav installed on your system.

By utilizing FFmpeg-python, you gain access to FFmpeg bindings, which can be installed via pip:

pip install ffmpeg-python

Once FFmpeg is set up, making playback for an MP3 file necessitates just a minor modification to our previous code snippet:

from pydub import AudioSegment
from pydub.playback import play

audio = AudioSegment.from_mp3('song.mp3')
play(audio)

With the help of the AudioSegment.from_file(filename, filetype) method, you have the flexibility to play audio files of any format supported by FFmpeg. For instance, you can effortlessly play a WMA file using the following code snippet:

audio = AudioSegment.from_file('sound.wma', 'wma')

Expanding its capabilities beyond sound playback, Pydub offers a plethora of functionalities. You can easily save audio in various file formats, slice audio segments, calculate audio file lengths, apply fade-in and fade-out effects, and even add crossfades between tracks.

A particularly interesting feature is AudioSegment.reverse(), which generates a mirrored copy of the AudioSegment, playing the audio backward.

PyAudio

Harnessing the power of PyAudio, you gain access to seamless Python bindings for PortAudio v19, a cross-platform audio I/O library. PyAudio empowers you to effortlessly leverage Python for audio playback and recording across multiple platforms, including GNU/Linux, Microsoft Windows, and Apple macOS.

import pyaudio
import wave

file = 'song.wav'

# chunk size
chunk = 1024 

wf = wave.open(file, 'rb')

p = pyaudio.PyAudio()

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

# Read data
data = wf.readframes(chunk)

# Play the sound
while data != '':
stream.write(data)
data = wf.readframes(chunk)

# Close and terminate the stream
stream.close()
p.terminate()

You may have noticed that working with sounds using PyAudio can be more intricate compared to other libraries you’ve encountered earlier. As a result, if your goal is to simply play a sound effect in your Python application, PyAudio might not be your immediate choice.

However, PyAudio offers the advantage of providing finer control at a low level, allowing you to access and modify parameters for both input and output devices, as well as check your CPU load and input/output latency.

Moreover, PyAudio empowers you to interact with audio using callback mode, wherein a callback function is triggered when there is a demand for new data during playback or when new data is available for recording. These capabilities make PyAudio an excellent choice when your audio requirements extend beyond basic playback functionality.

How to Record Audio In Python?

In the realm of audio recording with Python, you have two prominent libraries at your disposal: python-sounddevice and PyAudio. The former facilitates audio recording into NumPy arrays, while the latter accomplishes the same task with bytes objects. Leveraging the capabilities of the SciPy and wave libraries, you can efficiently store these recorded data as WAV files for further use.

import sounddevice as sd
from scipy.io.wavfile import write

seconds = 3 # Duration of recording
sample_rate= 44100 # Sample rate

recording = sd.rec(int(seconds * sample_rate), samplerate=sample_rate, channels=2)
sd.wait()
write('output.wav', sample_rate, recording)

PyAudio

To initiate audio recording, an alternative approach involves writing to the .Stream:

import pyaudio
import wave

chunk = 1024
format = pyaudio.paInt16
channels = 2
sample_rate = 44100
duration = 5
output = "recorded_audio.wav"

p = pyaudio.PyAudio()

stream = p.open(format=format,
channels=channels,
rate=sample_rate,
input=True,
frames_per_buffer=chunk)

print("Recording...")

frames = []

# Store data
for i in range(0, int(sample_rate / chunk * duration)):
data = stream.read(chunk)
frames.append(data)

# Stop and close the stream
stream.stop_stream()
stream.close()
p.terminate()

# Save the recorded data
wf = wave.open(output, 'wb')
wf.setnchannels(channels)
wf.setsampwidth(p.get_sample_size(format))
wf.setframerate(sample_rate)
wf.writeframes(b''.join(frames))
wf.close()

How to Save and Convert Audio in Python?

In a previous instance, it was demonstrated how the scipy.io.wavfile module proves useful for saving NumPy arrays as WAV files. However, there’s more to explore with the Wavio module, as it facilitates seamless conversion between WAV files and NumPy arrays. But what if you wish to store your audio in alternative formats? Fear not, for both Pydub and soundfile libraries come to your rescue! These powerful tools enable you to effortlessly read and write an extensive range of popular file formats, opening up new possibilities for your audio processing endeavors.

Wavio

Relying on the NumPy library, this module offers a seamless way to read WAV files as NumPy arrays while also allowing you to save NumPy arrays as WAV files.
When the time comes to store a NumPy array as a WAV file, you’ll find the function wavio.write() at your disposal. This handy feature ensures a smooth and efficient conversion process, giving you the flexibility to work with audio data in your desired format.

import numpy as np
import wavio

sample_rate = 44100 
seconds = 5 
frequency = 440
samples = np.arange(sample_rate * duration) / sample_rate
audio = np.sin(2 * np.pi * frequency * samples)

output = "output.wav"
wavio.write(output, audio, sample_rate, sampwidth=2)

Soundfile

Soundfile is a Python library that enables the reading and writing of various file formats, leveraging the capabilities of libsndfile. While it lacks audio playback functionality, it excels at audio conversion between formats like FLAC, AIFF, and some more uncommon audio types. For instance, if you wish to convert a WAV file to FLAC, the following code snippet can be employed:

import soundfile as sf

# Extract data from file 
data, sample_rate = sf.read('song.wav') 
# Save as FLAC file
sf.write('song.flac', data, sample_rate)

Pydub

Pydub offers extensive support for audio file formats, allowing you to save your audio in any format that is supported by FFmpeg. This encompasses a wide range of audio types commonly encountered in your everyday activities. For instance, the following code snippet demonstrates how you can effortlessly convert a WAV file to the popular MP3 format:

from pydub import AudioSegment

audio = AudioSegment.from_wav('song.wav')

audio.export('song.mp3', format='mp3')