summaryrefslogtreecommitdiff
path: root/src/audio/audio_converter.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-03-25 17:34:41 +1100
committerjacqueline <me@jacqueline.id.au>2024-03-25 17:34:41 +1100
commit175bfc4e3e9f7aa39e084d3f1625347f1d5711ec (patch)
treef71b458f19acca855815ab876944d48a3c5acbcb /src/audio/audio_converter.cpp
parent5c985afd258a96b68d6bd5a4fade17ed998d2c07 (diff)
downloadtangara-fw-175bfc4e3e9f7aa39e084d3f1625347f1d5711ec.tar.gz
WIP rewrie audio pipeline+fsm guts for more reliability
Diffstat (limited to 'src/audio/audio_converter.cpp')
-rw-r--r--src/audio/audio_converter.cpp51
1 files changed, 39 insertions, 12 deletions
diff --git a/src/audio/audio_converter.cpp b/src/audio/audio_converter.cpp
index 946a0b63..1b233731 100644
--- a/src/audio/audio_converter.cpp
+++ b/src/audio/audio_converter.cpp
@@ -5,14 +5,17 @@
*/
#include "audio_converter.hpp"
+#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <cstdint>
+#include "audio_events.hpp"
#include "audio_sink.hpp"
#include "esp_heap_caps.h"
#include "esp_log.h"
+#include "event_queue.hpp"
#include "freertos/portmacro.h"
#include "freertos/projdefs.h"
#include "i2s_dac.hpp"
@@ -35,7 +38,9 @@ SampleConverter::SampleConverter()
resampler_(nullptr),
source_(xStreamBufferCreateWithCaps(kSourceBufferLength,
sizeof(sample::Sample) * 2,
- MALLOC_CAP_DMA)) {
+ MALLOC_CAP_DMA)),
+ leftover_bytes_(0),
+ samples_sunk_(0) {
input_buffer_ = {
reinterpret_cast<sample::Sample*>(heap_caps_calloc(
kSampleBufferLength, sizeof(sample::Sample), MALLOC_CAP_DMA)),
@@ -107,6 +112,19 @@ auto SampleConverter::Main() -> void {
sink_->Configure(new_target);
}
target_format_ = new_target;
+
+ // Send a final sample count for the previous sample rate.
+ if (samples_sunk_ > 0) {
+ events::Audio().Dispatch(internal::ConverterProgress{
+ .samples_sunk = samples_sunk_,
+ });
+ }
+
+ samples_sunk_ = 0;
+ events::Audio().Dispatch(internal::ConverterConfigurationChanged{
+ .src_format = source_format_,
+ .dst_format = target_format_,
+ });
}
// Loop until we finish reading all the bytes indicated. There might be
@@ -154,9 +172,8 @@ auto SampleConverter::HandleSamples(cpp::span<sample::Sample> input,
if (source_format_ == target_format_) {
// The happiest possible case: the input format matches the output
// format already.
- std::size_t bytes_sent = xStreamBufferSend(
- sink_->stream(), input.data(), input.size_bytes(), portMAX_DELAY);
- return bytes_sent / sizeof(sample::Sample);
+ SendToSink(input);
+ return input.size();
}
size_t samples_used = 0;
@@ -186,16 +203,26 @@ auto SampleConverter::HandleSamples(cpp::span<sample::Sample> input,
samples_used = input.size();
}
- size_t bytes_sent = 0;
- size_t bytes_to_send = output_source.size_bytes();
- while (bytes_sent < bytes_to_send) {
- bytes_sent += xStreamBufferSend(
- sink_->stream(),
- reinterpret_cast<std::byte*>(output_source.data()) + bytes_sent,
- bytes_to_send - bytes_sent, portMAX_DELAY);
- }
+ SendToSink(output_source);
}
return samples_used;
}
+auto SampleConverter::SendToSink(cpp::span<sample::Sample> samples) -> void {
+ // Update the number of samples sunk so far *before* actually sinking them,
+ // since writing to the stream buffer will block when the buffer gets full.
+ samples_sunk_ += samples.size();
+ if (samples_sunk_ >=
+ target_format_.sample_rate * target_format_.num_channels) {
+ events::Audio().Dispatch(internal::ConverterProgress{
+ .samples_sunk = samples_sunk_,
+ });
+ samples_sunk_ = 0;
+ }
+
+ xStreamBufferSend(sink_->stream(),
+ reinterpret_cast<std::byte*>(samples.data()),
+ samples.size_bytes(), portMAX_DELAY);
+}
+
} // namespace audio