接前一篇文章:ESP32-S3模组上跑通ES8388(1)
本文内容参考:
从ESP32看ES8388低功耗音频芯片_es8388 芯片手册-优快云博客
ESP-ADF入门——从play_mp3_control入门adf-优快云博客
[005] [ESP32开发笔记] ADF基本框架_esp32 adf-优快云博客
ESP32学习笔记(38)——播放MP3文件(外部Codec方式)_esp32 音乐转码-优快云博客
特此致谢!
上一回对于ESP-ADF做了介绍。本回开始正式深入到代码,讲解ESP32-S3如何驱动和操作ES8388。
二、利用ESP-ADF操作ES8388
1. 总体介绍
ESP-ADF的audio_hal层主要操作包括:
- 初始化media编解码芯片驱动 —— audio_hal_init函数
audio_hal_init函数的声明在components\audio_hal\include\audio_hal.h中,原型如下:
/**
* @brief Initialize media codec driver
*
* @note If selected codec has already been installed, it'll return the audio_hal handle.
*
* @param audio_hal_conf Configure structure audio_hal_config_t
* @param audio_hal_func Structure containing functions used to operate audio the codec chip
*
* @return int, 0--success, others--fail
*/
audio_hal_handle_t audio_hal_init(audio_hal_codec_config_t *audio_hal_conf, audio_hal_func_t *audio_hal_func);
audio_hal_init函数的实现在components\audio_hal\audio_hal.c中,代码如下:
audio_hal_handle_t audio_hal_init(audio_hal_codec_config_t *audio_hal_conf, audio_hal_func_t *audio_hal_func)
{
esp_err_t ret = 0;
audio_hal_handle_t audio_hal = (audio_hal_handle_t)audio_calloc(1, sizeof(audio_hal_func_t));
AUDIO_MEM_CHECK(TAG, audio_hal, return NULL);
memcpy(audio_hal, audio_hal_func, sizeof(audio_hal_func_t));
audio_hal->audio_hal_lock = mutex_create();
AUDIO_MEM_CHECK(TAG, audio_hal->audio_hal_lock, {
audio_free(audio_hal);
return NULL;
});
mutex_lock(audio_hal->audio_hal_lock);
ret = audio_hal->audio_codec_initialize(audio_hal_conf);
if (ret == ESP_FAIL) {
audio_free(audio_hal);
if (audio_hal_func->handle) {
return audio_hal_func->handle;
} else {
ESP_LOGE(TAG, "codec init failed!");
return NULL;
}
}
ret |= audio_hal->audio_codec_config_iface(audio_hal_conf->codec_mode, &audio_hal_conf->i2s_iface);
if ((audio_hal_conf->codec_mode == AUDIO_HAL_CODEC_MODE_DECODE) || (audio_hal_conf->codec_mode == AUDIO_HAL_CODEC_MODE_BOTH)) {
ret |= audio_hal->audio_codec_set_volume(AUDIO_HAL_VOL_DEFAULT);
}
AUDIO_RET_ON_FALSE(TAG, ret, return NULL, "audio_hal_init failed");
audio_hal->handle = audio_hal;
audio_hal_func->handle = audio_hal;
mutex_unlock(audio_hal->audio_hal_lock);
return audio_hal;
}
- 去(解除)初始化media编解码芯片驱动 —— audio_hal_deinit函数
audio_hal_deinit函数的声明也在components\audio_hal\include\audio_hal.h中,原型如下:
/**
* @brief Uninitialize media codec driver
*
* @param audio_hal reference function pointer for selected audio codec
*
* @return int, 0--success, others--fail
*/
esp_err_t audio_hal_deinit(audio_hal_handle_t audio_hal);
audio_hal_deinit函数的实现也在components\audio_hal\audio_hal.c中,代码如下:
esp_err_t audio_hal_deinit(audio_hal_handle_t audio_hal)
{
esp_err_t ret;
AUDIO_HAL_CHECK_NULL(audio_hal, "audio_hal handle is null", -1);
mutex_destroy(audio_hal->audio_hal_lock);
ret = audio_hal->audio_codec_deinitialize();
audio_hal->audio_hal_lock = NULL;
audio_hal->handle = NULL;
audio_free(audio_hal);
audio_hal = NULL;
return ret;
}
- 启动/停止编解码芯片驱动,设置模式、启停 —— audio_hal_ctrl_codec函数
audio_hal_ctrl_codec函数的声明也在components\audio_hal\include\audio_hal.h中,原型如下:
/**
* @brief Start/stop codec driver
*
* @param audio_hal reference function pointer for selected audio codec
* @param mode select media hal codec mode either encode/decode/or both to start from audio_hal_codec_mode_t
* @param audio_hal_ctrl select start stop state for specific mode
*
* @return int, 0--success, others--fail
*/
esp_err_t audio_hal_ctrl_codec(audio_hal_handle_t audio_hal, audio_hal_codec_mode_t mode, audio_hal_ctrl_t audio_hal_ctrl);
audio_hal_ctrl_codec函数的实现也在components\audio_hal\audio_hal.c中,代码如下:
esp_err_t audio_hal_ctrl_codec(audio_hal_handle_t audio_hal, audio_hal_codec_mode_t mode, audio_hal_ctrl_t audio_hal_state)
{
esp_err_t ret;
AUDIO_HAL_CHECK_NULL(audio_hal, "audio_hal handle is null", -1);
mutex_lock(audio_hal->audio_hal_lock);
ESP_LOGI(TAG, "Codec mode is %d, Ctrl:%d", mode, audio_hal_state);
ret = audio_hal->audio_codec_ctrl(mode, audio_hal_state);
mutex_unlock(audio_hal->audio_hal_lock);
return ret;
}
- 设置I2S接口采样率和位宽以及I2S或PCM/DSP格式 —— audio_hal_codec_iface_config函数
audio_hal_codec_iface_config函数的声明也在components\audio_hal\include\audio_hal.h中,原型如下:
/**
* @brief Set codec I2S interface samples rate & bit width and format either I2S or PCM/DSP.
*
* @param audio_hal reference function pointer for selected audio codec
* @param mode select media hal codec mode either encode/decode/or both to start from audio_hal_codec_mode_t
* @param iface I2S sample rate (ex: 16000, 44100), I2S bit width (16, 24, 32),I2s format (I2S, PCM, DSP).
*
* @return
* - 0 Success
* - -1 Error
*/
esp_err_t audio_hal_codec_iface_config(audio_hal_handle_t audio_hal, audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface);
audio_hal_codec_iface_config函数的实现也在components\audio_hal\audio_hal.c中,代码如下:
esp_err_t audio_hal_codec_iface_config(audio_hal_handle_t audio_hal, audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface)
{
esp_err_t ret = 0;
AUDIO_HAL_CHECK_NULL(audio_hal, "audio_hal handle is null", -1);
AUDIO_HAL_CHECK_NULL(iface, "Get volume para is null", -1);
mutex_lock(audio_hal->audio_hal_lock);
ret = audio_hal->audio_codec_config_iface(mode, iface);
mutex_unlock(audio_hal->audio_hal_lock);
return ret;
}
- 静音 —— audio_hal_set_mute函数
audio_hal_set_mute函数的声明也在components\audio_hal\include\audio_hal.h中,原型如下:
/**
* @brief Set voice mute. Enables or disables DAC mute of a codec.
* @note `audio_hal_get_volume` will still give a non-zero number in mute state. It will be set to that number when speaker is unmuted.
*
* @param audio_hal reference function pointer for selected audio codec
* @param mute true/false. If true speaker will be muted and if false speaker will be unmuted.
*
* @return int, 0--success, others--fail
*/
esp_err_t audio_hal_set_mute(audio_hal_handle_t audio_hal, bool mute);
audio_hal_set_mute函数的实现也在components\audio_hal\audio_hal.c中,代码如下:
esp_err_t audio_hal_set_mute(audio_hal_handle_t audio_hal, bool mute)
{
esp_err_t ret;
AUDIO_HAL_CHECK_NULL(audio_hal, "audio_hal handle is null", -1);
mutex_lock(audio_hal->audio_hal_lock);
ret = audio_hal->audio_codec_set_mute(mute);
mutex_unlock(audio_hal->audio_hal_lock);
return ret;
}
- 设置音量 —— audio_hal_set_volume函数
audio_hal_set_volume函数的声明也在components\audio_hal\include\audio_hal.h中,原型如下:
/**
* @brief Set voice volume.
* @note if volume is 0, mute is enabled,range is 0-100.
*
* @param audio_hal reference function pointer for selected audio codec
* @param volume value of volume in percent(%)
*
* @return int, 0--success, others--fail
*/
esp_err_t audio_hal_set_volume(audio_hal_handle_t audio_hal, int volume);
audio_hal_set_volume函数的实现也在components\audio_hal\audio_hal.c中,代码如下:
esp_err_t audio_hal_set_volume(audio_hal_handle_t audio_hal, int volume)
{
esp_err_t ret;
AUDIO_HAL_CHECK_NULL(audio_hal, "audio_hal handle is null", -1);
mutex_lock(audio_hal->audio_hal_lock);
ret = audio_hal->audio_codec_set_volume(volume);
mutex_unlock(audio_hal->audio_hal_lock);
return ret;
}
- 获取音量 —— audio_hal_get_volume函数
audio_hal_get_volume函数的声明也在components\audio_hal\include\audio_hal.h中,原型如下:
/**
* @brief get voice volume.
* @note if volume is 0, mute is enabled, range is 0-100.
*
* @param audio_hal reference function pointer for selected audio codec
* @param volume value of volume in percent returned(%)
*
* @return int, 0--success, others--fail
*/
esp_err_t audio_hal_get_volume(audio_hal_handle_t audio_hal, int *volume);
audio_hal_get_volume函数的实现也在components\audio_hal\audio_hal.c中,代码如下:
esp_err_t audio_hal_get_volume(audio_hal_handle_t audio_hal, int *volume)
{
esp_err_t ret;
AUDIO_HAL_CHECK_NULL(audio_hal, "audio_hal handle is null", -1);
AUDIO_HAL_CHECK_NULL(volume, "Get volume para is null", -1);
mutex_lock(audio_hal->audio_hal_lock);
ret = audio_hal->audio_codec_get_volume(volume);
mutex_unlock(audio_hal->audio_hal_lock);
return ret;
}
- 启用/停止功放 —— audio_hal_enable_pa函数
audio_hal_enable_pa函数的声明也在components\audio_hal\include\audio_hal.h中,原型如下:
/**
* @brief Enables or disables PA.
*
* @param audio_hal reference function pointer for selected audio codec
* @param enable true/false.
*
* @return int, 0--success, others--fail
*/
esp_err_t audio_hal_enable_pa(audio_hal_handle_t audio_hal, bool enable);
audio_hal_enable_pa函数的实现也在components\audio_hal\audio_hal.c中,代码如下:
esp_err_t audio_hal_enable_pa(audio_hal_handle_t audio_hal, bool enable)
{
esp_err_t ret;
AUDIO_HAL_CHECK_NULL(audio_hal, "audio_hal handle is null", -1);
mutex_lock(audio_hal->audio_hal_lock);
ret = audio_hal->audio_codec_enable_pa(enable);
mutex_unlock(audio_hal->audio_hal_lock);
return ret;
}
由以上audio_hal层的各函数可以看到,hal(硬件抽象层)一词名副其实,各函数中都是调用的audio_hal->audio_codec_xxx(同名)函数。那么,这个audio_hal是何时定义的,其初始化又是在何时何地进行的呢?请看下回。