树莓派3项目:获取WAV文件FFT遇阻,寻求技术解决方案
Hey there, let's work through the FFT problem you're hitting with your Raspberry Pi 3 audio project. Looking at your code, there are a few clear issues that are preventing you from getting a valid FFT of your doorbell signal—let's break them down and fix it step by step.
First, Let's Spot the Code Problems
Your current code has two critical mistakes in how you're handling the WAV file data:
- You convert
input_data[1](the audio samples) to a float array but don't assign it to any variable—so that line does nothing. - The line
audio = input_data[...]is invalid syntax and doesn't correctly capture the audio samples from the WAV file's output.
Corrected Code with Explanations
Here's a revised version of your code that properly reads the audio, computes the FFT, and plots the result:
import scipy from scipy.io.wavfile import read from scipy.signal import hann from scipy.fftpack import rfft, rfftfreq import matplotlib.pyplot as plt import numpy as np # Read the WAV file: returns (sample_rate, audio_samples) sample_rate, raw_audio = read("/home/pi/Music/doorbell-1.wav") # Convert raw integer audio samples to normalized floats (range -1.0 to 1.0) # Most WAV files use 16-bit integers, so divide by 32768.0 audio = np.array(raw_audio, dtype=np.float32) / 32768.0 # Handle stereo audio: if the audio has 2 channels, convert to mono by averaging if len(audio.shape) > 1: audio = np.mean(audio, axis=1) # Apply Hann window to reduce spectral leakage window = hann(len(audio)) windowed_audio = audio * window # Compute real FFT (since audio is real-valued, rfft is more efficient) fft_result = rfft(windowed_audio) # Calculate corresponding frequency values for the FFT bins freqs = rfftfreq(len(windowed_audio), 1/sample_rate) # Compute magnitude spectrum (convert complex values to absolute magnitude) magnitude = np.abs(fft_result) # Plot the FFT result plt.figure(figsize=(10, 6)) plt.plot(freqs, magnitude) plt.xlabel("Frequency (Hz)") plt.ylabel("Magnitude") plt.title("FFT of Doorbell Audio Signal") plt.grid(True) plt.show()
Key Fixes & Notes
- Proper WAV Data Handling: We explicitly capture the
sample_rateandraw_audiofrom theread()function, then normalize the integer samples to floats—this is crucial because FFT works best with floating-point values. - Stereo to Mono Conversion: Many WAV files are stereo; averaging the channels ensures you're working with a single signal for your FFT.
- Windowing: Applying the Hann window reduces spectral leakage (artificial spread of energy across frequencies), which makes your FFT results more accurate.
- Frequency Axis Calculation: Using
rfftfreqautomatically computes the correct frequency bins for the real FFT, so you don't have to manually calculate them. - Magnitude Spectrum: The FFT returns complex numbers, so taking the absolute value gives you the magnitude of each frequency component.
Next Steps for Your Bandpass Filter
Once you have a valid FFT to verify your target signal's frequency range, you can use scipy.signal.butter or scipy.signal.firwin to design your bandpass filter, then apply it with scipy.signal.lfilter.
内容的提问来源于stack exchange,提问作者nanriat

