mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
sound, improve ym2612 accuracy (NB noticeably slower for low bitrates)
This commit is contained in:
parent
c3fcdf3f8d
commit
d127b3f3d5
3 changed files with 361 additions and 438 deletions
|
@ -8,7 +8,6 @@
|
||||||
**
|
**
|
||||||
** updated with fixes from mame 0.216 (file version 1.5.1) (kub)
|
** updated with fixes from mame 0.216 (file version 1.5.1) (kub)
|
||||||
** SSG-EG readded from GenPlus (kub)
|
** SSG-EG readded from GenPlus (kub)
|
||||||
** linear sample interpolation for chip to output rate adaption (kub)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -909,7 +908,7 @@ typedef struct
|
||||||
UINT32 eg_timer;
|
UINT32 eg_timer;
|
||||||
UINT32 eg_timer_add;
|
UINT32 eg_timer_add;
|
||||||
UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]
|
UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]
|
||||||
UINT32 algo; /* 50: algo[3], was_update */
|
UINT32 algo; /* 50: algo[3], was_update, unsued, upd_cnt[2], dac */
|
||||||
INT32 op1_out;
|
INT32 op1_out;
|
||||||
#ifdef _MIPS_ARCH_ALLEGREX
|
#ifdef _MIPS_ARCH_ALLEGREX
|
||||||
UINT32 pad1[3+8];
|
UINT32 pad1[3+8];
|
||||||
|
@ -927,20 +926,10 @@ static int clip(int n)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
static void update_ssg_eg_channel(chan_rend_context *ct)
|
||||||
{
|
{
|
||||||
int scounter; /* sample counter */
|
|
||||||
|
|
||||||
/* sample generating loop */
|
|
||||||
for (scounter = 0; scounter < length; scounter++)
|
|
||||||
{
|
|
||||||
int smp = 0; /* produced sample */
|
|
||||||
unsigned int eg_out, eg_out2, eg_out4;
|
|
||||||
FM_SLOT *SLOT;
|
FM_SLOT *SLOT;
|
||||||
UINT32 cnt = ct->eg_timer_add+(ct->eg_timer & ((1<<EG_SH)-1));
|
|
||||||
|
|
||||||
if (ct->pack & 2) while (cnt >= 1<<EG_SH) {
|
|
||||||
cnt -= 1<<EG_SH;
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT1];
|
SLOT = &ct->CH->SLOT[SLOT1];
|
||||||
if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)
|
if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200)
|
||||||
ct->phase1 = update_ssg_eg_phase(SLOT, ct->phase1);
|
ct->phase1 = update_ssg_eg_phase(SLOT, ct->phase1);
|
||||||
|
@ -955,145 +944,41 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
ct->phase4 = update_ssg_eg_phase(SLOT, ct->phase4);
|
ct->phase4 = update_ssg_eg_phase(SLOT, ct->phase4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */
|
static void update_eg_phase_channel(chan_rend_context *ct)
|
||||||
ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);
|
|
||||||
ct->lfo_cnt += ct->lfo_inc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ct->eg_timer += ct->eg_timer_add;
|
|
||||||
if (ct->eg_timer < EG_TIMER_OVERFLOW) {
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT1];
|
|
||||||
SLOT->vol_ipol = SLOT->vol_out;
|
|
||||||
if (SLOT->state > EG_REL) recalc_volout(SLOT);
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT2];
|
|
||||||
SLOT->vol_ipol = SLOT->vol_out;
|
|
||||||
if (SLOT->state > EG_REL) recalc_volout(SLOT);
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT3];
|
|
||||||
SLOT->vol_ipol = SLOT->vol_out;
|
|
||||||
if (SLOT->state > EG_REL) recalc_volout(SLOT);
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT4];
|
|
||||||
SLOT->vol_ipol = SLOT->vol_out;
|
|
||||||
if (SLOT->state > EG_REL) recalc_volout(SLOT);
|
|
||||||
}
|
|
||||||
else while (ct->eg_timer >= EG_TIMER_OVERFLOW)
|
|
||||||
{
|
{
|
||||||
ct->eg_timer -= EG_TIMER_OVERFLOW;
|
FM_SLOT *SLOT;
|
||||||
ct->eg_cnt++;
|
|
||||||
if (ct->eg_cnt >= 4096) ct->eg_cnt = 1;
|
|
||||||
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT1];
|
SLOT = &ct->CH->SLOT[SLOT1];
|
||||||
SLOT->vol_ipol = SLOT->vol_out;
|
|
||||||
if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);
|
if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);
|
||||||
SLOT = &ct->CH->SLOT[SLOT2];
|
SLOT = &ct->CH->SLOT[SLOT2];
|
||||||
SLOT->vol_ipol = SLOT->vol_out;
|
|
||||||
if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);
|
if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);
|
||||||
SLOT = &ct->CH->SLOT[SLOT3];
|
SLOT = &ct->CH->SLOT[SLOT3];
|
||||||
SLOT->vol_ipol = SLOT->vol_out;
|
|
||||||
if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);
|
if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);
|
||||||
SLOT = &ct->CH->SLOT[SLOT4];
|
SLOT = &ct->CH->SLOT[SLOT4];
|
||||||
SLOT->vol_ipol = SLOT->vol_out;
|
|
||||||
if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);
|
if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsigned int eg_out2, unsigned int eg_out4)
|
||||||
UINT32 ifrac0 = ct->eg_timer / (EG_TIMER_OVERFLOW>>EG_SH);
|
|
||||||
UINT32 ifrac1 = (1<<EG_SH) - ifrac0;
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT1];
|
|
||||||
ct->vol_out1 = (SLOT->vol_ipol*ifrac1 + SLOT->vol_out*ifrac0) >> EG_SH;
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT2];
|
|
||||||
ct->vol_out2 = (SLOT->vol_ipol*ifrac1 + SLOT->vol_out*ifrac0) >> EG_SH;
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT3];
|
|
||||||
ct->vol_out3 = (SLOT->vol_ipol*ifrac1 + SLOT->vol_out*ifrac0) >> EG_SH;
|
|
||||||
SLOT = &ct->CH->SLOT[SLOT4];
|
|
||||||
ct->vol_out4 = (SLOT->vol_ipol*ifrac1 + SLOT->vol_out*ifrac0) >> EG_SH;
|
|
||||||
#elif 1
|
|
||||||
switch (ct->eg_timer >> EG_SH)
|
|
||||||
{
|
{
|
||||||
case 0:
|
int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */
|
||||||
ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_ipol;
|
int smp = 0;
|
||||||
ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_ipol;
|
|
||||||
ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_ipol;
|
|
||||||
ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_ipol;
|
|
||||||
break;
|
|
||||||
case (EG_TIMER_OVERFLOW>>EG_SH)-1:
|
|
||||||
ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_out;
|
|
||||||
ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_out;
|
|
||||||
ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_out;
|
|
||||||
ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_out;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ct->vol_out1 = (ct->CH->SLOT[SLOT1].vol_ipol +
|
|
||||||
ct->CH->SLOT[SLOT1].vol_out) >> 1;
|
|
||||||
ct->vol_out2 = (ct->CH->SLOT[SLOT2].vol_ipol +
|
|
||||||
ct->CH->SLOT[SLOT2].vol_out) >> 1;
|
|
||||||
ct->vol_out3 = (ct->CH->SLOT[SLOT3].vol_ipol +
|
|
||||||
ct->CH->SLOT[SLOT3].vol_out) >> 1;
|
|
||||||
ct->vol_out4 = (ct->CH->SLOT[SLOT4].vol_ipol +
|
|
||||||
ct->CH->SLOT[SLOT4].vol_out) >> 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#elif 0
|
|
||||||
if (ct->eg_timer >> (EG_SH-1) < EG_TIMER_OVERFLOW >> EG_SH) {
|
|
||||||
ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_ipol;
|
|
||||||
ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_ipol;
|
|
||||||
ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_ipol;
|
|
||||||
ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_ipol;
|
|
||||||
} else {
|
|
||||||
ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_out;
|
|
||||||
ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_out;
|
|
||||||
ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_out;
|
|
||||||
ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_out;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_out;
|
|
||||||
ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_out;
|
|
||||||
ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_out;
|
|
||||||
ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_out;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ct->pack & 4) continue; /* output disabled */
|
|
||||||
|
|
||||||
/* calculate channel sample */
|
|
||||||
eg_out = ct->vol_out1;
|
|
||||||
if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);
|
|
||||||
|
|
||||||
if( eg_out < ENV_QUIET ) /* SLOT 1 */
|
|
||||||
{
|
|
||||||
int out = 0;
|
|
||||||
|
|
||||||
if (ct->pack&0xf000) out = ((ct->op1_out>>16) + ((ct->op1_out<<16)>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */
|
|
||||||
ct->op1_out <<= 16;
|
|
||||||
ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);
|
|
||||||
} else {
|
|
||||||
ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */
|
|
||||||
}
|
|
||||||
|
|
||||||
eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);
|
|
||||||
eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);
|
|
||||||
eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);
|
|
||||||
|
|
||||||
if (ct->pack & 8) {
|
|
||||||
unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);
|
|
||||||
if (ct->pack & (1<<(SLOT3+8))) eg_out += add;
|
|
||||||
if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;
|
|
||||||
if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch( ct->algo&0x7 )
|
switch( ct->algo&0x7 )
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
/* M1---C1---MEM---M2---C2---OUT */
|
/* M1---C1---MEM---M2---C2---OUT */
|
||||||
int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */
|
|
||||||
m2 = ct->mem;
|
m2 = ct->mem;
|
||||||
c1 = ct->op1_out>>16;
|
c1 = ct->op1_out>>16;
|
||||||
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
|
||||||
c2 = op_calc(ct->phase3, eg_out, m2);
|
|
||||||
}
|
|
||||||
if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
|
if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
|
||||||
ct->mem = op_calc(ct->phase2, eg_out2, c1);
|
ct->mem = op_calc(ct->phase2, eg_out2, c1);
|
||||||
}
|
}
|
||||||
else ct->mem = 0;
|
else ct->mem = 0;
|
||||||
|
if (ct->eg_timer >= (1<<EG_SH)) break;
|
||||||
|
|
||||||
|
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
||||||
|
c2 = op_calc(ct->phase3, eg_out, m2);
|
||||||
|
}
|
||||||
if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
|
if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
|
||||||
smp = op_calc(ct->phase4, eg_out4, c2);
|
smp = op_calc(ct->phase4, eg_out4, c2);
|
||||||
}
|
}
|
||||||
|
@ -1103,15 +988,16 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
{
|
{
|
||||||
/* M1------+-MEM---M2---C2---OUT */
|
/* M1------+-MEM---M2---C2---OUT */
|
||||||
/* C1-+ */
|
/* C1-+ */
|
||||||
int m2,c2=0;
|
|
||||||
m2 = ct->mem;
|
m2 = ct->mem;
|
||||||
ct->mem = ct->op1_out>>16;
|
ct->mem = ct->op1_out>>16;
|
||||||
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
|
||||||
c2 = op_calc(ct->phase3, eg_out, m2);
|
|
||||||
}
|
|
||||||
if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
|
if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
|
||||||
ct->mem+= op_calc(ct->phase2, eg_out2, 0);
|
ct->mem+= op_calc(ct->phase2, eg_out2, 0);
|
||||||
}
|
}
|
||||||
|
if (ct->eg_timer >= (1<<EG_SH)) break;
|
||||||
|
|
||||||
|
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
||||||
|
c2 = op_calc(ct->phase3, eg_out, m2);
|
||||||
|
}
|
||||||
if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
|
if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
|
||||||
smp = op_calc(ct->phase4, eg_out4, c2);
|
smp = op_calc(ct->phase4, eg_out4, c2);
|
||||||
}
|
}
|
||||||
|
@ -1121,16 +1007,17 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
{
|
{
|
||||||
/* M1-----------------+-C2---OUT */
|
/* M1-----------------+-C2---OUT */
|
||||||
/* C1---MEM---M2-+ */
|
/* C1---MEM---M2-+ */
|
||||||
int m2,c2;
|
|
||||||
m2 = ct->mem;
|
m2 = ct->mem;
|
||||||
c2 = ct->op1_out>>16;
|
c2 = ct->op1_out>>16;
|
||||||
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
|
||||||
c2 += op_calc(ct->phase3, eg_out, m2);
|
|
||||||
}
|
|
||||||
if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
|
if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
|
||||||
ct->mem = op_calc(ct->phase2, eg_out2, 0);
|
ct->mem = op_calc(ct->phase2, eg_out2, 0);
|
||||||
}
|
}
|
||||||
else ct->mem = 0;
|
else ct->mem = 0;
|
||||||
|
if (ct->eg_timer >= (1<<EG_SH)) break;
|
||||||
|
|
||||||
|
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
||||||
|
c2 += op_calc(ct->phase3, eg_out, m2);
|
||||||
|
}
|
||||||
if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
|
if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
|
||||||
smp = op_calc(ct->phase4, eg_out4, c2);
|
smp = op_calc(ct->phase4, eg_out4, c2);
|
||||||
}
|
}
|
||||||
|
@ -1140,16 +1027,17 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
{
|
{
|
||||||
/* M1---C1---MEM------+-C2---OUT */
|
/* M1---C1---MEM------+-C2---OUT */
|
||||||
/* M2-+ */
|
/* M2-+ */
|
||||||
int c1,c2;
|
|
||||||
c2 = ct->mem;
|
c2 = ct->mem;
|
||||||
c1 = ct->op1_out>>16;
|
c1 = ct->op1_out>>16;
|
||||||
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
|
||||||
c2 += op_calc(ct->phase3, eg_out, 0);
|
|
||||||
}
|
|
||||||
if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
|
if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */
|
||||||
ct->mem = op_calc(ct->phase2, eg_out2, c1);
|
ct->mem = op_calc(ct->phase2, eg_out2, c1);
|
||||||
}
|
}
|
||||||
else ct->mem = 0;
|
else ct->mem = 0;
|
||||||
|
if (ct->eg_timer >= (1<<EG_SH)) break;
|
||||||
|
|
||||||
|
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
||||||
|
c2 += op_calc(ct->phase3, eg_out, 0);
|
||||||
|
}
|
||||||
if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
|
if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */
|
||||||
smp = op_calc(ct->phase4, eg_out4, c2);
|
smp = op_calc(ct->phase4, eg_out4, c2);
|
||||||
}
|
}
|
||||||
|
@ -1160,7 +1048,8 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
/* M1---C1-+-OUT */
|
/* M1---C1-+-OUT */
|
||||||
/* M2---C2-+ */
|
/* M2---C2-+ */
|
||||||
/* MEM: not used */
|
/* MEM: not used */
|
||||||
int c1,c2=0;
|
if (ct->eg_timer >= (1<<EG_SH)) break;
|
||||||
|
|
||||||
c1 = ct->op1_out>>16;
|
c1 = ct->op1_out>>16;
|
||||||
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
||||||
c2 = op_calc(ct->phase3, eg_out, 0);
|
c2 = op_calc(ct->phase3, eg_out, 0);
|
||||||
|
@ -1178,7 +1067,8 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
/* +----C1----+ */
|
/* +----C1----+ */
|
||||||
/* M1-+-MEM---M2-+-OUT */
|
/* M1-+-MEM---M2-+-OUT */
|
||||||
/* +----C2----+ */
|
/* +----C2----+ */
|
||||||
int m2,c1,c2;
|
if (ct->eg_timer >= (1<<EG_SH)) break;
|
||||||
|
|
||||||
m2 = ct->mem;
|
m2 = ct->mem;
|
||||||
ct->mem = c1 = c2 = ct->op1_out>>16;
|
ct->mem = c1 = c2 = ct->op1_out>>16;
|
||||||
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
||||||
|
@ -1198,7 +1088,8 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
/* M2-+-OUT */
|
/* M2-+-OUT */
|
||||||
/* C2-+ */
|
/* C2-+ */
|
||||||
/* MEM: not used */
|
/* MEM: not used */
|
||||||
int c1;
|
if (ct->eg_timer >= (1<<EG_SH)) break;
|
||||||
|
|
||||||
c1 = ct->op1_out>>16;
|
c1 = ct->op1_out>>16;
|
||||||
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
||||||
smp = op_calc(ct->phase3, eg_out, 0);
|
smp = op_calc(ct->phase3, eg_out, 0);
|
||||||
|
@ -1218,6 +1109,8 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
/* M2-+ */
|
/* M2-+ */
|
||||||
/* C2-+ */
|
/* C2-+ */
|
||||||
/* MEM: not used*/
|
/* MEM: not used*/
|
||||||
|
if (ct->eg_timer >= (1<<EG_SH)) break;
|
||||||
|
|
||||||
smp = ct->op1_out>>16;
|
smp = ct->op1_out>>16;
|
||||||
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
if( eg_out < ENV_QUIET ) { /* SLOT 3 */
|
||||||
smp += op_calc(ct->phase3, eg_out, 0);
|
smp += op_calc(ct->phase3, eg_out, 0);
|
||||||
|
@ -1231,8 +1124,89 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return smp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
|
{
|
||||||
|
int scounter; /* sample counter */
|
||||||
|
|
||||||
|
/* sample generating loop */
|
||||||
|
for (scounter = 0; scounter < length; scounter++)
|
||||||
|
{
|
||||||
|
int smp = 0; /* produced sample */
|
||||||
|
unsigned int eg_out, eg_out2, eg_out4;
|
||||||
|
|
||||||
|
ct->eg_timer += ct->eg_timer_add;
|
||||||
|
while (ct->eg_timer >= 1<<EG_SH) {
|
||||||
|
ct->eg_timer -= 1<<EG_SH;
|
||||||
|
|
||||||
|
if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */
|
||||||
|
ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16);
|
||||||
|
ct->lfo_cnt += ct->lfo_inc;
|
||||||
|
}
|
||||||
|
if (ct->pack & 2)
|
||||||
|
update_ssg_eg_channel(ct);
|
||||||
|
|
||||||
|
if (ct->algo & 0x30)
|
||||||
|
ct->algo -= 0x10;
|
||||||
|
if (!(ct->algo & 0x30)) {
|
||||||
|
ct->algo |= 0x30;
|
||||||
|
ct->eg_cnt++;
|
||||||
|
if (ct->eg_cnt >= 4096) ct->eg_cnt = 1;
|
||||||
|
|
||||||
|
update_eg_phase_channel(ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_out;
|
||||||
|
ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_out;
|
||||||
|
ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_out;
|
||||||
|
ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_out;
|
||||||
|
|
||||||
|
if (ct->pack & 4) goto disabled; /* output disabled */
|
||||||
|
|
||||||
|
/* calculate channel sample */
|
||||||
|
if (ct->eg_timer < (2<<EG_SH) || (ct->pack&0xf000)) {
|
||||||
|
eg_out = ct->vol_out1;
|
||||||
|
if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) )
|
||||||
|
eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24);
|
||||||
|
|
||||||
|
if( eg_out < ENV_QUIET ) /* SLOT 1 */
|
||||||
|
{
|
||||||
|
int out = 0;
|
||||||
|
|
||||||
|
if (ct->pack&0xf000) out = ((ct->op1_out>>16) + ((ct->op1_out<<16)>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */
|
||||||
|
ct->op1_out <<= 16;
|
||||||
|
ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out);
|
||||||
|
} else {
|
||||||
|
ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ct->eg_timer < (2<<EG_SH)) {
|
||||||
|
eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]);
|
||||||
|
eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]);
|
||||||
|
eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]);
|
||||||
|
|
||||||
|
if (ct->pack & 8) {
|
||||||
|
unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24);
|
||||||
|
if (ct->pack & (1<<(SLOT3+8))) eg_out += add;
|
||||||
|
if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add;
|
||||||
|
if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add;
|
||||||
|
}
|
||||||
|
|
||||||
|
smp = update_algo_channel(ct, eg_out, eg_out2, eg_out4);
|
||||||
|
}
|
||||||
/* done calculating channel sample */
|
/* done calculating channel sample */
|
||||||
|
|
||||||
|
disabled:
|
||||||
|
/* update phase counters AFTER output calculations */
|
||||||
|
ct->phase1 += ct->incr1;
|
||||||
|
ct->phase2 += ct->incr2;
|
||||||
|
ct->phase3 += ct->incr3;
|
||||||
|
ct->phase4 += ct->incr4;
|
||||||
|
}
|
||||||
|
|
||||||
/* mix sample to output buffer */
|
/* mix sample to output buffer */
|
||||||
if (smp) {
|
if (smp) {
|
||||||
smp = clip(smp); /* saturate to 14 bit */
|
smp = clip(smp); /* saturate to 14 bit */
|
||||||
|
@ -1250,12 +1224,6 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
||||||
}
|
}
|
||||||
ct->algo |= 8;
|
ct->algo |= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update phase counters AFTER output calculations */
|
|
||||||
ct->phase1 += ct->incr1;
|
|
||||||
ct->phase2 += ct->incr2;
|
|
||||||
ct->phase3 += ct->incr3;
|
|
||||||
ct->phase4 += ct->incr4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1335,6 +1303,7 @@ static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: s
|
||||||
|
|
||||||
crct.op1_out = crct.CH->op1_out;
|
crct.op1_out = crct.CH->op1_out;
|
||||||
crct.algo = crct.CH->ALGO & 7;
|
crct.algo = crct.CH->ALGO & 7;
|
||||||
|
crct.algo |= crct.CH->upd_cnt << 4;
|
||||||
if (ym2612.OPN.ST.flags & ST_DAC)
|
if (ym2612.OPN.ST.flags & ST_DAC)
|
||||||
crct.algo |= 0x80;
|
crct.algo |= 0x80;
|
||||||
|
|
||||||
|
@ -1373,6 +1342,7 @@ static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: s
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ym2612.slot_mask &= ~(0xf << (c*4));
|
ym2612.slot_mask &= ~(0xf << (c*4));
|
||||||
|
crct.CH->upd_cnt = (crct.algo >> 4) & 0x7;
|
||||||
|
|
||||||
return (crct.algo & 8) >> 3; // had output
|
return (crct.algo & 8) >> 3; // had output
|
||||||
}
|
}
|
||||||
|
@ -1625,9 +1595,10 @@ static void OPNSetPres(int pres)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* frequency base */
|
/* frequency base */
|
||||||
ym2612.OPN.ST.freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;
|
double freqbase = (ym2612.OPN.ST.rate) ? ((double)ym2612.OPN.ST.clock / ym2612.OPN.ST.rate) / pres : 0;
|
||||||
|
|
||||||
ym2612.OPN.eg_timer_add = (1<<EG_SH) * ym2612.OPN.ST.freqbase;
|
ym2612.OPN.eg_timer_add = (1<<EG_SH) * freqbase;
|
||||||
|
ym2612.OPN.ST.freqbase = 1.0; // freqbase
|
||||||
|
|
||||||
/* make time tables */
|
/* make time tables */
|
||||||
init_timetables( dt_tab );
|
init_timetables( dt_tab );
|
||||||
|
|
|
@ -59,7 +59,7 @@ typedef struct
|
||||||
UINT8 ssgn;
|
UINT8 ssgn;
|
||||||
UINT16 ar_ksr; /* 0x32 ar+ksr */
|
UINT16 ar_ksr; /* 0x32 ar+ksr */
|
||||||
UINT16 vol_out; /* 0x34 current output from EG (without LFO) */
|
UINT16 vol_out; /* 0x34 current output from EG (without LFO) */
|
||||||
UINT16 vol_ipol; /* 0x36 interpolator memory */
|
UINT16 pad;
|
||||||
} FM_SLOT;
|
} FM_SLOT;
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ typedef struct
|
||||||
|
|
||||||
UINT8 kcode; /* +11 key code: */
|
UINT8 kcode; /* +11 key code: */
|
||||||
UINT8 fn_h; /* freq latch */
|
UINT8 fn_h; /* freq latch */
|
||||||
UINT8 pad2;
|
UINT8 upd_cnt; /* eg update counter */
|
||||||
UINT32 fc; /* fnum,blk:adjusted to sample rate */
|
UINT32 fc; /* fnum,blk:adjusted to sample rate */
|
||||||
UINT32 block_fnum; /* current blk/fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */
|
UINT32 block_fnum; /* current blk/fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include <pico/arm_features.h>
|
#include <pico/arm_features.h>
|
||||||
|
|
||||||
@ very simple YM2612 output rate to sample rate adaption (~500k cycles @44100)
|
@ very simple YM2612 output rate to sample rate adaption (~500k cycles @44100)
|
||||||
#define INTERPOL
|
|
||||||
#define SSG_EG
|
#define SSG_EG
|
||||||
|
|
||||||
.equiv SLOT1, 0
|
.equiv SLOT1, 0
|
||||||
|
@ -34,7 +33,6 @@
|
||||||
.equiv EG_OFF, 0
|
.equiv EG_OFF, 0
|
||||||
|
|
||||||
.equiv EG_SH, 16 @ 16.16 fixed point (envelope generator timing)
|
.equiv EG_SH, 16 @ 16.16 fixed point (envelope generator timing)
|
||||||
.equiv EG_TIMER_OVERFLOW, (3*(1<<EG_SH)) @ envelope generator timer overflows every 3 samples (on real chip)
|
|
||||||
.equiv LFO_SH, 24 /* 8.24 fixed point (LFO calculations) */
|
.equiv LFO_SH, 24 /* 8.24 fixed point (LFO calculations) */
|
||||||
|
|
||||||
.equiv ENV_QUIET, (2*13*256/8)
|
.equiv ENV_QUIET, (2*13*256/8)
|
||||||
|
@ -46,14 +44,8 @@
|
||||||
@ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
|
@ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
|
||||||
@ writes output to routp, but only if vol_out changes
|
@ writes output to routp, but only if vol_out changes
|
||||||
.macro update_eg_phase_slot
|
.macro update_eg_phase_slot
|
||||||
#if defined(INTERPOL)
|
|
||||||
ldrh r0, [r5,#0x34] @ vol_out
|
|
||||||
#endif
|
|
||||||
ldrb r2, [r5,#0x17] @ state
|
ldrb r2, [r5,#0x17] @ state
|
||||||
add r3, r5, #0x1c
|
add r3, r5, #0x1c
|
||||||
#if defined(INTERPOL)
|
|
||||||
strh r0, [r5,#0x36] @ vol_ipol
|
|
||||||
#endif
|
|
||||||
tst r2, r2
|
tst r2, r2
|
||||||
beq 0f @ EG_OFF
|
beq 0f @ EG_OFF
|
||||||
|
|
||||||
|
@ -211,7 +203,6 @@
|
||||||
cmp r2, #EG_REL+1 @ state > EG_REL &&
|
cmp r2, #EG_REL+1 @ state > EG_REL &&
|
||||||
cmpge r3, #0x200 @ volume >= 0x200?
|
cmpge r3, #0x200 @ volume >= 0x200?
|
||||||
blt 9f
|
blt 9f
|
||||||
orr r4, r4, #0x10 @ ssg_update
|
|
||||||
|
|
||||||
tst r0, #0x01
|
tst r0, #0x01
|
||||||
beq 1f
|
beq 1f
|
||||||
|
@ -259,14 +250,8 @@
|
||||||
|
|
||||||
@ r5=slot, trashes: r0,r2,r3
|
@ r5=slot, trashes: r0,r2,r3
|
||||||
.macro recalc_volout
|
.macro recalc_volout
|
||||||
#if defined(INTERPOL)
|
|
||||||
ldrh r0, [r5,#0x34] @ vol_out
|
|
||||||
#endif
|
|
||||||
ldrb r2, [r5,#0x30] @ ssg
|
ldrb r2, [r5,#0x30] @ ssg
|
||||||
ldrb r3, [r5,#0x17] @ state
|
ldrb r3, [r5,#0x17] @ state
|
||||||
#if defined(INTERPOL)
|
|
||||||
strh r0, [r5,#0x36] @ vol_ipol
|
|
||||||
#endif
|
|
||||||
ldrh r0, [r5,#0x1a] @ volume
|
ldrh r0, [r5,#0x1a] @ volume
|
||||||
|
|
||||||
@ and r2, r2, #0x0c
|
@ and r2, r2, #0x0c
|
||||||
|
@ -342,6 +327,9 @@
|
||||||
@ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
|
@ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
|
||||||
.macro upd_algo0_m
|
.macro upd_algo0_m
|
||||||
|
|
||||||
|
cmp r8, #(1<<EG_SH)
|
||||||
|
bge 1f
|
||||||
|
|
||||||
@ SLOT3
|
@ SLOT3
|
||||||
make_eg_out SLOT3
|
make_eg_out SLOT3
|
||||||
cmp r1, #ENV_QUIET
|
cmp r1, #ENV_QUIET
|
||||||
|
@ -383,6 +371,9 @@
|
||||||
|
|
||||||
.macro upd_algo1_m
|
.macro upd_algo1_m
|
||||||
|
|
||||||
|
cmp r8, #(1<<EG_SH)
|
||||||
|
bge 1f
|
||||||
|
|
||||||
@ SLOT3
|
@ SLOT3
|
||||||
make_eg_out SLOT3
|
make_eg_out SLOT3
|
||||||
cmp r1, #ENV_QUIET
|
cmp r1, #ENV_QUIET
|
||||||
|
@ -423,6 +414,9 @@
|
||||||
|
|
||||||
.macro upd_algo2_m
|
.macro upd_algo2_m
|
||||||
|
|
||||||
|
cmp r8, #(1<<EG_SH)
|
||||||
|
bge 1f
|
||||||
|
|
||||||
@ SLOT3
|
@ SLOT3
|
||||||
make_eg_out SLOT3
|
make_eg_out SLOT3
|
||||||
cmp r1, #ENV_QUIET
|
cmp r1, #ENV_QUIET
|
||||||
|
@ -464,6 +458,9 @@
|
||||||
|
|
||||||
.macro upd_algo3_m
|
.macro upd_algo3_m
|
||||||
|
|
||||||
|
cmp r8, #(1<<EG_SH)
|
||||||
|
bge 1f
|
||||||
|
|
||||||
@ SLOT3
|
@ SLOT3
|
||||||
make_eg_out SLOT3
|
make_eg_out SLOT3
|
||||||
cmp r1, #ENV_QUIET
|
cmp r1, #ENV_QUIET
|
||||||
|
@ -505,6 +502,9 @@
|
||||||
|
|
||||||
.macro upd_algo4_m
|
.macro upd_algo4_m
|
||||||
|
|
||||||
|
cmp r8, #(1<<EG_SH)
|
||||||
|
bge 2f
|
||||||
|
|
||||||
@ SLOT3
|
@ SLOT3
|
||||||
make_eg_out SLOT3
|
make_eg_out SLOT3
|
||||||
cmp r1, #ENV_QUIET
|
cmp r1, #ENV_QUIET
|
||||||
|
@ -542,6 +542,9 @@
|
||||||
|
|
||||||
.macro upd_algo5_m
|
.macro upd_algo5_m
|
||||||
|
|
||||||
|
cmp r8, #(1<<EG_SH)
|
||||||
|
bge 2f
|
||||||
|
|
||||||
@ SLOT3
|
@ SLOT3
|
||||||
make_eg_out SLOT3
|
make_eg_out SLOT3
|
||||||
cmp r1, #ENV_QUIET
|
cmp r1, #ENV_QUIET
|
||||||
|
@ -582,6 +585,9 @@
|
||||||
|
|
||||||
.macro upd_algo6_m
|
.macro upd_algo6_m
|
||||||
|
|
||||||
|
cmp r8, #(1<<EG_SH)
|
||||||
|
bge 2f
|
||||||
|
|
||||||
@ SLOT3
|
@ SLOT3
|
||||||
make_eg_out SLOT3
|
make_eg_out SLOT3
|
||||||
cmp r1, #ENV_QUIET
|
cmp r1, #ENV_QUIET
|
||||||
|
@ -617,6 +623,9 @@
|
||||||
|
|
||||||
.macro upd_algo7_m
|
.macro upd_algo7_m
|
||||||
|
|
||||||
|
cmp r8, #(1<<EG_SH)
|
||||||
|
bge 2f
|
||||||
|
|
||||||
@ SLOT3
|
@ SLOT3
|
||||||
make_eg_out SLOT3
|
make_eg_out SLOT3
|
||||||
cmp r1, #ENV_QUIET
|
cmp r1, #ENV_QUIET
|
||||||
|
@ -677,7 +686,7 @@
|
||||||
|
|
||||||
|
|
||||||
@ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
|
@ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
|
||||||
@ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|dac,unused[2],ssg_update,was_update,algo[3], r5=tl_tab/slot,
|
@ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|dac,upd_cnt[3],was_update,algo[3], r5=tl_tab/slot,
|
||||||
@ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer
|
@ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer
|
||||||
.global chan_render_loop @ chan_rend_context *ct, int *buffer, int length
|
.global chan_render_loop @ chan_rend_context *ct, int *buffer, int length
|
||||||
|
|
||||||
|
@ -688,47 +697,48 @@ chan_render_loop:
|
||||||
ldr r12, [lr, #0x4c]
|
ldr r12, [lr, #0x4c]
|
||||||
ldr r0, [lr, #0x50]
|
ldr r0, [lr, #0x50]
|
||||||
mov r11, r1
|
mov r11, r1
|
||||||
and r0, r0, #0x87
|
and r0, r0, #0xf7
|
||||||
orr r4, r4, r0 @ (length<<8)|dac,unused[4],algo[3]
|
orr r4, r4, r0 @ (length<<8)|dac,upd_cnt[2],unused,algo[3]
|
||||||
ldr r8, [lr, #0x44] @ eg_timer
|
ldr r8, [lr, #0x44] @ eg_timer
|
||||||
ldr r9, [lr, #0x48] @ eg_timer_add
|
ldr r9, [lr, #0x48] @ eg_timer_add
|
||||||
ldr r10, [lr, #0x54] @ op1_out
|
ldr r10, [lr, #0x54] @ op1_out
|
||||||
|
|
||||||
tst r12, #8 @ lfo?
|
crl_loop:
|
||||||
beq crl_loop
|
|
||||||
|
|
||||||
crl_loop_lfo:
|
|
||||||
ldr r1, [lr, #0x30] @ lfo_cnt
|
|
||||||
ldr r2, [lr, #0x34] @ lfo_inc
|
|
||||||
|
|
||||||
subs r4, r4, #0x100
|
subs r4, r4, #0x100
|
||||||
bmi crl_loop_end
|
bmi crl_loop_end
|
||||||
|
|
||||||
|
mov r0, #0
|
||||||
|
add r8, r8, r9
|
||||||
|
subs r8, r8, #(1<<EG_SH)
|
||||||
|
blt crl_smp_loop_end
|
||||||
|
|
||||||
|
|
||||||
|
@ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
|
||||||
|
advance_lfo_m
|
||||||
|
|
||||||
|
crl_smp_loop:
|
||||||
|
tst r12, #8 @ lfo?
|
||||||
|
beq lfo_done
|
||||||
|
|
||||||
|
|
||||||
|
ldr r2, [lr, #0x34] @ lfo_inc
|
||||||
|
ldr r1, [lr, #0x30] @ lfo_cnt
|
||||||
|
|
||||||
add r2, r2, r1
|
add r2, r2, r1
|
||||||
str r2, [lr, #0x30]
|
str r2, [lr, #0x30]
|
||||||
|
|
||||||
@ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
|
@ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
|
||||||
advance_lfo_m
|
advance_lfo_m
|
||||||
|
|
||||||
add r4, r4, #0x100
|
lfo_done:
|
||||||
|
|
||||||
crl_loop:
|
|
||||||
subs r4, r4, #0x100
|
|
||||||
bmi crl_loop_end
|
|
||||||
|
|
||||||
ldr r5, [lr, #0x40] @ CH
|
ldr r5, [lr, #0x40] @ CH
|
||||||
#if defined(SSG_EG)
|
#if defined(SSG_EG)
|
||||||
tst r12, #0x02 @ ssg_enabled?
|
tst r12, #0x02 @ ssg_enabled?
|
||||||
beq ssg_done
|
beq ssg_done
|
||||||
@ -- SSG --
|
|
||||||
lsl r7, r8, #EG_SH
|
|
||||||
add r7, r9, r7, lsr #EG_SH
|
|
||||||
subs r7, r7, #1<<EG_SH
|
|
||||||
blt ssg_done
|
|
||||||
|
|
||||||
|
@ -- SSG --
|
||||||
ssg_loop:
|
ssg_loop:
|
||||||
mov r6, #4
|
mov r6, #4
|
||||||
bic r4, r4, #0x10 @ ssg_update
|
|
||||||
ssg_upd_loop:
|
ssg_upd_loop:
|
||||||
@ use lr as a pointer to the slot phases stored in the context
|
@ use lr as a pointer to the slot phases stored in the context
|
||||||
update_ssg_eg
|
update_ssg_eg
|
||||||
|
@ -748,26 +758,25 @@ ssg_upd_loop:
|
||||||
sub lr, lr, #4*3
|
sub lr, lr, #4*3
|
||||||
sub r5, r5, #SLOT_STRUCT_SIZE*3
|
sub r5, r5, #SLOT_STRUCT_SIZE*3
|
||||||
|
|
||||||
subs r7, r7, #1<<EG_SH
|
|
||||||
bge ssg_loop
|
|
||||||
ssg_done:
|
ssg_done:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -- EG --
|
@ -- EG --
|
||||||
add r8, r8, r9
|
tst r4, #0x30
|
||||||
cmp r8, #EG_TIMER_OVERFLOW
|
subnes r4, r4, #0x10
|
||||||
blo volout_upd
|
bne eg_done
|
||||||
|
orr r4, r4, #0x30
|
||||||
|
|
||||||
ldr r1, [lr, #0x3c] @ eg_cnt
|
ldr r1, [lr, #0x3c] @ eg_cnt
|
||||||
eg_loop:
|
|
||||||
sub r8, r8, #EG_TIMER_OVERFLOW
|
|
||||||
add r1, r1, #1
|
add r1, r1, #1
|
||||||
cmp r1, #4096
|
cmp r1, #4096
|
||||||
movge r1, #1
|
movge r1, #1
|
||||||
|
str r1, [lr, #0x3c]
|
||||||
|
|
||||||
mov r6, #4
|
mov r6, #4
|
||||||
eg_upd_loop:
|
eg_upd_loop:
|
||||||
update_eg_phase_slot
|
update_eg_phase_slot
|
||||||
#if 1
|
#if 0
|
||||||
subs r6, r6, #1
|
subs r6, r6, #1
|
||||||
addne r5, r5, #SLOT_STRUCT_SIZE
|
addne r5, r5, #SLOT_STRUCT_SIZE
|
||||||
#else
|
#else
|
||||||
|
@ -777,96 +786,38 @@ eg_upd_loop:
|
||||||
subne r5, r5, #SLOT_STRUCT_SIZE
|
subne r5, r5, #SLOT_STRUCT_SIZE
|
||||||
#endif
|
#endif
|
||||||
bne eg_upd_loop
|
bne eg_upd_loop
|
||||||
|
|
||||||
cmp r8, #EG_TIMER_OVERFLOW
|
|
||||||
sub r5, r5, #SLOT_STRUCT_SIZE*3
|
sub r5, r5, #SLOT_STRUCT_SIZE*3
|
||||||
bhs eg_loop
|
|
||||||
str r1, [lr, #0x3c]
|
|
||||||
b eg_done
|
|
||||||
|
|
||||||
volout_upd:
|
|
||||||
#if defined(SSG_EG)
|
|
||||||
tst r4, #0x10 @ ssg_update?
|
|
||||||
beq eg_done
|
|
||||||
|
|
||||||
@ recalc vol_out
|
|
||||||
mov r6, #4
|
|
||||||
volout_loop:
|
|
||||||
recalc_volout
|
|
||||||
#if 0
|
|
||||||
subs r6, r6, #1
|
|
||||||
addne r5, r5, #SLOT_STRUCT_SIZE
|
|
||||||
#else
|
|
||||||
add r5, r5, #SLOT_STRUCT_SIZE*2
|
|
||||||
recalc_volout
|
|
||||||
subs r6, r6, #2
|
|
||||||
subne r5, r5, #SLOT_STRUCT_SIZE
|
|
||||||
#endif
|
|
||||||
bne volout_loop
|
|
||||||
sub r5, r5, #SLOT_STRUCT_SIZE*3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
eg_done:
|
eg_done:
|
||||||
@ -- disabled? --
|
@ -- disabled? --
|
||||||
and r0, r12, #0xC
|
tst r12, #0x4
|
||||||
cmp r0, #0xC
|
mov r0, #0
|
||||||
beq crl_loop_lfo
|
bne crl_algo_done
|
||||||
cmp r0, #0x4
|
|
||||||
beq crl_loop
|
|
||||||
|
|
||||||
@ output interpolation
|
cmp r8, #(2<<EG_SH) @ calculate only for operator memory, sample,
|
||||||
#if defined(INTERPOL)
|
tstge r12, #0xf000 @ ...feedback
|
||||||
#if 1 // possibly too expensive for slow platforms?
|
beq crl_algo_done
|
||||||
@ basic interpolator, interpolate in middle region, else use closer value
|
|
||||||
mov r3, r8, lsr #EG_SH @ eg_timer, [0..3<<EG_SH) after loop
|
|
||||||
cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH)/2
|
|
||||||
bne 0f @ mix is vol_out
|
|
||||||
|
|
||||||
ldr r6, [r5, #0x34] @ vol_out, vol_ipol for all slots
|
|
||||||
ldr r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
|
|
||||||
ldr r7, [r5, #0x34+SLOT_STRUCT_SIZE]
|
|
||||||
ldr r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
|
|
||||||
add r6, r6, r6, lsl #16
|
|
||||||
lsr r6, r6, #17
|
|
||||||
add r2, r2, r2, lsl #16
|
|
||||||
lsr r2, r2, #17
|
|
||||||
add r7, r7, r7, lsl #16
|
|
||||||
lsr r7, r7, #17
|
|
||||||
add r3, r3, r3, lsl #16
|
|
||||||
lsr r3, r3, #17
|
|
||||||
b 1f
|
|
||||||
#else
|
|
||||||
@ super-basic... just take value closest to sample point
|
|
||||||
mov r3, r8, lsr #EG_SH-1 @ eg_timer, [0..3<<EG_SH) after loop
|
|
||||||
cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
0: ldrgeh r6, [r5, #0x34] @ vol_out values for all slots
|
|
||||||
ldrlth r6, [r5, #0x36] @ vol_ipol values for all slots
|
|
||||||
ldrgeh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
|
|
||||||
ldrlth r2, [r5, #0x36+SLOT_STRUCT_SIZE*2]
|
|
||||||
ldrgeh r7, [r5, #0x34+SLOT_STRUCT_SIZE]
|
|
||||||
ldrlth r7, [r5, #0x36+SLOT_STRUCT_SIZE]
|
|
||||||
ldrgeh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
|
|
||||||
ldrlth r3, [r5, #0x36+SLOT_STRUCT_SIZE*3]
|
|
||||||
|
|
||||||
#else
|
|
||||||
ldrh r6, [r5, #0x34] @ vol_out values for all slots
|
ldrh r6, [r5, #0x34] @ vol_out values for all slots
|
||||||
ldrh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
|
ldrh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
|
||||||
ldrh r7, [r5, #0x34+SLOT_STRUCT_SIZE]
|
ldrh r7, [r5, #0x34+SLOT_STRUCT_SIZE]
|
||||||
ldrh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
|
ldrh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
|
||||||
#endif
|
|
||||||
1: orr r6, r6, r2, lsl #16
|
orr r6, r6, r2, lsl #16
|
||||||
orr r7, r7, r3, lsl #16
|
orr r7, r7, r3, lsl #16
|
||||||
|
|
||||||
@ -- SLOT1 --
|
|
||||||
PIC_LDR(r3, r2, ym_tl_tab)
|
PIC_LDR(r3, r2, ym_tl_tab)
|
||||||
|
|
||||||
@ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
|
@ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
|
||||||
@ r0-r2=scratch, r3=tl_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
|
@ r0-r2=scratch, r3=tl_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
|
||||||
|
|
||||||
|
@ -- SLOT1 --
|
||||||
upd_slot1_m
|
upd_slot1_m
|
||||||
|
|
||||||
@ -- SLOT2+ --
|
@ -- SLOT2+ --
|
||||||
|
cmp r8, #(2<<EG_SH) @ op mem or sample?
|
||||||
|
bge crl_algo_done
|
||||||
|
|
||||||
and r0, r4, #7
|
and r0, r4, #7
|
||||||
PIC_XB(,r0, lsl #2)
|
PIC_XB(,r0, lsl #2)
|
||||||
nop
|
nop
|
||||||
|
@ -920,6 +871,23 @@ crl_algo7:
|
||||||
|
|
||||||
|
|
||||||
crl_algo_done:
|
crl_algo_done:
|
||||||
|
@ -- PHASE UPDATE --
|
||||||
|
add lr, lr, #0x10
|
||||||
|
ldmia lr, {r1-r3,r5-r7}
|
||||||
|
add r1, r1, r6
|
||||||
|
add r2, r2, r7
|
||||||
|
ldr r6, [lr, #0x18]
|
||||||
|
ldr r7, [lr, #0x1c]
|
||||||
|
add r3, r3, r6
|
||||||
|
add r5, r5, r7
|
||||||
|
stmia lr, {r1-r3,r5}
|
||||||
|
sub lr, lr, #0x10
|
||||||
|
|
||||||
|
subs r8, r8, #(1<<EG_SH)
|
||||||
|
bge crl_smp_loop
|
||||||
|
|
||||||
|
crl_smp_loop_end:
|
||||||
|
add r8, r8, #(1<<EG_SH)
|
||||||
@ -- WRITE SAMPLE --
|
@ -- WRITE SAMPLE --
|
||||||
tst r0, r0
|
tst r0, r0
|
||||||
beq ctl_sample_skip
|
beq ctl_sample_skip
|
||||||
|
@ -944,36 +912,20 @@ crl_algo_done:
|
||||||
addeq r11, r11, #4
|
addeq r11, r11, #4
|
||||||
addne r1, r0, r1
|
addne r1, r0, r1
|
||||||
strne r1, [r11], #4
|
strne r1, [r11], #4
|
||||||
b crl_do_phase
|
b crl_loop
|
||||||
|
|
||||||
ctl_sample_mono:
|
ctl_sample_mono:
|
||||||
ldr r1, [r11]
|
ldr r1, [r11]
|
||||||
add r1, r0, r1
|
add r1, r0, r1
|
||||||
str r1, [r11], #4
|
str r1, [r11], #4
|
||||||
b crl_do_phase
|
b crl_loop
|
||||||
|
|
||||||
ctl_sample_skip:
|
ctl_sample_skip:
|
||||||
and r1, r12, #1
|
and r1, r12, #1
|
||||||
add r1, r1, #1
|
add r1, r1, #1
|
||||||
add r11,r11, r1, lsl #2
|
add r11,r11, r1, lsl #2
|
||||||
|
|
||||||
crl_do_phase:
|
|
||||||
@ -- PHASE UPDATE --
|
|
||||||
add r5, lr, #0x10
|
|
||||||
ldmia r5, {r0-r3,r6-r7}
|
|
||||||
add r0, r0, r6
|
|
||||||
add r1, r1, r7
|
|
||||||
ldr r6, [r5, #0x18]
|
|
||||||
ldr r7, [r5, #0x1c]
|
|
||||||
add r2, r2, r6
|
|
||||||
add r3, r3, r7
|
|
||||||
stmia r5, {r0-r3}
|
|
||||||
|
|
||||||
tst r12, #8
|
|
||||||
bne crl_loop_lfo
|
|
||||||
b crl_loop
|
b crl_loop
|
||||||
|
|
||||||
|
|
||||||
crl_loop_end:
|
crl_loop_end:
|
||||||
str r8, [lr, #0x44] @ eg_timer
|
str r8, [lr, #0x44] @ eg_timer
|
||||||
str r12, [lr, #0x4c] @ pack (for lfo_ampm)
|
str r12, [lr, #0x4c] @ pack (for lfo_ampm)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue