I2S microphone (RX)

theronic
Posts: 3
Joined: Tue Mar 05, 2019 10:31 pm

Re: Megaphone example for ESP32-LYRATD-MSC

Postby theronic » Tue Mar 12, 2019 7:48 am

Hi BuddyCasino, I'm trying to get your megaphone example working on the ESP32-LYRATD-MSC, but I'm only getting silence. I've spent a few days trying to cross-correlate what's different in the get-started/player examples and the newer esp-avs-sdk, but I'm only getting silence. Do you perhaps have some pointers or code lying around for the LYRATD?
BuddyCasino wrote:
Thu Jul 13, 2017 11:25 am
You might want to take a look at my megaphone example.

BuddyCasino
Posts: 263
Joined: Sun Jun 19, 2016 12:00 am

Re: I2S microphone (RX)

Postby BuddyCasino » Tue Mar 12, 2019 8:56 am

Sorry no, I don't have a Lyra.

User avatar
fly135
Posts: 606
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: I2S microphone (RX)

Postby fly135 » Tue Mar 12, 2019 4:14 pm

felipeduque wrote:
Fri Feb 01, 2019 2:27 pm
Now, I've only managed to get perfect I2S sound for sampling rate 8 kHz. From my experience with other I2S drivers (for H3 boards), it's a matter of proper clock handling. Probably some I2S master clock is too slow - maybe it didn't expect any sampling faster than 8 kHz? Anyway, I did not delve into it.
Just for reference I've had no problems capturing at 16Khz. However, If you try to capture and send in the same thread I would expect to have performance issues.

I just ordered a LyraT from China. Expect to get it in a couple weeks.

John A

pataga
Posts: 73
Joined: Sat Aug 12, 2017 5:53 am

Re: I2S microphone (RX)

Postby pataga » Fri Nov 15, 2019 7:25 am

Hi,

Just in case you guys didn't see this already

https://hackaday.io/project/162059-stre ... microphone

It seems the SPH0645 timing is incompatible with the ESP32 i2s peripheral. The data transitions on the rising edge of BCK, just when the ESP32 is sampling the data.

They ended the post by saying the INMP441 mems mic is compatible with the ESP32, showing a captured data sample, here the BCK rising edge is safely in the middle of the sample data.

I just got an INMP441 breakout board from aliexpress, and can confirm BuddyCasino's megaphone code example in this thread works without any modification. INMP441 LRCK grounded for left channel only. I used a MAX98357a breakout board for output with default board settings : SD and gain pins floating, (L+R)/2 output.

But I need to record mic samples myself to see what sort of dynamic range I am getting.

Tnarain5
Posts: 7
Joined: Fri Nov 29, 2019 11:22 am

Re: I2S microphone (RX)

Postby Tnarain5 » Wed Jan 01, 2020 1:15 pm

Thanks all for your support!

Tnarain5
Posts: 7
Joined: Fri Nov 29, 2019 11:22 am

Re: I2S microphone (RX)

Postby Tnarain5 » Mon Feb 10, 2020 7:24 am

Hi guys,
i tried reading and writing at the same time using two different i2s_config, (using as an amplifier) for output im having real_rate 502 and required rate 8000 causing echo and noise, can you help !!

sapparatus
Posts: 5
Joined: Sun Nov 01, 2020 4:36 pm

Re: I2S microphone (RX)

Postby sapparatus » Thu Dec 31, 2020 4:25 am

I follow this instruction and I can record the sound and write as WAV file to SD and put it on another machine to playback (sort of), except one problem - that I think it may have nothing to do with ESP32 and just general question.

sph0645 is connected with i2s initialization. so I read buf with:

i2s_read(I2S_NUM_0, buf, buf_len, &bytes_read, portMAX_DELAY);

since the data in buf is int32_t, and the 18 bit precise, I thought I can just do:
  1.                         for (int i = 0; i < buf_len ; i++)
  2.                         {
  3.                       [Codebox=text file=Untitled.txt]
int32_t tmpdata = buf;
tmpdata >>= 14;
((int16_t*) buf) = tmpdata;
}[/Codebox]
Then I thought the result buf[buf_len] would be 16bit after shifting 14bit and lost 2bit, with total of buf_len (same data size as original). It turns out this is only half is right, meaning if
(1) I write buf[ buf_len / 2 ], the data is good, except it is only half size - so every sound is faster (or drop off half).
(2) if I write entire buf[buf_len], then half of them is still correct as in (1), but the other half, is the same data repeat buf_len/2 times:
[good] [bad] [good] [bad]....

