summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-04-19 13:00:42 +1000
committerjacqueline <me@jacqueline.id.au>2023-04-19 13:00:42 +1000
commit561f9d2a07ee6ee1c2f18dc375125f87ea7b0d55 (patch)
treee55d86fa2a44b501ab2f190916b5cd9b207fd606 /src
parent25c5896dc5c239e3a175c6c8fc5d7368946adeb6 (diff)
downloadtangara-fw-561f9d2a07ee6ee1c2f18dc375125f87ea7b0d55.tar.gz
Ensure the sink buffer is large enough to not fully drain during
playback
Diffstat (limited to 'src')
-rw-r--r--src/audio/CMakeLists.txt2
-rw-r--r--src/audio/audio_decoder.cpp7
-rw-r--r--src/audio/audio_task.cpp7
-rw-r--r--src/audio/fatfs_audio_input.cpp3
-rw-r--r--src/audio/include/audio_sink.hpp3
-rw-r--r--src/audio/include/stream_info.hpp52
-rw-r--r--src/drivers/dac.cpp10
7 files changed, 31 insertions, 53 deletions
diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt
index 34fcd8ee..6361f827 100644
--- a/src/audio/CMakeLists.txt
+++ b/src/audio/CMakeLists.txt
@@ -1,7 +1,7 @@
idf_component_register(
SRCS "audio_decoder.cpp" "audio_task.cpp" "chunk.cpp" "fatfs_audio_input.cpp"
"stream_message.cpp" "i2s_audio_output.cpp" "stream_buffer.cpp"
- "audio_playback.cpp" "stream_event.cpp" "pipeline.cpp"
+ "audio_playback.cpp" "stream_event.cpp" "pipeline.cpp" "stream_info.cpp"
INCLUDE_DIRS "include"
REQUIRES "codecs" "drivers" "cbor" "result" "tasks" "span" "memory")
diff --git a/src/audio/audio_decoder.cpp b/src/audio/audio_decoder.cpp
index faaadb3e..af9abb94 100644
--- a/src/audio/audio_decoder.cpp
+++ b/src/audio/audio_decoder.cpp
@@ -68,8 +68,10 @@ auto AudioDecoder::Process(const std::vector<InputStream>& inputs,
OutputStream* output) -> void {
auto input = inputs.begin();
const StreamInfo& info = input->info();
- if (std::holds_alternative<std::monostate>(info.format) || info.bytes_in_stream == 0) {
- output->prepare({});
+ if (std::holds_alternative<std::monostate>(info.format) ||
+ info.bytes_in_stream == 0) {
+ // TODO(jacqueline): should we clear the stream format?
+ // output->prepare({});
return;
}
@@ -126,7 +128,6 @@ auto AudioDecoder::Process(const std::vector<InputStream>& inputs,
}
}
- ESP_LOGI(kTag, "decoded %u bytes", current_codec_->GetInputPosition() - 1);
input->consume(current_codec_->GetInputPosition() - 1);
}
diff --git a/src/audio/audio_task.cpp b/src/audio/audio_task.cpp
index 464879d8..3a2a5941 100644
--- a/src/audio/audio_task.cpp
+++ b/src/audio/audio_task.cpp
@@ -124,7 +124,7 @@ void AudioTaskMain(void* args) {
RawStream raw_sink_stream = elements.front()->OutStream(&out_region);
InputStream sink_stream(&raw_sink_stream);
- if (sink_stream.data().size_bytes() == 0) {
+ if (sink_stream.info().bytes_in_stream == 0) {
out_region.Unmap();
vTaskDelay(pdMS_TO_TICKS(100));
continue;
@@ -143,7 +143,8 @@ void AudioTaskMain(void* args) {
// We've reconfigured the sink, or it was already configured correctly.
// Send through some data.
- if (output_format == sink_stream.info().format && !std::holds_alternative<std::monostate>(*output_format)) {
+ if (output_format == sink_stream.info().format &&
+ !std::holds_alternative<std::monostate>(*output_format)) {
// TODO: tune the delay on this, as it's currently the only way to
// throttle this task's CPU time. Maybe also hold off on the pipeline
// if the buffer is already close to full?
@@ -160,7 +161,7 @@ void AudioTaskMain(void* args) {
vTaskDelete(NULL);
}
-static std::byte sDrainBuf[1024];
+static std::byte sDrainBuf[8 * 1024];
void AudioDrainMain(void* args) {
{
diff --git a/src/audio/fatfs_audio_input.cpp b/src/audio/fatfs_audio_input.cpp
index b4e6db75..22d707d6 100644
--- a/src/audio/fatfs_audio_input.cpp
+++ b/src/audio/fatfs_audio_input.cpp
@@ -48,7 +48,8 @@ auto FatfsAudioInput::OpenFile(const std::string& path) -> void {
auto FatfsAudioInput::Process(const std::vector<InputStream>& inputs,
OutputStream* output) -> void {
if (!is_file_open_) {
- output->prepare({});
+ // TODO(jacqueline): should we clear the stream format?
+ // output->prepare({});
return;
}
diff --git a/src/audio/include/audio_sink.hpp b/src/audio/include/audio_sink.hpp
index ad63ec2e..03a4690d 100644
--- a/src/audio/include/audio_sink.hpp
+++ b/src/audio/include/audio_sink.hpp
@@ -6,7 +6,8 @@ namespace audio {
class IAudioSink {
private:
- static const std::size_t kDrainBufferSize = 8 * 1024;
+ // TODO: tune. at least about 12KiB seems right for mp3
+ static const std::size_t kDrainBufferSize = 24 * 1024;
StreamBufferHandle_t buffer_;
public:
diff --git a/src/audio/include/stream_info.hpp b/src/audio/include/stream_info.hpp
index 6256f2ee..28095935 100644
--- a/src/audio/include/stream_info.hpp
+++ b/src/audio/include/stream_info.hpp
@@ -66,20 +66,13 @@ class InputStream {
public:
explicit InputStream(RawStream* s) : raw_(s) {}
- void consume(std::size_t bytes) const {
- assert(raw_->info->bytes_in_stream >= bytes);
- auto new_data = raw_->data.subspan(bytes);
- std::move(new_data.begin(), new_data.end(), raw_->data.begin());
- raw_->info->bytes_in_stream = new_data.size_bytes();
- }
+ void consume(std::size_t bytes) const;
- void mark_incomplete() const { raw_->is_incomplete = true; }
+ void mark_incomplete() const;
- const StreamInfo& info() const { return *raw_->info; }
+ const StreamInfo& info() const;
- cpp::span<const std::byte> data() const {
- return raw_->data.first(raw_->info->bytes_in_stream);
- }
+ cpp::span<const std::byte> data() const;
private:
RawStream* raw_;
@@ -89,34 +82,15 @@ class OutputStream {
public:
explicit OutputStream(RawStream* s) : raw_(s) {}
- void add(std::size_t bytes) const {
- assert(raw_->info->bytes_in_stream + bytes <= raw_->data.size_bytes());
- raw_->info->bytes_in_stream += bytes;
- }
-
- bool prepare(const StreamInfo::Format& new_format) {
- if (std::holds_alternative<std::monostate>(raw_->info->format)) {
- raw_->info->format = new_format;
- raw_->info->bytes_in_stream = 0;
- }
- if (new_format == raw_->info->format) {
- return true;
- }
- if (raw_->is_incomplete) {
- raw_->info->format = new_format;
- raw_->info->bytes_in_stream = 0;
- return true;
- }
- return false;
- }
-
- const StreamInfo& info() const { return *raw_->info; }
-
- cpp::span<std::byte> data() const {
- return raw_->data.subspan(raw_->info->bytes_in_stream);
- }
-
- bool is_incomplete() const { return raw_->is_incomplete; }
+ void add(std::size_t bytes) const;
+
+ bool prepare(const StreamInfo::Format& new_format);
+
+ const StreamInfo& info() const;
+
+ cpp::span<std::byte> data() const;
+
+ bool is_incomplete() const;
private:
RawStream* raw_;
diff --git a/src/drivers/dac.cpp b/src/drivers/dac.cpp
index 40663219..c99c88b0 100644
--- a/src/drivers/dac.cpp
+++ b/src/drivers/dac.cpp
@@ -91,11 +91,11 @@ auto AudioDac::create(GpioExpander* expander)
// dac->WriteRegister(Register::PLL_CLOCK_SOURCE, 1 << 4);
// dac->WriteRegister(Register::DAC_CLOCK_SOURCE, 0b11 << 5);
- //dac->WriteRegister(Register::PLL_ENABLE, 0);
- //dac->WriteRegister(Register::DAC_CLOCK_SOURCE, 0b0110000);
- //dac->WriteRegister(Register::CLOCK_ERRORS, 0b01000001);
- //dac->WriteRegister(Register::I2S_FORMAT, 0b110000);
- // dac->WriteRegister(Register::INTERPOLATION, 1 << 4);
+ // dac->WriteRegister(Register::PLL_ENABLE, 0);
+ // dac->WriteRegister(Register::DAC_CLOCK_SOURCE, 0b0110000);
+ // dac->WriteRegister(Register::CLOCK_ERRORS, 0b01000001);
+ // dac->WriteRegister(Register::I2S_FORMAT, 0b110000);
+ // dac->WriteRegister(Register::INTERPOLATION, 1 << 4);
dac->Reconfigure(BPS_16, SAMPLE_RATE_44_1);