fix(free): preserve expert chord/transpose across mode switch

NavBar no longer forces I after stop; remember context before leave and prefer saved fret chord on no-fret pick.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-09-24 08:05:50 +08:00
parent 3c01dc8c28
commit 4bfe3ca008
4 changed files with 44 additions and 23 deletions

View File

@ -105,7 +105,7 @@ int16_t MIC_VOL_MAP[11]= {-9000,-7000,-5000,-3000,-1000,1000,3000,5000,7000,9000
uint8_t TOUCH_AREA_NUM = (sizeof(Touch_Areas)/sizeof(Touch_AreaTypeDef));
const uint8_t Version[3] = {0,2,25}; /* major.minor.patch — 0.2.25: 普通无指板拨片沿用专业最后指板和弦 */
const uint8_t Version[3] = {0,2,27}; /* major.minor.patch — 0.2.27: 切模式前记专业移调/指板;无指板拨片优先用记忆 */
uint8_t Led = 8;
bool PressFlag = 0;
@ -648,9 +648,9 @@ void Accomp_ApplyDefaultIChord(void)
}
/* 专业/普通共用:最后一次指板和弦(供普通无指板拨片)。
* 另记专业停键时的移调:0xFF=尚未在专业停过;移调合法值 0~11。
* 另记专业侧移调:0xFF=尚未记下;移调合法值 0~11。
* chord: 0=无记录;1~21=指板键。 */
static uint8_t s_expert_stop_transpose = 0xFFu;
static uint8_t s_saved_transpose = 0xFFu;
static uint8_t s_last_fret_chord = 0;
static void Accomp_RememberLastFretChord(uint8_t key)
@ -659,14 +659,20 @@ static void Accomp_RememberLastFretChord(uint8_t key)
s_last_fret_chord = key;
}
static void Expert_RememberStopContext(void)
static void Accomp_RememberTranspose(void)
{
s_saved_transpose = (uint8_t)mGuiData[GUI_TRANSPOSE].Current;
}
/* 停键或切模式前:按当前页记住和弦;专业再记移调 */
void Accomp_RememberPlayContext(void)
{
uint8_t tab = (uint8_t)mGuiData[GUI_TAB_INDEX].Current;
uint8_t last = (uint8_t)mGuiData[GUI_TAB_LAST_INDEX].Current;
if (tab == 1 || (tab == 3 && last == 1))
{
s_expert_stop_transpose = (uint8_t)mGuiData[GUI_TRANSPOSE].Current;
Accomp_RememberTranspose();
Accomp_RememberLastFretChord(KEY_ID_1629);
}
else if (tab == 2 || (tab == 3 && last == 2))
@ -675,28 +681,35 @@ static void Expert_RememberStopContext(void)
}
}
/* 普通无指板拨片:移调用专业停键值;和弦用专业/普通记下的最后指板,否则一级 */
static void Expert_RememberStopContext(void)
{
Accomp_RememberPlayContext();
}
/* 普通无指板拨片:优先用记下的最后指板和弦(勿信切模式后的默认 KEY=一级);
* 移调用专业侧记下的值;都没有才退回一级。 */
static void FreeMode_ApplyLastFretChordForNoFretPick(void)
{
if (s_expert_stop_transpose != 0xFFu &&
(uint8_t)mGuiData[GUI_TRANSPOSE].Current != s_expert_stop_transpose)
if (s_saved_transpose != 0xFFu &&
(uint8_t)mGuiData[GUI_TRANSPOSE].Current != s_saved_transpose)
{
mGuiData[GUI_TRANSPOSE].Current = s_expert_stop_transpose;
mGuiData[GUI_TRANSPOSE].Current = s_saved_transpose;
UITask_Sendmsg(MSG_ID_BLE_UI_REFRESH, GUI_TRANSPOSE, 0, 0);
}
if (KEY_ID_1629 >= 1u && KEY_ID_1629 <= 21u)
{
Accomp_RememberLastFretChord(KEY_ID_1629);
PressFlag = 0;
return;
}
/* 切模式 NavBar 会把 KEY 打成一级,必须以记忆为准 */
if (s_last_fret_chord >= 1u && s_last_fret_chord <= 21u)
{
KEY_ID_1629 = s_last_fret_chord;
PressFlag = 0;
return;
}
if (KEY_ID_1629 >= 1u && KEY_ID_1629 <= 21u)
{
Accomp_RememberLastFretChord(KEY_ID_1629);
PressFlag = 0;
return;
}
Accomp_ApplyDefaultIChord();
}
@ -1482,12 +1495,16 @@ void TM1629_Handle(uint8_t key)
}
uint8_t group = (key - 1) / 3; /* 1~3→0, 4~6→1, ..., 19~21→6 */
KEY_ID_1629 = key;
/* 专业/普通(及对应设置页):记下最后指板和弦,供普通无指板拨片沿用 */
/* 专业/普通(及对应设置页):记下最后指板和弦;专业同时记移调 */
{
uint8_t tab = (uint8_t)mGuiData[GUI_TAB_INDEX].Current;
uint8_t last = (uint8_t)mGuiData[GUI_TAB_LAST_INDEX].Current;
if (tab == 1 || tab == 2 ||
(tab == 3 && (last == 1 || last == 2)))
if (tab == 1 || (tab == 3 && last == 1))
{
Accomp_RememberTranspose();
Accomp_RememberLastFretChord(key);
}
else if (tab == 2 || (tab == 3 && last == 2))
Accomp_RememberLastFretChord(key);
}
MIDI = (STRING_MIDI *)Chord_Midi_Table[group];
@ -1610,7 +1627,7 @@ void Pick_Handle()
}
/* 左手未触发和弦板(或落在拍速/停止键)时:拨片默认发当前调一级大和弦伴奏。
* 普通无指板也可起奏:用专业最后指板和弦(如 VI),无记录才退回一级;无操作则偶拍停。 */
* 普通无指板也可起奏:用专业/普通记下的最后指板和弦,无记录才退回一级;无操作则偶拍停。 */
{
uint8_t free_pick_no_fret =
(mGuiData[GUI_TAB_INDEX].Current == 2 &&
@ -1618,7 +1635,7 @@ void Pick_Handle()
if (free_pick_no_fret)
{
FreeMode_ApplyExpertChordForNoFretPick();
FreeMode_ApplyLastFretChordForNoFretPick();
chord_id = KEY_ID_1629;
}
else if (mGuiData[GUI_TAB_INDEX].Current != 2 &&

View File

@ -257,6 +257,8 @@ void BL_Set_led(uint8_t Led, uint8_t chord_type);
uint8_t GetChordNotesByType(uint8_t MIDI_Index,uint8_t type,uint8_t *buff);
/* 伴奏已在播时仅更新和弦音,不 Restart(快转调) */
void Accomp_UpdatePlayingChord(void);
/* 切模式/停键前记住专业移调与最后指板和弦 */
void Accomp_RememberPlayContext(void);
/* 段落键等主动刷新伴奏活动,避免 PlayTick 短暂停滞被判为已停 */
void Band_NotifyPlayActivity(void);
void BT_Chord_offset_map(uint8_t pos_offset,uint8_t chord_offset);

View File

@ -303,6 +303,8 @@ void Touch_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex,uint8_t value)
{
if(mGuiData[ID].Current != value)
{
/* 改 TAB 前先记住当前专业/普通指板与移调 */
Accomp_RememberPlayContext();
mGuiData[ID].Current = value;
app_tm1629_all_on(LED_COLOR_G);

View File

@ -1049,15 +1049,15 @@ void UI_NavBar_Action(uint8_t value)
{
/* 离开万能后 LOOP_LIGHT 停更,须显式恢复全绿(旧 GUI_TAB_INDEX 路径曾做) */
app_tm1629_all_on(LED_COLOR_G);
/* 底栏切模式/进设置:立即结束当前伴奏(设置页不走 ReloadTonePreset) */
/* 先记住当前专业/普通的指板与移调,再停;勿再强制一级(会盖掉记忆供普通无指板拨片) */
Accomp_RememberPlayContext();
Stop_AutoBand();
/* 切模式后拨片/前奏默认当前调一级 */
Accomp_ApplyDefaultIChord();
switch (value)
{
case UI0902_NAV_UNIVERSAL:
/* Init 内会设 TAB 并 ReloadTonePreset,勿在此前加载(会仍用旧 TAB) */
Accomp_ApplyDefaultIChord(); /* 万能拨片默认一级 */
MenuPage_SongMode_Proc();
break;
case UI0902_NAV_NORMAL: