From c9f1e8e4aefab758fdc25456c031ffe9f879e6e6 Mon Sep 17 00:00:00 2001 From: bonamin Date: Wed, 29 Oct 2025 08:55:36 +0200 Subject: [PATCH] Fixed Single-loop mode playing multiple times on fast speeds. --- vesper/src/BellEngine/BellEngine.cpp | 16 +++++++---- vesper/src/Player/Player.cpp | 41 ++++++++++------------------ 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/vesper/src/BellEngine/BellEngine.cpp b/vesper/src/BellEngine/BellEngine.cpp index 276ea1f..06a46cb 100644 --- a/vesper/src/BellEngine/BellEngine.cpp +++ b/vesper/src/BellEngine/BellEngine.cpp @@ -74,7 +74,7 @@ BellEngine::~BellEngine() { * */ void BellEngine::begin() { - LOG_DEBUG("Initializing BellEngine with high-precision timing"); + LOG_DEBUG("Initializing BellEngine..."); // Create engine task with HIGHEST priority on dedicated Core 1 // This ensures maximum performance and timing precision @@ -88,7 +88,7 @@ void BellEngine::begin() { 1 // 💻 Pin to Core 1 (dedicated) ); - LOG_INFO("BellEngine initialized - Ready for MAXIMUM PRECISION! 🎯"); + LOG_INFO("BellEngine initialized !"); } /** @@ -120,18 +120,18 @@ void BellEngine::start() { return; // ⛔ Early exit if no melody data } - LOG_INFO("🚀 BellEngine IGNITION - Starting precision playback"); + LOG_INFO("🚀 BellEngine Ignition - Starting precision playback"); _emergencyStop.store(false); // ✅ Clear any emergency stop state _engineRunning.store(true); // ✅ Activate the engine atomically } void BellEngine::stop() { - LOG_INFO("BellEngine stopping gracefully"); + LOG_INFO("BellEngine - Stopping Gracefully"); _engineRunning.store(false); } void BellEngine::emergencyStop() { - LOG_INFO("🛑 EMERGENCY STOP ACTIVATED"); + LOG_INFO("BellEngine 🛑 EMERGENCY STOP ACTIVATED"); _emergencyStop.store(true); _engineRunning.store(false); emergencyShutdown(); @@ -238,7 +238,11 @@ void BellEngine::playbackLoop() { // Mark segment completion and notify Player _player.segmentCmpltTime = millis(); - _player.onMelodyLoopCompleted(); // 🔥 Notify Player that melody actually finished! + _player.onMelodyLoopCompleted(); // 🔥 Notify Player that melody actually finished! + if ((_player.continuous_loop && _player.segment_duration == 0) || _player.total_duration == 0) { + vTaskDelay(pdMS_TO_TICKS(500)); //Give Player time to pause/stop + LOG_VERBOSE("Melody loop completed for SINGLE Mode - waiting for Player to handle pause/stop"); + } LOG_DEBUG("🎵 Melody loop completed with PRECISION"); } diff --git a/vesper/src/Player/Player.cpp b/vesper/src/Player/Player.cpp index e7ad096..5c0beaf 100644 --- a/vesper/src/Player/Player.cpp +++ b/vesper/src/Player/Player.cpp @@ -135,9 +135,13 @@ void Player::stop() { isPlaying = false; // Set STOPPING status - actual stop message will be sent when BellEngine finishes - setStatus(PlayerStatus::STOPPING); - LOG_DEBUG("Plbck: SOFT STOP (waiting for melody to complete)"); - + if (isPaused) { + setStatus(PlayerStatus::STOPPED); + LOG_DEBUG("Plbck: STOP from PAUSED state"); + } else { + setStatus(PlayerStatus::STOPPING); + LOG_DEBUG("Plbck: SOFT STOP (waiting for melody to complete)"); + } // NOTE: The actual "stop" message is now sent in onMelodyLoopCompleted() // when the BellEngine actually finishes the current loop } @@ -294,13 +298,7 @@ void Player::durationTimerCallback(TimerHandle_t xTimer) { // Check if it's time to stop playback bool Player::timeToStop(unsigned long now) { - if (isPlaying && !infinite_play && total_duration == 0) { - if (now > startTime){} - LOG_DEBUG("(Single Loop Run Seelected) Soft Stopping."); - return true; - } - } - else if (isPlaying && !infinite_play) { + if (isPlaying && !infinite_play) { uint64_t stopTime = startTime + total_duration; if (now >= stopTime) { LOG_DEBUG("(TimerFunction) Total Run Duration Reached. Soft Stopping."); @@ -374,23 +372,12 @@ void Player::onMelodyLoopCompleted() { // Check if it's time to pause playback bool Player::timeToPause(unsigned long now) { if (isPlaying && continuous_loop) { - // Special case: segment_duration = 0 means "one loop only" - if (segment_duration == 0) { - // Only pause after first loop completes (segmentCmpltTime updated) - if (segmentCmpltTime > segmentStartTime && !isPaused) { - LOG_DEBUG("(TimerFunction) One-loop segment completed. Pausing."); - pauseTime = now; - return true; - } - } else { - // Normal duration-based pausing - uint64_t timeToPause = segmentStartTime + segment_duration; - LOG_DEBUG("PTL: %llu // NOW: %lu", timeToPause, now); - if (now >= timeToPause && !isPaused) { - LOG_DEBUG("(TimerFunction) Segment Duration Reached. Pausing."); - pauseTime = now; - return true; - } + uint64_t timeToPause = segmentStartTime + segment_duration; + LOG_DEBUG("PTL: %llu // NOW: %lu", timeToPause, now); + if (now >= timeToPause && !isPaused) { + LOG_DEBUG("(TimerFunction) Segment Duration Reached. Pausing."); + pauseTime = now; + return true; } } return false;