From 158c02d27b388fca80ad7d3cc1baba42ba38e7a2 Mon Sep 17 00:00:00 2001 From: yuquanjun Date: Mon, 21 Sep 2026 15:23:10 +0800 Subject: [PATCH] fix(free): stop accompaniment on next even beat after fret release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In normal mode, releasing the fretboard now finishes the current beat-pair (beat 1→end of 2, beat 3→end of 4) instead of cutting immediately. Co-authored-by: Cursor --- Global/Global.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++-- Global/Global.h | 2 + 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/Global/Global.c b/Global/Global.c index 3c03366..262820a 100644 --- a/Global/Global.c +++ b/Global/Global.c @@ -761,8 +761,106 @@ void Tap_to_Speed() } +/* 普通模式松手:对齐到下一偶拍末再停(拍1→拍2末,拍3→拍4末)。 + * piece 窗口 1920=4 拍,每拍 480 tick(与起奏 SetPiecePlayMode(1,0,1920) 一致)。 */ +#define FREE_BEAT_TICKS 480u +#define FREE_PIECE_TICKS 1920u + +static uint8_t s_free_even_stop_arm = 0; +static uint64_t s_free_even_stop_tick = 0; +static int s_free_even_stop_beat = 2; /* 目标偶拍 2 或 4 */ +static uint8_t s_free_even_seen_target = 0; + +static void FreeMode_CancelEvenBeatStop(void) +{ + s_free_even_stop_arm = 0; + s_free_even_stop_tick = 0; + s_free_even_stop_beat = 2; + s_free_even_seen_target = 0; +} + +/* 再次按住指板:取消待停并恢复 piece 循环 */ +static void FreeMode_ResumePieceLoop(void) +{ + if (!s_free_even_stop_arm) + return; + FreeMode_CancelEvenBeatStop(); + if (StartFlag && mGuiData[GUI_TAB_INDEX].Current == 2 && + !mGuiData[GUI_AUTOBAND_SW].Current) + { + AutoBandTop1_SetPiecePlayMode(1, 0, FREE_PIECE_TICKS); + AutoBandTop1_SetLoopMode(0, 1); + } +} + +static void FreeMode_ArmEvenBeatStop(void) +{ + uint64_t play; + int beat; + int target; + + if (!StartFlag) + { + FreeMode_CancelEvenBeatStop(); + return; + } + + play = AutoBandTop1_GetCurrentPlayTick(); + beat = AutoBandTop1_GetCurrentBeat(); + if (beat < 1) + beat = 1; + /* 拍1→2,拍2→2,拍3→4,拍4→4 */ + target = ((beat + 1) / 2) * 2; + s_free_even_stop_beat = target; + s_free_even_seen_target = (beat >= target) ? 1u : 0u; + /* ((beat0/2)+1)*2*480 → 拍1/2→960,拍3/4→1920,跨小节同理 */ + s_free_even_stop_tick = + ((play / FREE_BEAT_TICKS) / 2ull + 1ull) * 2ull * (uint64_t)FREE_BEAT_TICKS; + s_free_even_stop_arm = 1; + + /* 禁循环并裁 piece,库播到 stop tick 自停;Poll 作兜底 */ + AutoBandTop1_SetLoopMode(0, 0); + if (s_free_even_stop_tick <= 0xFFFFFFFFull) + AutoBandTop1_SetPiecePlayMode(1, 0, (uint32_t)s_free_even_stop_tick); + + LOG_I("pick", "free even-stop arm beat=%d target=%d play=%u stop=%u", + beat, target, (unsigned)play, (unsigned)s_free_even_stop_tick); +} + +void FreeMode_PollEvenBeatStop(void) +{ + int beat; + uint8_t tick_done; + uint8_t beat_done; + + if (!s_free_even_stop_arm) + return; + if (PressFlag || mGuiData[GUI_TAB_INDEX].Current != 2 || !StartFlag) + { + FreeMode_CancelEvenBeatStop(); + return; + } + + beat = AutoBandTop1_GetCurrentBeat(); + if (beat == s_free_even_stop_beat) + s_free_even_seen_target = 1; + /* 已到达目标偶拍后离开该拍 = 该拍播完;或 play tick 到点 */ + beat_done = (s_free_even_seen_target && beat != s_free_even_stop_beat && beat != 0) ? 1u : 0u; + tick_done = (AutoBandTop1_GetCurrentPlayTick() >= s_free_even_stop_tick) ? 1u : 0u; + + if (tick_done || beat_done) + { + FreeMode_CancelEvenBeatStop(); + KEY_ID_1629 = 0; + Stop_AutoBand(); + LOG_I("pick", "free even-stop done beat=%d tick=%u beatDone=%u", + beat, (unsigned)tick_done, (unsigned)beat_done); + } +} + void Stop_AutoBand() { + FreeMode_CancelEvenBeatStop(); AutoBandTop1_Stop(); for(uint8_t i = 0;i < 16;i++) { @@ -914,10 +1012,10 @@ void TM1629_Handle(uint8_t key) PressFlag = 0; if(mGuiData[GUI_TAB_INDEX].Current == 2) { - /* 普通:松手立即结束当前和弦伴奏 */ + /* 普通:松手对齐到偶拍末再停(拍1→拍2末,拍3→拍4末) */ KEY_ID_1629 = 0; if (StartFlag) - Stop_AutoBand(); + FreeMode_ArmEvenBeatStop(); } else if(mGuiData[GUI_TAB_INDEX].Current == 0) { @@ -940,7 +1038,8 @@ void TM1629_Handle(uint8_t key) } else if(mGuiData[GUI_TAB_INDEX].Current == 2) { - /* 普通:按住指板,等待拨片起奏当前和弦 */ + /* 普通:按住指板;若正在偶拍收束则恢复循环续奏 */ + FreeMode_ResumePieceLoop(); PressFlag = 1; } uint8_t group = (key - 1) / 3; /* 1~3→0, 4~6→1, ..., 19~21→6 */ @@ -1637,6 +1736,7 @@ void Read_Cur_Measure() (tab == 3 && (last == 0 || last == 2)); Band_TrackPlayTick(); + FreeMode_PollEvenBeatStop(); /* 尾奏中保持全绿,不刷新和弦走向红灯 */ if (loop_light_ok && StartFlag && !s_outro_led_all_green) diff --git a/Global/Global.h b/Global/Global.h index 521d913..cb4d15e 100644 --- a/Global/Global.h +++ b/Global/Global.h @@ -206,6 +206,8 @@ extern void (*CurrUIProcress)(DisplayTaskMessage_Type xEvent); void Stop_AutoBand(); +/* 普通模式:松手后偶拍收束轮询(由 Read_Cur_Measure 调用) */ +void FreeMode_PollEvenBeatStop(void); /* 当前调一级大和弦(把位1 + maj);开机/进模式/前奏/拨片兜底共用 */ void Accomp_ApplyDefaultIChord(void);