diff --git a/Global/Global.c b/Global/Global.c index 8431341..3c03366 100644 --- a/Global/Global.c +++ b/Global/Global.c @@ -612,6 +612,9 @@ void Accomp_UpdatePlayingChord(void) AutoBandTop1_Note_On(midi_note_buff[i], 0x50); } +/* 尾奏期间冻结走向灯:保持全绿,避免 LOOP_LIGHT 按小节刷红 */ +static uint8_t s_outro_led_all_green = 0; + /* 尾奏起奏:Postamble(0) + 同步起奏 + 当前和弦 Note_On。 * 供 ADC 独立尾奏键与万能模式第4段落键共用。 * 万能走 piece 循环,须先退出 piece,否则 Postamble 舞台切不过去; @@ -627,6 +630,9 @@ void AutoBand_StartOutro(void) /* 退出和弦走向 piece,再进风格尾奏舞台 */ AutoBandTop1_SetPiecePlayMode(0, 0, 0); AutoBandTop1_Postamble(0); + /* 尾奏:指板 LED 全绿(停走 LOOP 走向红灯) */ + s_outro_led_all_green = 1; + app_tm1629_all_on(LED_COLOR_G); /* 尾奏起奏前补发主音量,保证与图标一致 */ MasterVolume_Reapply(); AutoBandTop1_SyncStart(); @@ -654,6 +660,7 @@ void ADC_IN1_KEY_Handle(uint8_t key,bool on) } else { + s_outro_led_all_green = 0; /* 前奏/断奏:恢复走向灯 */ switch(key) { case 3: AutoBandTop1_Preamble(0); is_preamble = 1; break; @@ -765,6 +772,7 @@ void Stop_AutoBand() SendMidiDataToDreamDSP(AllControlOff_buff,sizeof(AllControlOff_buff)); } StartFlag = 0; + s_outro_led_all_green = 0; //tick_ever_positive = false; 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) { 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 midi = 0; + uint8_t session = StartFlag ? 1u : 0u; StartFlag = 1; if (mGuiData[GUI_AUTOBAND_SW].Current) { - AutoBandTop1_Stop(); + /* 会话内勿 Stop:段落圆键切变奏后指板续奏若 Stop 会直接关音; + * 与节奏类型一致,仅换和弦/重进当前段。冷启动仍 Stop 清残留。 */ + if (!session) + AutoBandTop1_Stop(); AutoBandTop1_SetLoopMode(0, 1); AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current); midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current; AutoBandTop1_StartWithNote(midi); 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", midi, 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_StartWithNotes(midi_note_buff, note_cnt); AutoBandTop1_SetLoopMode(0, 1); + Band_NotifyPlayActivity(); LOG_I("pick", "expert/rhythm piece name=%s trigger=%s chord=%u", AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?", trigger, @@ -958,11 +981,24 @@ void TM1629_Handle(uint8_t key) * 松手再按同一键也必须能续奏(与「指板+拨片」一致,拨片本无去重) */ if (!Band_IsPlaying()) { - /* 段落已停:仅按指板续奏下一节。转主任务走 Pick_Handle - *(与「指板+拨片」等价)。勿在播放中 Stop+Start——本地曲目 - * 中途重启常静音,表现为换把位关音、再按才有声。 */ - MainTask_Sendmsg(MSG_ID_BP_KEY, 0, 0, 0); - LOG_I("pick", "expert/fret continue chord=%u", (unsigned)KEY_ID_1629); + /* 节奏:段落自然停后指板续奏 → piece 重启。 + * 本地曲:圆键切段后 PlayTick 常短暂停滞,若走 Stop+Start 会关音; + * 与节奏「播放中换把」一致,仅换和弦音持续播放。段落后续奏用拨片/再按圆键。 */ + if (mGuiData[GUI_AUTOBAND_SW].Current) + { + 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 { @@ -1120,6 +1156,7 @@ void Pick_Handle() case 0: /* 万能:和弦走向用 piece 模式;须 SetLoopMode,否则无循环时常听不到伴奏 */ StartFlag = 1; + s_outro_led_all_green = 0; /* 拨片重开 piece,恢复走向灯 */ AutoBandTop1_SetPiecePlayMode(1, 0, 480); AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt); AutoBandTop1_SetLoopMode(0, 1); @@ -1601,7 +1638,8 @@ void Read_Cur_Measure() Band_TrackPlayTick(); - if (loop_light_ok && StartFlag) + /* 尾奏中保持全绿,不刷新和弦走向红灯 */ + if (loop_light_ok && StartFlag && !s_outro_led_all_green) { if(now - last_tick_i >= 10) { diff --git a/Global/Global.h b/Global/Global.h index 5add3dd..521d913 100644 --- a/Global/Global.h +++ b/Global/Global.h @@ -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); /* 伴奏已在播时仅更新和弦音,不 Restart(快转调) */ void Accomp_UpdatePlayingChord(void); +/* 段落键等主动刷新伴奏活动,避免 PlayTick 短暂停滞被判为已停 */ +void Band_NotifyPlayActivity(void); 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 Read_Cur_Measure(); diff --git a/UI/UI_SongMode.c b/UI/UI_SongMode.c index e8b0beb..e03c4df 100644 --- a/UI/UI_SongMode.c +++ b/UI/UI_SongMode.c @@ -277,13 +277,18 @@ void Touch_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex,uint8_t value) if(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 { /* 触摸起奏前补发主音量,保证实际音量与图标一致 */ MasterVolume_Reapply(); AutoBandTop1_FillinWithIndex(value); AutoBandTop1_Start(); + if (StartFlag) + Band_NotifyPlayActivity(); } if (!UI_SetFocus(GUI_PLAY_SECTION)) Refresh_SectionSelect(last_value, &UI_Label[ID], &mGuiData[ID]);