summaryrefslogtreecommitdiff
path: root/src/audio/audio_decoder.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-01-30 15:52:54 +1100
committerjacqueline <me@jacqueline.id.au>2023-01-30 15:52:54 +1100
commitef8d404b15e6d32506617a95aa3161fbe59ecdaf (patch)
treef05d5f0a81b1477846e85bf44f0154db015b9789 /src/audio/audio_decoder.cpp
parent2cc0a38a1ac7fc54d7333dafa8b99479a7f5dc86 (diff)
downloadtangara-fw-ef8d404b15e6d32506617a95aa3161fbe59ecdaf.tar.gz
Continue ironing out i2s pipeline
still at least one heap corruption issue, plus the i2s write method seems to block forever :/
Diffstat (limited to 'src/audio/audio_decoder.cpp')
-rw-r--r--src/audio/audio_decoder.cpp46
1 files changed, 30 insertions, 16 deletions
diff --git a/src/audio/audio_decoder.cpp b/src/audio/audio_decoder.cpp
index 4478b2c4..b3415647 100644
--- a/src/audio/audio_decoder.cpp
+++ b/src/audio/audio_decoder.cpp
@@ -40,36 +40,31 @@ auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info)
stream_info_ = info;
if (info.chunk_size) {
- chunk_reader_.emplace(*info.chunk_size);
+ chunk_reader_ = ChunkReader(info.chunk_size.value());
} else {
- // TODO.
+ ESP_LOGE(kTag, "no chunk size given");
+ return cpp::fail(UNSUPPORTED_STREAM);
}
// Reuse the existing codec if we can. This will help with gapless playback,
// since we can potentially just continue to decode as we were before,
// without any setup overhead.
- if (current_codec_->CanHandleFile(info.path.value_or(""))) {
+ if (current_codec_ != nullptr &&
+ current_codec_->CanHandleFile(info.path.value_or(""))) {
current_codec_->ResetForNewStream();
return {};
}
- auto result = codecs::CreateCodecForFile(*info.path);
- if (result) {
- current_codec_ = std::move(*result);
+ auto result = codecs::CreateCodecForFile(info.path.value_or(""));
+ if (result.has_value()) {
+ current_codec_ = std::move(result.value());
} else {
+ ESP_LOGE(kTag, "no codec for this file");
return cpp::fail(UNSUPPORTED_STREAM);
}
- // TODO: defer until first header read, so we can give better info about
- // sample rate, chunk size, etc.
- StreamInfo downstream_info(info);
- downstream_info.bits_per_sample = 32;
- downstream_info.sample_rate = 48'000;
- chunk_size_ = 128;
- downstream_info.chunk_size = chunk_size_;
-
- auto event = StreamEvent::CreateStreamInfo(input_events_, downstream_info);
- SendOrBufferEvent(std::unique_ptr<StreamEvent>(event));
+ stream_info_ = info;
+ has_sent_stream_info_ = false;
return {};
}
@@ -78,10 +73,13 @@ auto AudioDecoder::ProcessChunk(const cpp::span<std::byte>& chunk)
-> cpp::result<size_t, AudioProcessingError> {
if (current_codec_ == nullptr || !chunk_reader_) {
// Should never happen, but fail explicitly anyway.
+ ESP_LOGW(kTag, "received chunk without chunk size or codec");
return cpp::fail(UNSUPPORTED_STREAM);
}
+ ESP_LOGI(kTag, "received new chunk (size %u)", chunk.size());
current_codec_->SetInput(chunk_reader_->HandleNewData(chunk));
+ needs_more_input_ = false;
return {};
}
@@ -92,6 +90,22 @@ auto AudioDecoder::Process() -> cpp::result<void, AudioProcessingError> {
// Writing samples is relatively quick (it's just a bunch of memcopy's), so
// do them all at once.
while (has_samples_to_send_ && !IsOverBuffered()) {
+ if (!has_sent_stream_info_) {
+ has_sent_stream_info_ = true;
+ auto format = current_codec_->GetOutputFormat();
+ stream_info_->bits_per_sample = format.bits_per_sample;
+ stream_info_->sample_rate = format.sample_rate_hz;
+ stream_info_->channels = format.num_channels;
+
+ chunk_size_ = kSamplesPerChunk * (*stream_info_->bits_per_sample);
+ stream_info_->chunk_size = chunk_size_;
+ ESP_LOGI(kTag, "pcm stream chunk size: %u bytes", chunk_size_);
+
+ auto event =
+ StreamEvent::CreateStreamInfo(input_events_, *stream_info_);
+ SendOrBufferEvent(std::unique_ptr<StreamEvent>(event));
+ }
+
auto chunk = std::unique_ptr<StreamEvent>(
StreamEvent::CreateChunkData(input_events_, chunk_size_));
auto write_res =