ESP32 with INM441 I2S microphone.

mave25
Posts: 4
Joined: Thu Jun 27, 2024 9:21 am

ESP32 with INM441 I2S microphone.

Postby mave25 » Thu Oct 10, 2024 9:32 am

Hi,

how do I get data from INMP441 I2S microphone, every tutorial I have seen are using getting only 16 bit whereas the microphone is 24 bit and also most of the codes available online seem to calculate the average of received data. I dont understand it, can someone throw some light on this ? thanks.

ow_birds
Posts: 13
Joined: Sun Jan 26, 2025 7:11 pm

Re: ESP32 with INM441 I2S microphone.

Postby ow_birds » Sat Apr 26, 2025 4:34 pm

The INMP441 I2S interface delivers 24 bits of data in the high order bits of a 32 bit word. This is fixed and cannot be configured otherwise. You need to shift the 32 bit word right by 8 bits, then you will have your 32 bit sample.
Note this is a signed integer.

Code below is converting the sample to 16 bits.

char audio_buffer[samples * bytesPerInputSample];
int32_t *input_buffer;
input_buffer = (int32_t *)&audio_buffer;
uint16_t *output_buffer; // the output buffer, uint16_t required by file write
output_buffer = (uint16_t *)&audio_buffer;
for (int i = 0; i < samples; i++) {
int32_t val32 = input_buffer >> 8; // shift out the empty byte - this is a signed int, the shift will preserve the sign
int16_t val16 = (int16_t)val32; // convert 32 bit signed to 16 bit signed
output_buffer = (uint16_t)val16; // output buffer is unsigned
}

xenpac
Posts: 33
Joined: Sun Dec 08, 2019 1:20 am

Re: ESP32 with INM441 I2S microphone.

Postby xenpac » Sat Jan 10, 2026 1:39 pm

Just having the same problem.

yes, right-shift by 8 gives the proper 24bit.

just leaving it as is, gives amplification by 256.

however, inspecting the data, i do see, that the low-byte is not always 00, but sometimes C0 , so some artifacts going on.

hmm?? that is strange.



Also one should note that the I2S interface cannot really work in "mono".
left and right lane are always transmitted.

i2s_channel_read() will also always read both lanes from the I2S modul.

"mono" would mean, place only one audio signal on the left or the right channel of the I2S device and leave the other one connected to GND = 0.

We would like it the other way, that mono mode results in reading only the one active mono channel, thus halfing the datarate to the correct value of a mono channel.

suggestion to improve !?

ow_birds
Posts: 13
Joined: Sun Jan 26, 2025 7:11 pm

Re: ESP32 with INM441 I2S microphone.

Postby ow_birds » Sat Jan 10, 2026 5:58 pm

just leaving it as is, gives amplification by 256.
Why do you say that? Shifting the 24 bit value doesn't change it. Agreed, the signal is quite loud, my code has the ability to attenuate the value if necessary (configurable):

Code: Select all

// first, shift out the lower empty byte
int32_t val32 = input_buffer[i] >> 8; // shift out the empty byte - this is a signed int, the shift will preserve the sign
// we now need to reduce this to a 16 bit integer value, ensuring values are between -32,768 and 32,767
// but if we just reduce the high values we'll be clipping the sound, better to attenuate it (by experience)
      
// apply an attenuation factor if it sounds too high
val32 = val32 / ATTENUATION_FACTOR; // reduce the overall signal strength if requested
however, inspecting the data, i do see, that the low-byte is not always 00, but sometimes C0 , so some artifacts going on.
If the low order byte is unused, I don't see what it contains is unimportant. It could just be random data.
We would like it the other way, that mono mode results in reading only the one active mono channel, thus halfing the datarate to the correct value of a mono channel.
Surely if configured as mono, it only samples from the configured microphone.

Code: Select all

