summaryrefslogtreecommitdiff
path: root/src/audio
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio')
-rw-r--r--src/audio/audio_fsm.cpp28
-rw-r--r--src/audio/track_queue.cpp57
2 files changed, 57 insertions, 28 deletions
diff --git a/src/audio/audio_fsm.cpp b/src/audio/audio_fsm.cpp
index bb7d33dc..b5b6e04b 100644
--- a/src/audio/audio_fsm.cpp
+++ b/src/audio/audio_fsm.cpp
@@ -13,7 +13,9 @@
#include "audio_sink.hpp"
#include "bluetooth_types.hpp"
+#include "esp_heap_caps.h"
#include "esp_log.h"
+#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
#include "freertos/projdefs.h"
@@ -192,20 +194,28 @@ void AudioState::react(const TogglePlayPause& ev) {
namespace states {
+// Two seconds of samples for two channels, at a representative sample rate.
+constexpr size_t kDrainBufferSize = sizeof(sample::Sample) * 48000 * 4;
+static StreamBufferHandle_t sDrainBuffer;
+
void Uninitialised::react(const system_fsm::BootComplete& ev) {
sServices = ev.services;
- constexpr size_t kDrainBufferSize =
- drivers::kI2SBufferLengthFrames * sizeof(sample::Sample) * 2 * 8;
ESP_LOGI(kTag, "allocating drain buffer, size %u KiB",
kDrainBufferSize / 1024);
- StreamBufferHandle_t stream = xStreamBufferCreateWithCaps(
- kDrainBufferSize, sizeof(sample::Sample), MALLOC_CAP_DMA);
+
+ auto meta = reinterpret_cast<StaticStreamBuffer_t*>(
+ heap_caps_malloc(sizeof(StaticStreamBuffer_t), MALLOC_CAP_DMA));
+ auto storage = reinterpret_cast<uint8_t*>(
+ heap_caps_malloc(kDrainBufferSize, MALLOC_CAP_SPIRAM));
+
+ sDrainBuffer = xStreamBufferCreateStatic(
+ kDrainBufferSize, sizeof(sample::Sample), storage, meta);
sFileSource.reset(
new FatfsAudioInput(sServices->tag_parser(), sServices->bg_worker()));
- sI2SOutput.reset(new I2SAudioOutput(stream, sServices->gpios()));
- sBtOutput.reset(new BluetoothAudioOutput(stream, sServices->bluetooth(),
+ sI2SOutput.reset(new I2SAudioOutput(sDrainBuffer, sServices->gpios()));
+ sBtOutput.reset(new BluetoothAudioOutput(sDrainBuffer, sServices->bluetooth(),
sServices->bg_worker()));
auto& nvs = sServices->nvs();
@@ -366,6 +376,12 @@ void Playback::react(const internal::InputFileFinished& ev) {
ESP_LOGI(kTag, "finished playing file");
sServices->track_queue().finish();
if (!sServices->track_queue().current()) {
+ for (int i = 0; i < 20; i++) {
+ if (xStreamBufferIsEmpty(sDrainBuffer)) {
+ break;
+ }
+ vTaskDelay(pdMS_TO_TICKS(200));
+ }
transit<Standby>();
}
}
diff --git a/src/audio/track_queue.cpp b/src/audio/track_queue.cpp
index 534da10c..b75230fc 100644
--- a/src/audio/track_queue.cpp
+++ b/src/audio/track_queue.cpp
@@ -200,39 +200,52 @@ auto TrackQueue::append(Item i) -> void {
}
auto TrackQueue::next() -> void {
- const std::unique_lock<std::shared_mutex> lock(mutex_);
- if (shuffle_) {
- shuffle_->next();
- pos_ = shuffle_->current();
- } else {
- if (pos_ + 1 >= tracks_.size()) {
- if (replay_) {
- pos_ = 0;
- }
+ bool changed = true;
+
+ {
+ const std::unique_lock<std::shared_mutex> lock(mutex_);
+ if (shuffle_) {
+ shuffle_->next();
+ pos_ = shuffle_->current();
} else {
- pos_++;
+ if (pos_ + 1 >= tracks_.size()) {
+ if (replay_) {
+ pos_ = 0;
+ } else {
+ pos_ = tracks_.size();
+ changed = false;
+ }
+ } else {
+ pos_++;
+ }
}
}
- notifyChanged(true);
+ notifyChanged(changed);
}
auto TrackQueue::previous() -> void {
- const std::unique_lock<std::shared_mutex> lock(mutex_);
- if (shuffle_) {
- shuffle_->prev();
- pos_ = shuffle_->current();
- } else {
- if (pos_ == 0) {
- if (repeat_) {
- pos_ = tracks_.size() - 1;
- }
+ bool changed = true;
+
+ {
+ const std::unique_lock<std::shared_mutex> lock(mutex_);
+ if (shuffle_) {
+ shuffle_->prev();
+ pos_ = shuffle_->current();
} else {
- pos_--;
+ if (pos_ == 0) {
+ if (repeat_) {
+ pos_ = tracks_.size() - 1;
+ } else {
+ changed = false;
+ }
+ } else {
+ pos_--;
+ }
}
}
- notifyChanged(true);
+ notifyChanged(changed);
}
auto TrackQueue::finish() -> void {