From 13bd2051ad760e90c77f09fb6710fc0ad6c708e6 Mon Sep 17 00:00:00 2001 From: Simon Weidacher Date: Sun, 26 Dec 2021 14:00:30 +0100 Subject: [PATCH] SDCard music player from dueros example. --- device/components/player/CMakeLists.txt | 7 + device/components/player/component.mk | 6 + device/components/player/esp_player_wrapper.c | 236 ++++++++++++++++++ device/components/player/esp_player_wrapper.h | 93 +++++++ device/main/AudioPlayer.cpp | 14 ++ device/main/AudioPlayer.hpp | 9 + device/main/CMakeLists.txt | 2 +- device/main/audio_setup.c | 213 ++++++++++++++++ device/main/audio_setup.h | 41 +++ device/main/main.cpp | 4 + 10 files changed, 624 insertions(+), 1 deletion(-) create mode 100644 device/components/player/CMakeLists.txt create mode 100644 device/components/player/component.mk create mode 100644 device/components/player/esp_player_wrapper.c create mode 100644 device/components/player/esp_player_wrapper.h create mode 100644 device/main/AudioPlayer.cpp create mode 100644 device/main/AudioPlayer.hpp create mode 100644 device/main/audio_setup.c create mode 100644 device/main/audio_setup.h diff --git a/device/components/player/CMakeLists.txt b/device/components/player/CMakeLists.txt new file mode 100644 index 0000000..781b494 --- /dev/null +++ b/device/components/player/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_SRCS "esp_player_wrapper.c") +set(COMPONENT_ADD_INCLUDEDIRS .) + + +set(COMPONENT_REQUIRES audio_sal esp-adf-libs audio_pipeline) + +register_component() diff --git a/device/components/player/component.mk b/device/components/player/component.mk new file mode 100644 index 0000000..65866c5 --- /dev/null +++ b/device/components/player/component.mk @@ -0,0 +1,6 @@ +# +# Main Makefile. This is basically the same as a component makefile. + +COMPONENT_ADD_INCLUDEDIRS := . + +COMPONENT_SRCDIRS := . \ No newline at end of file diff --git a/device/components/player/esp_player_wrapper.c b/device/components/player/esp_player_wrapper.c new file mode 100644 index 0000000..fe20ef5 --- /dev/null +++ b/device/components/player/esp_player_wrapper.c @@ -0,0 +1,236 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2018 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include +#include "esp_player_wrapper.h" +#include "esp_log.h" +#include "audio_mem.h" +#include "audio_error.h" + +typedef struct { + esp_audio_handle_t handle; + esp_audio_info_t backup_info; + bool backup_flag; +} esp_player_t; + +static const char *TAG = "ESP_PLAYER"; +static esp_player_t *esp_player; + +audio_err_t esp_player_init(esp_audio_handle_t handle) +{ + esp_player = audio_calloc(1, sizeof(esp_player_t)); + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + esp_player->handle = handle; + return ESP_ERR_AUDIO_NO_ERROR; +} + +audio_err_t esp_player_deinit() +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + audio_free(esp_player); + return 0; +} + +audio_err_t esp_player_music_play(const char *url, int pos, media_source_type_t type) +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + esp_audio_state_t st = {0}; + int ret = ESP_OK; + esp_audio_state_get(esp_player->handle, &st); + if (st.status == AUDIO_STATUS_RUNNING) { + ret = esp_audio_stop(esp_player->handle, TERMINATION_TYPE_NOW); + if (ret != ESP_ERR_AUDIO_NO_ERROR) { + return ret; + } + } + ret = esp_audio_media_type_set(esp_player->handle, type); + ret |= esp_audio_play(esp_player->handle, AUDIO_CODEC_TYPE_DECODER, url, pos); + return ret; +} + +audio_err_t esp_player_http_music_play(const char *url, int pos) +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + esp_audio_state_t st = {0}; + int ret = ESP_OK; + esp_audio_state_get(esp_player->handle, &st); + if (st.status == AUDIO_STATUS_RUNNING) { + ret = esp_audio_stop(esp_player->handle, TERMINATION_TYPE_NOW); + if (ret != ESP_ERR_AUDIO_NO_ERROR) { + return ret; + } + } + ret = esp_audio_media_type_set(esp_player->handle, MEDIA_SRC_TYPE_MUSIC_HTTP); + ret |= esp_audio_play(esp_player->handle, AUDIO_CODEC_TYPE_DECODER, url, pos); + return ret; +} + +audio_err_t esp_player_sdcard_music_play(const char *url, int pos) +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + esp_audio_state_t st = {0}; + int ret = ESP_OK; + esp_audio_state_get(esp_player->handle, &st); + if (st.status == AUDIO_STATUS_RUNNING) { + ret = esp_audio_stop(esp_player->handle, TERMINATION_TYPE_NOW); + if (ret != ESP_ERR_AUDIO_NO_ERROR) { + return ret; + } + } + ret = esp_audio_media_type_set(esp_player->handle, MEDIA_SRC_TYPE_MUSIC_SD); + ret |= esp_audio_play(esp_player->handle, AUDIO_CODEC_TYPE_DECODER, url, pos); + return ret; +} + +audio_err_t esp_player_flash_music_play(const char *url, int pos) +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + esp_audio_state_t st = {0}; + int ret = ESP_OK; + esp_audio_state_get(esp_player->handle, &st); + if (st.status == AUDIO_STATUS_RUNNING) { + ret = esp_audio_stop(esp_player->handle, TERMINATION_TYPE_NOW); + if (ret != ESP_ERR_AUDIO_NO_ERROR) { + return ret; + } + } + ret = esp_audio_media_type_set(esp_player->handle, MEDIA_SRC_TYPE_MUSIC_FLASH); + ret |= esp_audio_play(esp_player->handle, AUDIO_CODEC_TYPE_DECODER, url, pos); + return ret; +} + +audio_err_t esp_player_music_stop() +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + int ret = esp_audio_media_type_set(esp_player->handle, MEDIA_SRC_TYPE_NULL); + ret = esp_audio_stop(esp_player->handle, TERMINATION_TYPE_NOW); + return ret; +} + +audio_err_t esp_player_music_pause() +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + int ret = ESP_ERR_AUDIO_NOT_SUPPORT; + esp_audio_state_t st = {0}; + esp_audio_state_get(esp_player->handle, &st); + if (st.status == AUDIO_STATUS_RUNNING) { + ret = esp_audio_pause(esp_player->handle); + ret |= esp_audio_info_get(esp_player->handle, &esp_player->backup_info); + esp_player->backup_flag = true; + ESP_LOGD(TAG, "%s, i:%p, c:%p, f:%p, o:%p,status:%d", __func__, + esp_player->backup_info.in_el, + esp_player->backup_info.codec_el, + esp_player->backup_info.filter_el, + esp_player->backup_info.out_el, esp_player->backup_info.st.status); + return ret; + } else { + return ret; + } +} + +audio_err_t esp_player_music_resume() +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + int ret = ESP_ERR_AUDIO_NO_ERROR; + if (esp_player->backup_flag) { + esp_audio_info_set(esp_player->handle, &esp_player->backup_info); + esp_player->backup_flag = false; + ret = esp_audio_resume(esp_player->handle); + } else { + ret = esp_audio_resume(esp_player->handle); + } + return ret; +} + +audio_err_t esp_player_tone_play(const char *url, bool blocked, media_source_type_t type) +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + if ((type <= MEDIA_SRC_TYPE_TONE_BASE) + || (type >= MEDIA_SRC_TYPE_TONE_MAX) + || (url == NULL)) { + ESP_LOGE(TAG, "Invalid parameters, url:%p, type:%x", url, type); + return ESP_ERR_AUDIO_INVALID_PARAMETER; + } + int ret = esp_audio_media_type_set(esp_player->handle, type); + if (blocked) { + ret |= esp_audio_sync_play(esp_player->handle, url, 0); + } else { + ret |= esp_audio_play(esp_player->handle, AUDIO_CODEC_TYPE_DECODER, url, 0); + } + return ret; +} + +audio_err_t esp_player_tone_stop() +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + int ret = esp_audio_stop(esp_player->handle, TERMINATION_TYPE_NOW); + return ret; +} + +audio_err_t esp_player_state_get(esp_audio_state_t *state) +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + return esp_audio_state_get(esp_player->handle, state); +} + +media_source_type_t esp_player_media_src_get() +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + esp_audio_state_t st = {0}; + esp_audio_state_get(esp_player->handle, &st); + return st.media_src; +} + +bool esp_player_is_backup() +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + return esp_player->backup_flag; +} + +audio_err_t esp_player_time_get(int *time) +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + return esp_audio_time_get(esp_player->handle, time); +} + +audio_err_t esp_player_pos_get(int *pos) +{ + AUDIO_MEM_CHECK(TAG, esp_player, return ESP_ERR_AUDIO_MEMORY_LACK); + return esp_audio_pos_get(esp_player->handle, pos); +} + +audio_err_t esp_player_vol_get(int *vol) +{ + esp_audio_vol_get(esp_player->handle, vol); + return ESP_OK; +} + +audio_err_t esp_player_vol_set(int vol) +{ + esp_audio_vol_set(esp_player->handle, vol); + return ESP_OK; +} diff --git a/device/components/player/esp_player_wrapper.h b/device/components/player/esp_player_wrapper.h new file mode 100644 index 0000000..973a00f --- /dev/null +++ b/device/components/player/esp_player_wrapper.h @@ -0,0 +1,93 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2018 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef ESP_PLAYER_WRAPPER_H +#define ESP_PLAYER_WRAPPER_H + +#include "esp_audio.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * init audio wrapper + * + * @param cb audio wrapper callback function + * + * @return ESP_OK or ESP_FAIL + * + */ +audio_err_t esp_player_init(esp_audio_handle_t handle); + +/* + * deinit audio wrapper + * + * @param none + * + * @return ESP_OK or ESP_FAIL + * + */ +audio_err_t esp_player_deinit(); + +audio_err_t esp_player_music_play(const char *url, int pos, media_source_type_t type); + +audio_err_t esp_player_http_music_play(const char *url, int pos); + +audio_err_t esp_player_sdcard_music_play(const char *url, int pos); + +audio_err_t esp_player_flash_music_play(const char *url, int pos); + +audio_err_t esp_player_music_stop(); + +audio_err_t esp_player_music_pause(); + +audio_err_t esp_player_music_resume(); + +audio_err_t esp_player_tone_play(const char *url, bool blocked, media_source_type_t type); + +audio_err_t esp_player_tone_stop(); + + +audio_err_t esp_player_state_get(esp_audio_state_t *state); + +media_source_type_t esp_player_media_src_get(); + +bool esp_player_is_backup(); + +audio_err_t esp_player_time_get(int *time); + +audio_err_t esp_player_pos_get(int *pos); +audio_err_t esp_player_vol_get(int *vol); +audio_err_t esp_player_vol_set(int vol); + + +#ifdef __cplusplus +} +#endif + + +#endif // diff --git a/device/main/AudioPlayer.cpp b/device/main/AudioPlayer.cpp new file mode 100644 index 0000000..5632e8c --- /dev/null +++ b/device/main/AudioPlayer.cpp @@ -0,0 +1,14 @@ +#include "AudioPlayer.hpp" + +#include +#include "audio_setup.h" + + +AudioPlayer::AudioPlayer() { + playerHandle = setup_player(NULL, NULL); + esp_player_init(playerHandle); +} + +void AudioPlayer::play(char* uri) { + esp_player_sdcard_music_play(uri, 0); +} \ No newline at end of file diff --git a/device/main/AudioPlayer.hpp b/device/main/AudioPlayer.hpp new file mode 100644 index 0000000..61388b7 --- /dev/null +++ b/device/main/AudioPlayer.hpp @@ -0,0 +1,9 @@ +#pragma once + +class AudioPlayer { + void* playerHandle; + + public: + AudioPlayer(); + void play(char* uri); +}; \ No newline at end of file diff --git a/device/main/CMakeLists.txt b/device/main/CMakeLists.txt index 8391ded..bdce93c 100644 --- a/device/main/CMakeLists.txt +++ b/device/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "Networking.cpp" "main.cpp" "WebInterface.cpp" "RFIDInterface.cpp" +idf_component_register(SRCS "Networking.cpp" "main.cpp" "WebInterface.cpp" "RFIDInterface.cpp" "audio_setup.c" "AudioPlayer.cpp" INCLUDE_DIRS ".") diff --git a/device/main/audio_setup.c b/device/main/audio_setup.c new file mode 100644 index 0000000..ebec21e --- /dev/null +++ b/device/main/audio_setup.c @@ -0,0 +1,213 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/timers.h" +#include + +#include "esp_log.h" +#include "recorder_engine.h" +#include "esp_audio.h" +#include "audio_element.h" +#include "audio_pipeline.h" +#include "audio_mem.h" +#include "board.h" +#include "audio_common.h" +#include "audio_hal.h" +#include "filter_resample.h" +#include "fatfs_stream.h" +#include "raw_stream.h" +#include "i2s_stream.h" +#include "wav_decoder.h" +#include "wav_encoder.h" +#include "mp3_decoder.h" +#include "aac_decoder.h" +#include "http_stream.h" + +static char *TAG = "AUDIO_SETUP"; +static audio_element_handle_t raw_read; + +static int _http_stream_event_handle(http_stream_event_msg_t *msg) +{ + if (msg->event_id == HTTP_STREAM_RESOLVE_ALL_TRACKS) { + return ESP_OK; + } + + if (msg->event_id == HTTP_STREAM_FINISH_TRACK) { + return http_stream_next_track(msg->el); + } + if (msg->event_id == HTTP_STREAM_FINISH_PLAYLIST) { + return http_stream_restart(msg->el); + } + return ESP_OK; +} + + +void *setup_player(void *cb, void *ctx) +{ + esp_audio_cfg_t cfg = DEFAULT_ESP_AUDIO_CONFIG(); + audio_board_handle_t board_handle = audio_board_init(); + audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START); + + 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.resample_rate = 48000; + cfg.prefer_type = ESP_AUDIO_PREFER_MEM; + cfg.cb_func = cb; + cfg.cb_ctx = ctx; + esp_audio_handle_t handle = esp_audio_create(&cfg); + + // Create readers and add to esp_audio + fatfs_stream_cfg_t fs_reader = FATFS_STREAM_CFG_DEFAULT(); + fs_reader.type = AUDIO_STREAM_READER; + + esp_audio_input_stream_add(handle, fatfs_stream_init(&fs_reader)); + http_stream_cfg_t http_cfg = HTTP_STREAM_CFG_DEFAULT(); + http_cfg.event_handle = _http_stream_event_handle; + http_cfg.type = AUDIO_STREAM_READER; + http_cfg.enable_playlist_parser = true; + audio_element_handle_t http_stream_reader = http_stream_init(&http_cfg); + esp_audio_input_stream_add(handle, http_stream_reader); + http_stream_reader = http_stream_init(&http_cfg); + esp_audio_input_stream_add(handle, http_stream_reader); + + // Add decoders and encoders to esp_audio + wav_decoder_cfg_t wav_dec_cfg = DEFAULT_WAV_DECODER_CONFIG(); + mp3_decoder_cfg_t mp3_dec_cfg = DEFAULT_MP3_DECODER_CONFIG(); + mp3_dec_cfg.task_core = 1; + aac_decoder_cfg_t aac_cfg = DEFAULT_AAC_DECODER_CONFIG(); + aac_cfg.task_core = 1; + esp_audio_codec_lib_add(handle, AUDIO_CODEC_TYPE_DECODER, aac_decoder_init(&aac_cfg)); + esp_audio_codec_lib_add(handle, AUDIO_CODEC_TYPE_DECODER, wav_decoder_init(&wav_dec_cfg)); + esp_audio_codec_lib_add(handle, AUDIO_CODEC_TYPE_DECODER, mp3_decoder_init(&mp3_dec_cfg)); + + audio_element_handle_t m4a_dec_cfg = aac_decoder_init(&aac_cfg); + audio_element_set_tag(m4a_dec_cfg, "m4a"); + esp_audio_codec_lib_add(handle, AUDIO_CODEC_TYPE_DECODER, m4a_dec_cfg); + + audio_element_handle_t ts_dec_cfg = aac_decoder_init(&aac_cfg); + audio_element_set_tag(ts_dec_cfg, "ts"); + esp_audio_codec_lib_add(handle, AUDIO_CODEC_TYPE_DECODER, ts_dec_cfg); + + // Create writers and add to esp_audio + i2s_stream_cfg_t i2s_writer = I2S_STREAM_CFG_DEFAULT(); + i2s_writer.type = AUDIO_STREAM_WRITER; + i2s_writer.i2s_config.sample_rate = 48000; + esp_audio_output_stream_add(handle, i2s_stream_init(&i2s_writer)); + + // Set default volume + esp_audio_vol_set(handle, 60); + AUDIO_MEM_SHOW(TAG); + ESP_LOGI(TAG, "esp_audio instance is:%p", handle); + return handle; +} + +static esp_err_t recorder_pipeline_open(void **handle) +{ + audio_element_handle_t i2s_stream_reader; + audio_pipeline_handle_t recorder; + audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG(); + recorder = audio_pipeline_init(&pipeline_cfg); + if (NULL == recorder) { + return ESP_FAIL; + } + +#ifdef CONFIG_ESP_LYRAT_MINI_V1_1_BOARD + i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT(); + i2s_cfg.i2s_port = 1; + i2s_cfg.i2s_config.use_apll = 0; + i2s_cfg.i2s_config.sample_rate = 16000; + i2s_cfg.i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT; + i2s_cfg.type = AUDIO_STREAM_READER; + i2s_stream_reader = i2s_stream_init(&i2s_cfg); +#else + i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT(); + i2s_cfg.type = AUDIO_STREAM_READER; + i2s_stream_reader = i2s_stream_init(&i2s_cfg); + audio_element_info_t i2s_info = {0}; + audio_element_getinfo(i2s_stream_reader, &i2s_info); + i2s_info.bits = 16; + i2s_info.channels = 2; + i2s_info.sample_rates = 48000; + audio_element_setinfo(i2s_stream_reader, &i2s_info); + + rsp_filter_cfg_t rsp_cfg = DEFAULT_RESAMPLE_FILTER_CONFIG(); + rsp_cfg.src_rate = 48000; + rsp_cfg.src_ch = 2; + rsp_cfg.dest_rate = 16000; + rsp_cfg.dest_ch = 1; + audio_element_handle_t filter = rsp_filter_init(&rsp_cfg); +#endif + + raw_stream_cfg_t raw_cfg = RAW_STREAM_CFG_DEFAULT(); + raw_cfg.type = AUDIO_STREAM_READER; + raw_read = raw_stream_init(&raw_cfg); + + audio_pipeline_register(recorder, i2s_stream_reader, "i2s"); + audio_pipeline_register(recorder, raw_read, "raw"); + + +#ifdef CONFIG_ESP_LYRAT_MINI_V1_1_BOARD + const char *link_tag[2] = {"i2s", "raw"}; + audio_pipeline_link(recorder, &link_tag[0], 2); +#else + audio_pipeline_register(recorder, filter, "filter"); + const char *link_tag[3] = {"i2s", "filter", "raw"}; + audio_pipeline_link(recorder, &link_tag[0], 3); +#endif + + audio_pipeline_run(recorder); + ESP_LOGI(TAG, "Recorder has been created"); + *handle = recorder; + return ESP_OK; +} + +static esp_err_t recorder_pipeline_read(void *handle, char *data, int data_size) +{ + raw_stream_read(raw_read, data, data_size); + return ESP_OK; +} + +static esp_err_t recorder_pipeline_close(void *handle) +{ + audio_pipeline_deinit(handle); + return ESP_OK; +} + +void setup_recorder(rec_callback cb, void *ctx) +{ + rec_config_t eng = DEFAULT_REC_ENGINE_CONFIG(); + eng.vad_off_delay_ms = 800; + eng.wakeup_time_ms = 10 * 1000; + eng.evt_cb = cb; + eng.open = recorder_pipeline_open; + eng.close = recorder_pipeline_close; + eng.fetch = recorder_pipeline_read; + eng.extension = NULL; + eng.support_encoding = false; + eng.user_data = ctx; + rec_engine_create(&eng); +} diff --git a/device/main/audio_setup.h b/device/main/audio_setup.h new file mode 100644 index 0000000..3501f9b --- /dev/null +++ b/device/main/audio_setup.h @@ -0,0 +1,41 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __AUDIO_SETUP_H__ +#define __AUDIO_SETUP_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +void *setup_player(void* cb, void *ctx); +void setup_recorder(void* cb, void *ctx); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/device/main/main.cpp b/device/main/main.cpp index 8d28186..ab355b3 100644 --- a/device/main/main.cpp +++ b/device/main/main.cpp @@ -3,6 +3,7 @@ #include "Networking.hpp" #include "WebInterface.hpp" #include "RFIDInterface.hpp" +#include "AudioPlayer.hpp" extern "C" { void app_main(); @@ -21,4 +22,7 @@ void app_main(void) { rfid.registerWebResources(&webInterface); webInterface.finishResourceRegistrations(); + + AudioPlayer audioPlayer; // initialize here, because the ctor does init stuff that fails when executed before `app_main()` + audioPlayer.play("file://sdcard/howcanwehangontoadream.mp3"); }