I am working with the ADF example play_sdcard_mp3_example in the Lyrat board.
I can play the test.mp3 but now I want to do operations with the SDcard like open files, list files… etc. Since the SDcard was initialized in
audio_board_sdcard_init(), how can I get the sdcard handler that is used in the IDF example?
Hi.
Can you share a link to the example? So that I can take a look at the code?
I’m not familiar with ESP-IDF, but I can take a look.
Regards,
Sara
I Sara, so it’s the ESP-ADF which is their Audio Development Framework.
I’ll paste the whole example below. The relevant parts are:
ESP_LOGI(TAG, “[3.1] Set up uri for save file name”);
audio_element_set_uri(el_fatfs_wr_stream, “/sdcard/test_output.wav”);
ESP_LOGI(TAG, “[ 4] Start and wait for SDCARD to mount”);
// Initialize peripherals management
esp_periph_config_tperiph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
esp_periph_set_handle_tset = esp_periph_set_init(&periph_cfg);
audio_board_sdcard_init(set, SD_MODE_1_LINE);
After waiting for the SD card to mount, I’d like to see the file system (do an ls) so I can pick a file.
In the example, the file name is hard coded.
The documentation doesn’t say anything about getting a handle to the file descriptor.
There is code in the ESP-IDF that can open the SD card, but that handle is not compatible with the SD card.
So I guess I could open it with the IDF code, fine the file name, close the file system, the=n open it again with the ASDF, but that seems very cheesy.
Here is the hole example
/* Play music from Bluetooth device
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include “nvs_flash.h”
#include “freertos/FreeRTOS.h”
#include “freertos/task.h”
#include “esp_log.h”
#include “esp_peripherals.h”
#include “periph_touch.h”
#include “periph_adc_button.h”
#include “periph_button.h”
#include “esp_bt_defs.h”
#include “esp_gap_bt_api.h”
#include “esp_hf_client_api.h”
#include “audio_element.h”
#include “audio_pipeline.h”
#include “audio_event_iface.h”
#include “audio_mem.h”
#include “i2s_stream.h”
#include “board.h”
#include “bluetooth_service.h”
#include “filter_resample.h”
#include “raw_stream.h”
#include “fatfs_stream.h”
#include “mp3_decoder.h”
#if (CONFIG_ESP_LYRATD_MSC_V2_1_BOARD || CONFIG_ESP_LYRATD_MSC_V2_2_BOARD)
#include “filter_resample.h”
#endif
#include “audio_idf_version.h”
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0))
#define HFP_RESAMPLE_RATE 16000
#else
#define HFP_RESAMPLE_RATE 8000
#endif
static const char *TAG = “BLUETOOTH_EXAMPLE”;
static const char *BT_HF_TAG = “BT_HF”;
static audio_element_handle_t bt_stream_reader, mp3_decoder, el_fatfs_wr_stream;
static audio_pipeline_handle_t pipeline;
static bool is_get_hfp = true;
const char *c_hf_evt_str[] = {
“CONNECTION_STATE_EVT”, /*!< connection state changed event */
“AUDIO_STATE_EVT”, /*!< audio connection state change event */
“VR_STATE_CHANGE_EVT”, /*!< voice recognition state changed */
“CALL_IND_EVT”, /*!< call indication event */
“CALL_SETUP_IND_EVT”, /*!< call setup indication event */
“CALL_HELD_IND_EVT”, /*!< call held indicator event */
“NETWORK_STATE_EVT”, /*!< network state change event */
“SIGNAL_STRENGTH_IND_EVT”, /*!< signal strength indication event */
“ROAMING_STATUS_IND_EVT”, /*!< roaming status indication event */
“BATTERY_LEVEL_IND_EVT”, /*!< battery level indication event */
“CURRENT_OPERATOR_EVT”, /*!< current operator name event */
“RESP_AND_HOLD_EVT”, /*!< response and hold event */
“CLIP_EVT”, /*!< Calling Line Identification notification event */
“CALL_WAITING_EVT”, /*!< call waiting notification */
“CLCC_EVT”, /*!< listing current calls event */
“VOLUME_CONTROL_EVT”, /*!< audio volume control event */
“AT_RESPONSE”, /*!< audio volume control event */
“SUBSCRIBER_INFO_EVT”, /*!< subscriber information event */
“INBAND_RING_TONE_EVT”, /*!< in-band ring tone settings */
“LAST_VOICE_TAG_NUMBER_EVT”, /*!< requested number from AG event */
“RING_IND_EVT”, /*!< ring indication event */
};
// esp_hf_client_connection_state_t
const char *c_connection_state_str[] = {
“disconnected”,
“connecting”,
“connected”,
“slc_connected”,
“disconnecting”,
};
// esp_hf_client_audio_state_t
const char *c_audio_state_str[] = {
“disconnected”,
“connecting”,
“connected”,
“connected_msbc”,
};
/// esp_hf_vr_state_t
const char *c_vr_state_str[] = {
“disabled”,
“enabled”,
};
// esp_hf_service_availability_status_t
const char *c_service_availability_status_str[] = {
“unavailable”,
“available”,
};
// esp_hf_roaming_status_t
const char *c_roaming_status_str[] = {
“inactive”,
“active”,
};
// esp_hf_client_call_state_t
const char *c_call_str[] = {
“NO call in progress”,
“call in progress”,
};
// esp_hf_client_callsetup_t
const char *c_call_setup_str[] = {
“NONE”,
“INCOMING”,
“OUTGOING_DIALING”,
“OUTGOING_ALERTING”
};
// esp_hf_client_callheld_t
const char *c_call_held_str[] = {
“NONE held”,
“Held and Active”,
“Held”,
};
// esp_hf_response_and_hold_status_t
const char *c_resp_and_hold_str[] = {
“HELD”,
“HELD ACCEPTED”,
“HELD REJECTED”,
};
// esp_hf_client_call_direction_t
const char *c_call_dir_str[] = {
“outgoing”,
“incoming”,
};
// esp_hf_client_call_state_t
const char *c_call_state_str[] = {
“active”,
“held”,
“dialing”,
“alerting”,
“incoming”,
“waiting”,
“held_by_resp_hold”,
};
// esp_hf_current_call_mpty_type_t
const char *c_call_mpty_type_str[] = {
“single”,
“multi”,
};
// esp_hf_volume_control_target_t
const char *c_volume_control_target_str[] = {
“SPEAKER”,
“MICROPHONE”
};
// esp_hf_at_response_code_t
const char *c_at_response_code_str[] = {
“OK”,
“ERROR”
“ERR_NO_CARRIER”,
“ERR_BUSY”,
“ERR_NO_ANSWER”,
“ERR_DELAYED”,
“ERR_BLACKLILSTED”,
“ERR_CME”,
};
// esp_hf_subscriber_service_type_t
const char *c_subscriber_service_type_str[] = {
“unknown”,
“voice”,
“fax”,
};
// esp_hf_client_in_band_ring_state_t
const char *c_inband_ring_state_str[] = {
“NOT provided”,
“Provided”,
};
static void bt_app_hf_client_audio_open(void)
{
ESP_LOGE(BT_HF_TAG, “bt_app_hf_client_audio_open”);
intsample_rate = HFP_RESAMPLE_RATE;
audio_element_info_tbt_info = {0};
audio_element_getinfo(bt_stream_reader, &bt_info);
bt_info.sample_rates = sample_rate;
bt_info.channels = 1;
bt_info.bits = 16;
audio_element_setinfo(bt_stream_reader, &bt_info);
audio_element_report_info(bt_stream_reader);
}
static void bt_app_hf_client_audio_close(void)
{
ESP_LOGE(BT_HF_TAG, “bt_app_hf_client_audio_close”);
intsample_rate = periph_bluetooth_get_a2dp_sample_rate();
audio_element_info_tbt_info = {0};
audio_element_getinfo(bt_stream_reader, &bt_info);
bt_info.sample_rates = sample_rate;
bt_info.channels = 2;
bt_info.bits = 16;
audio_element_setinfo(bt_stream_reader, &bt_info);
audio_element_report_info(bt_stream_reader);
}
static uint32_t bt_app_hf_client_outgoing_cb(uint8_t *p_buf, uint32_t sz)
{
intout_len_bytes = 0;
char *enc_buffer = (char *)audio_malloc(sz);
AUDIO_MEM_CHECK(BT_HF_TAG, enc_buffer, return0);
if (is_get_hfp) {
out_len_bytes = raw_stream_read(bt_stream_reader, enc_buffer, sz);
}
if (out_len_bytes == sz) {
is_get_hfp = false;
memcpy(p_buf, enc_buffer, out_len_bytes);
free(enc_buffer);
returnsz;
} else {
is_get_hfp = true;
free(enc_buffer);
return0;
}
}
static void bt_app_hf_client_incoming_cb(const uint8_t *buf, uint32_t sz)
{
if (bt_stream_reader) {
if (audio_element_get_state(bt_stream_reader) == AEL_STATE_RUNNING) {
audio_element_output(bt_stream_reader, (char *)buf, sz);
esp_hf_client_outgoing_data_ready();
}
}
}
/* callback for HF_CLIENT */
void bt_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_t *param)
{
if (event <= ESP_HF_CLIENT_RING_IND_EVT) {
ESP_LOGE(BT_HF_TAG, “APP HFP event: %s”, c_hf_evt_str[event]);
} else {
ESP_LOGE(BT_HF_TAG, “APP HFP invalid event %d”, event);
}
switch (event) {
case ESP_HF_CLIENT_CONNECTION_STATE_EVT:
ESP_LOGE(BT_HF_TAG, “–connection state %s, peer feats 0x%x, chld_feats 0x%x”,
c_connection_state_str[param->conn_stat.state],
param->conn_stat.peer_feat,
param->conn_stat.chld_feat);
break;
case ESP_HF_CLIENT_AUDIO_STATE_EVT:
ESP_LOGE(BT_HF_TAG, “–audio state %s”,
c_audio_state_str[param->audio_stat.state]);
#if CONFIG_HFP_AUDIO_DATA_PATH_HCI
if ((param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_CONNECTED)
|| (param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC)) {
bt_app_hf_client_audio_open();
esp_hf_client_register_data_callback(bt_app_hf_client_incoming_cb,
bt_app_hf_client_outgoing_cb);
} else if (param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED) {
bt_app_hf_client_audio_close();
}
#endif /* #if CONFIG_HFP_AUDIO_DATA_PATH_HCI */
break;
case ESP_HF_CLIENT_BVRA_EVT:
ESP_LOGE(BT_HF_TAG, “–VR state %s”,
c_vr_state_str[param->bvra.value]);
break;
case ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT:
ESP_LOGE(BT_HF_TAG, “–NETWORK STATE %s”,
c_service_availability_status_str[param->service_availability.status]);
break;
case ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT:
ESP_LOGE(BT_HF_TAG, “–ROAMING: %s”,
c_roaming_status_str[param->roaming.status]);
break;
case ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT:
ESP_LOGE(BT_HF_TAG, “– signal strength: %d”,
param->signal_strength.value);
break;
case ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT:
ESP_LOGE(BT_HF_TAG, “–battery level %d”,
param->battery_level.value);
break;
case ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT:
ESP_LOGE(BT_HF_TAG, “–operator name: %s”,
param->cops.name);
break;
case ESP_HF_CLIENT_CIND_CALL_EVT:
ESP_LOGE(BT_HF_TAG, “–Call indicator %s”,
c_call_str[param->call.status]);
break;
case ESP_HF_CLIENT_CIND_CALL_SETUP_EVT:
ESP_LOGE(BT_HF_TAG, “–Call setup indicator %s”,
c_call_setup_str[param->call_setup.status]);
break;
case ESP_HF_CLIENT_CIND_CALL_HELD_EVT:
ESP_LOGE(BT_HF_TAG, “–Call held indicator %s”,
c_call_held_str[param->call_held.status]);
break;
case ESP_HF_CLIENT_BTRH_EVT:
ESP_LOGE(BT_HF_TAG, “–response and hold %s”,
c_resp_and_hold_str[param->btrh.status]);
break;
case ESP_HF_CLIENT_CLIP_EVT:
ESP_LOGE(BT_HF_TAG, “–clip number %s”,
(param->clip.number == NULL) ? “NULL” : (param->clip.number));
break;
case ESP_HF_CLIENT_CCWA_EVT:
ESP_LOGE(BT_HF_TAG, “–call_waiting %s”,
(param->ccwa.number == NULL) ? “NULL” : (param->ccwa.number));
break;
case ESP_HF_CLIENT_CLCC_EVT:
ESP_LOGE(BT_HF_TAG, “–Current call: idx %d, dir %s, state %s, mpty %s, number %s”,
param->clcc.idx,
c_call_dir_str[param->clcc.dir],
c_call_state_str[param->clcc.status],
c_call_mpty_type_str[param->clcc.mpty],
(param->clcc.number == NULL) ? “NULL” : (param->clcc.number));
break;
case ESP_HF_CLIENT_VOLUME_CONTROL_EVT:
ESP_LOGE(BT_HF_TAG, “–volume_target: %s, volume %d”,
c_volume_control_target_str[param->volume_control.type],
param->volume_control.volume);
break;
case ESP_HF_CLIENT_AT_RESPONSE_EVT:
ESP_LOGE(BT_HF_TAG, “–AT response event, code %d, cme %d”,
param->at_response.code, param->at_response.cme);
break;
case ESP_HF_CLIENT_CNUM_EVT:
ESP_LOGE(BT_HF_TAG, “–subscriber type %s, number %s”,
c_subscriber_service_type_str[param->cnum.type],
(param->cnum.number == NULL) ? “NULL” : param->cnum.number);
break;
case ESP_HF_CLIENT_BSIR_EVT:
ESP_LOGE(BT_HF_TAG, “–inband ring state %s”,
c_inband_ring_state_str[param->bsir.state]);
break;
case ESP_HF_CLIENT_BINP_EVT:
ESP_LOGE(BT_HF_TAG, “–last voice tag number: %s”,
(param->binp.number == NULL) ? “NULL” : param->binp.number);
break;
default:
ESP_LOGE(BT_HF_TAG, “HF_CLIENT EVT: %d”, event);
break;
}
}
void app_main(void)
{
esp_log_level_set(“*”, ESP_LOG_INFO);
esp_log_level_set(TAG, ESP_LOG_DEBUG);
esp_err_terr = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
// NVS partition was truncated and needs to be erased
// Retry nvs_flash_init
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_LOGI(TAG, “[ 1 ] Start codec chip”);
audio_board_handle_tboard_handle = audio_board_init();
audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_DECODE, AUDIO_HAL_CTRL_START);
ESP_LOGI(TAG, “[2.0] Create Bluetooth service”);
bluetooth_service_cfg_tbt_cfg = {
.device_name = “ESP-ADF-AUDIO”,
.mode = BLUETOOTH_A2DP_SINK,
};
bluetooth_service_start(&bt_cfg);
esp_hf_client_register_callback(bt_hf_client_cb);
esp_hf_client_init();
ESP_LOGI(TAG, “[2.0] Create audio pipelines for playback and save”);
audio_pipeline_cfg_tpipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
pipeline = audio_pipeline_init(&pipeline_cfg);
mem_assert(pipeline);
ESP_LOGI(TAG, “[3.0] Create fatfs stream to save file”);
fatfs_stream_cfg_tfatfs_cfg = FATFS_STREAM_CFG_DEFAULT();
fatfs_cfg.type = AUDIO_STREAM_WRITER;
el_fatfs_wr_stream = fatfs_stream_init(&fatfs_cfg);
ESP_LOGI(TAG, “[3.1] Set up uri for save file name”);
audio_element_set_uri(el_fatfs_wr_stream, “/sdcard/test_output.wav”);
ESP_LOGI(TAG, “[3.2] Create wav decoder to decode mp3 stream,”);
mp3_decoder_cfg_tmp3_cfg = DEFAULT_MP3_DECODER_CONFIG();
mp3_decoder = mp3_decoder_init(& mp3_cfg);
ESP_LOGI(TAG, “[3.2] Create Bluetooth stream”);
bt_stream_reader = bluetooth_service_create_stream();
ESP_LOGI(TAG, “[3.3] Register all elements to audio pipeline”);
audio_pipeline_register(pipeline, bt_stream_reader, “bt”);
audio_pipeline_register(pipeline, mp3_decoder, “mp3”);
audio_pipeline_register(pipeline, el_fatfs_wr_stream, “file”);
//vTaskDelay(1000);
// ESP_LOGI(TAG, “[3.4] Link elements together[Bluetooth]–>mp3_decoer–>bt_stream_reader–>file”);
// const char *link_save[3] = {“bt”, “mp3”, “file”};
// audio_pipeline_link(pipeline, &link_save[0], 3);
ESP_LOGI(TAG, “[3.4] Link elements together[Bluetooth]–>bt_stream_reader–>file”);
constchar *link_save[2] = {“bt”, “file”};
audio_pipeline_link(pipeline, &link_save[0], 2);
ESP_LOGI(TAG, “[ 4] Start and wait for SDCARD to mount”);
// Initialize peripherals management
esp_periph_config_tperiph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
esp_periph_set_handle_tset = esp_periph_set_init(&periph_cfg);
audio_board_sdcard_init(set, SD_MODE_1_LINE);
ESP_LOGI(TAG, “[ 5 ] Create Bluetooth peripheral”);
esp_periph_handle_tbt_periph = bluetooth_service_create_periph();
ESP_LOGI(TAG, “[ 6 ] Start all peripherals”);
esp_periph_start(set, bt_periph);
ESP_LOGI(TAG, “[ 7 ] Set up event listener”);
audio_event_iface_cfg_tevt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
audio_event_iface_handle_tevt = audio_event_iface_init(&evt_cfg);
ESP_LOGI(TAG, “[7.1] Listening event from all elements of pipeline”);
audio_pipeline_set_listener(pipeline, evt);
ESP_LOGI(TAG, “[7.2] Listening event from peripherals”);
audio_event_iface_set_listener(esp_periph_set_get_event_iface(set), evt);
ESP_LOGI(TAG, “[ 8 ] Start audio_pipeline”);
audio_pipeline_run(pipeline);
ESP_LOGI(TAG, “[ 9 ] Listen for all pipeline events”);
while (1) {
audio_event_iface_msg_tmsg;
esp_err_tret = audio_event_iface_listen(evt, &msg, portMAX_DELAY);
if (ret != ESP_OK) {
ESP_LOGE(TAG, “[ * ] Event interface error : %d”, ret);
continue;
}
/* Stop when the Bluetooth is disconnected or suspended */
if (msg.source_type == PERIPH_ID_BLUETOOTH
&& msg.source == (void *)bt_periph) {
if (msg.cmd == PERIPH_BLUETOOTH_DISCONNECTED) {
ESP_LOGW(TAG, “[ * ] Bluetooth disconnected”);
break;
}
}
/* Stop when the last pipeline element (file in this case) receives stop event */
if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void *) el_fatfs_wr_stream
&& msg.cmd == AEL_MSG_CMD_REPORT_STATUS && (int) msg.data == AEL_STATUS_STATE_STOPPED) {
ESP_LOGW(TAG, “[ * ] Stop event received”);
break;
}
}
ESP_LOGI(TAG, “[ 8 ] Stop audio_pipeline”);
audio_pipeline_stop(pipeline);
audio_pipeline_wait_for_stop(pipeline);
audio_pipeline_terminate(pipeline);
audio_pipeline_unregister(pipeline, bt_stream_reader);
audio_pipeline_unregister(pipeline, mp3_decoder);
audio_pipeline_unregister(pipeline, el_fatfs_wr_stream);
/* Terminate the pipeline before removing the listener */
audio_pipeline_remove_listener(pipeline);
/* Stop all peripherals before removing the listener */
esp_periph_set_stop_all(set);
audio_event_iface_remove_listener(esp_periph_set_get_event_iface(set), evt);
/* Make sure audio_pipeline_remove_listener & audio_event_iface_remove_listener are called before destroying event_iface */
audio_event_iface_destroy(evt);
/* Release all resources */
audio_pipeline_deinit(pipeline);
audio_element_deinit(bt_stream_reader);
audio_element_deinit(mp3_decoder);
audio_element_deinit(el_fatfs_wr_stream);
esp_periph_set_destroy(set);
bluetooth_service_destroy();
}
Hi.
To be honest, I have no idea.
Let us know if you find the solution.
Regards,
Sara