summaryrefslogtreecommitdiff
path: root/src/audio/i2s_audio_output.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/i2s_audio_output.cpp')
-rw-r--r--src/audio/i2s_audio_output.cpp83
1 files changed, 28 insertions, 55 deletions
diff --git a/src/audio/i2s_audio_output.cpp b/src/audio/i2s_audio_output.cpp
index 110227cf..7766ebed 100644
--- a/src/audio/i2s_audio_output.cpp
+++ b/src/audio/i2s_audio_output.cpp
@@ -1,6 +1,7 @@
#include "i2s_audio_output.hpp"
#include <algorithm>
+#include <variant>
#include "esp_err.h"
#include "freertos/portmacro.h"
@@ -10,14 +11,12 @@
#include "freertos/projdefs.h"
#include "gpio_expander.hpp"
#include "result.hpp"
+#include "stream_info.hpp"
-static const TickType_t kIdleTimeBeforeMute = pdMS_TO_TICKS(1000);
static const char* kTag = "I2SOUT";
namespace audio {
-static const std::size_t kDmaQueueLength = 8;
-
auto I2SAudioOutput::create(drivers::GpioExpander* expander)
-> cpp::result<std::shared_ptr<I2SAudioOutput>, Error> {
// First, we need to perform initial configuration of the DAC chip.
@@ -38,40 +37,26 @@ auto I2SAudioOutput::create(drivers::GpioExpander* expander)
I2SAudioOutput::I2SAudioOutput(drivers::GpioExpander* expander,
std::unique_ptr<drivers::AudioDac> dac)
- : expander_(expander),
- dac_(std::move(dac)),
- chunk_reader_(),
- latest_chunk_() {}
+ : expander_(expander), dac_(std::move(dac)), current_config_() {}
I2SAudioOutput::~I2SAudioOutput() {}
-auto I2SAudioOutput::HasUnprocessedInput() -> bool {
- return latest_chunk_.size() > 0;
-}
-
-auto I2SAudioOutput::IsOverBuffered() -> bool {
- return false;
-}
-
-auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) -> void {
- // TODO(jacqueline): probs do something with the channel hey
-
- if (!info.bits_per_sample || !info.sample_rate) {
- ESP_LOGE(kTag, "audio stream missing bits or sample rate");
- return;
+auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) -> bool {
+ if (!std::holds_alternative<StreamInfo::Pcm>(info.data)) {
+ return false;
}
- if (!info.chunk_size) {
- ESP_LOGE(kTag, "audio stream missing chunk size");
- return;
+ StreamInfo::Pcm pcm = std::get<StreamInfo::Pcm>(info.data);
+
+ if (current_config_ && pcm == *current_config_) {
+ return true;
}
- chunk_reader_.emplace(*info.chunk_size);
- ESP_LOGI(kTag, "incoming audio stream: %u bpp @ %u Hz", *info.bits_per_sample,
- *info.sample_rate);
+ ESP_LOGI(kTag, "incoming audio stream: %u bpp @ %u Hz", pcm.bits_per_sample,
+ pcm.sample_rate);
drivers::AudioDac::BitsPerSample bps;
- switch (*info.bits_per_sample) {
+ switch (pcm.bits_per_sample) {
case 16:
bps = drivers::AudioDac::BPS_16;
break;
@@ -83,11 +68,11 @@ auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) -> void {
break;
default:
ESP_LOGE(kTag, "dropping stream with unknown bps");
- return;
+ return false;
}
drivers::AudioDac::SampleRate sample_rate;
- switch (*info.sample_rate) {
+ switch (pcm.sample_rate) {
case 44100:
sample_rate = drivers::AudioDac::SAMPLE_RATE_44_1;
break;
@@ -96,37 +81,25 @@ auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) -> void {
break;
default:
ESP_LOGE(kTag, "dropping stream with unknown rate");
- return;
+ return false;
}
- dac_->Reconfigure(bps, sample_rate);
-}
-
-auto I2SAudioOutput::ProcessChunk(const cpp::span<std::byte>& chunk) -> void {
- latest_chunk_ = chunk_reader_->HandleNewData(chunk);
-}
+ // TODO(jacqueline): probs do something with the channel hey
-auto I2SAudioOutput::ProcessEndOfStream() -> void {
- dac_->Stop();
- SendOrBufferEvent(std::unique_ptr<StreamEvent>(
- StreamEvent::CreateEndOfStream(input_events_)));
-}
+ dac_->Reconfigure(bps, sample_rate);
+ current_config_ = pcm;
-auto I2SAudioOutput::ProcessLogStatus() -> void {
- dac_->LogStatus();
+ return true;
}
-auto I2SAudioOutput::Process() -> void {
- // Note: avoid logging here! We need to get bytes from the chunk buffer into
- // the I2S DMA buffer as fast as possible, to avoid running out of samples.
- std::size_t bytes_written = dac_->WriteData(latest_chunk_);
- if (bytes_written == latest_chunk_.size_bytes()) {
- latest_chunk_ = cpp::span<std::byte>();
- chunk_reader_->HandleBytesLeftOver(0);
- } else {
- latest_chunk_ = latest_chunk_.subspan(bytes_written);
- }
- return;
+auto I2SAudioOutput::Process(std::vector<Stream>* inputs, MutableStream* output)
+ -> void {
+ std::for_each(inputs->begin(), inputs->end(), [&](Stream& s) {
+ if (ProcessStreamInfo(s.info)) {
+ std::size_t bytes_written = dac_->WriteData(s.data);
+ s.data = s.data.subspan(bytes_written);
+ }
+ });
}
auto I2SAudioOutput::SetVolume(uint8_t volume) -> void {