乐鑫技术交流
直播中

刘丹

7年用户 1506经验值
私信 关注
[问答]

使用esp_audio_pay 播放SD卡音乐发现播放完成后要2秒才能进入回调函数,为什么?

我想使用esp_audio_play 来播放SD卡音乐,用回调函数判断播放完成后重新播放,进而实现循环播放功能。
现在的问题是:每次播放完成后都要差不多2秒才能进回调函数。
我的程序初始化是:
static esp_audio_handle_t setup_player()
{
    esp_audio_cfg_t cfg = DEFAULT_ESP_AUDIO_CONFIG();
    audio_board_handle_t board_handle = audio_board_init();
    cfg.vol_handle = board_handle->audio_hal;
    cfg.vol_set = (audio_volume_set)audio_hal_set_volume;
    cfg.vol_get = (audio_volume_get)audio_hal_get_volume;
    cfg.prefer_type = ESP_AUDIO_PREFER_MEM;
    cfg.resample_rate = 44100;
    cfg.evt_que = xQueueCreate(3, sizeof(esp_audio_state_t));
        cfg.cb_func = audio_service_cb;
    esp_audio_handle_t player = esp_audio_create(&cfg);
    audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START);
    a2dp_stream_config_t a2dp_config = {
        .type = AUDIO_STREAM_READER,
        .user_callback.user_a2d_cb = user_a2dp_sink_cb,
    };
    audio_element_handle_t bt_stream_reader = a2dp_stream_init(&a2dp_config);
    esp_audio_input_stream_add(player, bt_stream_reader);

    ESP_LOGI(TAG, "[4.4] Create fatfs stream to read data from sdcard");
    char *url = NULL;
    sdcard_list_current(sdcard_list_handle, &url);
    fatfs_stream_cfg_t fatfs_cfg = FATFS_STREAM_CFG_DEFAULT();
    fatfs_cfg.type = AUDIO_STREAM_READER;
    fatfs_stream_reader = fatfs_stream_init(&fatfs_cfg);
    audio_element_set_uri(fatfs_stream_reader, url);
   esp_audio_input_stream_add(player, fatfs_stream_reader);

    ESP_LOGI(TAG, "[2.1] Create tone stream to read data from flash");
    tone_stream_cfg_t tone_cfg = TONE_STREAM_CFG_DEFAULT();
    tone_cfg.type = AUDIO_STREAM_READER;
    audio_element_handle_t tone_stream_reader = tone_stream_init(&tone_cfg);
    esp_audio_input_stream_add(player, tone_stream_reader);

    // Add decoders and encoders to esp_audio
    mp3_decoder_cfg_t  mp3_dec_cfg  = DEFAULT_MP3_DECODER_CONFIG();
    wav_decoder_cfg_t  wav_dec_cfg  = DEFAULT_WAV_DECODER_CONFIG();
    pcm_decoder_cfg_t  pcm_dec_cfg  = DEFAULT_PCM_DECODER_CONFIG();
    esp_audio_codec_lib_add(player, AUDIO_CODEC_TYPE_DECODER, mp3_decoder_init(&mp3_dec_cfg));
    esp_audio_codec_lib_add(player, AUDIO_CODEC_TYPE_DECODER, wav_decoder_init(&wav_dec_cfg));
    esp_audio_codec_lib_add(player, AUDIO_CODEC_TYPE_DECODER, pcm_decoder_init(&pcm_dec_cfg));

    // Create writers and add to esp_audio
    i2s_stream_cfg_t i2s_writer = I2S_STREAM_CFG_DEFAULT();
    i2s_writer.i2s_config.sample_rate = 44100;
    i2s_writer.type = AUDIO_STREAM_WRITER;
    esp_audio_output_stream_add(player, i2s_stream_init(&i2s_writer));
        esp_audio_play_timeout_set(player,500);
    esp_audio_vol_set(player, 60);
        
    AUDIO_MEM_SHOW(TAG);
    ESP_LOGI(TAG, "esp_audio instance is:%prn", player);
    return player;
}

回调函数是:
void audio_service_cb(esp_audio_state_t *audio, void *ctx)
{
     ESP_LOGI(TAG, "Entry audio call back function status is %d",audio->status);
         ESP_LOGI(TAG, "Entry audio call back function media type is  is %d",audio->media_src);
         esp_audio_state_t state = {0};
         esp_audio_state_get(test_handle->player, &state);
         if(test_handle->work_mode != SD_MODE)
                 return;
         if(music_repeat == 1){
                 if((audio->status == AUDIO_STATUS_FINISHED)&&(state.media_src == MEDIA_SRC_TYPE_MUSIC_SD))
                         {
        
                        ESP_LOGI(TAG, "repeat play music is %s",music_name);
                        esp_audio_media_type_set(test_handle->player, MEDIA_SRC_TYPE_MUSIC_SD);
                        esp_audio_play(test_handle->player, AUDIO_CODEC_TYPE_DECODER, music_name, 0);
                        test_handle->work_mode = SD_MODE;
                        }        
         }
}

播放功能就是正常的函数使用:
   memcpy(music_name,url,strlen(url));
   ESP_LOGI("BS-X001", "play music is %s",url);
   esp_audio_vol_set(test_handle->player, music_volume);
   esp_audio_media_type_set(test_handle->player, MEDIA_SRC_TYPE_MUSIC_SD);
   esp_audio_play(test_handle->player, AUDIO_CODEC_TYPE_DECODER, music_name, 0);
   int duration = 0;
   esp_audio_duration_get(test_handle->player, &duration);
   ESP_LOGI("BS-X001", " music duration time %d ms",duration);
   music_repeat = raw_datas[3];

                                                                                                                                                                                                                                                                            

回帖(1)

龙献益

2024-6-28 16:32:46
首先,让我们分析一下问题。在使用esp_audio_play播放SD卡音乐时,您希望在播放完成后立即进入回调函数以实现循环播放功能。但是,您发现播放完成后需要等待大约2秒才能进入回调函数。

这个问题可能是由以下几个原因导致的:

1. 回调函数的优先级较低:在ESP32系统中,回调函数的优先级可能较低,导致在其他任务执行时,回调函数被延迟执行。

2. 播放完成后的处理逻辑:在播放完成后,可能有一些额外的处理逻辑需要执行,这会导致一定的延迟。

3. 硬件或软件问题:可能是硬件或软件的问题导致播放完成后的回调函数延迟执行。

为了解决这个问题,您可以尝试以下方法:

1. 检查回调函数的优先级:确保回调函数的优先级足够高,以便在播放完成后立即执行。

2. 优化播放完成后的处理逻辑:检查播放完成后的处理逻辑,看看是否有可以优化的地方,以减少延迟。

3. 更新ESP-ADF:确保您使用的ESP-ADF库是最新版本,因为新版本可能修复了一些已知的问题。

4. 使用其他播放策略:如果问题仍然存在,您可以考虑使用其他播放策略,例如使用一个定时器在播放完成后立即触发回调函数。

关于您的程序初始化部分,您已经使用了DEFAULT_ESP_AUDIO_CONFIG()来初始化esp_audio配置。这是一个正确的方法。但是,如果您发现问题仍然存在,您可以尝试以下步骤:

1. 确保您的音频板初始化是正确的,例如audio_board_init()。

2. 确保您的音量设置函数(如audio_hal_set_volume)是正确的。

3. 在回调函数中添加一些调试信息,以便更好地了解播放完成后的执行流程。

4. 如果可能的话,尝试使用其他音频播放库,看看问题是否仍然存在。

希望这些建议能帮助您解决问题。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分