i2s_std_config_t std_cfg = {
		... .slot_cfg =  {
			.data_bit_width = I2S_DATA_BIT_WIDTH_32BIT, // INMP441 provides 24 bits of data, we have to use 32 bit and discard a byte
			.slot_mode = I2S_SLOT_MODE_MONO,
			.slot_mask = I2S_STD_SLOT_LEFT,   // L/R pin is connected to GND
		etc
I've not played with stereo recording, but my limited understanding is that in stereo mode, samples alternate from left/right, whereas in mono mode all the samples are from the single configured mic.

MicroController
Posts: 2661
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32 with INM441 I2S microphone.

Postby MicroController » Sun Jan 11, 2026 7:57 pm

just leaving it as is, gives amplification by 256.
Why do you say that?
Because a left-aligned 24-bit value in a 32-bit integer is numerically 'too big' by a factor of 2^8. Right-shifting by 8 bits scales it back into the correct 24-bit range. (Depends on how you look at the values though. You could say they're 32-bit values without data in the lowest bits, or that they're 24-bit values left-shifted by 8.)

To get the 16-bit signed value you want, you can either do

Code: Select all

int32_t sample32 = *(const int32_t*)&audiodata;
int16_t sample16 = sample32 >> 16;
or for example

Code: Select all

const int16_t* const samples16 = (const int16_t*)&audiodata;
for(unsigned i = 0; i < samplecnt; ++i) {
  int16_t sample16 = samples16[2*i + 1]; // ignore even indices, only consider the odd ones
  ...
}

ow_birds
Posts: 13
Joined: Sun Jan 26, 2025 7:11 pm

Re: ESP32 with INM441 I2S microphone.

Postby ow_birds » Mon Jan 12, 2026 8:26 am

Because a left-aligned 24-bit value in a 32-bit integer is numerically 'too big' by a factor of 2^8.
But it's not a 32 bit integer, yet. The original value is 24 bit, and the shift is just moving it into the correct position and making it a 32 bit value. It's not an arithmetic shift because the low order byte doesn't form part of the value.

Consider this: let's say the 24 bit value is 1, and we want to end up with this value as 32 bit integer also of 1. Shifting it >> 8 does this. Your mistake is viewing the low order byte as part of the sample value, which it isn't, so you're seeing the original value as 256.

MicroController
Posts: 2661
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32 with INM441 I2S microphone.

Postby MicroController » Mon Jan 12, 2026 9:26 am

Because a left-aligned 24-bit value in a 32-bit integer is numerically 'too big' by a factor of 2^8.
But it's not a 32 bit integer, yet.
It most definitely is. You may want to reconsider the equivalence between bit-shifting and multiplication/division.

(Btw, "arithmetic shift" is the term normally used for a sign-preserving right shift, as opposed to a "logical shift".)

More importantly, your original proposal

Code: Select all

int32_t val32 = input_buffer[i] >> 8; // shift out the empty byte - this is a signed int, the shift will preserve the sign
int16_t val16 = (int16_t)val32; // convert 32 bit signed to 16 bit signed
is wrong because it discards the most-significant 8 bits of the data.

ow_birds
Posts: 13
Joined: Sun Jan 26, 2025 7:11 pm

Re: ESP32 with INM441 I2S microphone.

Postby ow_birds » Tue Jan 13, 2026 8:19 am

We'll just have to agree to disagree about this.

In the actual code, I do check that the value will fit into a int16_t:

Code: Select all

// check for int16_t overflow
signal_overflow = signal_overflow || val32 < SHRT_MIN || val32 > SHRT_MAX;
signalMax = max(val32, signalMax);
signalMin = min(val32, signalMin);
That's partly what the attenuation factor is for (note the equivalence between bit-shifting and multiplication/division). If overflow occurs a warning is logged so that the attenuation can be increased if it becomes excessive, but the occasional overflow is acceptable if caused by a transient noise spike.

MicroController
Posts: 2661
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32 with INM441 I2S microphone.

Postby MicroController » Tue Jan 13, 2026 9:07 am

however, inspecting the data, i do see, that the low-byte is not always 00, but sometimes C0 , so some artifacts going on.
https://docs.espressif.com/projects/esp ... ndard-mode
Check for "Phillips" vs. "MSB" format. The mic seems to use "Phillips" format, and if you read in "MSB" format the data will appear right-shifted by one bit.

xenpac
Posts: 33
Joined: Sun Dec 08, 2019 1:20 am

Re: ESP32 with INM441 I2S microphone.

Postby xenpac » Sat Jan 17, 2026 1:15 pm

Code: Select all

int32_t val32 = input_buffer[i] >> 8; // shift out the empty byte - this is a signed int, the shift will preserve the sign
int16_t val16 = (int16_t)val32; // convert 32 bit signed to 16 bit signed
Assuming you inited the i2s to transport 32bit values, you will get 32bit values.
int16_t val16 = (int16_t)val32; // convert 32 bit signed to 16 bit signed...this will take the low-16bits of val32 to be put into val16!!
Check for "Phillips" vs. "MSB" format. The mic seems to use "Phillips" format, and if you read in "MSB" format the data will appear right-shifted by one bit.
I am using Philips format, still observe 0xdb in the lowbyte in times. but yeah..just zero it out.

My other concern is that the volume of the mics data is extremely low. So need to amplify.

Who is online

Users browsing this forum: Baidu [Spider] and 12 guests