Normal i2s init works, but trying to init via i2s stream no sound/data

iemand33
Posts: 2
Joined: Mon Nov 18, 2024 10:48 pm

Normal i2s init works, but trying to init via i2s stream no sound/data

Postby iemand33 » Mon Nov 18, 2024 11:21 pm

Hi all,
This has been driving me absolutely nuts for the past couple days and I have been able to resolve the issue. Some help is greatly appreciated!

I'm trying to use my INMP441 as an input for my ESP-ADF pipeline but it's not working, however using the same i2s config for the more traditional init of the microphone works fine.

'Traditional' code which is working:

Code: Select all

void i2s_init_old(){
	i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
    i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan);
    
    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000),
        .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO),
        .gpio_cfg = {
	            .mclk = I2S_GPIO_UNUSED,
            	.bclk = BCLK_PIN,
            	.ws   = LRCLK_PIN,
            	.dout = DATA_OUT_PIN,
            	.din  = DATA_IN_PIN, // In duplex mode, bind output and input to a same gpio can loopback internally
                .invert_flags = {
                        .mclk_inv = false,
                        .bclk_inv = false,
                        .ws_inv   = false,
                },
        },
    };
    ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &std_cfg));
    ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_chan, &std_cfg));
    ESP_ERROR_CHECK(i2s_channel_enable(tx_chan));
    ESP_ERROR_CHECK(i2s_channel_enable(rx_chan));
}


static void i2s_test_loopback(){
	uint8_t *r_buf = (uint8_t *)calloc(1, EXAMPLE_BUFF_SIZE);
    assert(r_buf); // Check if r_buf allocation success
    size_t r_bytes = 0;
    size_t w_bytes = 0;
    
	while (1) {
        /* Read i2s data */
        i2s_channel_read(rx_chan, r_buf, EXAMPLE_BUFF_SIZE, &r_bytes, 1000);
        printf("Read Task: i2s read %d bytes\n-----------------------------------\n", r_bytes);
        printf("[0] %x [1] %x [2] %x [3] %x\n[4] %x [5] %x [6] %x [7] %x\n\n",
               r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]);
        
        if (i2s_channel_write(tx_chan, r_buf, EXAMPLE_BUFF_SIZE, &w_bytes, 1000) == ESP_OK) {
            printf("Write Task: i2s write %d bytes\n", w_bytes);
        } else {
            printf("Write Task: i2s write failed\n");
        }
    }	
}

So this works fine, I'm hearing sound from the speaker and this is the output:

Code: Select all

Write Task: i2s write 4096 bytes
Read Task: i2s read 4096 bytes
-----------------------------------
[0] 0 [1] 2a [2] ff [3] ff
[4] 0 [5] 64 [6] 0 [7] 0

Write Task: i2s write 4096 bytes
Read Task: i2s read 4096 bytes
-----------------------------------
[0] 0 [1] a0 [2] a [3] 0
[4] 0 [5] ba [6] 7 [7] 0

Write Task: i2s write 4096 bytes
Read Task: i2s read 4096 bytes
-----------------------------------
[0] 0 [1] 42 [2] 5 [3] 0
[4] 80 [5] d9 [6] 6 [7] 0

So now on to the i2s_stream code:

Code: Select all

