fix(band): cut intro and endings in immediately

Normal and expert modes no longer wait for the next bar before preamble, interlude, outro, and ending. Universal mode ignores those keys. Bump firmware to 0.2.22.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-09-23 08:39:39 +08:00
parent 93e633472a
commit 96fd815ca9
2 changed files with 76 additions and 19 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)); uint8_t TOUCH_AREA_NUM = (sizeof(Touch_Areas)/sizeof(Touch_AreaTypeDef));
const uint8_t Version[3] = {0,2,21}; /* major.minor.patch — 0.2.21: 问题2 曲目LED不再改写和弦映射(6m/Am 不再变 AM7); 和弦读回编码 m7/M7/ad9/sus 修正, 属七兼容 0x0D */ const uint8_t Version[3] = {0,2,22}; /* major.minor.patch — 0.2.22: 普通/专业模式前奏间奏尾奏断奏即刻切入;万能模式忽略这四键 */
uint8_t Led = 8; uint8_t Led = 8;
bool PressFlag = 0; bool PressFlag = 0;
@ -664,14 +664,52 @@ void Accomp_UpdatePlayingChord(void)
/* 尾奏期间冻结走向灯:保持全绿,避免 LOOP_LIGHT 按小节刷红 */ /* 尾奏期间冻结走向灯:保持全绿,避免 LOOP_LIGHT 按小节刷红 */
static uint8_t s_outro_led_all_green = 0; static uint8_t s_outro_led_all_green = 0;
/* libAutoBand m_ABSystem:+0x59 舞台,+0x50 小节相位。
* 前奏挂起舞台 0x0E、尾奏挂起舞台 0x0B 都要等相位对上小节线才真正切入。 */
extern uint8_t m_ABSystem[];
#define AB_STAGE_OFF 0x59u
#define AB_BAR_PHASE_OFF 0x50u
#define AB_STAGE_PRE_WAIT 0x0Eu
#define AB_STAGE_POST_WAIT 0x0Bu
#define AB_STAGE_POST 0x0Cu
static void FreeMode_CancelEvenBeatStop(void);
static void Accomp_FireSectionNotes(void)
{
uint8_t midi_note_buff[4] = {0,};
uint8_t note_cnt;
uint8_t i;
note_cnt = GetChordNotesByType(KEY_ID_1629,
chord_type_index_map[KEY_ID_1629].type,
midi_note_buff);
for (i = 0; i < note_cnt; i++)
AutoBandTop1_Note_On(midi_note_buff[i], 0x50);
}
/* 已在播:不要等下一小节。落到挂起舞台并把相位清零,下一毫秒 tick 即切入。 */
static void Accomp_PreambleCutNow(void)
{
m_ABSystem[AB_STAGE_OFF] = AB_STAGE_PRE_WAIT;
*(volatile uint32_t *)(m_ABSystem + AB_BAR_PHASE_OFF) = 0;
}
static void Accomp_PostambleCutNow(void)
{
if (m_ABSystem[AB_STAGE_OFF] != AB_STAGE_POST)
m_ABSystem[AB_STAGE_OFF] = AB_STAGE_POST_WAIT;
*(volatile uint32_t *)(m_ABSystem + AB_BAR_PHASE_OFF) = 0;
}
/* 尾奏起奏:Postamble(0) + 同步起奏 + 当前和弦 Note_On。 /* 尾奏起奏:Postamble(0) + 同步起奏 + 当前和弦 Note_On。
* 供 ADC 独立尾奏键与万能模式第4段落键共用。 * 供 ADC 独立尾奏键与万能模式第4段落键共用。
* 万能走 piece 循环,须先退出 piece,否则 Postamble 舞台切不过去; * 万能走 piece 循环,须先退出 piece,否则 Postamble 舞台切不过去;
* 尾奏 MIDI 须由音师写入 3.bin(见 Doc/音师需求_万能3.bin尾奏_20260914.md)。 */ * 尾奏 MIDI 须由音师写入 3.bin(见 Doc/音师需求_万能3.bin尾奏_20260914.md)。
* 已在播时清小节相位,避免库把尾奏挂到下一小节线。 */
void AutoBand_StartOutro(void) void AutoBand_StartOutro(void)
{ {
uint8_t midi_note_buff[4] = {0,}; uint8_t was_playing = StartFlag;
uint8_t note_cnt = 0;
if (KEY_ID_1629 == 0 || KEY_ID_1629 == 22 || KEY_ID_1629 == 23) if (KEY_ID_1629 == 0 || KEY_ID_1629 == 22 || KEY_ID_1629 == 23)
Accomp_ApplyDefaultIChord(); Accomp_ApplyDefaultIChord();
@ -684,23 +722,32 @@ void AutoBand_StartOutro(void)
app_tm1629_all_on(LED_COLOR_G); app_tm1629_all_on(LED_COLOR_G);
/* 尾奏起奏前补发主音量,保证与图标一致 */ /* 尾奏起奏前补发主音量,保证与图标一致 */
MasterVolume_Reapply(); MasterVolume_Reapply();
if (was_playing)
Accomp_PostambleCutNow();
else
{
Band_SyncStartRetry(); Band_SyncStartRetry();
wk_delay_ms(50); wk_delay_ms(50);
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);
} }
Accomp_FireSectionNotes();
} }
void ADC_IN1_KEY_Handle(uint8_t key,bool on) void ADC_IN1_KEY_Handle(uint8_t key,bool on)
{ {
uint8_t midi_note_buff[4] = {0,};
uint8_t note_cnt = 0;
uint8_t is_preamble = 0; uint8_t is_preamble = 0;
uint8_t is_postamble = 0;
uint8_t was_playing;
(void)on;
/* 万能:前奏/间奏/尾奏/断奏无响应(含 App 06 指令) */
if (mGuiData[GUI_TAB_INDEX].Current == 0)
return;
key_toggle[key] = !key_toggle[key]; key_toggle[key] = !key_toggle[key];
if(key_toggle[key] == 1) if(key_toggle[key] == 1)
{ {
was_playing = StartFlag;
FreeMode_CancelEvenBeatStop();
//ResetAutoPowerCount(); //ResetAutoPowerCount();
if(key == 1) if(key == 1)
{ {
@ -714,7 +761,12 @@ void ADC_IN1_KEY_Handle(uint8_t key,bool on)
{ {
case 3: AutoBandTop1_Preamble(0); is_preamble = 1; break; case 3: AutoBandTop1_Preamble(0); is_preamble = 1; break;
case 0: AutoBandTop1_Preamble(1); is_preamble = 1; break; case 0: AutoBandTop1_Preamble(1); is_preamble = 1; break;
case 2: AutoBandTop1_Postamble(1); break; case 2:
/* 断奏同尾奏:piece 循环里 Postamble 切不过去 */
AutoBandTop1_SetPiecePlayMode(0, 0, 0);
AutoBandTop1_Postamble(1);
is_postamble = 1;
break;
} }
/* 前奏:须在 SyncStart 前落到当前调一级,否则前 50ms 伴奏按旧把位进 */ /* 前奏:须在 SyncStart 前落到当前调一级,否则前 50ms 伴奏按旧把位进 */
if (is_preamble) if (is_preamble)
@ -723,14 +775,19 @@ void ADC_IN1_KEY_Handle(uint8_t key,bool on)
Accomp_ApplyDefaultIChord(); Accomp_ApplyDefaultIChord();
/* 前奏/断奏起奏前补发主音量,保证与图标一致 */ /* 前奏/断奏起奏前补发主音量,保证与图标一致 */
MasterVolume_Reapply(); MasterVolume_Reapply();
//AutoBandTop1_Start(); if (was_playing)
{
if (is_preamble)
Accomp_PreambleCutNow();
else if (is_postamble)
Accomp_PostambleCutNow();
}
else
{
Band_SyncStartRetry(); Band_SyncStartRetry();
wk_delay_ms(50); wk_delay_ms(50);
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);
} }
Accomp_FireSectionNotes();
if (is_preamble) if (is_preamble)
StartFlag = 1; StartFlag = 1;
} }

View File

@ -38,7 +38,7 @@ TONE_HDR = PROJ / "project" / "inc" / "ExtFlash_Tone_Addr.h"
IAP_DIR = REPO / "升级" / "MCU主控升级" IAP_DIR = REPO / "升级" / "MCU主控升级"
OUT_ROOT = REPO / "tools" / "out" OUT_ROOT = REPO / "tools" / "out"
FW_VER = "0.2.21" FW_VER = "0.2.22"
UI0902_RES_BASE = 0x00100000 UI0902_RES_BASE = 0x00100000
BOOT_FLASH_ADDR = 0x08000000 BOOT_FLASH_ADDR = 0x08000000
APP_FLASH_ADDR = 0x08008000 APP_FLASH_ADDR = 0x08008000