I2S Microphone, Getting data but it not making sense, data biased up 255000?

Using the SPH0645LM4H-B with an MKR 1010 brd.
I get data streams from the device but the data is biased up about 25500 (dec).
When I use the serial plotter I do see waves but the waves are biased up about 255000 (dec)
So I ran the serial out (binary) with out >>14.
See the binary out below.

Then I ran the serial out (binary) with the >>14.
The 8 LSB seem to vary.

I'm probably not reading the I2S coming out of the chip correctly.
Any pointers what I'm doing wrong?

// start I2S at 40 kHz with 32-bits per sample
if (!I2S.begin(I2S_PHILIPS_MODE, 40000, 32)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing

unsigned int sample=0;
sample=I2S.read();
// sample>>14:

0111 1001 0011 1101 0100 0000 0000 0000
0111 1001 0011 1111 0100 0000 0000 0000
0111 1001 0100 0010 1100 0000 0000 0000
0111 1001 0100 0100 0000 0000 0000 0000
0111 1001 0100 0000 0000 0000 0000 0000
0111 1001 0011 1010 0000 0000 0000 0000
0111 1001 0100 1000 1100 0000 0000 0000
0111 1001 0100 1001 0100 0000 0000 0000

Then I shift right 14 bits
Now this is a quiet room, but I’m get values of 255000 and higher.
There seems to be a bias built in.

// start I2S at 40 kHz with 32-bits per sample
if (!I2S.begin(I2S_PHILIPS_MODE, 40000, 32)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing

unsigned int sample=0;
sample=I2S.read();
sample>>14:

0000 0000 0000 0011 1110 0101 0100 0001
0000 0000 0000 0011 1110 0101 0100 0101
0000 0000 0000 0011 1110 0101 0100 0011
0000 0000 0000 0011 1110 0101 0100 0001
0000 0000 0000 0011 1110 0101 0100 0101
0000 0000 0000 0011 1110 0101 0100 0111
0000 0000 0000 0011 1110 0101 0100 0100
0000 0000 0000 0011 1110 0101 0011 1111
0000 0000 0000 0011 1110 0101 0011 1110
0000 0000 0000 0011 1110 0101 0011 1110
0000 0000 0000 0011 1110 0101 0011 1101
0000 0000 0000 0011 1110 0101 0011 1110
0000 0000 0000 0011 1110 0101 0011 1110
0000 0000 0000 0011 1110 0101 0011 1100
This data stream is room quiet.

I would suggest spending some time understanding how they work. USB can carry digital audio is defined in 3 different classes named Class 1, 2 and 3.

Class 1 can send up to a maximum of 24-bit 96 kHz while Class 2 can support up to 24-bit 192 kHz. Class 3 simply uses less power and is less susceptible to jitter and data loss.

USB audio data transmits information as packets rather than a continuous stream of PCM audio (like much other digital audio transferring). USB requires a clock signal to keep everything in time and the choice of clock system is actually very important for USB audio.

USB audio utilized isochronous transfer mode for its real-time characteristics at the expense of error recovery.
Isochronous mode trades a fully guaranteed bandwidth and cyclic redundancy checking (CRC) of data transmission errors for the downside of there being no packet acknowledgement or retransmission in the event of an error.

Note: there are 3 sub-modes within isochronous mode:

Adaptive: the peripheral sink or source adapts to a potentially varying sample rate of the host.
Asynchronous: the sink or source determines the sample rate, and the host accommodates.
Synchronous: a fixed number of bytes is transferred to each SOF period. The audio sample rate is effectively derived from the USB clock.

USB Microphones As Audio Interfaces effectively connect to computers (or other digital devices) and act as their very own audio interfaces.

Here is a link to get you going, the above is derived from this link: How Do USB Microphones Work And How To Use Them – My New Microphone

Are you saying the I2S format is the same as USB?

USB audio is nothing to do with this thread.

From what I can see this microphone is using standard I2S mode and should be reading correctly
with I2S_PHILIPS_MODE.

The result value is not what I'd expect though.

You keep saying "sample>>14;" rather than "sample >>= 14;" - best to copy and paste code
verbatim, rather than produce typos to further confuse the issue.

You right shift by 14 of

0b01111001001111010100000000000000

claims to generate

0b00000000000000111110010101000001

Which both is a shift of 13 or is creating an extra 1 at the start.

I suspect your method of printing the values is flawed and your values are fine.
This may well be because you are using unsigned for sample values - I2S samples
are signed integers.

If so then the

0b00000000000000111110010101000001

would be from

0b11111001010100000100000000000000

Which is what you'd expect, a value "close" to 0. Of course when doing this
correctly with signed quantities your shift would give

0b11111111111111111110010101000001

Using binary is hard on the brain, hexadecimal is worth learning ASAP.

BTW you mention both 25500 and 255000. Slips like this in programming will give nothing
but grief...

Thanks for the reply.
I am using sample>>=14;

I'll digest the rest later tonight.
The unsigned vs signed is a good catch.

Yes, I should brush up on my hex, too many years in management. hahahahh

rjclarke61:
Using the SPH0645LM4H-B ....

I'm not a fan of that device as its timing violates the I2S specification. I've confirmed that with both the datasheet and oscilloscope measurements. You can read my screed about it here:

Well that explains a lot. I'm finding it very difficult to get decent tech support on the SPH0645LM4H.
It seems to take forever to settle down, but I'm wondering if the non-compliance to the I2L spec that maybe the issue.

Sucks I just ordered 10 circuit boards laid out for this and I'm on a 10/9/2020 deadline (it's 10/3).

Thanks for the post, I really appreciate it.

gfvalvo:
I'm not a fan of that device as its timing violates the I2S specification. I've confirmed that with both the datasheet and oscilloscope measurements. You can read my screed about it here:
I2S Microphone (SPH0645LM4H-B) | Teensy Forum

FWIW, when I tested this microphone, it did indeed have a strong DC offset. I had to use a software high-pass filter to get rid of the DC part. Code and a little FFT demo video here:

I presume the high-pass filter isn't on-board the microphone die itself due to lack of room - ADC chips
often include one but they don't need to spend silicon real-estate on a MEMS diaphragm structure, or
high gain analog amplifiers. An RC filter down to 20Hz isn't practical on silicon due to the very limited capacitance available.

MarkT:
I presume the high-pass filter isn't on-board the microphone die itself due to lack of room

pjrc:
FWIW, when I tested this microphone, it did indeed have a strong DC offset. I had to use a software high-pass filter to get rid of the DC part.

Guess not.

rjclarke61:
Sucks I just ordered 10 circuit boards laid out for this and I'm on a 10/9/2020 deadline (it's 10/3).

Yea, sucks to cut metal prematurely.

Recommend an Invensense device like ICS-43434. If interested, there are several module makers on Tindie.

I did get the SPH0645LM4H to work goodly enough.

signed int for reading samples
shift sample >> 14
Digital Low Pass Filter to get rid of the DC bias. THIS WAS KEY.

So we can use the boards that just came in.
I'm thinking Rev B will be the ICS-43434

Thanks everyone for their help.

Bytheway, the documentation for the ICS-43434 is light years better than the SPH0645LM4H and the manufacturer has a lot of tech notes on general usage.

Some of which helped me with the SPH.

Digital Low Pass Filter to get rid of the DC bias

A low pass filter will not remove DC bias, but a high pass will. Are you sure you have that right?

Digital Low Pass Filter to get rid of the DC bias. THIS WAS KEY.

I assume the bias is intentional and a fixed-known digital value? In that case you can simply SUBTRACT it out. :wink:

When you have an unknown or uncontrolled/unexpected DC bias/offset caused by a cheap soundcard, HIGH-pass filtering (or a similar algorithm) is a common solution. (DC is zero-Hz so a high-pass filter removes it.)