📄 mzpokeysnd.c
字号:
static unsigned char readout1_normal(PokeyState* ps)
{
if(ps->c1t2)
return ps->vol1;
else return 0;
}
/***********************************
READ OUTPUT 2
************************************/
static unsigned char readout2_vo(PokeyState* ps)
{
return ps->vol2;
}
static unsigned char readout2_normal(PokeyState* ps)
{
if(ps->c2t2)
return ps->vol2;
else return 0;
}
/***********************************
READ OUTPUT 3
************************************/
static unsigned char readout3_vo(PokeyState* ps)
{
return ps->vol3;
}
static unsigned char readout3_normal(PokeyState* ps)
{
if(ps->c3t2)
return ps->vol3;
else return 0;
}
/***********************************
EVENT CHANNEL 0
************************************/
static void event0_pure(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c0t2 = !ps->c0t2;
ps->c0t1 = p5v;
}
static void event0_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c0t1)
ps->c0t2 = !ps->c0t2;
ps->c0t1 = p5v;
}
static void event0_p4(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c0t2 = p4v;
ps->c0t1 = p5v;
}
static void event0_p917(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c0t2 = p917v;
ps->c0t1 = p5v;
}
static void event0_p4_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c0t1)
ps->c0t2 = p4v;
ps->c0t1 = p5v;
}
static void event0_p917_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c0t1)
ps->c0t2 = p917v;
ps->c0t1 = p5v;
}
/***********************************
EVENT CHANNEL 1
************************************/
static void event1_pure(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c1t2 = !ps->c1t2;
ps->c1t1 = p5v;
}
static void event1_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c1t1)
ps->c1t2 = !ps->c1t2;
ps->c1t1 = p5v;
}
static void event1_p4(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c1t2 = p4v;
ps->c1t1 = p5v;
}
static void event1_p917(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c1t2 = p917v;
ps->c1t1 = p5v;
}
static void event1_p4_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c1t1)
ps->c1t2 = p4v;
ps->c1t1 = p5v;
}
static void event1_p917_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c1t1)
ps->c1t2 = p917v;
ps->c1t1 = p5v;
}
/***********************************
EVENT CHANNEL 2
************************************/
static void event2_pure(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c2t2 = !ps->c2t2;
ps->c2t1 = p5v;
/* high-pass clock for channel 0 */
ps->c0t3 = ps->c0t2;
}
static void event2_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c2t1)
ps->c2t2 = !ps->c2t2;
ps->c2t1 = p5v;
/* high-pass clock for channel 0 */
ps->c0t3 = ps->c0t2;
}
static void event2_p4(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c2t2 = p4v;
ps->c2t1 = p5v;
/* high-pass clock for channel 0 */
ps->c0t3 = ps->c0t2;
}
static void event2_p917(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c2t2 = p917v;
ps->c2t1 = p5v;
/* high-pass clock for channel 0 */
ps->c0t3 = ps->c0t2;
}
static void event2_p4_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c2t1)
ps->c2t2 = p4v;
ps->c2t1 = p5v;
/* high-pass clock for channel 0 */
ps->c0t3 = ps->c0t2;
}
static void event2_p917_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c2t1)
ps->c2t2 = p917v;
ps->c2t1 = p5v;
/* high-pass clock for channel 0 */
ps->c0t3 = ps->c0t2;
}
/***********************************
EVENT CHANNEL 3
************************************/
static void event3_pure(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c3t2 = !ps->c3t2;
ps->c3t1 = p5v;
/* high-pass closk for channel 1 */
ps->c1t3 = ps->c1t2;
}
static void event3_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c3t1)
ps->c3t2 = !ps->c3t2;
ps->c3t1 = p5v;
/* high-pass closk for channel 1 */
ps->c1t3 = ps->c1t2;
}
static void event3_p4(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c3t2 = p4v;
ps->c3t1 = p5v;
/* high-pass closk for channel 1 */
ps->c1t3 = ps->c1t2;
}
static void event3_p917(PokeyState* ps, char p5v, char p4v, char p917v)
{
ps->c3t2 = p917v;
ps->c3t1 = p5v;
/* high-pass closk for channel 1 */
ps->c1t3 = ps->c1t2;
}
static void event3_p4_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c3t1)
ps->c3t2 = p4v;
ps->c3t1 = p5v;
/* high-pass closk for channel 1 */
ps->c1t3 = ps->c1t2;
}
static void event3_p917_p5(PokeyState* ps, char p5v, char p4v, char p917v)
{
if(ps->c3t1)
ps->c3t2 = p917v;
ps->c3t1 = p5v;
/* high-pass closk for channel 1 */
ps->c1t3 = ps->c1t2;
}
static void advance_ticks(PokeyState* ps, unsigned long ticks)
{
unsigned long ta,tbe, tbe0, tbe1, tbe2, tbe3;
char p5v,p4v,p917v;
unsigned char outvol_new;
unsigned char need0=0;
unsigned char need1=0;
unsigned char need2=0;
unsigned char need3=0;
unsigned char need=0;
if(ps->forcero)
{
ps->forcero = 0;
outvol_new = ps->outvol_0 + ps->outvol_1 + ps->outvol_2 + ps->outvol_3;
if(outvol_new != ps->outvol_all)
{
ps->outvol_all = outvol_new;
add_change(ps, outvol_new);
}
}
while(ticks>0)
{
tbe0 = ps->c0divpos;
tbe1 = ps->c1divpos;
tbe2 = ps->c2divpos;
tbe3 = ps->c3divpos;
tbe = ticks+1;
if(!ps->c0stop && tbe0 < tbe)
tbe = tbe0;
if(!ps->c1stop && tbe1 < tbe)
tbe = tbe1;
if(!ps->c2stop && tbe2 < tbe)
tbe = tbe2;
if(!ps->c3stop && tbe3 < tbe)
tbe = tbe3;
if(tbe>ticks)
ta = ticks;
else
{
ta = tbe;
need = 1;
}
ticks -= ta;
if(!ps->c0stop) ps->c0divpos -= ta;
if(!ps->c1stop) ps->c1divpos -= ta;
if(!ps->c2stop) ps->c2divpos -= ta;
if(!ps->c3stop) ps->c3divpos -= ta;
advance_polies(ps,ta);
bump_qe_subticks(ps,ta);
if(need)
{
p5v = poly5tbl[ps->poly5pos] & 1;
p4v = poly4tbl[ps->poly4pos] & 1;
if(ps->selpoly9)
p917v = poly9tbl[ps->poly9pos] & 1;
else
p917v = poly17tbl[ps->poly17pos] & 1;
if(!ps->c0stop && ta == tbe0)
{
ps->event_0(ps,p5v,p4v,p917v);
ps->c0divpos = ps->c0divstart;
need0 = 1;
}
if(!ps->c1stop && ta == tbe1)
{
ps->event_1(ps,p5v,p4v,p917v);
ps->c1divpos = ps->c1divstart;
if(ps->c1_f0)
ps->c0divpos = ps->c0divstart_p;
need1 = 1;
}
if(!ps->c2stop && ta == tbe2)
{
ps->event_2(ps,p5v,p4v,p917v);
ps->c2divpos = ps->c2divstart;
need2 = 1;
if(ps->c0sw4)
need0 = 1;
}
if(!ps->c3stop && ta == tbe3)
{
ps->event_3(ps,p5v,p4v,p917v);
ps->c3divpos = ps->c3divstart;
if(ps->c3_f2)
ps->c2divpos = ps->c2divstart_p;
need3 = 1;
if(ps->c1sw4)
need1 = 1;
}
if(need0)
{
ps->outvol_0 = 2*ps->readout_0(ps);
}
if(need1)
{
ps->outvol_1 = 2*ps->readout_1(ps);
}
if(need2)
{
ps->outvol_2 = 2*ps->readout_2(ps);
}
if(need3)
{
ps->outvol_3 = 2*ps->readout_3(ps);
}
outvol_new = ps->outvol_0 + ps->outvol_1 + ps->outvol_2 + ps->outvol_3;
if(outvol_new != ps->outvol_all)
{
ps->outvol_all = outvol_new;
add_change(ps, outvol_new);
}
}
}
}
static double generate_sample(PokeyState* ps)
{
/*unsigned long ta = (subticks+pokey_frq)/sample_rate;
subticks = (subticks+pokey_frq)%sample_rate;*/
advance_ticks(ps, pokey_frq/sample_rate);
return read_resam_all(ps);
}
/******************************************
filter table generator by Krzysztof Nikiel
******************************************/
#if 0
static int remez_filter_table(double resamp_rate, /* output_rate/input_rate */
double *cutoff, int quality)
{
int i;
static const int orders[] = {600, 800, 1000, 1200};
static const struct {
int stop; /* stopband ripple */
double weight; /* stopband weight */
double twidth[sizeof(orders)/sizeof(orders[0])];
} paramtab[] =
{
{70, 90, {4.9e-3, 3.45e-3, 2.65e-3, 2.2e-3}},
{55, 25, {3.4e-3, 2.7e-3, 2.05e-3, 1.7e-3}},
{40, 6.0, {2.6e-3, 1.8e-3, 1.5e-3, 1.2e-3}},
{-1, 0, {0, 0, 0, 0}}
};
static const double passtab[] = {0.5, 0.6, 0.7};
int ripple = 0, order = 0;
int size;
double weights[2], desired[2], bands[4];
static const int interlevel = 5;
double step = 1.0 / interlevel;
*cutoff = 0.95 * 0.5 * resamp_rate;
if (quality >= (int) (sizeof(passtab) / sizeof(passtab[0])))
quality = (int) (sizeof(passtab) / sizeof(passtab[0])) - 1;
for (ripple = 0; paramtab[ripple].stop > 0; ripple++)
{
for (order = 0; order < (int) (sizeof(orders)/sizeof(orders[0])); order++)
{
if ((*cutoff - paramtab[ripple].twidth[order])
> passtab[quality] * 0.5 * resamp_rate)
/* transition width OK */
goto found;
}
}
/* not found -- use shortest trasition */
ripple--;
order--;
found:
#if 0
printf("order: %d, cutoff: %g\tstopband:%d\ttranswidth:%f\n",
orders[order],
1789790 * *cutoff,
paramtab[ripple].stop,
1789790 * paramtab[ripple].twidth[order]);
exit(1);
#endif
size = orders[order] + 1;
if (size > SND_FILTER_SIZE) /* static table too short */
return 0;
desired[0] = 1;
desired[1] = 0;
weights[0] = 1;
weights[1] = paramtab[ripple].weight;
bands[0] = 0;
bands[2] = *cutoff;
bands[1] = bands[2] - paramtab[ripple].twidth[order];
bands[3] = 0.5;
bands[1] *= (double)interlevel;
bands[2] *= (double)interlevel;
remez(filter_data, (size / interlevel) + 1, 2, bands, desired, weights, BANDPASS);
for (i = size - interlevel; i >= 0; i -= interlevel)
{
int s;
double h1 = filter_data[i/interlevel];
double h2 = filter_data[i/interlevel+1];
for (s = 0; s < interlevel; s++)
{
double d = (double)s * step;
filter_data[i+s] = (h1*(1.0 - d) + h2 * d) * step;
}
}
/* compute reversed cumulative sum table */
for (i = size - 2; i >= 0; i--)
filter_data[i] += filter_data[i + 1];
#if 0
for (i = 0; i < size; i++)
printf("%.15f,\n", filter_data[i]);
fflush(stdout);
exit(1);
#endif
return size;
}
#endif
/*****************************************************************************/
/* Module: Pokey_sound_init() */
/* Purpose: to handle the power-up initialization functions */
/* these functions should only be executed on a cold-restart */
/* */
/* Authors: Michael Borisov, Krzystof Nikiel */
/* */
/* Inputs: freq17 - the value for the '1.79MHz' Pokey audio clock */
/* playback_freq - the playback frequency in samples per second */
/* num_pokeys - specifies the number of pokey chips to be emulated */
/* */
/* Outputs: Adjusts local globals - no return value */
/* */
/*****************************************************************************/
static void Pokey_process_8(void* sndbuffer, unsigned sndn);
static void Pokey_process_16(void* sndbuffer, unsigned sndn);
static void Update_pokey_sound_mz(uint16 addr, uint8 val, uint8 chip, uint8 gain);
#ifdef SERIO_SOUND
static void Update_serio_sound_mz(int out, UBYTE data);
#endif
#ifdef CONSOLE_SOUND
static void Update_consol_sound_mz( int set );
#endif
#ifdef VOL_ONLY_SOUND
static void Update_vol_only_sound_mz( void );
#endif
int Pokey_sound_init_mz(uint32 freq17, uint16 playback_freq, uint8 num_pokeys,
int flags, int quality
#ifdef __PLUS
, int clear_regs
#endif
)
{
double cutoff;
sample_rate = playback_freq;
snd_flags = flags;
snd_quality = quality;
Update_pokey_sound = Update_pokey_sound_mz;
#ifdef SERIO_SOUND
Update_serio_sound = Update_serio_sound_mz;
#endif
#ifdef CONSOLE_SOUND
Update_consol_sound = Update_consol_sound_mz;
#endif
#ifdef VOL_ONLY_SOUND
Update_vol_only_sound = Update_vol_only_sound_mz;
#endif
#ifdef VOL_ONLY_SOUND
samp_freq=playback_freq;
#endif /* VOL_ONLY_SOUND */
Pokey_process_ptr = (flags & SND_BIT16) ? Pokey_process_16 : Pokey_process_8;
switch(playback_freq)
{
#if 0
case 44100:
if(flags & SND_BIT16)
{
filter_data = filter_44;
filter_size = filter_size_44;
}
else
{
filter_data = filter_44_8;
filter_size = filter_size_44_8;
}
pokey_frq = 1808100; /* 1.02% off ideal */
audible_frq = 20000; /* ultrasound */
break;
case 22050:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -