fix(accomp): keep the sixth arpeggio note on the next eighth

The extra note stacked on the fifth eighth was consuming the next sequence step, so later bars drifted. Drop that trigger instead of delaying the rest of the cycle.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-10-16 15:35:01 +08:00
parent b9fcddd9b3
commit 5b9ab3c098
1 changed files with 46 additions and 10 deletions

View File

@ -59,10 +59,11 @@ static uint8_t s_seq_po;
#define ARP_CH 12 /* 逐音琶音;垫音通道同一拍会叠多个音,不参与网格 */ #define ARP_CH 12 /* 逐音琶音;垫音通道同一拍会叠多个音,不参与网格 */
static uint8_t s_seq_step[16]; static uint8_t s_seq_step[16];
static struct { uint8_t ch, in, out, used; } s_seq_slot[SEQ_SLOTS]; static struct { uint8_t ch, in, out, used; } s_seq_slot[SEQ_SLOTS];
/* 红圈:同一拍叠上来的音向右 1 个音(图上 1 tik = 两个格子 = 一个八分音符)。 */ /* 第 5 拍会叠来一个多余触发。丢掉它,不占发音顺序,第 6 个音就落在下一拍。 */
static uint32_t s_grid_t0; static uint32_t s_grid_t0;
static uint16_t s_grid_unit; static uint16_t s_grid_unit;
static uint8_t s_grid_on; static uint8_t s_grid_on;
static uint8_t s_seq_drop;
static uint16_t s_pending_hold_ms; static uint16_t s_pending_hold_ms;
static uint8_t s_slot_hold4[SEQ_SLOTS]; static uint8_t s_slot_hold4[SEQ_SLOTS];
static volatile uint16_t s_hold_report; static volatile uint16_t s_hold_report;
@ -181,6 +182,7 @@ static int App_Auto_MapSeq(int channel, int key, int is_on, int *out)
int i; int i;
s_pending_hold_ms = 0; s_pending_hold_ms = 0;
s_seq_drop = 0;
App_Auto_SeqRefresh(); App_Auto_SeqRefresh();
if (!s_seq_on || channel == BASS_CH || channel == DRUM_CH) if (!s_seq_on || channel == BASS_CH || channel == DRUM_CH)
return 0; return 0;
@ -191,9 +193,14 @@ static int App_Auto_MapSeq(int channel, int key, int is_on, int *out)
{ {
if (s_seq_slot[i].used && s_seq_slot[i].ch == (uint8_t)ch if (s_seq_slot[i].used && s_seq_slot[i].ch == (uint8_t)ch
&& s_seq_slot[i].in == (uint8_t)key) && s_seq_slot[i].in == (uint8_t)key)
{
if (s_seq_slot[i].used == 2u)
s_seq_drop = 1u;
else
{ {
*out = s_seq_slot[i].out; *out = s_seq_slot[i].out;
s_pending_hold_ms = (uint16_t)s_slot_hold4[i] * 4u; s_pending_hold_ms = (uint16_t)s_slot_hold4[i] * 4u;
}
s_seq_slot[i].used = 0; s_seq_slot[i].used = 0;
s_slot_hold4[i] = 0; s_slot_hold4[i] = 0;
return 1; return 1;
@ -203,21 +210,44 @@ static int App_Auto_MapSeq(int channel, int key, int is_on, int *out)
return 1; return 1;
} }
{ {
uint8_t step = (uint8_t)(s_seq_step[ch] & 7u); uint8_t step;
uint32_t now; uint32_t now;
*out = s_seq[step]; uint8_t piled = 0;
s_seq_step[ch] = (uint8_t)((step + 1u) & 7u);
/* 琶音通道同一拍里的后一个音,晚一个八分音符再发出 */
if (ch == ARP_CH) if (ch == ARP_CH)
{ {
now = wk_timebase_get(); now = wk_timebase_get();
if (s_grid_on && (now - s_grid_t0) < (uint32_t)(s_grid_unit / 4u)) if (!s_grid_on || s_grid_unit == 0u
s_pending_hold_ms = s_grid_unit; || (now - s_grid_t0) >= (uint32_t)(s_grid_unit / 4u))
else
s_grid_unit = App_Auto_EighthMs(); s_grid_unit = App_Auto_EighthMs();
piled = (s_grid_on
&& (now - s_grid_t0) < (uint32_t)(s_grid_unit / 4u)) ? 1u : 0u;
s_grid_t0 = now; s_grid_t0 = now;
s_grid_on = 1u; s_grid_on = 1u;
} }
if (piled)
{
/* 同一拍的后一个触发不发声,也不占用下一个顺序音 */
s_seq_drop = 1u;
for (i = 0; i < SEQ_SLOTS; i++)
{
if (!s_seq_slot[i].used)
{
s_seq_slot[i].used = 2u;
s_seq_slot[i].ch = (uint8_t)ch;
s_seq_slot[i].in = (uint8_t)key;
s_seq_slot[i].out = 0;
return 1;
}
}
s_seq_slot[0].used = 2u;
s_seq_slot[0].ch = (uint8_t)ch;
s_seq_slot[0].in = (uint8_t)key;
s_seq_slot[0].out = 0;
return 1;
}
step = (uint8_t)(s_seq_step[ch] & 7u);
*out = s_seq[step];
s_seq_step[ch] = (uint8_t)((step + 1u) & 7u);
} }
for (i = 0; i < SEQ_SLOTS; i++) for (i = 0; i < SEQ_SLOTS; i++)
{ {
@ -556,6 +586,8 @@ static int App_Auto_MapNoteOn(int channel, int key)
} }
out = App_Auto_MapNote(channel, key, &flags, 1); out = App_Auto_MapNote(channel, key, &flags, 1);
if (s_seq_drop)
return out;
if (channel >= 0 && channel < 16) if (channel >= 0 && channel < 16)
{ {
uint16_t bit = (uint16_t)(1u << channel); uint16_t bit = (uint16_t)(1u << channel);
@ -610,6 +642,8 @@ static void Func_CallBack_NoteOff(int channel,int key)
MidiFifoItem_t midimsg = {0}; MidiFifoItem_t midimsg = {0};
uint8_t flags = 0; uint8_t flags = 0;
int out_key = App_Auto_MapNote(channel, key, &flags, 0); int out_key = App_Auto_MapNote(channel, key, &flags, 0);
if (s_seq_drop)
return;
midimsg.msg[0] = 0x80 | (channel & 0x0F); midimsg.msg[0] = 0x80 | (channel & 0x0F);
midimsg.msg[1] = (uint8_t)out_key; midimsg.msg[1] = (uint8_t)out_key;
midimsg.msg[2] = 0; midimsg.msg[2] = 0;
@ -630,6 +664,8 @@ static void Func_CallBack_NoteOn(int channel,int key,int vel)
} }
else else
out_key = App_Auto_MapNoteOn(channel, key); out_key = App_Auto_MapNoteOn(channel, key);
if (s_seq_drop)
return;
midimsg.msg[0] = 0x90 | (channel & 0x0F); midimsg.msg[0] = 0x90 | (channel & 0x0F);
midimsg.msg[1] = (uint8_t)out_key; midimsg.msg[1] = (uint8_t)out_key;