In addition, the data seems to be offset on the negative side even though it seems have no affect on the results.

I am reading google but have hard time to understand this - one thing particularly bothers me is why 1, 2, 3, ....buf_len/2, which does not match [good][bad][good][bad]..., not 1, 3, 5, ...buf_len

khanware
Posts: 2
Joined: Tue May 04, 2021 3:51 pm

Re: I2S microphone (RX)

Postby khanware » Tue May 04, 2021 4:03 pm

I am trying to connect I2S mic to ESP32 with no luck. (using SPH0645LM4H-B mic)

I am using the code below:

#include "driver/i2s.h"
const i2s_port_t I2S_PORT = I2S_NUM_0;

void setup() {
Serial.begin(115200);
esp_err_t err;

// The I2S config as per the example
const i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = 1024,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0};

// The pin config as per the setup
const i2s_pin_config_t pin_config = {
.bck_io_num = GPIO_NUM_34, // Serial Clock (SCK)
.ws_io_num = GPIO_NUM_32, // Word Select (WS)
.data_out_num = I2S_PIN_NO_CHANGE, // not used (only for speakers)
.data_in_num = GPIO_NUM_35 // Serial Data (SD)
};

// Configuring the I2S driver and pins.
// This function must be called before any I2S driver read/write operations.
err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
if (err != ESP_OK) {
Serial.printf("Failed installing driver: %d\n", err);
while (true);
}
err = i2s_set_pin(I2S_PORT, &pin_config);
if (err != ESP_OK) {
Serial.printf("Failed setting pin: %d\n", err);
while (true);
}
Serial.println("I2S driver installed.");
}

void loop() {
// Read a single sample and log it for the Serial Plotter.
int32_t sample = 0;
int bytes_read = i2s_pop_sample(I2S_PORT, (char *)&sample, portMAX_DELAY); // no timeout
if (bytes_read > 0) {
Serial.println(sample);
}
}

But on running it, I am getting 0 all the time.
Please Help me, I have to use this in my college project.
I have attached Circuit Diagram. Pl find it in the attachment.
Attachments
Screenshot 2021-05-04 at 9.28.31 PM.png
Screenshot 2021-05-04 at 9.28.31 PM.png (82.26 KiB) Viewed 13214 times
Screenshot 2021-05-04 at 9.27.54 PM.png
Screenshot 2021-05-04 at 9.27.54 PM.png (36.81 KiB) Viewed 13214 times

mike84
Posts: 4
Joined: Sat Jun 05, 2021 7:43 am

Re: I2S microphone (RX)

Postby mike84 » Sat Jun 05, 2021 9:27 am

BuddyCasino wrote:
Thu May 25, 2017 1:44 pm
Here is a complete example, I verified it works:

Code: Select all

/*
 * app_main.c
 *
 *  Created on: 30.03.2017
 *      Author: michaelboeckling
 */

#include <stdlib.h>
#include <stddef.h>
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <sys/time.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/i2s.h"

#define TAG "main"

static void init_i2s()
{
	const int sample_rate = 44100;

	/* TX: I2S_NUM_0 */
    i2s_config_t i2s_config_tx = {
	.mode = I2S_MODE_MASTER | I2S_MODE_TX,
	.sample_rate = sample_rate,
	.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
	.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,   // 2-channels
	.communication_format = I2S_COMM_FORMAT_I2S_MSB,
	.dma_buf_count = 32,                            // number of buffers, 128 max.
	.dma_buf_len = 32 * 2,                          // size of each buffer
	.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1        // Interrupt level 1
    };

    i2s_pin_config_t pin_config_tx = {
			.bck_io_num = GPIO_NUM_26,
			.ws_io_num = GPIO_NUM_25,
			.data_out_num = GPIO_NUM_22,
			.data_in_num = GPIO_NUM_23
	};
    i2s_driver_install(I2S_NUM_0, &i2s_config_tx, 0, NULL);
    i2s_set_pin(I2S_NUM_0, &pin_config_tx);


    /* RX: I2S_NUM_1 */
    i2s_config_t i2s_config_rx = {
	.mode = I2S_MODE_MASTER | I2S_MODE_RX, // Only TX
	.sample_rate = sample_rate,
	.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,    // Only 8-bit DAC support
	.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,   // 2-channels
	.communication_format = I2S_COMM_FORMAT_I2S_MSB,
	.dma_buf_count = 32,                            // number of buffers, 128 max.
	.dma_buf_len = 32 * 2,                          // size of each buffer
	.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1        // Interrupt level 1
	};

	i2s_pin_config_t pin_config_rx = {
		.bck_io_num = GPIO_NUM_17,
		.ws_io_num = GPIO_NUM_18,
		.data_out_num = I2S_PIN_NO_CHANGE,
		.data_in_num = GPIO_NUM_5
	};

	i2s_driver_install(I2S_NUM_1, &i2s_config_rx, 0, NULL);
	i2s_set_pin(I2S_NUM_1, &pin_config_rx);

}


