summaryrefslogtreecommitdiff
path: root/src/audio/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/include')
-rw-r--r--src/audio/include/audio_decoder.hpp13
-rw-r--r--src/audio/include/audio_element.hpp18
-rw-r--r--src/audio/include/audio_playback.hpp85
-rw-r--r--src/audio/include/audio_task.hpp3
-rw-r--r--src/audio/include/chunk.hpp13
-rw-r--r--src/audio/include/fatfs_audio_input.hpp11
-rw-r--r--src/audio/include/i2s_audio_output.hpp8
-rw-r--r--src/audio/include/stream_buffer.hpp37
-rw-r--r--src/audio/include/stream_info.hpp5
9 files changed, 96 insertions, 97 deletions
diff --git a/src/audio/include/audio_decoder.hpp b/src/audio/include/audio_decoder.hpp
index a6b15d9e..eaef2f8c 100644
--- a/src/audio/include/audio_decoder.hpp
+++ b/src/audio/include/audio_decoder.hpp
@@ -21,11 +21,15 @@ class AudioDecoder : public IAudioElement {
AudioDecoder();
~AudioDecoder();
- auto SetInputBuffer(MessageBufferHandle_t*) -> void;
- auto SetOutputBuffer(MessageBufferHandle_t*) -> void;
-
auto StackSizeBytes() const -> std::size_t override { return 8196; };
+ auto InputMinChunkSize() const -> std::size_t override {
+ // 128 kbps MPEG-1 @ 44.1 kHz is approx. 418 bytes according to the
+ // internet.
+ // TODO(jacqueline): tune as more codecs are added.
+ return 1024;
+ }
+
auto ProcessStreamInfo(const StreamInfo& info)
-> cpp::result<void, AudioProcessingError> override;
auto ProcessChunk(const cpp::span<std::byte>& chunk)
@@ -38,9 +42,6 @@ class AudioDecoder : public IAudioElement {
private:
std::unique_ptr<codecs::ICodec> current_codec_;
std::optional<StreamInfo> stream_info_;
-
- std::byte* raw_chunk_buffer_;
- cpp::span<std::byte> chunk_buffer_;
};
} // namespace audio
diff --git a/src/audio/include/audio_element.hpp b/src/audio/include/audio_element.hpp
index 1973fccf..590889bd 100644
--- a/src/audio/include/audio_element.hpp
+++ b/src/audio/include/audio_element.hpp
@@ -2,6 +2,7 @@
#include <cstdint>
+#include "chunk.hpp"
#include "freertos/FreeRTOS.h"
#include "freertos/message_buffer.h"
@@ -9,6 +10,7 @@
#include "result.hpp"
#include "span.hpp"
+#include "stream_buffer.hpp"
#include "stream_info.hpp"
#include "types.hpp"
@@ -41,7 +43,7 @@ enum AudioProcessingError {
class IAudioElement {
public:
IAudioElement() : input_buffer_(nullptr), output_buffer_(nullptr) {}
- virtual ~IAudioElement();
+ virtual ~IAudioElement() {}
/*
* Returns the stack size in bytes that this element requires. This should
@@ -57,11 +59,17 @@ class IAudioElement {
*/
virtual auto IdleTimeout() const -> TickType_t { return portMAX_DELAY; }
+ virtual auto InputMinChunkSize() const -> std::size_t { return 0; }
+
/* Returns this element's input buffer. */
- auto InputBuffer() const -> MessageBufferHandle_t* { return input_buffer_; }
+ auto InputBuffer() const -> StreamBuffer* { return input_buffer_; }
/* Returns this element's output buffer. */
- auto OutputBuffer() const -> MessageBufferHandle_t* { return output_buffer_; }
+ auto OutputBuffer() const -> StreamBuffer* { return output_buffer_; }
+
+ auto InputBuffer(StreamBuffer* b) -> void { input_buffer_ = b; }
+
+ auto OutputBuffer(StreamBuffer* b) -> void { output_buffer_ = b; }
/*
* Called when a StreamInfo message is received. Used to configure this
@@ -87,8 +95,8 @@ class IAudioElement {
virtual auto ProcessIdle() -> cpp::result<void, AudioProcessingError> = 0;
protected:
- MessageBufferHandle_t* input_buffer_;
- MessageBufferHandle_t* output_buffer_;
+ StreamBuffer* input_buffer_;
+ StreamBuffer* output_buffer_;
};
} // namespace audio
diff --git a/src/audio/include/audio_playback.hpp b/src/audio/include/audio_playback.hpp
index 41ab46d2..9a7c5fc0 100644
--- a/src/audio/include/audio_playback.hpp
+++ b/src/audio/include/audio_playback.hpp
@@ -3,95 +3,44 @@
#include <cstdint>
#include <memory>
#include <string>
+#include <vector>
-#include "audio_common.h"
-#include "audio_element.h"
-#include "audio_event_iface.h"
-#include "audio_pipeline.h"
+#include "audio_element.hpp"
#include "esp_err.h"
-#include "fatfs_stream.h"
-#include "i2s_stream.h"
-#include "mp3_decoder.h"
+#include "gpio_expander.hpp"
#include "result.hpp"
-
-#include "audio_output.hpp"
-#include "dac.hpp"
+#include "span.hpp"
#include "storage.hpp"
+#include "stream_buffer.hpp"
-namespace drivers {
+namespace audio {
/*
- * 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.
+ * TODO.
*/
class AudioPlayback {
public:
- enum Error { FATFS_INIT, I2S_INIT, PIPELINE_INIT };
- static auto create(std::unique_ptr<IAudioOutput> output)
+ enum Error { ERR_INIT_ELEMENT, ERR_MEM };
+ static auto create(drivers::GpioExpander* expander,
+ std::shared_ptr<drivers::SdStorage> storage)
-> 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);
+ // TODO(jacqueline): configure on the fly once we have things to configure.
+ AudioPlayback();
~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_;
+ auto ConnectElements(IAudioElement* src, IAudioElement* sink) -> void;
- audio_element_handle_t decoder_ = nullptr;
- Decoder decoder_type_ = NONE;
+ StreamBuffer stream_start_;
+ StreamBuffer stream_end_;
+ std::vector<std::unique_ptr<StreamBuffer>> element_buffers_;
};
-} // namespace drivers
+} // namespace audio
diff --git a/src/audio/include/audio_task.hpp b/src/audio/include/audio_task.hpp
index 05888170..ca75fbd2 100644
--- a/src/audio/include/audio_task.hpp
+++ b/src/audio/include/audio_task.hpp
@@ -10,7 +10,8 @@ struct AudioTaskArgs {
std::shared_ptr<IAudioElement>& element;
};
-auto StartAudioTask(std::shared_ptr<IAudioElement>& element) -> void;
+auto StartAudioTask(const std::string& name,
+ std::shared_ptr<IAudioElement> element) -> void;
void AudioTaskMain(void* args);
diff --git a/src/audio/include/chunk.hpp b/src/audio/include/chunk.hpp
index aadcbbdb..d55e5d9d 100644
--- a/src/audio/include/chunk.hpp
+++ b/src/audio/include/chunk.hpp
@@ -13,11 +13,10 @@
#include "freertos/queue.h"
#include "result.hpp"
#include "span.hpp"
+#include "stream_buffer.hpp"
namespace audio {
-extern const std::size_t kMaxChunkSize;
-
enum ChunkWriteResult {
// Returned when the callback does not write any data.
CHUNK_OUT_OF_DATA,
@@ -37,8 +36,7 @@ enum ChunkWriteResult {
* number of bytes it wrote. Return a value of 0 to indicate that there is no
* more input to read.
*/
-auto WriteChunksToStream(MessageBufferHandle_t* stream,
- cpp::span<std::byte> working_buffer,
+auto WriteChunksToStream(StreamBuffer* stream,
std::function<size_t(cpp::span<std::byte>)> callback,
TickType_t max_wait) -> ChunkWriteResult;
@@ -59,7 +57,7 @@ enum ChunkReadResult {
class ChunkReader {
public:
- ChunkReader(MessageBufferHandle_t* stream);
+ explicit ChunkReader(StreamBuffer* buffer);
~ChunkReader();
auto Reset() -> void;
@@ -83,10 +81,7 @@ class ChunkReader {
TickType_t max_wait) -> ChunkReadResult;
private:
- MessageBufferHandle_t* stream_;
- std::byte* raw_working_buffer_;
- cpp::span<std::byte> working_buffer_;
-
+ StreamBuffer* stream_;
std::size_t leftover_bytes_ = 0;
std::size_t last_message_size_ = 0;
};
diff --git a/src/audio/include/fatfs_audio_input.hpp b/src/audio/include/fatfs_audio_input.hpp
index 63555ddc..21c729be 100644
--- a/src/audio/include/fatfs_audio_input.hpp
+++ b/src/audio/include/fatfs_audio_input.hpp
@@ -4,6 +4,7 @@
#include <memory>
#include <string>
+#include "chunk.hpp"
#include "freertos/FreeRTOS.h"
#include "freertos/message_buffer.h"
@@ -12,6 +13,7 @@
#include "audio_element.hpp"
#include "storage.hpp"
+#include "stream_buffer.hpp"
namespace audio {
@@ -28,6 +30,9 @@ class FatfsAudioInput : public IAudioElement {
auto SendChunk(cpp::span<std::byte> dest) -> size_t;
+ FatfsAudioInput(const FatfsAudioInput&) = delete;
+ FatfsAudioInput& operator=(const FatfsAudioInput&) = delete;
+
private:
auto GetRingBufferDistance() const -> size_t;
@@ -39,14 +44,8 @@ class FatfsAudioInput : public IAudioElement {
cpp::span<std::byte>::iterator pending_read_pos_;
cpp::span<std::byte>::iterator file_buffer_write_pos_;
- std::byte* raw_chunk_buffer_;
- cpp::span<std::byte> chunk_buffer_;
-
FIL current_file_;
bool is_file_open_;
-
- uint8_t* output_buffer_memory_;
- StaticMessageBuffer_t output_buffer_metadata_;
};
} // namespace audio
diff --git a/src/audio/include/i2s_audio_output.hpp b/src/audio/include/i2s_audio_output.hpp
index 4b4a458d..9e59f8fd 100644
--- a/src/audio/include/i2s_audio_output.hpp
+++ b/src/audio/include/i2s_audio_output.hpp
@@ -16,13 +16,17 @@ class I2SAudioOutput : public IAudioElement {
public:
enum Error { DAC_CONFIG, I2S_CONFIG, STREAM_INIT };
static auto create(drivers::GpioExpander* expander)
- -> cpp::result<std::unique_ptr<I2SAudioOutput>, Error>;
+ -> cpp::result<std::shared_ptr<I2SAudioOutput>, Error>;
I2SAudioOutput(drivers::GpioExpander* expander,
std::unique_ptr<drivers::AudioDac> dac);
~I2SAudioOutput();
- auto SetInputBuffer(MessageBufferHandle_t* in) -> void { input_buffer_ = in; }
+ auto InputMinChunkSize() const -> std::size_t override {
+ // TODO(jacqueline): work out a good value here. Maybe similar to the total
+ // DMA buffer size?
+ return 128;
+ }
auto IdleTimeout() const -> TickType_t override;
auto ProcessStreamInfo(const StreamInfo& info)
diff --git a/src/audio/include/stream_buffer.hpp b/src/audio/include/stream_buffer.hpp
new file mode 100644
index 00000000..cfb4bf9d
--- /dev/null
+++ b/src/audio/include/stream_buffer.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <cstddef>
+#include <cstdint>
+
+#include "freertos/FreeRTOS.h"
+
+#include "freertos/message_buffer.h"
+#include "span.hpp"
+
+namespace audio {
+
+class StreamBuffer {
+ public:
+ explicit StreamBuffer(std::size_t chunk_size, std::size_t buffer_size);
+ ~StreamBuffer();
+
+ auto Handle() -> MessageBufferHandle_t* { return &handle_; }
+ auto ReadBuffer() -> cpp::span<std::byte> { return input_chunk_; }
+ auto WriteBuffer() -> cpp::span<std::byte> { return output_chunk_; }
+
+ StreamBuffer(const StreamBuffer&) = delete;
+ StreamBuffer& operator=(const StreamBuffer&) = delete;
+
+ private:
+ std::byte* raw_memory_;
+ StaticMessageBuffer_t metadata_;
+ MessageBufferHandle_t handle_;
+
+ std::byte* raw_input_chunk_;
+ cpp::span<std::byte> input_chunk_;
+
+ std::byte* raw_output_chunk_;
+ cpp::span<std::byte> output_chunk_;
+};
+
+} // namespace audio
diff --git a/src/audio/include/stream_info.hpp b/src/audio/include/stream_info.hpp
index 47bcaa45..45f10fc6 100644
--- a/src/audio/include/stream_info.hpp
+++ b/src/audio/include/stream_info.hpp
@@ -3,6 +3,7 @@
#include <cstdint>
#include <optional>
#include <string>
+#include <string_view>
#include "cbor.h"
#include "result.hpp"
@@ -19,10 +20,14 @@ class StreamInfo {
~StreamInfo() = default;
auto Path() const -> const std::optional<std::string>& { return path_; }
+ auto Path(const std::string_view& d) -> void { path_ = d; }
+
auto Channels() const -> const std::optional<uint8_t>& { return channels_; }
+
auto BitsPerSample() const -> const std::optional<uint8_t>& {
return bits_per_sample_;
}
+
auto SampleRate() const -> const std::optional<uint16_t>& {
return sample_rate_;
}