From: kub Date: Wed, 22 Dec 2021 23:42:11 +0000 (+0100) Subject: sound, improve ym2612 accuracy (NB noticeably slower for low bitrates) X-Git-Tag: v2.00~388 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d127b3f3d51149d2d0eb11ce0a1bb975465e7d14;p=picodrive.git sound, improve ym2612 accuracy (NB noticeably slower for low bitrates) --- diff --git a/pico/sound/ym2612.c b/pico/sound/ym2612.c index a10e6789..ccdce778 100644 --- a/pico/sound/ym2612.c +++ b/pico/sound/ym2612.c @@ -8,7 +8,6 @@ ** ** updated with fixes from mame 0.216 (file version 1.5.1) (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_add; 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; #ifdef _MIPS_ARCH_ALLEGREX UINT32 pad1[3+8]; @@ -921,317 +920,292 @@ typedef struct #include static int clip(int n) { - unsigned b = 14, s = n < 0; - int m = s + INT_MAX; - if (s + (n>>(b-1))) n = m >> (8*sizeof(int)-b); - return n; + unsigned b = 14, s = n < 0; + int m = s + INT_MAX; + if (s + (n>>(b-1))) n = m >> (8*sizeof(int)-b); + 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 */ + FM_SLOT *SLOT; - /* sample generating loop */ - for (scounter = 0; scounter < length; scounter++) + SLOT = &ct->CH->SLOT[SLOT1]; + if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200) + ct->phase1 = update_ssg_eg_phase(SLOT, ct->phase1); + SLOT = &ct->CH->SLOT[SLOT2]; + if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200) + ct->phase2 = update_ssg_eg_phase(SLOT, ct->phase2); + SLOT = &ct->CH->SLOT[SLOT3]; + if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200) + ct->phase3 = update_ssg_eg_phase(SLOT, ct->phase3); + SLOT = &ct->CH->SLOT[SLOT4]; + if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200) + ct->phase4 = update_ssg_eg_phase(SLOT, ct->phase4); +} + +static void update_eg_phase_channel(chan_rend_context *ct) +{ + FM_SLOT *SLOT; + + SLOT = &ct->CH->SLOT[SLOT1]; + if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2); + SLOT = &ct->CH->SLOT[SLOT2]; + if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2); + SLOT = &ct->CH->SLOT[SLOT3]; + if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2); + SLOT = &ct->CH->SLOT[SLOT4]; + if (SLOT->state != EG_OFF) update_eg_phase(SLOT, ct->eg_cnt, ct->pack & 2); +} + +static int update_algo_channel(chan_rend_context *ct, unsigned int eg_out, unsigned int eg_out2, unsigned int eg_out4) +{ + int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */ + int smp = 0; + + switch( ct->algo&0x7 ) { - int smp = 0; /* produced sample */ - unsigned int eg_out, eg_out2, eg_out4; - FM_SLOT *SLOT; - UINT32 cnt = ct->eg_timer_add+(ct->eg_timer & ((1<pack & 2) while (cnt >= 1<CH->SLOT[SLOT1]; - if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200) - ct->phase1 = update_ssg_eg_phase(SLOT, ct->phase1); - SLOT = &ct->CH->SLOT[SLOT2]; - if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200) - ct->phase2 = update_ssg_eg_phase(SLOT, ct->phase2); - SLOT = &ct->CH->SLOT[SLOT3]; - if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200) - ct->phase3 = update_ssg_eg_phase(SLOT, ct->phase3); - SLOT = &ct->CH->SLOT[SLOT4]; - if ((SLOT->ssg&0x08) && SLOT->state > EG_REL && SLOT->volume >= 0x200) - ct->phase4 = update_ssg_eg_phase(SLOT, ct->phase4); - } + case 0: + { + /* M1---C1---MEM---M2---C2---OUT */ + m2 = ct->mem; + c1 = ct->op1_out>>16; + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + ct->mem = op_calc(ct->phase2, eg_out2, c1); + } + else ct->mem = 0; + if (ct->eg_timer >= (1<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( eg_out < ENV_QUIET ) { /* SLOT 3 */ + c2 = op_calc(ct->phase3, eg_out, m2); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp = op_calc(ct->phase4, eg_out4, c2); + } + break; } + case 1: + { + /* M1------+-MEM---M2---C2---OUT */ + /* C1-+ */ + m2 = ct->mem; + ct->mem = ct->op1_out>>16; + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + ct->mem+= op_calc(ct->phase2, eg_out2, 0); + } + if (ct->eg_timer >= (1<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); + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + c2 = op_calc(ct->phase3, eg_out, m2); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp = op_calc(ct->phase4, eg_out4, c2); + } + break; } - else while (ct->eg_timer >= EG_TIMER_OVERFLOW) + case 2: { - ct->eg_timer -= EG_TIMER_OVERFLOW; - ct->eg_cnt++; - if (ct->eg_cnt >= 4096) ct->eg_cnt = 1; - - 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); - 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); - 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); - 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); - } + /* M1-----------------+-C2---OUT */ + /* C1---MEM---M2-+ */ + m2 = ct->mem; + c2 = ct->op1_out>>16; + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + ct->mem = op_calc(ct->phase2, eg_out2, 0); + } + else ct->mem = 0; + if (ct->eg_timer >= (1<eg_timer / (EG_TIMER_OVERFLOW>>EG_SH); - UINT32 ifrac1 = (1<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: - 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; - 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; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + c2 += op_calc(ct->phase3, eg_out, m2); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp = op_calc(ct->phase4, eg_out4, c2); + } + break; } -#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 */ + case 3: { - int out = 0; + /* M1---C1---MEM------+-C2---OUT */ + /* M2-+ */ + c2 = ct->mem; + c1 = ct->op1_out>>16; + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + ct->mem = op_calc(ct->phase2, eg_out2, c1); + } + else ct->mem = 0; + if (ct->eg_timer >= (1<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( eg_out < ENV_QUIET ) { /* SLOT 3 */ + c2 += op_calc(ct->phase3, eg_out, 0); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp = op_calc(ct->phase4, eg_out4, c2); + } + break; } - - 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; + case 4: + { + /* M1---C1-+-OUT */ + /* M2---C2-+ */ + /* MEM: not used */ + if (ct->eg_timer >= (1<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 */ + smp = op_calc(ct->phase2, eg_out2, c1); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp+= op_calc(ct->phase4, eg_out4, c2); + } + break; } - - switch( ct->algo&0x7 ) + case 5: { - case 0: - { - /* M1---C1---MEM---M2---C2---OUT */ - int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */ - m2 = ct->mem; - 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 */ - ct->mem = op_calc(ct->phase2, eg_out2, c1); - } - else ct->mem = 0; - if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ - smp = op_calc(ct->phase4, eg_out4, c2); - } - break; + /* +----C1----+ */ + /* M1-+-MEM---M2-+-OUT */ + /* +----C2----+ */ + if (ct->eg_timer >= (1<mem; + ct->mem = c1 = c2 = ct->op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + smp = op_calc(ct->phase3, eg_out, m2); } - case 1: - { - /* M1------+-MEM---M2---C2---OUT */ - /* C1-+ */ - int m2,c2=0; - m2 = ct->mem; - 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 */ - ct->mem+= op_calc(ct->phase2, eg_out2, 0); - } - if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ - smp = op_calc(ct->phase4, eg_out4, c2); - } - break; + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + smp+= op_calc(ct->phase2, eg_out2, c1); } - case 2: - { - /* M1-----------------+-C2---OUT */ - /* C1---MEM---M2-+ */ - int m2,c2; - m2 = ct->mem; - 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 */ - ct->mem = op_calc(ct->phase2, eg_out2, 0); - } - else ct->mem = 0; - if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ - smp = op_calc(ct->phase4, eg_out4, c2); - } - break; + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp+= op_calc(ct->phase4, eg_out4, c2); } - case 3: - { - /* M1---C1---MEM------+-C2---OUT */ - /* M2-+ */ - int c1,c2; - c2 = ct->mem; - 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 */ - ct->mem = op_calc(ct->phase2, eg_out2, c1); - } - else ct->mem = 0; - if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ - smp = op_calc(ct->phase4, eg_out4, c2); - } - break; + break; + } + case 6: + { + /* M1---C1-+ */ + /* M2-+-OUT */ + /* C2-+ */ + /* MEM: not used */ + if (ct->eg_timer >= (1<op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + smp = op_calc(ct->phase3, eg_out, 0); } - case 4: - { - /* M1---C1-+-OUT */ - /* M2---C2-+ */ - /* MEM: not used */ - int c1,c2=0; - 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 */ - smp = op_calc(ct->phase2, eg_out2, c1); - } - if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ - smp+= op_calc(ct->phase4, eg_out4, c2); - } - break; + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + smp+= op_calc(ct->phase2, eg_out2, c1); } - case 5: - { - /* +----C1----+ */ - /* M1-+-MEM---M2-+-OUT */ - /* +----C2----+ */ - int m2,c1,c2; - m2 = ct->mem; - ct->mem = c1 = c2 = ct->op1_out>>16; - if( eg_out < ENV_QUIET ) { /* SLOT 3 */ - smp = op_calc(ct->phase3, eg_out, m2); - } - if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ - smp+= op_calc(ct->phase2, eg_out2, c1); - } - if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ - smp+= op_calc(ct->phase4, eg_out4, c2); - } - break; + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp+= op_calc(ct->phase4, eg_out4, 0); } - case 6: - { - /* M1---C1-+ */ - /* M2-+-OUT */ - /* C2-+ */ - /* MEM: not used */ - int c1; - c1 = ct->op1_out>>16; - if( eg_out < ENV_QUIET ) { /* SLOT 3 */ - smp = op_calc(ct->phase3, eg_out, 0); - } - if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ - smp+= op_calc(ct->phase2, eg_out2, c1); - } - if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ - smp+= op_calc(ct->phase4, eg_out4, 0); - } - break; + break; + } + case 7: + { + /* M1-+ */ + /* C1-+-OUT */ + /* M2-+ */ + /* C2-+ */ + /* MEM: not used*/ + if (ct->eg_timer >= (1<op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + smp += op_calc(ct->phase3, eg_out, 0); } - case 7: - { - /* M1-+ */ - /* C1-+-OUT */ - /* M2-+ */ - /* C2-+ */ - /* MEM: not used*/ - smp = ct->op1_out>>16; - if( eg_out < ENV_QUIET ) { /* SLOT 3 */ - smp += op_calc(ct->phase3, eg_out, 0); - } - if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ - smp += op_calc(ct->phase2, eg_out2, 0); + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + smp += op_calc(ct->phase2, eg_out2, 0); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp += op_calc(ct->phase4, eg_out4, 0); + } + 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_timer -= 1<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<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( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ - smp += op_calc(ct->phase4, eg_out4, 0); + } + + if (ct->eg_timer < (2<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; } - break; + + smp = update_algo_channel(ct, eg_out, eg_out2, eg_out4); } + /* 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; } - /* done calculating channel sample */ /* mix sample to output buffer */ if (smp) { @@ -1250,12 +1224,6 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length) } 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 @@ -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.algo = crct.CH->ALGO & 7; + crct.algo |= crct.CH->upd_cnt << 4; if (ym2612.OPN.ST.flags & ST_DAC) crct.algo |= 0x80; @@ -1373,6 +1342,7 @@ static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: s } else ym2612.slot_mask &= ~(0xf << (c*4)); + crct.CH->upd_cnt = (crct.algo >> 4) & 0x7; return (crct.algo & 8) >> 3; // had output } @@ -1625,9 +1595,10 @@ static void OPNSetPres(int pres) int i; /* 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< @ very simple YM2612 output rate to sample rate adaption (~500k cycles @44100) -#define INTERPOL #define SSG_EG .equiv SLOT1, 0 @@ -34,7 +33,6 @@ .equiv EG_OFF, 0 .equiv EG_SH, 16 @ 16.16 fixed point (envelope generator timing) -.equiv EG_TIMER_OVERFLOW, (3*(1< EG_REL && cmpge r3, #0x200 @ volume >= 0x200? blt 9f - orr r4, r4, #0x10 @ ssg_update tst r0, #0x01 beq 1f @@ -259,14 +250,8 @@ @ r5=slot, trashes: r0,r2,r3 .macro recalc_volout -#if defined(INTERPOL) - ldrh r0, [r5,#0x34] @ vol_out -#endif ldrb r2, [r5,#0x30] @ ssg ldrb r3, [r5,#0x17] @ state -#if defined(INTERPOL) - strh r0, [r5,#0x36] @ vol_ipol -#endif ldrh r0, [r5,#0x1a] @ volume @ and r2, r2, #0x0c @@ -342,6 +327,9 @@ @ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out .macro upd_algo0_m + cmp r8, #(1<>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) -#endif + tst r12, #0x4 + mov r0, #0 + bne crl_algo_done -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] + cmp r8, #(2<