I2S Input Downsampling

I am looking to sample multiple I2S input (MEMS microphones) for downstream processing on a laptop connected via serial. My processing is quite intensive and I've identified downsampling as one of the possible options to speed it up. My processing does fine even on 8kHz audio data. Is there a way for me to change the sampling rate of Teensy's I2S inputs? I understand that I could just naively index into the 44.1kHz audio data and get myself downsampled audio, but I'm wondering if there's a better way to do it.
 
Yes, a decimation filter. Just selecting every 6th sample or whatever will mean lots of aliasing all across the band of interest.
If the relevant ADC can work at 8k or 11.025k that's also an option (the device will have its own internal decimation filter if its a sigma-delta chip, which I2S ADCs generally are.
 
For clarification, I'm currently using digital-out microphones (Adafruit's SPH0645LM4H). I see in its datasheet that it already has a decimator in it, and I assume that the mic's sampling rate is (at least in part) controlled by the clock signal I pass into it. Since it's connected to an I2S clock pin on the Teensy, is there a way to control that clock frequency? Or am I going down the wrong path here? Could simple array indexing make sense if I've already got a digital signal?
 
It must be clocked at 2.048MHz to 4.096MHz, meaning it can handle 44.1kSPS and 48kSPS, not a low rate though. So its decimation filter is limiting to 20kHz basically. You'd have to take those samples and further decimate.
 
I understand that I could just naively index into the 44.1kHz audio data and get myself downsampled audio, but I'm wondering if there's a better way to do it.

Downsampling is indeed the way, since those mics operate over a fairly limited range. The hardware simply can not give you a very low sample rate.

To repeat what MarkT already said, you must low pass filter the audio data before downsampling. Fortunately Teensy 4.x is plenty fast enough to implement digital filters. You can find a few in the audio library. They might take a little work to come up with the taps or coefficients / number of stages for a filter response you want, but actually implementing them is pretty simple with the design tool and example code.

Many people have gone down the path you mentioned "just naively index into the 44.1kHz audio data". If you do this without first low pass filtering, you'll get horribly bad results. The reason is because sampled audio data can only represent sounds up to 1/2 the sample rate. So if you just take every 5th sample for 8.82 kHz sample rate, you must first filter away everything higher than 4.4 kHz. Since filters have limited roll off rates, this inevitable trade-off involves losing some of the audio somewhat below 4.4 kHz and maybe not fully getting rid of frequencies higher than 4.4 kHz.

Aliasing is a hard concept. If you search, you'll probably turn up tons of highly academic (heavy on equations, light on explanations) material about Nyquist sampling theory. The simple no-math concept is any frequencies you have higher than 4.4 kHz don't just go away when you downsample. They remain, but are (might as well be magically) transformed into other frequencies between 0 to 4.4 kHz. Usually the resulting sound is of very poor quality, depending on how much of the original material was higher than 4.4 kHz before you downsampled.

Many, many people have gone down a no-filtering path with naive wishful thinking, almost always based only on how easy discarding data feels and how hard filtering seems. On Teensy 4.x, you have plenty of CPU power to low pass filter. You just need to put a little thought into how many biquad stages or FIR taps and maybe use online tools to compute the coefficients to get the filter response you need.
 
Back
Top