📄 ym2151.c
字号:
o = 8*log(127.0/m)/log(2); /* convert to 'decibels' */ else { if (m<0.0) o = 8*log(-128.0/m)/log(2); /* convert to 'decibels' */ else o = 8*log(127.0/0.01)/log(2); /* small number */ } o = o / (ENV_STEP/4); n = (int)(2.0*o); if (n&1) /* round to closest */ n = (n>>1)+1; else n = n>>1; lfo_tab[ x*LFO_LEN*2 + i*2 + 1 ] = n*2 + (m>=0.0? 0: 1 ); /*logerror("lfo pm waveofs[%i] %04i = %i\n", x, i*2+1, lfo_tab[ x*LFO_LEN*2 + i*2 + 1 ] );*/ } } /* calculate D1L_tab table */ for (i=0; i<16; i++) { m = (i!=15 ? i : i+16) * (4.0/ENV_STEP); /*every 3 'dB' except for all bits = 1 = 45dB+48dB*/ D1L_tab[i] = (unsigned int)(m * (1<<ENV_SH)); /*logerror("D1L_tab[%02x]=%08x\n",i,D1L_tab[i] );*/ }#ifdef SAVE_SAMPLEsample[8]=fopen("sampsum.raw","ab");#endif#ifdef SAVE_SEPARATE_CHANNELSsample[0]=fopen("samp0.raw","wb");sample[1]=fopen("samp1.raw","wb");sample[2]=fopen("samp2.raw","wb");sample[3]=fopen("samp3.raw","wb");sample[4]=fopen("samp4.raw","wb");sample[5]=fopen("samp5.raw","wb");sample[6]=fopen("samp6.raw","wb");sample[7]=fopen("samp7.raw","wb");#endif}static void init_chip_tables(YM2151 *chip){ int i,j; double mult,pom,pom2,clk,phaseinc,Hz; double scaler; /* formula below is true for chip clock=3579545 */ /* so we need to scale its output accordingly to the chip clock */ /*scaler = (double)chip->clock / 3579545.0;*/ scaler = ( (double)chip->clock / 64.0 ) / ( (double)chip->sampfreq );#if 0 logerror("scaler = %20.15f\n", scaler); logerror("scalerold = %20.15f\n", (double)chip->clock / 3579545.0 );#endif /*this loop calculates Hertz values for notes from c-0 to b-7*/ /*including 64 'cents' (100/64 that is 1.5625 of real cent) per note*/ /* i*100/64/1200 is equal to i/768 */ /* real chip works with 10 bits fixed point values (10.10)*/ mult = (1<<(FREQ_SH-10)); /* -10 because phaseinc_rom table values are already in 10.10 format */ for (i=0; i<768; i++) { /* 3.4375 Hz is note A; C# is 4 semitones higher */ Hz = 1000;#if 0/* Hz is close, but not perfect */ /*Hz = scaler * 3.4375 * pow (2, (i + 4 * 64 ) / 768.0 ); */ /* calculate phase increment */ phaseinc = (Hz*SIN_LEN) / (double)chip->sampfreq;#endif phaseinc = phaseinc_rom[i]; /*real chip phase increment*/ phaseinc *= scaler; /*adjust*/ /*octave 2 - reference octave*/ chip->freq[ 768+2*768+i ] = ((int)(phaseinc*mult)) & 0xffffffc0; /*adjust to X.10 fixed point*/ /*octave 0 and octave 1*/ for (j=0; j<2; j++) { chip->freq[768 + j*768 + i] = (chip->freq[ 768+2*768+i ] >> (2-j) ) & 0xffffffc0; /*adjust to X.10 fixed point*/ } /*octave 3 to 7*/ for (j=3; j<8; j++) { chip->freq[768 + j*768 + i] = chip->freq[ 768+2*768+i ] << (j-2); } #if 0 pom = (double)chip->freq[ 768+2*768+i ] / ((double)(1<<FREQ_SH)); pom = pom * (double)chip->sampfreq / (double)SIN_LEN; logerror("1freq[%4i][%08x]= real %20.15f Hz emul %20.15f Hz\n", i, chip->freq[ 768+2*768+i ], Hz, pom); #endif } /*octave -1 (all equal to: oct 0, KC 00, KF 00) */ for (i=0; i<768; i++) { chip->freq[ 0*768 + i ] = chip->freq[1*768+0]; } /*octave 8 and 9 (all equal to: oct 7, _KC_14_, _KF_63_) */ for (j=8; j<10; j++) { for (i=0; i<768; i++) { chip->freq[768+ j*768 + i ] = chip->freq[768 + 8*768 -1]; } } #if 0 for (i=0; i<11*768; i++) { pom = (double)chip->freq[i] / ((double)(1<<FREQ_SH)); pom = pom * (double)chip->sampfreq / (double)SIN_LEN; logerror("freq[%4i][%08x]= emul %20.15f Hz\n", i, chip->freq[i], pom); } #endif mult = (1<<FREQ_SH); for (j=0; j<4; j++) { for (i=0; i<32; i++) { Hz = ( (double)DT1_tab[j*32+i] * ((double)chip->clock/64.0) ) / (double)(1<<20); /*calculate phase increment*/ phaseinc = (Hz*SIN_LEN) / (double)chip->sampfreq; /*positive and negative values*/ chip->DT1freq[ (j+0)*32 + i ] = (int)(phaseinc * mult); chip->DT1freq[ (j+4)*32 + i ] = -chip->DT1freq[ (j+0)*32 + i ]; #if 0 { int x = j*32 + i; pom = (double)chip->DT1freq[x] / mult; pom = pom * (double)chip->sampfreq / (double)SIN_LEN; logerror("DT1(%03i)[%02i %02i][%08x]= real %19.15f Hz emul %19.15f Hz\n", x, j, i, chip->DT1freq[x], Hz, pom); } #endif } } mult = (1<<LFO_SH); clk = (double)chip->clock; for (i=0; i<256; i++) { j = i & 0x0f; pom = fabs( (clk/65536/(1<<(i/16)) ) - (clk/65536/32/(1<<(i/16)) * (j+1)) ); /*calculate phase increment*/ chip->LFOfreq[0xff-i] = (unsigned int)(( (pom*LFO_LEN) / (double)chip->sampfreq ) * mult); /*fixed point*/ /*logerror("LFO[%02x] (%08x)= real %20.15f Hz emul %20.15f Hz\n",0xff-i, chip->LFOfreq[0xff-i], pom, (((double)chip->LFOfreq[0xff-i] / mult) * (double)chip->sampfreq ) / (double)LFO_LEN );*/ } for (i=0; i<34; i++) chip->EG_tab[i] = 0; /* infinity */ for (i=2; i<64; i++) { pom2 = (double)chip->clock / (double)chip->sampfreq; if (i<60) pom2 *= ( 1 + (i&3)*0.25 ); pom2 *= 1<<((i>>2)); pom2 /= 768.0 * 1024.0; pom2 *= (double)(1<<ENV_SH); chip->EG_tab[32+i] = (unsigned int)pom2; #if 0 logerror("Rate %2i %1i Decay [real %11.4f ms][emul %11.4f ms][d=%08x]\n",i>>2, i&3, ( ((double)(ENV_LEN<<ENV_SH)) / pom2 ) * (1000.0 / (double)chip->sampfreq), ( ((double)(ENV_LEN<<ENV_SH)) / (double)chip->EG_tab[32+i] ) * (1000.0 / (double)chip->sampfreq), chip->EG_tab[32+i] ); #endif } for (i=0; i<32; i++) { chip->EG_tab[ 32+64+i ] = chip->EG_tab[32+63]; } /* precalculate timers' deltas */ /* User's Manual pages 15,16 */ mult = (1<<TIMER_SH); for (i=0; i<1024; i++) { /* ASG 980324: changed to compute both TimerA and TimerATime */ pom= ( 64.0 * (1024.0-i) / (double)chip->clock ); #ifdef USE_MAME_TIMERS chip->TimerATime[i] = pom; #else chip->TimerA[i] = (unsigned int)(pom * (double)chip->sampfreq * mult); /*number of samples that timer period takes (fixed point) */ #endif } for (i=0; i<256; i++) { /* ASG 980324: changed to compute both TimerB and TimerBTime */ pom= ( 1024.0 * (256.0-i) / (double)chip->clock ); #ifdef USE_MAME_TIMERS chip->TimerBTime[i] = pom; #else chip->TimerB[i] = (unsigned int)(pom * (double)chip->sampfreq * mult); /*number of samples that timer period takes (fixed point) */ #endif } /* calculate noise periods table */ scaler = ( (double)chip->clock / 64.0 ) / ( (double)chip->sampfreq ); for (i=0; i<32; i++) { j = (i!=31 ? i : 30); /*period 30 and 31 are the same*/ j = 32-j; j = (int)(65536.0 / (double)(j*32.0)); /*number of samples per one shift of the shift register*/ /*chip->noise_tab[i] = j * 64;*/ /*number of chip clock cycles per one shift*/ chip->noise_tab[i] = (unsigned int)(j * 64 * scaler); /*logerror("noise_tab[%02x]=%08x\n", i, chip->noise_tab[i]);*/ }}/*#define RESET_FEEDBACK_ON_KEYON*/INLINE void envelope_KONKOFF(OscilRec * op, int v){ if (v&0x08) { if (!op->key) { op->key = 1; /*KEYON'ed*/ op->phase = 0; /*clear phase */ op->state = EG_ATT; /*KEY ON = attack*/ } } else { if (op->key) { op->key = 0; /*KEYOFF'ed*/ if (op->state>EG_REL) op->state = EG_REL; /*release*/ } } op+=8; if (v&0x20) { if (!op->key) { op->key = 1; op->phase = 0; op->state = EG_ATT; } } else { if (op->key) { op->key = 0; if (op->state>EG_REL) op->state = EG_REL; } } op+=8; if (v&0x10) { if (!op->key) { op->key = 1; op->phase = 0; op->state = EG_ATT; } } else { if (op->key) { op->key = 0; if (op->state>EG_REL) op->state = EG_REL; } } op+=8; if (v&0x40) { if (!op->key) { op->key = 1; op->phase = 0; op->state = EG_ATT; } } else { if (op->key) { op->key = 0; if (op->state>EG_REL) op->state = EG_REL; } }}#ifdef USE_MAME_TIMERSstatic void timer_callback_a (int n){ YM2151 *chip = &YMPSG[n]; chip->TimATimer = timer_set (chip->TimerATime[ chip->TimAIndex ], n, timer_callback_a); chip->TimAOldIndex = chip->TimAIndex; if (chip->IRQenable & 0x04) { int oldstate = chip->status & 3; chip->status |= 1; if ((!oldstate) && (chip->irqhandler)) (*chip->irqhandler)(1); } if (chip->IRQenable & 0x80) chip->CSMreq = 2; /*request KEYON/KEYOFF sequence*/}static void timer_callback_b (int n){ YM2151 *chip = &YMPSG[n]; chip->TimBTimer = timer_set (chip->TimerBTime[ chip->TimBIndex ], n, timer_callback_b); chip->TimBOldIndex = chip->TimBIndex; if (chip->IRQenable & 0x08) { int oldstate = chip->status & 3; chip->status |= 2; if ((!oldstate) && (chip->irqhandler)) (*chip->irqhandler)(1); }}#if 0static void timer_callback_chip_write_busy (int n){ YM2151 *chip = &YMPSG[n]; chip->status &= 0x7f; /*reset busy flag*/}#endif#endifINLINE void set_connect( OscilRec *om1, int v, int cha){ OscilRec *om2 = om1+8; OscilRec *oc1 = om1+16; /*OscilRec *oc2 = om1+24;*/ /*oc2->connect = &chanout[cha];*/ /* set connect algorithm */ switch( v & 7 ) { case 0: /* M1---C1---M2---C2---OUT */ om1->connect = &c1; oc1->connect = &m2; om2->connect = &c2; break; case 1: /* M1-+-M2---C2---OUT */ /* C1-+ */ om1->connect = &m2; oc1->connect = &m2; om2->connect = &c2; break; case 2: /* M1------+-C2---OUT */ /* C1---M2-+ */ om1->connect = &c2; oc1->connect = &m2; om2->connect = &c2; break; case 3: /* M1---C1-+-C2---OUT */ /* M2------+ */ om1->connect = &c1; oc1->connect = &c2; om2->connect = &c2; break; case 4: /* M1---C1-+--OUT */ /* M2---C2-+ */ om1->connect = &c1; oc1->connect = &chanout[cha]; om2->connect = &c2; break; case 5: /* +-C1-+ */ /* M1-+-M2-+-OUT */ /* +-C2-+ */ om1->connect = 0; /* special mark */ oc1->connect = &chanout[cha]; om2->connect = &chanout[cha]; break; case 6: /* M1---C1-+ */ /* M2-+-OUT */ /* C2-+ */ om1->connect = &c1; oc1->connect = &chanout[cha]; om2->connect = &chanout[cha]; break; case 7: /* M1-+ */ /* C1-+-OUT */ /* M2-+ */ /* C2-+ */ om1->connect = &chanout[cha]; oc1->connect = &chanout[cha]; om2->connect = &chanout[cha]; break; }}INLINE void refresh_EG( YM2151 *chip, OscilRec * op){ unsigned int kc; unsigned int v; kc = op->KC; /*v = 32 + 2*RATE + RKS (max 126)*/ v = kc >> op->KS; if ((op->AR+v) < 32+62) op->delta_AR = chip->EG_tab[ op->AR + v]; else op->delta_AR = MAX_ATT_INDEX+1; op->delta_D1R = chip->EG_tab[op->D1R + v]; op->delta_D2R = chip->EG_tab[op->D2R + v]; op->delta_RR = chip->EG_tab[ op->RR + v]; op+=8; v = kc >> op->KS; if ((op->AR+v) < 32+62) op->delta_AR = chip->EG_tab[ op->AR + v]; else op->delta_AR = MAX_ATT_INDEX+1; op->delta_D1R = chip->EG_tab[op->D1R + v]; op->delta_D2R = chip->EG_tab[op->D2R + v]; op->delta_RR = chip->EG_tab[ op->RR + v]; op+=8; v = kc >> op->KS; if ((op->AR+v) < 32+62) op->delta_AR = chip->EG_tab[ op->AR + v]; else op->delta_AR = MAX_ATT_INDEX+1; op->delta_D1R = chip->EG_tab[op->D1R + v]; op->delta_D2R = chip->EG_tab[op->D2R + v]; op->delta_RR = chip->EG_tab[ op->RR + v]; op+=8; v = kc >> op->KS; if ((op->AR+v) < 32+62) op->delta_AR = chip->EG_tab[ op->AR + v]; else op->delta_AR = MAX_ATT_INDEX+1; op->delta_D1R = chip->EG_tab[op->D1R + v]; op->delta_D2R = chip->EG_tab[op->D2R + v]; op->delta_RR = chip->EG_tab[ op->RR + v];}/* write a register on YM2151 chip number 'n' */void YM2151WriteReg(int n, int r, int v){ YM2151 *chip = &(YMPSG[n]); OscilRec *op = &chip->Oscils[ r&0x1f ]; /*adjust bus to 8 bits*/ r &= 0xff; v &= 0xff;#if 0 /*There's no info on what YM2151 really does when busy flag is set*/ if ( chip->status & 0x80 ) return; timer_set ( 68.0 / (double)chip->clock, n, timer_callback_chip_write_busy); chip->status |= 0x80; /* set busy flag for 68 chip clock cycles */#endif#ifdef LOG_CYM_FILE if ((cymfile) && (r!=0) ) { fputc( (unsigned char)r, cymfile ); fputc( (unsigned char)v, cymfile ); }#endif switch(r & 0xe0){ case 0x00: switch(r){ case 0x01: /*LFO reset(bit 1), Test Register (other bits)*/ chip->test = v; if (v&2) chip->LFOphase = 0; break; case 0x08: envelope_KONKOFF(&chip->Oscils[ v&7 ], v ); break; case 0x0f: /*noise mode enable, noise period*/ chip->noise = v;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -