用Pyaudi记录后的FFT归一化

2024-09-28 05:25:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个USB麦克风,有一个24位的ADC,但是,Pyaudio不允许24位编码,所以我用了16位。我希望这不是问题。话虽如此,我希望确保我应用汉宁窗口正确和规范化的FFT幅度正确

import numpy as np
import pyaudio
import matplotlib.pyplot as plt
from scipy.fftpack import fft
from scipy.io import wavfile # get the api
import wave

CHUNK = 2048
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 20480
RECORD_SECONDS = 34

p = pyaudio.PyAudio()

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

n = CHUNK
k=np.arange(n)
T = n/RATE     #reciprocal of freq resolution
frq = k/T      #k* freq resolution
frq = frq[range(int(n/2))]    # one side frequency range, for plotting
freq_resolution=RATE/n        #frequency resolution 
window=np.hanning(n)          #Hanning window 
num_frames=int(RATE*RECORD_SECONDS/CHUNK)

for i in range(0, num_frames):
    data = stream.read(CHUNK)
    decoded = np.frombuffer(data, dtype=np.int16)
    windowed=window*decoded      #apply Hanning window
    fft_decode=fft(windowed)/(len(decoded)/2)
    mags=np.absolute(fft_decode) 

    plt.ylim(top=2)
    plt.xlabel('Freq (Hz)')
    plt.ylabel('|Y(freq)|')
    plt.plot(frq), mags[range(int(n/2))],'b') 
    plt.pause(.001)
    plt.gcf().clear()
plt.close()

我用(样本数/2)标准化了幅值,因为我只对单边图感兴趣,我希望幅值与真实信号相对应。这意味着实际信号是5sin(2pi*3000*t),我希望在3000hz单边幅度图上的幅度是5。如果我只除以样本数,它会给我这个值的一半。是这样吗

但是,我也会打印出数据的最大值(已解码)和循环每次迭代的fft幅度的最大值,虽然它们大部分是相关的,但有时并不相关。我可能会得到一个很高的“解码”最大值(比如32000),但是fft的最大值并不接近这个值。这怎么可能

谢谢


Tags: importfftframesratenprangepltwindow

热门问题