You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.8 KiB
98 lines
2.8 KiB
2 years ago
|
#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"
|
||
|
|
||
2 years ago
|
#include "audio_output.hpp"
|
||
|
#include "dac.hpp"
|
||
|
#include "storage.hpp"
|
||
|
|
||
2 years ago
|
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>;
|
||
|
|
||
2 years ago
|
AudioPlayback(std::unique_ptr<IAudioOutput>& output,
|
||
|
audio_pipeline_handle_t pipeline,
|
||
|
audio_element_handle_t source_element,
|
||
|
audio_event_iface_handle_t event_interface);
|
||
2 years ago
|
~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.
|
||
|
*/
|
||
2 years ago
|
auto Play(const std::string& filename) -> void;
|
||
2 years ago
|
/* Toogle between resumed and paused. */
|
||
2 years ago
|
auto Toggle() -> void;
|
||
|
auto Resume() -> void;
|
||
|
auto Pause() -> void;
|
||
2 years ago
|
|
||
|
enum PlaybackState { PLAYING, PAUSED, STOPPED };
|
||
2 years ago
|
auto GetPlaybackState() const -> PlaybackState;
|
||
2 years ago
|
|
||
|
/*
|
||
|
* 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.
|
||
|
*/
|
||
2 years ago
|
auto ProcessEvents(uint16_t max_time_ms) -> void;
|
||
2 years ago
|
|
||
|
/*
|
||
|
* Sets the file that should be played immediately after the current file
|
||
|
* finishes. This is used for gapless playback
|
||
|
*/
|
||
2 years ago
|
auto SetNextFile(const std::string& filename) -> void;
|
||
2 years ago
|
|
||
2 years ago
|
auto SetVolume(uint8_t volume) -> void;
|
||
|
auto GetVolume() const -> uint8_t;
|
||
2 years ago
|
|
||
|
// Not copyable or movable.
|
||
|
AudioPlayback(const AudioPlayback&) = delete;
|
||
|
AudioPlayback& operator=(const AudioPlayback&) = delete;
|
||
|
|
||
|
private:
|
||
2 years ago
|
PlaybackState playback_state_;
|
||
2 years ago
|
|
||
2 years ago
|
enum Decoder { NONE, MP3, AMR, OPUS, OGG, FLAC, WAV, AAC };
|
||
2 years ago
|
auto GetDecoderForFilename(std::string filename) const -> Decoder;
|
||
|
auto CreateDecoder(Decoder decoder) const -> audio_element_handle_t;
|
||
2 years ago
|
auto ReconfigurePipeline(Decoder decoder) -> void;
|
||
2 years ago
|
|
||
|
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
|