2
$\begingroup$

I have a streaming audio signal that I am recording in real time. To make the explanation easy, say the signal that I receive is calibrated and has a sampling frequency, $F_s = 44100\textrm{ Hz}$.

I am then finding the Sound Pressure Level of this signal. For this purpose, I get a frame of audio data of t seconds.

Then, RMS Sound Pressure Level (dB) is given by: $$ \rm Amplitude_{RMS} = \sqrt{mean\left(frame ^2\right)} $$

This gives the instantaneous RMS of a $t$-second frame of audio. Then, to find a $\textrm{ dB}$ level, $$ L_p = 20\log_{10}\left(\rm Amplitude_{RMS}\right) $$

Things get tricky here with the definitions of 'Fast' or 'Slow' sound pressure level. As this post points out, for time-weighted exponential average, I created a low-pass filter with a real pole at $1/\tau$ (where $\tau= 125\textrm{ ms}$ for 'fast' or $1\textrm{ s}$ for 'slow')

τ = 0.125; %fast
[b a] = bilinear(1, [1 1/τ], Fs);
frame_filtered = filter(b, a, frame.^2);
L_fast = 20*log10(sqrt(mean(frame_filtered)));

The IEC 61672 specifies the time weightings to be Fast and Slow for determining the speed at which the instrument responds to changing noise levels.

  • How does this work for digital audio?
  • Does it mean that the analysis needs to be performed on a fixed frame of data?
  • For this particular example, this frame would be $t\cdot F_s$ samples?

    Slow: 1*44100 = 441000 samples
    Fast: 0.125*44100 ~= 5513 samples

  • If so, is it true that I would need to know in advance whether I need fast or slow levels?

$\endgroup$
  • 3
    $\begingroup$ this is about what we call "meter ballistics" and has existed long before digital audio. the frames of data are not fixed in time, but are fixed relatively to the current sample, which i will call "$x[n]$". this low-pass filtering of the RMS amplitude is really a moving average or a weighted moving average (with exponential weighting). now, whether you need fast or slow really simply depends on how fast you need the virtual "needle" of your meter to move. $\endgroup$ – robert bristow-johnson Jul 31 '17 at 20:53
  • $\begingroup$ @robertbristow-johnson Correct me if I am wrong, size of frame of data does not matter. As long as the τ of the Low Pass Filter is 0.125, based on definition, it will give me the fast level? The way currently I am implementing this is not a moving average. I am taking a frame of data, finding the RMS/fast/slow levels, and then moving onto next frame (not next sample) of data. So, for 10 seconds of audio, with a frame size of 1 second, I get 10 SPL output values - one for each frame. Similarly, for a frame size of 125 ms, I get 80 (=10/0.125) SPL output values $\endgroup$ – Arnav Mendiratta Jul 31 '17 at 21:17
  • 1
    $\begingroup$ strictly speaking, for exponential weighting, the size of your data is from the present sample to forever ago. if it were a sliding average instead (with equal weighting) the size of your data would define the meter ballistic speed. $\endgroup$ – robert bristow-johnson Jul 31 '17 at 21:42
  • 1
    $\begingroup$ @robertbristow-johnson is the audio-expert here but afaics in this mode you are just computing the RMS of a frame (a block indeed) and converting that into dB SPL, then moving onto the next frame, where frame size depends on fast-slow response timing. But you have no sliding window here. What's your purpose of computing dB SPL? For a simulated analog Vu-meter, you should mimic the behaviour of sliding window to some extent; not necessaily one sample jump per computation but reasonably smooth jumps with overlapping frames (unless they are already short enough) $\endgroup$ – Fat32 Jul 31 '17 at 23:13
  • $\begingroup$ yeah, i wasn't paying attention until the OP pointed it out. $\endgroup$ – robert bristow-johnson Jul 31 '17 at 23:56
0
$\begingroup$

By "time weighting" in acoustics we are applying an RC (resistor–capacitor) circuit to a time signal.

See: RC circuit on Wikipedia

The time constant for FAST is 0,125 s and 1 s for SLOW.

You can also apply this digitally on your time signal by using my code below - it is basically a exponential moving average filter. I think you understand the steps by just looking at the comments in the code below.

public class FilterTimeWeighting {

private int nBands = 29; //number of bands
private float initValue;

FilterTimeWeighting() {
    initValue=0;
}

/**
 * Apply the LAmax RC-filter on the signal. Valid for fsamp=44100 Hz.
 * Returns the signal in Volts after applying filter.
 * 
 * //y(n)=a*y(n-1)+(1-a)*x(n)
 *
 * 
 *
 * @param signalIn
 * @return
 */
public float[] applyLmaxFilter(float[] signal) {

    int n_samples = signal.length;

    float[] x_signal = new float[n_samples];
    float[] y_signal = new float[n_samples];
    float[] ret_signal = new float[n_samples];


    //Square the signal
    for (int i_sample = 0; i_sample < n_samples; i_sample++) {
        x_signal[i_sample] = signal[i_sample] * signal[i_sample];
    }

    //Exponential moving average parameters
    float tau=0.125f;
    float fs=44100f;
    float alpha=tau/(1f/fs+tau);

    //for the first sample 
    y_signal[0] = initValue*alpha+(1-alpha)*x_signal[0];

    //for the rest of the samples
    for (int i_sample = 1; i_sample < n_samples; i_sample++) {
        y_signal[i_sample] = y_signal[i_sample-1]*alpha+(1-alpha)*x_signal[i_sample];
    }

    //remember last sample for next time step;
    initValue=y_signal[n_samples-1];

    //Square root
    for (int i_sample = 0; i_sample < n_samples; i_sample++) {
        ret_signal[i_sample] = (float) Math.sqrt(y_signal[i_sample]);
    } 

    return ret_signal;
}

}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.