fix: universal outro all-green LED; expert local song keeps playing after section+fret

Keep fretboard LEDs all green during outro, and for expert local songs treat section-key + fret changes as continuous chord updates like rhythm mode (no mid-session Stop).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-09-21 15:13:53 +08:00
parent 7ebb7cf265
commit 8fa5220b82
3 changed files with 53 additions and 8 deletions

View File

@ -612,6 +612,9 @@ void Accomp_UpdatePlayingChord(void)
AutoBandTop1_Note_On(midi_note_buff[i], 0x50); AutoBandTop1_Note_On(midi_note_buff[i], 0x50);
} }
/* 尾奏期间冻结走向灯:保持全绿,避免 LOOP_LIGHT 按小节刷红 */
static uint8_t s_outro_led_all_green = 0;
/* 尾奏起奏:Postamble(0) + 同步起奏 + 当前和弦 Note_On。 /* 尾奏起奏:Postamble(0) + 同步起奏 + 当前和弦 Note_On。
* 供 ADC 独立尾奏键与万能模式第4段落键共用。 * 供 ADC 独立尾奏键与万能模式第4段落键共用。
* 万能走 piece 循环,须先退出 piece,否则 Postamble 舞台切不过去; * 万能走 piece 循环,须先退出 piece,否则 Postamble 舞台切不过去;
@ -627,6 +630,9 @@ void AutoBand_StartOutro(void)
/* 退出和弦走向 piece,再进风格尾奏舞台 */ /* 退出和弦走向 piece,再进风格尾奏舞台 */
AutoBandTop1_SetPiecePlayMode(0, 0, 0); AutoBandTop1_SetPiecePlayMode(0, 0, 0);
AutoBandTop1_Postamble(0); AutoBandTop1_Postamble(0);
/* 尾奏:指板 LED 全绿(停走 LOOP 走向红灯) */
s_outro_led_all_green = 1;
app_tm1629_all_on(LED_COLOR_G);
/* 尾奏起奏前补发主音量,保证与图标一致 */ /* 尾奏起奏前补发主音量,保证与图标一致 */
MasterVolume_Reapply(); MasterVolume_Reapply();
AutoBandTop1_SyncStart(); AutoBandTop1_SyncStart();
@ -654,6 +660,7 @@ void ADC_IN1_KEY_Handle(uint8_t key,bool on)
} }
else else
{ {
s_outro_led_all_green = 0; /* 前奏/断奏:恢复走向灯 */
switch(key) switch(key)
{ {
case 3: AutoBandTop1_Preamble(0); is_preamble = 1; break; case 3: AutoBandTop1_Preamble(0); is_preamble = 1; break;
@ -765,6 +772,7 @@ void Stop_AutoBand()
SendMidiDataToDreamDSP(AllControlOff_buff,sizeof(AllControlOff_buff)); SendMidiDataToDreamDSP(AllControlOff_buff,sizeof(AllControlOff_buff));
} }
StartFlag = 0; StartFlag = 0;
s_outro_led_all_green = 0;
//tick_ever_positive = false; //tick_ever_positive = false;
for(uint8_t i = 0;i < 4;i++) key_toggle[i] = 0; for(uint8_t i = 0;i < 4;i++) key_toggle[i] = 0;
} }
@ -826,6 +834,15 @@ void Band_TrackPlayTick(void)
} }
} }
/* 段落键 SetRunVar 后 PlayTick 可能短暂不变;主动刷新以免误判为已停。 */
void Band_NotifyPlayActivity(void)
{
if (!StartFlag)
return;
s_play_tick_last = AutoBandTop1_GetCurrentPlayTick();
s_play_adv_tick = rt_tick_get();
}
uint8_t Band_IsPlaying(void) uint8_t Band_IsPlaying(void)
{ {
if (!StartFlag || s_play_adv_tick == 0) if (!StartFlag || s_play_adv_tick == 0)
@ -839,16 +856,21 @@ static void Expert_StartWithChord(uint8_t chord_id, uint8_t *midi_note_buff,
uint8_t note_cnt, const char *trigger) uint8_t note_cnt, const char *trigger)
{ {
uint8_t midi = 0; uint8_t midi = 0;
uint8_t session = StartFlag ? 1u : 0u;
StartFlag = 1; StartFlag = 1;
if (mGuiData[GUI_AUTOBAND_SW].Current) if (mGuiData[GUI_AUTOBAND_SW].Current)
{ {
AutoBandTop1_Stop(); /* 会话内勿 Stop:段落圆键切变奏后指板续奏若 Stop 会直接关音;
* 与节奏类型一致,仅换和弦/重进当前段。冷启动仍 Stop 清残留。 */
if (!session)
AutoBandTop1_Stop();
AutoBandTop1_SetLoopMode(0, 1); AutoBandTop1_SetLoopMode(0, 1);
AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current); AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current);
midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current; midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current;
AutoBandTop1_StartWithNote(midi); AutoBandTop1_StartWithNote(midi);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt); AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
Band_NotifyPlayActivity();
LOG_I("pick", "local/expert root=%u name=%s sw=%u tab=%u trigger=%s chord=%u", LOG_I("pick", "local/expert root=%u name=%s sw=%u tab=%u trigger=%s chord=%u",
midi, midi,
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?", AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
@ -862,6 +884,7 @@ static void Expert_StartWithChord(uint8_t chord_id, uint8_t *midi_note_buff,
AutoBandTop1_SetPiecePlayMode(1, 0, 1920); AutoBandTop1_SetPiecePlayMode(1, 0, 1920);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt); AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
AutoBandTop1_SetLoopMode(0, 1); AutoBandTop1_SetLoopMode(0, 1);
Band_NotifyPlayActivity();
LOG_I("pick", "expert/rhythm piece name=%s trigger=%s chord=%u", LOG_I("pick", "expert/rhythm piece name=%s trigger=%s chord=%u",
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?", AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
trigger, trigger,
@ -958,11 +981,24 @@ void TM1629_Handle(uint8_t key)
* 松手再按同一键也必须能续奏(与「指板+拨片」一致,拨片本无去重) */ * 松手再按同一键也必须能续奏(与「指板+拨片」一致,拨片本无去重) */
if (!Band_IsPlaying()) if (!Band_IsPlaying())
{ {
/* 段落已停:仅按指板续奏下一节。转主任务走 Pick_Handle /* 节奏:段落自然停后指板续奏 → piece 重启。
*(与「指板+拨片」等价)。勿在播放中 Stop+Start——本地曲目 * 本地曲:圆键切段后 PlayTick 常短暂停滞,若走 Stop+Start 会关音;
* 中途重启常静音,表现为换把位关音、再按才有声。 */ * 与节奏「播放中换把」一致,仅换和弦音持续播放。段落后续奏用拨片/再按圆键。 */
MainTask_Sendmsg(MSG_ID_BP_KEY, 0, 0, 0); if (mGuiData[GUI_AUTOBAND_SW].Current)
LOG_I("pick", "expert/fret continue chord=%u", (unsigned)KEY_ID_1629); {
uint8_t midi_note_buff[4] = {0,};
uint8_t note_cnt = GetChordNotesByType(KEY_ID_1629,chord_type_index_map[KEY_ID_1629].type,midi_note_buff);
for(uint8_t i = 0;i < note_cnt;i++)
AutoBandTop1_Note_On(midi_note_buff[i],0x50);
Return_Light_buff(KEY_ID_1629);
Band_NotifyPlayActivity();
LOG_I("pick", "expert/fret change(local) chord=%u", (unsigned)KEY_ID_1629);
}
else
{
MainTask_Sendmsg(MSG_ID_BP_KEY, 0, 0, 0);
LOG_I("pick", "expert/fret continue chord=%u", (unsigned)KEY_ID_1629);
}
} }
else else
{ {
@ -1120,6 +1156,7 @@ void Pick_Handle()
case 0: case 0:
/* 万能:和弦走向用 piece 模式;须 SetLoopMode,否则无循环时常听不到伴奏 */ /* 万能:和弦走向用 piece 模式;须 SetLoopMode,否则无循环时常听不到伴奏 */
StartFlag = 1; StartFlag = 1;
s_outro_led_all_green = 0; /* 拨片重开 piece,恢复走向灯 */
AutoBandTop1_SetPiecePlayMode(1, 0, 480); AutoBandTop1_SetPiecePlayMode(1, 0, 480);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt); AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
AutoBandTop1_SetLoopMode(0, 1); AutoBandTop1_SetLoopMode(0, 1);
@ -1601,7 +1638,8 @@ void Read_Cur_Measure()
Band_TrackPlayTick(); Band_TrackPlayTick();
if (loop_light_ok && StartFlag) /* 尾奏中保持全绿,不刷新和弦走向红灯 */
if (loop_light_ok && StartFlag && !s_outro_led_all_green)
{ {
if(now - last_tick_i >= 10) if(now - last_tick_i >= 10)
{ {

View File

@ -238,6 +238,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); uint8_t GetChordNotesByType(uint8_t MIDI_Index,uint8_t type,uint8_t *buff);
/* 伴奏已在播时仅更新和弦音,不 Restart(快转调) */ /* 伴奏已在播时仅更新和弦音,不 Restart(快转调) */
void Accomp_UpdatePlayingChord(void); void Accomp_UpdatePlayingChord(void);
/* 段落键等主动刷新伴奏活动,避免 PlayTick 短暂停滞被判为已停 */
void Band_NotifyPlayActivity(void);
void BT_Chord_offset_map(uint8_t pos_offset,uint8_t chord_offset); void BT_Chord_offset_map(uint8_t pos_offset,uint8_t chord_offset);
void BT_Pitch_offset_map(uint8_t pos_offset,uint8_t pitch_offset); void BT_Pitch_offset_map(uint8_t pos_offset,uint8_t pitch_offset);
void Read_Cur_Measure(); void Read_Cur_Measure();

View File

@ -277,13 +277,18 @@ void Touch_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex,uint8_t value)
if(mGuiData[ID].Current != value) if(mGuiData[ID].Current != value)
{ {
mGuiData[ID].Current = value; mGuiData[ID].Current = value;
AutoBandTop1_SetRunVar(mGuiData[ID].Current); AutoBandTop1_SetRunVar(mGuiData[ID].Current);
/* 专业本地曲:切段后 PlayTick 可能短暂不变,刷新活动以免随后指板误走 Stop */
if (StartFlag)
Band_NotifyPlayActivity();
}else }else
{ {
/* 触摸起奏前补发主音量,保证实际音量与图标一致 */ /* 触摸起奏前补发主音量,保证实际音量与图标一致 */
MasterVolume_Reapply(); MasterVolume_Reapply();
AutoBandTop1_FillinWithIndex(value); AutoBandTop1_FillinWithIndex(value);
AutoBandTop1_Start(); AutoBandTop1_Start();
if (StartFlag)
Band_NotifyPlayActivity();
} }
if (!UI_SetFocus(GUI_PLAY_SECTION)) if (!UI_SetFocus(GUI_PLAY_SECTION))
Refresh_SectionSelect(last_value, &UI_Label[ID], &mGuiData[ID]); Refresh_SectionSelect(last_value, &UI_Label[ID], &mGuiData[ID]);