|
|
@ -1,5 +1,6 @@ |
|
|
|
#!/usr/bin/env python3 |
|
|
|
#!/usr/bin/env python3 |
|
|
|
import numpy as np |
|
|
|
import numpy as np |
|
|
|
|
|
|
|
from functools import cache |
|
|
|
|
|
|
|
|
|
|
|
from cereal import messaging |
|
|
|
from cereal import messaging |
|
|
|
from openpilot.common.realtime import Ratekeeper |
|
|
|
from openpilot.common.realtime import Ratekeeper |
|
|
@ -10,7 +11,16 @@ RATE = 10 |
|
|
|
FFT_SAMPLES = 4096 |
|
|
|
FFT_SAMPLES = 4096 |
|
|
|
REFERENCE_SPL = 2e-5 # newtons/m^2 |
|
|
|
REFERENCE_SPL = 2e-5 # newtons/m^2 |
|
|
|
SAMPLE_RATE = 44100 |
|
|
|
SAMPLE_RATE = 44100 |
|
|
|
SAMPLE_BUFFER = 4096 # (approx 100ms) |
|
|
|
SAMPLE_BUFFER = 4096 # approx 100ms |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@cache |
|
|
|
|
|
|
|
def get_a_weighting_filter(): |
|
|
|
|
|
|
|
# Calculate the A-weighting filter |
|
|
|
|
|
|
|
# https://en.wikipedia.org/wiki/A-weighting |
|
|
|
|
|
|
|
freqs = np.fft.fftfreq(FFT_SAMPLES, d=1 / SAMPLE_RATE) |
|
|
|
|
|
|
|
A = 12194 ** 2 * freqs ** 4 / ((freqs ** 2 + 20.6 ** 2) * (freqs ** 2 + 12194 ** 2) * np.sqrt((freqs ** 2 + 107.7 ** 2) * (freqs ** 2 + 737.9 ** 2))) |
|
|
|
|
|
|
|
return A / np.max(A) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_spl(measurements): |
|
|
|
def calculate_spl(measurements): |
|
|
@ -27,16 +37,8 @@ def apply_a_weighting(measurements: np.ndarray) -> np.ndarray: |
|
|
|
# Generate a Hanning window of the same length as the audio measurements |
|
|
|
# Generate a Hanning window of the same length as the audio measurements |
|
|
|
measurements_windowed = measurements * np.hanning(len(measurements)) |
|
|
|
measurements_windowed = measurements * np.hanning(len(measurements)) |
|
|
|
|
|
|
|
|
|
|
|
# Calculate the frequency axis for the signal |
|
|
|
|
|
|
|
freqs = np.fft.fftfreq(measurements_windowed.size, d=1 / SAMPLE_RATE) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Calculate the A-weighting filter |
|
|
|
|
|
|
|
# https://en.wikipedia.org/wiki/A-weighting |
|
|
|
|
|
|
|
A = 12194 ** 2 * freqs ** 4 / ((freqs ** 2 + 20.6 ** 2) * (freqs ** 2 + 12194 ** 2) * np.sqrt((freqs ** 2 + 107.7 ** 2) * (freqs ** 2 + 737.9 ** 2))) |
|
|
|
|
|
|
|
A /= np.max(A) # Normalize the filter |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Apply the A-weighting filter to the signal |
|
|
|
# Apply the A-weighting filter to the signal |
|
|
|
return np.abs(np.fft.ifft(np.fft.fft(measurements_windowed) * A)) |
|
|
|
return np.abs(np.fft.ifft(np.fft.fft(measurements_windowed) * get_a_weighting_filter())) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Mic: |
|
|
|
class Mic: |
|
|
|