24

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?

4 Answers 4

34

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
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. I've used alsaaudio instead of pyaudio in my solution. Is there a difference between the two?
I think alsaaudio is Linux only whereas PyAudio provides PortAudio-bindings and works on multiple platforms.
Hello @FrankZalkow, could you please have a look at my question - stackoverflow.com/questions/53292811/… Thanks
Can you show how to parse two channels into a shaped numpy array?
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.

3 Comments

Not bad for your first post :)
@deW1 Thanks for revising my answer and highlighting the terms. :)
@StitchesGuy90 I wish to plot the incoming audio data so that I get a real time graph of the audio is it possible.
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)

Comments

-1
import librosa
file = 'audio/a1.wav'
signal, _ = librosa.load(file)
print(type(signal))

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.