void task_megaphone(void *pvParams)
{
	uint16_t buf_len = 1024;
	char *buf = calloc(buf_len, sizeof(char));

	struct timeval tv = {0};
	struct timezone *tz = {0};
	gettimeofday(&tv, &tz);
	uint64_t micros = tv.tv_usec + tv.tv_sec * 1000000;
	uint64_t micros_prev = micros;
	uint64_t delta = 0;

	init_i2s();

	int cnt = 0;
	int bytes_written = 0;

	while(1)
	{
		char *buf_ptr_read = buf;
		char *buf_ptr_write = buf;

		// read whole block of samples
		int bytes_read = 0;
		while(bytes_read == 0) {
			bytes_read = i2s_read_bytes(I2S_NUM_1, buf, buf_len, 0);
		}

		uint32_t samples_read = bytes_read / 2 / (I2S_BITS_PER_SAMPLE_32BIT / 8);

		//  convert 2x 32 bit stereo -> 1 x 16 bit mono
		for(int i = 0; i < samples_read; i++) {

			// const char samp32[4] = {ptr_l[0], ptr_l[1], ptr_r[0], ptr_r[1]};

			// left
			buf_ptr_write[0] = buf_ptr_read[2]; // mid
			buf_ptr_write[1] = buf_ptr_read[3]; // high

			// right
			buf_ptr_write[2] = buf_ptr_write[0]; // mid
			buf_ptr_write[3] = buf_ptr_write[1]; // high


			buf_ptr_write += 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8);
			buf_ptr_read += 2 * (I2S_BITS_PER_SAMPLE_32BIT / 8);
		}

		// local echo
		bytes_written = samples_read * 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8);
		i2s_write_bytes(I2S_NUM_0, buf, bytes_written, portMAX_DELAY);

		cnt += samples_read;

		if(cnt >= 44100) {
			gettimeofday(&tv, &tz);
			micros = tv.tv_usec + tv.tv_sec * 1000000;
			delta = micros - micros_prev;
			micros_prev = micros;
			printf("%d samples in %" PRIu64 " usecs\n", cnt, delta);

			cnt = 0;
		}
	}
}

/**
 * entry point
 */
void app_main()
{
    printf("starting app_main()\n");
    xTaskCreatePinnedToCore(&task_megaphone, "task_megaphone", 16384, NULL, 20, NULL, 0);
}

Hi friends!
This is a very interesting forum topic!
Please tell me the answer to this problem.
I want to input sound to ESP32 via I2S interface from INMP441 MEMS microphone. And immediately output sound from ESP32 via the I2S interface to any DAC (for example, PCM5102A).

I went through this forum thread in detail.
Here BuddyCasino has posted an example that may suit me. But this example is in ESP-IDF.
I redid it a bit for the Arduino IDE and removed a few things.

Please look at my code and tell me what is wrong with it.
Thank you very much Friends !!!

Code: Select all

#include <driver/i2s.h>

const int sample_rate = 44100;
esp_err_t err1; 
esp_err_t err2;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("Setup I2S ...");
  delay(1000);
  i2s_install();
  i2s_setpin();
  delay(500);
}

void loop() {
   uint16_t buf_len = 1024;
   char *buf = (char*) calloc(buf_len, sizeof(char));
   int bytes_written = 0;
   int bytes_read = 0;
   bytes_read = i2s_read_bytes(I2S_NUM_1, buf, buf_len, 0);
   uint32_t samples_read = bytes_read / 2 / (I2S_BITS_PER_SAMPLE_32BIT / 8);
   bytes_written = samples_read * 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8);
   i2s_write_bytes(I2S_NUM_0, buf, bytes_written, portMAX_DELAY);
}
void i2s_install(){
    /* TX: I2S_NUM_0 */
  const i2s_config_t i2s_config_tx = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX),
    .sample_rate = sample_rate,
    .bits_per_sample = i2s_bits_per_sample_t(16),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // default interrupt priority
    .dma_buf_count = 32,
    .dma_buf_len = 32 * 2,
  };
  err1 = i2s_driver_install(I2S_NUM_0, &i2s_config_tx, 0, NULL);
  if (err1 != ESP_OK) {
  Serial.printf("Failed installing driver_1: %d\n", err1);
  while (true);
  }
       /* RX: I2S_NUM_1 */
  const i2s_config_t i2s_config_rx = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = sample_rate,
    .bits_per_sample = i2s_bits_per_sample_t(32),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // default interrupt priority
    .dma_buf_count = 32,
    .dma_buf_len = 32 * 2,
  };
  err2 = i2s_driver_install(I2S_NUM_1, &i2s_config_rx, 0, NULL);
  if (err2 != ESP_OK) {
  Serial.printf("Failed installing driver_2: %d\n", err2);
  while (true);
  }
  Serial.println("I2S driver installed.");
}

