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:
parent
b9fcddd9b3
commit
5b9ab3c098
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue