23

how can I read real-time audio into numpy array and use matplotlib to plot ?

Right Now I am recording audio on an wav file then using scikits.audiolab.wavread to read it into an array. Is there a way I could do this directly in realtime?

Ada Xu
  • 953
  • 4
  • 14
  • 31

4 Answers4

32

You can use PyAudio to record audio and use np.frombuffer to convert it into a numpy array.

import pyaudio
import numpy as np
from matplotlib import pyplot as plt

CHUNKSIZE = 1024 # fixed chunk size

# initialize portaudio
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=44100, input=True, frames_per_buffer=CHUNKSIZE)

# do this as long as you want fresh samples
data = stream.read(CHUNKSIZE)
numpydata = np.frombuffer(data, dtype=np.int16)

# plot data
plt.plot(numpydata)
plt.show()

# close stream
stream.stop_stream()
stream.close()
p.terminate()

If you want to record stereo instead of mono, you have to set channels to 2. Then you get an array with interleaved channels. You can reshape it like this:

frame = np.frombuffer(data, dtype=numpy.int16)       # interleaved channels
frame = np.stack((frame[::2], frame[1::2]), axis=0)  # channels on separate axes
Frank Zalkow
  • 3,850
  • 1
  • 22
  • 23
  • Thanks. I've used `alsaaudio` instead of `pyaudio` in my solution. Is there a difference between the two? – Ada Xu Jul 28 '14 at 17:51
  • 2
    I think `alsaaudio` is Linux only whereas `PyAudio` provides [`PortAudio`](http://www.portaudio.com/)-bindings and works on multiple platforms. – Frank Zalkow Jul 29 '14 at 07:05
  • Hello @FrankZalkow, could you please have a look at my question - https://stackoverflow.com/questions/53292811/convert-alsaaudio-to-pyaudio Thanks – Arun Nov 14 '18 at 04:51
  • Can you show how to parse two channels into a shaped numpy array? – Petrus Theron Apr 21 '19 at 09:52
22

There is a library called PyAudio. You can use it to record in real-time. Plus with the help of numpy.fromstring() and numpy.hstack(), you can get the desired output. Please note that the following snippet is for MONO-CHANNEL.

import pyaudio
import numpy

RATE=16000
RECORD_SECONDS = 2.5
CHUNKSIZE = 1024

# initialize portaudio
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, input=True, frames_per_buffer=CHUNKSIZE)

frames = [] # A python-list of chunks(numpy.ndarray)
for _ in range(0, int(RATE / CHUNKSIZE * RECORD_SECONDS)):
    data = stream.read(CHUNKSIZE)
    frames.append(numpy.fromstring(data, dtype=numpy.int16))

#Convert the list of numpy-arrays into a 1D array (column-wise)
numpydata = numpy.hstack(frames)

# close stream
stream.stop_stream()
stream.close()
p.terminate()

This is a tested code. It should work as charm. In order to check if your recorded data is correctly available in numpydata, you can add this following snippet after the previous code.

import scipy.io.wavfile as wav
wav.write('out.wav',RATE,numpydata)

These lines will write your numpydata into "out.wav". Play the file to check the data.

PS: This is my first response in StackOverflow. Hope it helps.

Nickil Maveli
  • 29,155
  • 8
  • 82
  • 85
stitchesguy90
  • 373
  • 4
  • 10
0

This answer is similar to the first answer here, but I have included missing part of plotting the Audio Data.

import pyaudio
import wave
import numpy as np
import noisereduce as nr

#This library helps us in plotting the  audio
import matplotlib.pyplot as plt 

def plotAudio2(output):
        fig, ax = plt.subplots(nrows=1,ncols=1, figsize=(20,4))
        plt.plot(output, color='blue')
        ax.set_xlim((0, len(output)))
        plt.show()

CHUNK = 22050
FORMAT = pyaudio.paFloat32
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 20

p = pyaudio.PyAudio()

stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

print("* recording")

frames = []


for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)
    data_sample = np.frombuffer(data, dtype=np.float32)

    print("data sample")
    plotAudio2(data_sample)

stream.stop_stream()
stream.close()
p.terminate()

I have tested above code snippet, this worked for me perfectly fine.

Note: This code snippet was tested in Windows, and matplotlib might have some issue in MacOS (I am not sure though)

Ananth Kamath
  • 528
  • 6
  • 13
-1
import librosa
file = 'audio/a1.wav'
signal, _ = librosa.load(file)
print(type(signal))
erptocoding
  • 305
  • 3
  • 5