86

I want to create "heart rate monitor" effect from a 2D array in numpy and want the tone to reflect the values in the array.

1

8 Answers 8

112

You can use the write function from scipy.io.wavfile to create a wav file which you can then play however you wish. Note that the array must be integers, so if you have floats, you might want to scale them appropriately:

import numpy as np
from scipy.io.wavfile import write

rate = 44100
data = np.random.uniform(-1, 1, rate) # 1 second worth of random samples between -1 and 1
scaled = np.int16(data / np.max(np.abs(data)) * 32767)
write('test.wav', rate, scaled)

If you want Python to actually play audio, then this page provides an overview of some of the packages/modules.

Sign up to request clarification or add additional context in comments.

5 Comments

Question - the data/np.max(np.abs(data)) - am I right that this is normalising to 1/-1 before scaling, such that if the max is 0.8, it would be scaled up?
Yes (it isn't required though).
Thanks. Shouldn't that be * 32768? It is a signed 16 bit.
Please add explanation that 44100 is the sample rate.
@huon What if I have numpy array of a wav file and want to generate text from the array?
46

For the people coming here in 2016 scikits.audiolab doesn't really seem to work anymore. I was able to get a solution using sounddevice.

import numpy as np
import sounddevice as sd

fs = 44100
data = np.random.uniform(-1, 1, fs)
sd.play(data, fs)

4 Comments

I actually tried and scikits.audiolab worked on my Ubuntu 16.04 + python 2.7 (anaconda 4.1.1). I just needed to sudo apt-get install libsndfile1-dev. And on the other hand, sounddevice doesn't work for me: nothing is played when I replace scikits.audiolab with sd.
no luck with python3, even with libsndfile1-dev installed, better luck with sounddevice
Thanks, works perfectly! sd.play(data, fs, blocking=True) to make the program wait until the sound is played.
pip install sounddevice
42

in Jupyter the best option is:

from IPython.display import Audio
wave_audio = numpy.sin(numpy.linspace(0, 3000, 20000))
Audio(wave_audio, rate=20000)

3 Comments

This is THE solution I have been looking for for years!
not yet supported in vscode/jupyter. see github.com/spatialaudio/python-sounddevice/issues/…
Supported in VScode now
17

I had some problems using scikit.audiolabs, so I looked for some other options for this task. I came up with sounddevice, which seems a lot more up-to-date. I have not checked if it works with Python 3.

A simple way to perform what you want is this:

import numpy as np
import sounddevice as sd

sd.default.samplerate = 44100

time = 2.0
frequency = 440

# Generate time of samples between 0 and two seconds
samples = np.arange(44100 * time) / 44100.0
# Recall that a sinusoidal wave of frequency f has formula w(t) = A*sin(2*pi*f*t)
wave = 10000 * np.sin(2 * np.pi * frequency * samples)
# Convert it to wav format (16 bits)
wav_wave = np.array(wave, dtype=np.int16)

sd.play(wav_wave, blocking=True)

3 Comments

It works fine with Python 3. If you use the above code in a script, you should make sure to use blocking=True, otherwise the script will exit without finishing playback.
I did that, in fact. Updated answer. Thanks!
sounddevice has a problem on Mac OS X, you need to give your application [which one?] the entitlement com.apple.security.cs.allow-unsigned-executable-memory
16

In addition, you could try scikits.audiolab. It features file IO and the ability to 'play' arrays. Arrays don't have to be integers. To mimick dbaupp's example:

import numpy as np
import scikits.audiolab

data = np.random.uniform(-1,1,44100)
# write array to file:
scikits.audiolab.wavwrite(data, 'test.wav', fs=44100, enc='pcm16')
# play the array:
scikits.audiolab.play(data, fs=44100)

2 Comments

scikits.audiolab is not available for python(32) +Windows(64)+Hardware(64) bit configuration and thus I guess not so useful to me
It's not available in Python 3, and it has been a long time since last update.
6

Another modern and convenient solution is to use pysoundfile, which can read and write a wide range of audio file formats:

import numpy as np
import soundfile as sf

data = np.random.uniform(-1, 1, 44100)
sf.write('new_file.wav', data, 44100)

Comments

3

PyGame has the module pygame.sndarray which can play numpy data as audio. The other answers are probably better, as PyGame can be difficult to get up and running. Then again, scipy and numpy come with their own difficulties, so maybe it isn't a large step to add PyGame into the mix.

http://www.pygame.org/docs/ref/sndarray.html

Comments

1

Not sure of the particulars of how you would produce the audio from the array, but I have found mpg321 to be a great command-line audio player, and could potentially work for you.

I use it as my player of choice for Anki, which is written in python and has libraries that could be a great starting place for interfacing your code/arrays with audio.

Check out:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.