Page 6 of 7

Re: Megaphone example for ESP32-LYRATD-MSC

Posted: Tue Mar 12, 2019 7:48 am
by theronic
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.

Re: I2S microphone (RX)

Posted: Tue Mar 12, 2019 8:56 am
by BuddyCasino
Sorry no, I don't have a Lyra.

Re: I2S microphone (RX)

Posted: Tue Mar 12, 2019 4:14 pm
by fly135
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

Re: I2S microphone (RX)

Posted: Fri Nov 15, 2019 7:25 am
by pataga
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.

Re: I2S microphone (RX)

Posted: Wed Jan 01, 2020 1:15 pm
by Tnarain5
Thanks all for your support!

Re: I2S microphone (RX)

Posted: Mon Feb 10, 2020 7:24 am
by Tnarain5
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 !!

Re: I2S microphone (RX)

Posted: Thu Dec 31, 2020 4:25 am
by sapparatus
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

Re: I2S microphone (RX)

Posted: Tue May 04, 2021 4:03 pm
by khanware
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.

Re: I2S microphone (RX)

Posted: Sat Jun 05, 2021 9:27 am
by mike84
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.

Re: I2S microphone (RX)

Posted: Thu Jun 10, 2021 11:30 am
by mike84
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.