Spectre fréquence et RPI4

dongle usb micro

pip3 install pyalsaaudio
176 pip3 install matplotlib
178 pip3 install scipy

#!/usr/bin/python3

# display sound spectral view with scipy FFT and matplotlib
#   here sound source is the system microphone with ALSA (channel 1)

from collections import deque
import struct
import sys
import threading
import alsaaudio
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
from scipy.fftpack import fft

import time,datetime

# some const
# 44100 Hz sampling rate (for 0-22050 Hz view, 0.0227ms/sample)
SAMPLE_FREQ = 44100
# 66000 samples buffer size (near 1.5 second)
#NB_SAMPLE = 66000
NB_SAMPLE = 100000

f=open('data.txt','a')

class Sampler(threading.Thread):
    def __init__(self, cardindex=-1):
        # init thread
        threading.Thread.__init__(self)
        self.daemon = True
        # init ALSA audio
        self.inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, cardindex=cardindex)
        # set attributes: Mono, frequency, 16 bit little endian samples
        self.inp.setchannels(1)
        self.inp.setrate(SAMPLE_FREQ)
        self.inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
        self.inp.setperiodsize(512)
        # sample FIFO
        self._s_lock = threading.Lock()
        self._s_fifo = deque([0] * NB_SAMPLE, maxlen=NB_SAMPLE)

    def get_sample(self):
        with self._s_lock:
            return list(self._s_fifo)

    def run(self):
        while True:
            # read data from device
            l, data = self.inp.read()
            if l > 0:
                # extract and format sample (normalize sample to 1.0/-1.0 float)
                raw_smp_l = struct.unpack('h' * l, data)
                #print(data)
                #raw_smp_l=data
                smp_l = (float(raw_smp / 32767) for raw_smp in raw_smp_l)
                    self._s_fifo.extend(smp_l)
            else:
                print('sampler error occur (l=%s and len data=%s)' % (l, len(data)))


def plot_anim(i):
    # read samples
    samples = spr.get_sample()
    # compute FFT
    y_freq = fft(samples)
    # frequency axe in Hz:
    # 0.0 to max frequency (= sample rate/2), number of step is half of NB_SAMPLE
    x_freq = np.linspace(0.0, SAMPLE_FREQ // 2, NB_SAMPLE // 2)

    # level axe at each frequency:
    # yf between 0.0 and 1.0 for every xf step
    y_level = 1.0 / (NB_SAMPLE / 2) * np.abs(y_freq[0:NB_SAMPLE // 2]) * 100
    # wipe and redraw
    ax1.clear()
    ax1.set_xlabel('Frequency (Hz)')
    ax1.set_xlim(0,1000)
    ax1.set_ylabel('Level (%)')
    ax1.plot(x_freq, y_level, 'b', lw=2)
    # find higher level frequency
    index_max = np.argmax(y_level)
    
    freq_max = x_freq[index_max]
    if  freq_max > 600 and freq_max < 800 :
        f.write(str(datetime.datetime.utcnow().strftime("%Y%m%d %H:%M:%S"))+','+str(freq_max)+','+str(y_level[index_max])+'\n')
        f.flush()


    print('max level at f=%i Hz (lvl=%.02f %%)' % (freq_max, y_level[index_max]))
    #print('sample: max %.04f, min %.04f' % (max(samples), min(samples)))

if __name__ == '__main__':
    # start sound sampler thread
    spr = Sampler(2)
    spr.start()
    # init a dynamic plotter
    fig, (ax1) = plt.subplots(nrows=1, ncols=1)
    fig.canvas.set_window_title('Sound spectral view')
    ani = animation.FuncAnimation(fig, plot_anim, interval=1000)
    plt.show()

https://www.szynalski.com/tone-generator/