Page 1 of 1

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

Posted: Mon Nov 18, 2024 11:21 pm
by iemand33
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.

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

Posted: Tue Nov 19, 2024 12:47 pm
by iemand33
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!