Python - Real-time high-pass filter (HPF) spectrum analyser is lagging

849 views Asked by At

I created a python coding that apply HPF to the input audio in real-time. It works just fine.

import pyaudio
import time
import numpy as np
from scipy.signal import firwin, firwin2, lfilter, freqz

WIDTH = 2
CHANNELS = 2
RATE = 44100

p = pyaudio.PyAudio()
f1 = 500/1000

def bytes_to_float(byte_array):
    int_array = np.frombuffer(byte_array, dtype=np.float32)
    return int_array

def float_to_bytes(float_array):
    int_array = float_array.astype(np.float32)
    return int_array.tostring()

def callback(in_data, frame_count, time_info, flag):
    signal = bytes_to_float(in_data)
    a = [1]
    b = firwin(129, f1, pass_zero=False)
    filtered= lfilter(b, a, signal)
    output = float_to_bytes(filtered)
return (output, pyaudio.paContinue)

stream = p.open(format=pyaudio.paFloat32,
                channels=CHANNELS,
                rate=RATE,
                output=True,
                input=True,
                stream_callback=callback)

stream.start_stream()

while stream.is_active():
    time.sleep(0.1)

stream.stop_stream()
stream.close()

p.terminate()

Now, I wanted to display the frequency spectrum of filtered audio. So, I edited the python coding above.

from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import time
import pyqtgraph as pg
import pyaudio
from scipy.signal import firwin, firwin2, lfilter, freqz

app = QtGui.QApplication([])
win = pg.GraphicsWindow(title="Basic plotting examples")
win.resize(1000,600)
win.setWindowTitle('pyqtgraph example: Plotting')
pg.setConfigOptions(antialias=True)

p6 = win.addPlot(title="Updating plot")
p6.setYRange(-100, 20)
curve = p6.plot(pen='y')

chunks = 1024

freq = np.linspace(1e-6, (chunks / 2), chunks, endpoint=True)

def bytes_to_float(byte_array):
    int_array = np.frombuffer(byte_array, dtype=np.float32)
    return int_array

def float_to_bytes(float_array):
    int_array = float_array.astype(np.float32)
    return int_array.tostring()

def update_freq_plot(x):
    global curve, freq
    h = 20 * np.log10(np.abs(np.fft.rfft(x, n=2 * chunks)[:chunks]))
    curve.setData(x=freq, y=h, clear=True)

def update():

    WIDTH = 2
    CHANNELS = 2
    RATE = 44100
    p = pyaudio.PyAudio()

    f1 = 500/1000

    def callback(in_data, frame_count, time_info, flag):
        signal = bytes_to_float(in_data)
        a = [1]
        b = firwin(129, f1, pass_zero=False)
        z = np.zeros(129 - 1)
        filtered, z = lfilter(b, a, signal, zi=z)
        update_freq_plot(filtered)
        output = float_to_bytes(filtered)
        return (output, pyaudio.paContinue)

    stream = p.open(format=pyaudio.paFloat32,
                channels=CHANNELS,
                rate=RATE,
                output=True,
                input=True,
                stream_callback=callback)

    stream.start_stream()


timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(20)

## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

I used this as a reference. When I run the coding, it does display the spectrum, but it is lagging. I'm using jupyter to run the coding.

I would like to ask how to improve my coding so that the lagging issue won't appear? Any help is much appreciated. Thank you.

0

There are 0 answers