void i2s_init(){
	ESP_LOGI("i2s_init", "Create reader pipeline");
	audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
	pipeline_reader = audio_pipeline_init(&pipeline_cfg);
    
    i2s_std_config_t std_config = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000),
        .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO),
        .gpio_cfg = {
	            .mclk = I2S_GPIO_UNUSED,
            	.bclk = BCLK_PIN,
            	.ws   = LRCLK_PIN,
            	.dout = DATA_OUT_PIN,
            	.din  = DATA_IN_PIN,
                .invert_flags = {
                        .mclk_inv = false,
                        .bclk_inv = false,
                        .ws_inv   = false,
                },
        },
    };

    i2s_stream_cfg_t i2s_reader_cfg = I2S_STREAM_CFG_DEFAULT();
    i2s_reader_cfg.type = AUDIO_STREAM_READER;
    i2s_reader_cfg.std_cfg = std_config;
    
    ESP_LOGI("i2s_init", "Configs created, init the reader stream");
    i2s_stream_reader = i2s_stream_init(&i2s_reader_cfg);
	
	raw_stream_cfg_t raw_cfg = RAW_STREAM_CFG_DEFAULT();
	raw_cfg.type = AUDIO_STREAM_READER;
	audio_element_handle_t raw_writer = raw_stream_init(&raw_cfg);
	
	ESP_LOGI("i2s_init", "Register all elements to audio pipeline");
    audio_pipeline_register(pipeline_reader, i2s_stream_reader, "i2s_read");
    audio_pipeline_register(pipeline_reader, raw_writer, "raw");
    
    ESP_LOGI("i2s_init", "Link it together");
	const char *link_tag[2] = {"i2s_read", "raw"};
	audio_pipeline_link(pipeline_reader, &link_tag[0], 2);
	
	ESP_LOGI("i2s_init", "Run the pipeline");
    audio_pipeline_run(pipeline_reader);
    
    char *r_buf = (char *)calloc(1, EXAMPLE_BUFF_SIZE);
    assert(r_buf); // Check if r_buf allocation success
    
    while(1){
        ESP_LOGI("Pipeline", "Element state: %d %d",
        audio_element_get_state(i2s_stream_reader),
        audio_element_get_state(raw_writer));
		
    	int bytes_read = raw_stream_read(raw_writer, r_buf, EXAMPLE_BUFF_SIZE);
		if (bytes_read < 0) {
		    ESP_LOGE("buf", "Error reading from raw stream");
		    
		} else if (bytes_read == 0) {
		    ESP_LOGW("buf", "End of stream or no data available");
		    
		}
		
		printf("[0] %x [1] %x [2] %x [3] %x\n[4] %x [5] %x [6] %x [7] %x\n\n",
               r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]);
               
        vTaskDelay(1000 / portTICK_PERIOD_MS);
		
    };
        
}
Look great right? same i2s settings as before.
But no joy on the data...:

Code: Select all

I (3114) i2s_init: Create reader pipeline
I (3114) i2s_init: Configs created, init the reader stream
D (3114) i2s_common: rx channel is registered on I2S0 successfully
D (3114) i2s_common: DMA malloc info: dma_desc_num = 3, dma_desc_buf_size = dma_frame_num * slot_num * data_bit_width = 1248
D (3124) i2s_std: Clock division info: [sclk] 160000000 Hz [mdiv] 39 [mclk] 4096000 Hz [bdiv] 4 [bclk] 1024000 Hz
D (3144) i2s_common: MCLK is pinned to GPIO0 on I2S0
D (3144) i2s_std: The rx channel on I2S0 has been initialized to STD mode successfully
D (3154) i2s_common: i2s rx channel enabled
I (3154) i2s_init: Register all elements to audio pipeline
I (3164) i2s_init: Link it together
I (3164) AUDIO_PIPELINE: link el->rb, el:0x3ffb79dc, tag:i2s_read, rb:0x3ffb921c
I (3174) i2s_init: Run the pipeline
I (3184) AUDIO_THREAD: The i2s_read task allocate stack on internal memory
I (3184) AUDIO_ELEMENT: [i2s_read-0x3ffb79dc] Element task created
I (3194) AUDIO_ELEMENT: [raw-0x3ffb8ea0] Element task created
I (3204) AUDIO_PIPELINE: Func:audio_pipeline_run, Line:359, MEM Total:270792 Bytes

I (3204) AUDIO_ELEMENT: [i2s_read] AEL_MSG_CMD_RESUME,state:1
I (3214) AUDIO_PIPELINE: Pipeline started
I (3224) Pipeline: Element state: 3 3
[0] 0 [1] 0 [2] 0 [3] 0
[4] 0 [5] 0 [6] 0 [7] 0

I (4284) Pipeline: Element state: 3 3
[0] 0 [1] 0 [2] 0 [3] 0
[4] 0 [5] 0 [6] 0 [7] 0

I (5284) Pipeline: Element state: 3 3
[0] 0 [1] 0 [2] 0 [3] 0
[4] 0 [5] 0 [6] 0 [7] 0

I (6284) Pipeline: Element state: 3 3
[0] 0 [1] 0 [2] 0 [3] 0
[4] 0 [5] 0 [6] 0 [7] 0
Can someone please help me out? I'm been hurting my brain over this for days and for the life of me cannot figure this one out.

iemand33
Posts: 2
Joined: Mon Nov 18, 2024 10:48 pm

Re: Normal i2s init works, but trying to init via i2s stream no sound/data

Postby iemand33 » Tue Nov 19, 2024 12:47 pm

Pfff I've finally figured it out.

So ESF-ADF overwrites the GPIO pins set in the i2s_cfg with it's own pins, based on the audio board selected in menuconfig.
I've changed the pins in the board_pins_config.c associated with my selected board and now it's working.
Trying to include a custom board (which is also an option is the menuconfig) is the more elegant option which I'll try and make work.

Thanks for reading, cheers!

Who is online

Users browsing this forum: No registered users and 10 guests