void i2s_setpin(){
     /* TX: I2S_NUM_0 */
  const i2s_pin_config_t pin_config_tx = {
    .bck_io_num =   26,
    .ws_io_num =    25,
    .data_out_num = 22,
    .data_in_num =  I2S_PIN_NO_CHANGE  };
    
    err1 = i2s_set_pin(I2S_NUM_0, &pin_config_tx);
    if (err1 != ESP_OK) {
    Serial.printf("Failed setting pin_1: %d\n", err1);
    while (true);
    }
    /* RX: I2S_NUM_1 */
  const i2s_pin_config_t pin_config_rx = {
    .bck_io_num =   17,
    .ws_io_num =    27,
    .data_out_num = I2S_PIN_NO_CHANGE,
    .data_in_num =  33  };

    err2 = i2s_set_pin(I2S_NUM_1, &pin_config_rx);
    if (err2 != ESP_OK) {
    Serial.printf("Failed setting pin_2: %d\n", err2);
    while (true);
    }
  Serial.println("I2S pins installed.");
}
Please, help.

mike84
Posts: 4
Joined: Sat Jun 05, 2021 7:43 am

Re: I2S microphone (RX)

Postby mike84 » Thu Jun 10, 2021 11:30 am

Hi friends!
I have modified my code. It works well now.
The sound from the MEMS microphone via the I2S_NUM_0 I2S interface goes to the ESP32 and immediately to the output via I2S_NUM_0 I2S to the DAC PCM5102A.
Now I want to try processing my sound. This will take time.
If I insert a delay of 6-8 ms (delay (8);) between the functions i2s_read_bytes and i2s_write_bytes, then distortion begins in the dynamics, not similar to voice.
Here is my code:

Code: Select all

#include <driver/i2s.h>
const int sample_rate = 16000;  // 44100
esp_err_t err; 

uint16_t buf_len = 32;   // 1024
uint8_t *buf = (uint8_t*) calloc(buf_len, sizeof(uint8_t));
int bytes_written = 0;

void setup() {
  Serial.begin(500000);
  delay(100);
  Serial.println("  ");  Serial.println("Setup I2S ...");
  delay(500);
  i2s_install();
  i2s_setpin();
  delay(500);
}

void loop() {
   int bytes_read = 0;
   while(bytes_read == 0) {
      bytes_read = i2s_read_bytes(I2S_NUM_0, buf, buf_len, portMAX_DELAY);  
    }

delay (1);

   i2s_write_bytes(I2S_NUM_0, buf, bytes_read, portMAX_DELAY);  
}

void i2s_install(){
  const i2s_config_t i2s_config = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX),
    .sample_rate = sample_rate,
    .bits_per_sample = i2s_bits_per_sample_t(16),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // default interrupt priority
    .dma_buf_count = 16,  // 32
    .dma_buf_len =  64,  // 32 * 2
  };
  err = i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  if (err != ESP_OK) {
  Serial.printf("Failed installing driver_1: %d\n", err);
  while (true);
  }
  Serial.println("I2S driver installed.");
}

void i2s_setpin(){
  const i2s_pin_config_t pin_config = {
    .bck_io_num =   26,
    .ws_io_num =    25,
    .data_out_num = 22,
    .data_in_num =  33    
    };   
    err = i2s_set_pin(I2S_NUM_0, &pin_config);
    if (err != ESP_OK) {
    Serial.printf("Failed setting pin_1: %d\n", err);
    while (true);
    }
  Serial.println("I2S pins installed.");   Serial.println("  ");
}
Why is this happening?
Why can't I hear my own normal voice, but with a slight delay (5-8 ms)?
When I figure this out, I want to insert an encryption function between the i2s_read_bytes and i2s_write_bytes functions, which takes up to 10ms to run.

Who is online

Users browsing this forum: asargent and 149 guests