diff --git a/src/drivers/audio_playback.cpp b/src/drivers/audio_playback.cpp index b38d0bd3..55da2bfb 100644 --- a/src/drivers/audio_playback.cpp +++ b/src/drivers/audio_playback.cpp @@ -1,36 +1,30 @@ #include "audio_playback.hpp" #include "audio_output.hpp" -#include "dac.hpp" #include #include -#include #include #include #include "audio_element.h" #include "audio_event_iface.h" #include "audio_pipeline.h" -#include "driver/i2s.h" #include "esp_err.h" -#include "freertos/portmacro.h" + +#include "aac_decoder.h" +#include "amr_decoder.h" +#include "flac_decoder.h" #include "mp3_decoder.h" +#include "ogg_decoder.h" +#include "opus_decoder.h" +#include "wav_decoder.h" static const char* kTag = "PLAYBACK"; static const char* kSource = "src"; -static const char* kEncoder = "enc"; +static const char* kDecoder = "dec"; static const char* kSink = "sink"; -static bool endsWith(std::string_view str, std::string_view suffix) { - return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix); -} - -static void toLower(std::string &str) { - std::transform(str.begin(), str.end(), str.begin(), - [](unsigned char c) { return std::tolower(c); }); -} - namespace drivers { static audio_element_status_t status_from_the_void(void* status) { @@ -38,6 +32,16 @@ static audio_element_status_t status_from_the_void(void* status) { return static_cast(as_pointer_int); } +static bool endsWith(std::string_view str, std::string_view suffix) { + return str.size() >= suffix.size() && + 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix); +} + +static void toLower(std::string& str) { + std::transform(str.begin(), str.end(), str.begin(), + [](unsigned char c) { return std::tolower(c); }); +} + auto AudioPlayback::create(std::unique_ptr output) -> cpp::result, Error> { audio_pipeline_handle_t pipeline; @@ -67,18 +71,17 @@ auto AudioPlayback::create(std::unique_ptr output) audio_element_msg_set_listener(output->GetAudioElement(), event_interface); audio_pipeline_register(pipeline, fatfs_stream_reader, kSource); - audio_pipeline_register(pipeline, outut->GetAudioElement(), kSink); - + audio_pipeline_register(pipeline, output->GetAudioElement(), kSink); - return std::make_unique(output, pipeline, fatfs_stream_reader, event_interface + return std::make_unique(output, pipeline, fatfs_stream_reader, + event_interface); } -AudioPlayback::AudioPlayback(std::unique_ptr output, - audio_pipeline_handle_t pipeline, - audio_element_handle_t source_element, - audio_event_iface_handle_t event_interface, - audio_element_handle_t mp3_decoder) - : output_(std::move(outout)), +AudioPlayback::AudioPlayback(std::unique_ptr& output, + audio_pipeline_handle_t pipeline, + audio_element_handle_t source_element, + audio_event_iface_handle_t event_interface) + : output_(std::move(output)), pipeline_(pipeline), source_element_(source_element), event_interface_(event_interface) {} @@ -86,7 +89,8 @@ AudioPlayback::AudioPlayback(std::unique_ptr output, AudioPlayback::~AudioPlayback() { audio_pipeline_remove_listener(pipeline_); audio_element_msg_remove_listener(source_element_, event_interface_); - audio_element_msg_remove_listener(output_->GetAudioElement(), event_interface_); + audio_element_msg_remove_listener(output_->GetAudioElement(), + event_interface_); audio_pipeline_stop(pipeline_); audio_pipeline_wait_for_stop(pipeline_); @@ -117,7 +121,7 @@ void AudioPlayback::Play(const std::string& filename) { audio_pipeline_reset_ringbuffer(pipeline_); audio_pipeline_reset_elements(pipeline_); audio_pipeline_run(pipeline_); - dac_->WriteVolume(volume_); + output_->SetVolume(volume_); } void AudioPlayback::Resume() { @@ -143,8 +147,8 @@ void AudioPlayback::ProcessEvents(uint16_t max_time_ms) { } while (1) { audio_event_iface_msg_t event; - esp_err_t err = - audio_event_iface_listen(event_interface_, &event, pdMS_TO_TICKS(max_time_ms)); + esp_err_t err = audio_event_iface_listen(event_interface_, &event, + pdMS_TO_TICKS(max_time_ms)); if (err != ESP_OK) { ESP_LOGE(kTag, "error listening for event:%x", err); continue; @@ -176,7 +180,7 @@ void AudioPlayback::ProcessEvents(uint16_t max_time_ms) { if (next_filename_ != "") { Decoder decoder = GetDecoderForFilename(next_filename_); if (decoder == decoder_type_) { - audio_element_set_uri(source_element_, next_filename_); + audio_element_set_uri(source_element_, next_filename_.c_str()); audio_pipeline_reset_ringbuffer(pipeline_); audio_pipeline_reset_elements(pipeline_); audio_pipeline_change_state(pipeline_, AEL_STATE_INIT); @@ -221,7 +225,7 @@ auto AudioPlayback::GetDecoderForFilename(std::string filename) -> Decoder { if (endsWith(filename, "mp3")) { return MP3; } - if (endsWith(filename, "amr") || endsWith(filename, "wamr") { + if (endsWith(filename, "amr") || endsWith(filename, "wamr")) { return AMR; } if (endsWith(filename, "opus")) { @@ -236,38 +240,43 @@ auto AudioPlayback::GetDecoderForFilename(std::string filename) -> Decoder { if (endsWith(filename, "wav")) { return WAV; } - if (endsWith(filename, "aac") || endsWith(filename, "m4a") || endsWith(filename, "ts") || endsWith(filename, "mp4")) { + if (endsWith(filename, "aac") || endsWith(filename, "m4a") || + endsWith(filename, "ts") || endsWith(filename, "mp4")) { return AAC; } return NONE; } auto AudioPlayback::CreateDecoder(Decoder decoder) -> audio_element_handle_t { - switch (decoder) { - case MP3: - mp3_decoder_cfg_t config = DEFAULT_MP3_DECODER_CONFIG(); - return mp3_decoder_init(&config); - case AMR: - amr_decoder_cfg_t config = DEFAULT_AMR_DECODER_CONFIG(); - return amr_decoder_init(&config); - case OPUS: - opus_decoder_cfg_t config = DEFAULT_OPUS_DECODER_CONFIG(); - return decoder_opus_init(&config); - case OGG: - ogg_decoder_cfg_t config = DEFAULT_OGG_DECODER_CONFIG(); - return ogg_decoder_init(&config); - case FLAC: - flac_decoder_cfg_t config = DEFAULT_FLAC_DECODER_CONFIG(); - return flac_decoder_init(&config); - case WAV: - wav_decoder_cfg_t config = DEFAULT_WAV_DECODER_CONFIG(); - return wav_decoder_init(&config); - case AAC: - aac_decoder_cfg_t aac_dec_cfg = DEFAULT_AAC_DECODER_CONFIG(); - return aac_decoder_init(&aac_dec_cfg); - default: - return nullptr; + if (decoder == MP3) { + mp3_decoder_cfg_t config = DEFAULT_MP3_DECODER_CONFIG(); + return mp3_decoder_init(&config); + } + if (decoder == AMR) { + amr_decoder_cfg_t config = DEFAULT_AMR_DECODER_CONFIG(); + return amr_decoder_init(&config); + } + if (decoder == OPUS) { + opus_decoder_cfg_t config = DEFAULT_OPUS_DECODER_CONFIG(); + return decoder_opus_init(&config); + } + if (decoder == OGG) { + ogg_decoder_cfg_t config = DEFAULT_OGG_DECODER_CONFIG(); + return ogg_decoder_init(&config); + } + if (decoder == FLAC) { + flac_decoder_cfg_t config = DEFAULT_FLAC_DECODER_CONFIG(); + return flac_decoder_init(&config); + } + if (decoder == WAV) { + wav_decoder_cfg_t config = DEFAULT_WAV_DECODER_CONFIG(); + return wav_decoder_init(&config); + } + if (decoder == AAC) { + aac_decoder_cfg_t config = DEFAULT_AAC_DECODER_CONFIG(); + return aac_decoder_init(&config); } + return nullptr; } void AudioPlayback::ReconfigurePipeline(Decoder decoder) { @@ -276,7 +285,7 @@ void AudioPlayback::ReconfigurePipeline(Decoder decoder) { } if (decoder_type_ != NONE) { - audio_pipeline_unlink(pipeline); + audio_pipeline_unlink(pipeline_); audio_element_msg_remove_listener(decoder_, event_interface_); audio_pipeline_unregister(pipeline_, decoder_); audio_element_deinit(decoder_); @@ -288,7 +297,7 @@ void AudioPlayback::ReconfigurePipeline(Decoder decoder) { audio_pipeline_register(pipeline_, decoder_, kDecoder); audio_element_msg_set_listener(decoder_, event_interface_); static const char* link_tag[3] = {kSource, kDecoder, kSink}; - audio_pipeline_link(pipeline, &link_tag[0], 3); + audio_pipeline_link(pipeline_, &link_tag[0], 3); } } diff --git a/src/drivers/i2s_audio_output.cpp b/src/drivers/i2s_audio_output.cpp index 6b231f0e..8505895b 100644 --- a/src/drivers/i2s_audio_output.cpp +++ b/src/drivers/i2s_audio_output.cpp @@ -1,19 +1,24 @@ #include "i2s_audio_output.hpp" + #include -#include "audio_output.hpp" -#include "gpio-expander.hpp" + +#include "audio_element.h" +#include "driver/i2s.h" +#include "esp_err.h" +#include "freertos/portmacro.h" +#include "i2s_stream.h" static const i2s_port_t kI2SPort = I2S_NUM_0; +static const char* kTag = "I2SOUT"; namespace drivers { -auto I2SAudioOutput::create(GpioExpander *expander) +auto I2SAudioOutput::create(GpioExpander* expander) -> cpp::result, Error> { - // First, we need to perform initial configuration of the DAC chip. auto dac_result = drivers::AudioDac::create(expander); if (dac_result.has_error()) { - ESP_LOGE(TAG, "failed to init dac: %d", dac_result.error()); + ESP_LOGE(kTag, "failed to init dac: %d", dac_result.error()); return cpp::fail(DAC_CONFIG); } std::unique_ptr dac = std::move(dac_result.value()); @@ -54,7 +59,8 @@ auto I2SAudioOutput::create(GpioExpander *expander) .need_expand = false, .expand_src_bits = I2S_BITS_PER_SAMPLE_16BIT, }; - i2s_stream_writer = i2s_stream_init(&i2s_stream_config); + audio_element_handle_t i2s_stream_writer = + i2s_stream_init(&i2s_stream_config); if (i2s_stream_writer == NULL) { return cpp::fail(Error::STREAM_INIT); } @@ -74,8 +80,10 @@ auto I2SAudioOutput::create(GpioExpander *expander) return std::make_unique(dac, i2s_stream_writer); } -I2SAudioOutput(std::unique dac, audio_element_handle_t element) : IAudioOutput(element), dac_(dac) {} -~I2SAudioOutput() { +I2SAudioOutput::I2SAudioOutput(std::unique_ptr& dac, + audio_element_handle_t element) + : IAudioOutput(element), dac_(std::move(dac)) {} +I2SAudioOutput::~I2SAudioOutput() { // TODO: power down the DAC. } @@ -83,10 +91,9 @@ auto I2SAudioOutput::SetVolume(uint8_t volume) -> void { dac_->WriteVolume(255); } -auto I2SAudioOutput::Configure(audio_element_info_t info) -> void { - audio_element_setinfo(element_, &music_info); - i2s_stream_set_clk(element_, music_info.sample_rates, - music_info.bits, music_info.channels); +auto I2SAudioOutput::Configure(audio_element_info_t& info) -> void { + audio_element_setinfo(element_, &info); + i2s_stream_set_clk(element_, info.sample_rates, info.bits, info.channels); } -} +} // namespace drivers diff --git a/src/drivers/include/a2dp_audio_output.hpp b/src/drivers/include/a2dp_audio_output.hpp index 43b55956..32398880 100644 --- a/src/drivers/include/a2dp_audio_output.hpp +++ b/src/drivers/include/a2dp_audio_output.hpp @@ -1,15 +1,15 @@ #pragma once +#include #include "audio_common.h" #include "audio_element.h" #include "audio_output.hpp" -#include namespace drivers { class A2DPAudioOutput : IAudioOutput { - public: - virtual auto SetVolume(uint8_t volume) -> void; + public: + virtual auto SetVolume(uint8_t volume) -> void; }; -} // namespace drivers +} // namespace drivers diff --git a/src/drivers/include/audio_output.hpp b/src/drivers/include/audio_output.hpp index 63cba465..739dddfe 100644 --- a/src/drivers/include/audio_output.hpp +++ b/src/drivers/include/audio_output.hpp @@ -1,27 +1,24 @@ #pragma once +#include +#include #include "audio_common.h" #include "audio_element.h" -#include namespace drivers { class IAudioOutput { - public: - IAudioOutput(audio_element_handle_t element) : element_(element) {} - virtual ~IAudioOutput() { - audio_element_deinit(element_); - } + public: + IAudioOutput(audio_element_handle_t element) : element_(element) {} + virtual ~IAudioOutput() { audio_element_deinit(element_); } - auto GetAudioElement() -> audio_element_handle_t { - return element_; - } + auto GetAudioElement() -> audio_element_handle_t { return element_; } - virtual auto SetVolume(uint8_t volume) -> void = 0; - virtual auto Configure(audio_element_info_t info) -> void = 0; + virtual auto SetVolume(uint8_t volume) -> void = 0; + virtual auto Configure(audio_element_info_t& info) -> void = 0; - protected: - audio_element_handle_t element_; + protected: + audio_element_handle_t element_; }; -} // namespace drivers +} // namespace drivers diff --git a/src/drivers/include/audio_playback.hpp b/src/drivers/include/audio_playback.hpp index dd0f7f7a..d26fcda2 100644 --- a/src/drivers/include/audio_playback.hpp +++ b/src/drivers/include/audio_playback.hpp @@ -32,10 +32,10 @@ class AudioPlayback { static auto create(std::unique_ptr output) -> cpp::result, Error>; - AudioPlayback(std::unqiue_ptr output, - audio_pipeline_handle_t pipeline, - audio_element_handle_t source_element, - audio_event_iface_handle_t event_interface); + AudioPlayback(std::unique_ptr& output, + audio_pipeline_handle_t pipeline, + audio_element_handle_t source_element, + audio_event_iface_handle_t event_interface); ~AudioPlayback(); /* @@ -77,10 +77,10 @@ class AudioPlayback { private: PlaybackState current_state_; - enum Decoder {NONE, MP3, AMR, OPUS, OGG, FLAC, WAV, AAC}; + enum Decoder { NONE, MP3, AMR, OPUS, OGG, FLAC, WAV, AAC }; auto GetDecoderForFilename(std::string filename) -> Decoder; auto CreateDecoder(Decoder decoder) -> audio_element_handle_t; - void ReconfigurePipeline(); + auto ReconfigurePipeline(Decoder decoder) -> void; std::unique_ptr output_; std::mutex playback_lock_; diff --git a/src/drivers/include/i2s_audio_output.hpp b/src/drivers/include/i2s_audio_output.hpp index 531bddbc..1ec97307 100644 --- a/src/drivers/include/i2s_audio_output.hpp +++ b/src/drivers/include/i2s_audio_output.hpp @@ -1,30 +1,32 @@ #pragma once -#include "audio_common.h" -#include "audio_element.h" #include "audio_output.hpp" +#include "dac.hpp" #include "gpio-expander.hpp" +#include "result.hpp" + #include #include -#include "result.hpp" -#include "dac.hpp" + +#include "audio_element.h" namespace drivers { class I2SAudioOutput : public IAudioOutput { - public: + public: enum Error { DAC_CONFIG, I2S_CONFIG, STREAM_INIT }; - static auto create(GpioExpander* expander) - -> cpp::result, Error>; + static auto create(GpioExpander* expander) + -> cpp::result, Error>; - I2SAudioOutput(AudioDac* dac, audio_element_handle_t element); + I2SAudioOutput(std::unique_ptr& dac, + audio_element_handle_t element); ~I2SAudioOutput(); virtual auto SetVolume(uint8_t volume) -> void; - virtual auto Configure(audio_element_info_t info) -> void; + virtual auto Configure(audio_element_info_t& info) -> void; - private: - std::unique_ptr dac_; + private: + std::unique_ptr dac_; }; -} // namespace drivers +} // namespace drivers diff --git a/src/main/main.cpp b/src/main/main.cpp index 8233b15f..1bcf14ae 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -11,7 +11,8 @@ #include "i2s_audio_output.hpp" #include "misc/lv_color.h" #include "misc/lv_timer.h" -#include "playback.hpp" +#include "audio_playback.hpp" +#include "i2s_audio_output.hpp" #include "spi.hpp" #include "storage.hpp" @@ -119,7 +120,7 @@ extern "C" void app_main(void) { ESP_LOGE(TAG, "Failed: %d", sink_res.error()); return; } - std::unique_ptr sink = std::move(sink_res.value()); + std::unique_ptr sink = std::move(sink_res.value()); ESP_LOGI(TAG, "Init Audio Pipeline"); auto playback_res = drivers::AudioPlayback::create(std::move(sink));