diff options
Diffstat (limited to 'src/audio/include/audio_playback.hpp')
| -rw-r--r-- | src/audio/include/audio_playback.hpp | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/audio/include/audio_playback.hpp b/src/audio/include/audio_playback.hpp new file mode 100644 index 00000000..41ab46d2 --- /dev/null +++ b/src/audio/include/audio_playback.hpp @@ -0,0 +1,97 @@ +#pragma once + +#include <cstdint> +#include <memory> +#include <string> + +#include "audio_common.h" +#include "audio_element.h" +#include "audio_event_iface.h" +#include "audio_pipeline.h" +#include "esp_err.h" +#include "fatfs_stream.h" +#include "i2s_stream.h" +#include "mp3_decoder.h" +#include "result.hpp" + +#include "audio_output.hpp" +#include "dac.hpp" +#include "storage.hpp" + +namespace drivers { + +/* + * Sends an I2S audio stream to the DAC. Includes basic controls for pausing + * and resuming the stream, as well as support for gapless playback of the next + * queued song, but does not implement any kind of sophisticated queing or + * playback control; these should be handled at a higher level. + */ +class AudioPlayback { + public: + enum Error { FATFS_INIT, I2S_INIT, PIPELINE_INIT }; + static auto create(std::unique_ptr<IAudioOutput> output) + -> cpp::result<std::unique_ptr<AudioPlayback>, Error>; + + AudioPlayback(std::unique_ptr<IAudioOutput>& output, + audio_pipeline_handle_t pipeline, + audio_element_handle_t source_element, + audio_event_iface_handle_t event_interface); + ~AudioPlayback(); + + /* + * Replaces any currently playing file with the one given, and begins + * playback. + * + * Any value set in `set_next_file` is cleared by this method. + */ + auto Play(const std::string& filename) -> void; + /* Toogle between resumed and paused. */ + auto Toggle() -> void; + auto Resume() -> void; + auto Pause() -> void; + + enum PlaybackState { PLAYING, PAUSED, STOPPED }; + auto GetPlaybackState() const -> PlaybackState; + + /* + * Handles any pending events from the underlying audio pipeline. This must + * be called regularly in order to handle configuring the I2S stream for + * different audio types (e.g. sample rate, bit depth), and for gapless + * playback. + */ + auto ProcessEvents(uint16_t max_time_ms) -> void; + + /* + * Sets the file that should be played immediately after the current file + * finishes. This is used for gapless playback + */ + auto SetNextFile(const std::string& filename) -> void; + + auto SetVolume(uint8_t volume) -> void; + auto GetVolume() const -> uint8_t; + + // Not copyable or movable. + AudioPlayback(const AudioPlayback&) = delete; + AudioPlayback& operator=(const AudioPlayback&) = delete; + + private: + PlaybackState playback_state_; + + enum Decoder { NONE, MP3, AMR, OPUS, OGG, FLAC, WAV, AAC }; + auto GetDecoderForFilename(std::string filename) const -> Decoder; + auto CreateDecoder(Decoder decoder) const -> audio_element_handle_t; + auto ReconfigurePipeline(Decoder decoder) -> void; + + std::unique_ptr<IAudioOutput> output_; + + std::string next_filename_ = ""; + + audio_pipeline_handle_t pipeline_; + audio_element_handle_t source_element_; + audio_event_iface_handle_t event_interface_; + + audio_element_handle_t decoder_ = nullptr; + Decoder decoder_type_ = NONE; +}; + +} // namespace drivers |
