espressif / esp-adf

Espressif Audio Development Framework
Other
1.54k stars 677 forks source link

play_tts_example例程中是使用i2s stream进行输出,那这个i2s stream 替换成pwm_stream流是否支持正常播放? #1127

Open shapefire opened 9 months ago

shapefire commented 9 months ago

使用esp32-s3开发板,外接PAM8406功放板,将play_tts_example 的i2s stream 流更改为pwm_stream流,其运行后无法正常播放音频。 更改前的代码: i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT(); i2s_cfg.volume = 100; i2s_cfg.type = AUDIO_STREAM_WRITER; i2s_cfg.i2s_config.sample_rate = 16000; i2s_cfg.i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT; i2s_stream_writer = i2s_stream_init(&i2s_cfg); 更改后的代码: pwm_stream_cfg_t pwm_cfg = PWM_STREAM_CFG_DEFAULT(); pwm_cfg.type = AUDIO_STREAM_WRITER; pwm_cfg.pwm_config.gpio_num_left = GPIO_NUM_17; pwm_cfg.pwm_config.gpio_num_right = GPIO_NUM_18; i2s_stream_writer = pwm_stream_init(&pwm_cfg);

若play_tts_example例程支持pwm播放,那应该怎样修改?

yyjdelete commented 8 months ago

可以播, 但有点其他的bug 在while(1)里面添加一条新的if

        if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void*) i2s_stream_writer
                && msg.cmd == AEL_MSG_CMD_REPORT_STATUS
                && (((int)msg.data == AEL_STATUS_STATE_RUNNING))) {

            //FIXME: 会丢音频最后1~2个字
            // TTS默认输出格式为单声道, 16bit@16000Hz。
            pwm_stream_set_clk(i2s_stream_writer, 16000, 16, 1);
        }
  1. 请确保你同时设置了gpio_num_left和gpio_num_right, 否则其他情况可能都需要修改pwm_stream.c里的timer_group_isr, 修复下跳过数据的长度和实际需要的长度不匹配的问题
    //L R channel_cnt
    //L R 1 => OK
    //L R 2 => OK
    //L - 1 => OK
    //L - 2 => BAD(3/5 instead of 2/4)
    //- R 1 => BAD(0/0 instead of 1/2)
    //- R 2 => BAD(1/2 instead of 2/4)
  2. 停止时会丢音频最后的1~2个字(#1137), 我自己的一个临时解决方法是在pwm_stream.c的_pwm_process添加如下代码(未严格测试, 可能会造成其他问题)
    if (r_size == AEL_IO_DONE)
    {
        audio_pwm_handle_t handle = g_audio_pwm_handle;
        pwm_data_handle_t data = handle->data;
        //wait for pwm complete
        while(true)
        {
            if (ESP_OK != pwm_data_list_wait_semaphore(data, 2000 / portTICK_RATE_MS))
            {
                break;
            }
            uint32_t count = pwm_data_list_get_count(data);
            if (count == 0)
            {
                break;
            }
        }
    }
  3. 在异常退出时, 释放element之前, 请确保你已经调用过pwm_stream_set_clk, 否则可能会卡死在下面这个等待中, 无法释放这个audio_element所对应的任务 https://github.com/espressif/esp-adf/blob/7a7c66e63dade6fa7003b9d0d77b64c17bfeb064/components/audio_stream/pwm_stream.c#L542