void exidy_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { sh6840_timer_channel *sh6840_timer = m_sh6840_timer; /* hack to skip the expensive lfsr noise generation unless at least one of the 3 channels actually depends on it being generated */ int noisy = ((sh6840_timer[0].cr & sh6840_timer[1].cr & sh6840_timer[2].cr & 0x02) == 0); stream_sample_t *buffer = outputs[0]; /* loop over samples */ while (samples--) { sh6840_timer_channel *t; int clocks; stream_sample_t sample = 0; /* determine how many 6840 clocks this sample */ m_sh6840_clock_count += m_sh6840_clocks_per_sample; int clocks_this_sample = m_sh6840_clock_count >> 24; m_sh6840_clock_count &= (1 << 24) - 1; /* skip if nothing enabled */ if ((sh6840_timer[0].cr & 0x01) == 0) { int noise_clocks_this_sample = 0; uint32_t chan0_clocks; /* generate E-clocked noise if configured to do so */ if (noisy && !(m_sfxctrl & 0x01)) noise_clocks_this_sample = sh6840_update_noise(clocks_this_sample); /* handle timer 0 if enabled */ t = &sh6840_timer[0]; chan0_clocks = t->clocks; clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample; sh6840_apply_clock(t, clocks); if (t->state && !(m_sfxctrl & 0x02) && (t->cr & 0x80)) sample += m_sh6840_volume[0]; /* generate channel 0-clocked noise if configured to do so */ if (noisy && (m_sfxctrl & 0x01)) noise_clocks_this_sample = sh6840_update_noise(t->clocks - chan0_clocks); /* handle timer 1 if enabled */ t = &sh6840_timer[1]; clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample; sh6840_apply_clock(t, clocks); if (t->state && (t->cr & 0x80)) sample += m_sh6840_volume[1]; /* handle timer 2 if enabled */ t = &sh6840_timer[2]; clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample; /* prescale */ if (t->cr & 0x01) { clocks += t->leftovers; t->leftovers = clocks % 8; clocks /= 8; } sh6840_apply_clock(t, clocks); if (t->state && (t->cr & 0x80)) sample += m_sh6840_volume[2]; } /* music (if present) */ sample += generate_music_sample(); /* stash */ *buffer++ = sample; } }
void beezer_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { struct sh6840_timer_channel *sh6840_timer = m_sh6840_timer; /* hack to skip the expensive lfsr noise generation unless at least one of the 2 channels which actually depend on it are set to use it as a source */ int noisy = ((sh6840_timer[0].cr & sh6840_timer[2].cr & 0x02) == 0); stream_sample_t *buffer = outputs[0]; /* loop over samples */ while (samples--) { struct sh6840_timer_channel *t; int clocks_this_sample; int clocks; INT16 sample1, sample2, sample3, sample0; INT16 sample = 0; sample1 = sample2 = sample3 = sample0 = 0; /* determine how many 6840 clocks this sample */ m_sh6840_clock_count += m_sh6840_clocks_per_sample; clocks_this_sample = m_sh6840_clock_count >> 24; m_sh6840_clock_count &= (1 << 24) - 1; /* skip if nothing enabled */ if ((sh6840_timer[0].cr & 0x01) == 0) // if we're not in reset... { // int noise_clocks_this_sample = 0; UINT32 chan1_clocks; /* generate noise if configured to do so */ if (noisy != 0) sh6840_update_noise(clocks_this_sample); /* handle timer 0 if enabled */ t = &sh6840_timer[0]; clocks = (t->cr & 0x02) ? clocks_this_sample : m_sh6840_noiselatch1; sh6840_apply_clock(t, clocks); sample1 = (t->state && (t->cr & 0x80))?1:0; /* handle timer 1 if enabled */ t = &sh6840_timer[1]; chan1_clocks = t->clocks; clocks = (t->cr & 0x02) ? clocks_this_sample : 0; // TODO: this is WRONG: channel 1 is clocked by a mystery "VCO CLOCK" signal if not set to E clock. it may not even be connected to anything! sh6840_apply_clock(t, clocks); sample2 = (t->state && (t->cr & 0x80))?1:0; /* generate channel 1-clocked noise if configured to do so */ if (noisy != 0) { sh6840_update_noise(t->clocks - chan1_clocks); if (clocks) m_sh6840_noiselatch3 = (m_sh6840_LFSR&0x1); } /* handle timer 2 if enabled */ t = &sh6840_timer[2]; clocks = (t->cr & 0x02) ? clocks_this_sample : m_sh6840_noiselatch3; /* prescale */ if (t->cr & 0x01) { clocks += t->leftovers; t->leftovers = clocks % 8; clocks /= 8; } sh6840_apply_clock(t, clocks); sample3 = (t->state && (t->cr & 0x80))?1:0; } sample0 = m_sh6840_latchwrite?1:0; /* stash */ /* each sample feeds an xor bit on the sign bit of a sign-magnitude (NOT 2'S COMPLEMENT) * DAC. This requires some rather convoluted processing: * samplex*0x80 brings the sample to the sign bit * m_sh6840_volume[x]&0x80 pulls the sign bit from the dac sample * m_sh6840_volume[x]&0x7F pulls the magnitude from the dac sample */ sample += (((sample0*0x80)^(m_sh6840_volume[0]&0x80))?-1:1)*(m_sh6840_volume[0]&0x7F); sample += (((sample1*0x80)^(m_sh6840_volume[1]&0x80))?-1:1)*(m_sh6840_volume[1]&0x7F); sample += (((sample2*0x80)^(m_sh6840_volume[2]&0x80))?-1:1)*(m_sh6840_volume[2]&0x7F); sample += (((sample3*0x80)^(m_sh6840_volume[3]&0x80))?-1:1)*(m_sh6840_volume[3]&0x7F); *buffer++ = sample*64; // adding 4 numbers ranging from -128 to 127 yields a range of -512 to 508; to scale that to '-32768 to 32767' we multiply by 64 } }
static void exidy_stream_update(void *param, stream_sample_t **inputs, stream_sample_t **outputs, int length) { int noisy = ((sh6840_timer[0].cr & sh6840_timer[1].cr & sh6840_timer[2].cr & 0x02) == 0); stream_sample_t *buffer = outputs[0]; /* loop over samples */ while (length--) { struct sh6840_timer_channel *t; struct sh8253_timer_channel *c; int clocks_this_sample; INT16 sample = 0; /* determine how many 6840 clocks this sample */ sh6840_clock_count += sh6840_clocks_per_sample; clocks_this_sample = sh6840_clock_count >> 24; sh6840_clock_count &= (1 << 24) - 1; /* skip if nothing enabled */ if ((sh6840_timer[0].cr & 0x01) == 0) { int noise_clocks_this_sample = 0; UINT32 chan0_clocks; /* generate E-clocked noise if necessary */ if (noisy && !(exidy_sfxctrl & 0x01)) noise_clocks_this_sample = sh6840_update_noise(clocks_this_sample); /* handle timer 0 if enabled */ t = &sh6840_timer[0]; chan0_clocks = t->clocks; if (t->cr & 0x80) { int clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample; sh6840_apply_clock(t, clocks); if (t->state && !(exidy_sfxctrl & 0x02)) sample += sh6840_volume[0]; } /* generate channel 0-clocked noise if necessary */ if (noisy && (exidy_sfxctrl & 0x01)) noise_clocks_this_sample = sh6840_update_noise(t->clocks - chan0_clocks); /* handle timer 1 if enabled */ t = &sh6840_timer[1]; if (t->cr & 0x80) { int clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample; sh6840_apply_clock(t, clocks); if (t->state) sample += sh6840_volume[1]; } /* handle timer 2 if enabled */ t = &sh6840_timer[2]; if (t->cr & 0x80) { int clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample; /* prescale */ if (t->cr & 0x01) { clocks += t->leftovers; t->leftovers = clocks % 8; clocks /= 8; } sh6840_apply_clock(t, clocks); if (t->state) sample += sh6840_volume[2]; } } /* music (if present) */ if (has_sh8253) { /* music channel 0 */ c = &sh8253_timer[0]; if (c->enable) { c->fraction += c->step; if (c->fraction & 0x0800000) sample += BASE_VOLUME; } /* music channel 1 */ c = &sh8253_timer[1]; if (c->enable) { c->fraction += c->step; if (c->fraction & 0x0800000) sample += BASE_VOLUME; } /* music channel 2 */ c = &sh8253_timer[2]; if (c->enable) { c->fraction += c->step; if (c->fraction & 0x0800000) sample += BASE_VOLUME; } } /* stash */ *buffer++ = sample; } }
static STREAM_UPDATE( exidy_stream_update ) { /* hack to skip the expensive lfsr noise generation unless at least one of the 3 channels actually depends on it being generated */ int noisy = ((sh6840_timer[0].cr & sh6840_timer[1].cr & sh6840_timer[2].cr & 0x02) == 0); stream_sample_t *buffer = outputs[0]; /* loop over samples */ while (samples--) { struct sh6840_timer_channel *t; struct sh8253_timer_channel *c; int clocks_this_sample; int clocks; INT16 sample = 0; /* determine how many 6840 clocks this sample */ sh6840_clock_count += sh6840_clocks_per_sample; clocks_this_sample = sh6840_clock_count >> 24; sh6840_clock_count &= (1 << 24) - 1; /* skip if nothing enabled */ if ((sh6840_timer[0].cr & 0x01) == 0) { int noise_clocks_this_sample = 0; UINT32 chan0_clocks; /* generate E-clocked noise if configured to do so */ if (noisy && !(exidy_sfxctrl & 0x01)) noise_clocks_this_sample = sh6840_update_noise(clocks_this_sample); /* handle timer 0 if enabled */ t = &sh6840_timer[0]; chan0_clocks = t->clocks; clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample; sh6840_apply_clock(t, clocks); if (t->state && !(exidy_sfxctrl & 0x02) && (t->cr & 0x80)) sample += sh6840_volume[0]; /* generate channel 0-clocked noise if configured to do so */ if (noisy && (exidy_sfxctrl & 0x01)) noise_clocks_this_sample = sh6840_update_noise(t->clocks - chan0_clocks); /* handle timer 1 if enabled */ t = &sh6840_timer[1]; clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample; sh6840_apply_clock(t, clocks); if (t->state && (t->cr & 0x80)) sample += sh6840_volume[1]; /* handle timer 2 if enabled */ t = &sh6840_timer[2]; clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample; /* prescale */ if (t->cr & 0x01) { clocks += t->leftovers; t->leftovers = clocks % 8; clocks /= 8; } sh6840_apply_clock(t, clocks); if (t->state && (t->cr & 0x80)) sample += sh6840_volume[2]; } /* music (if present) */ if (has_sh8253) { /* music channel 0 */ c = &sh8253_timer[0]; if (c->enable) { c->fraction += c->step; if (c->fraction & 0x0800000) sample += BASE_VOLUME; } /* music channel 1 */ c = &sh8253_timer[1]; if (c->enable) { c->fraction += c->step; if (c->fraction & 0x0800000) sample += BASE_VOLUME; } /* music channel 2 */ c = &sh8253_timer[2]; if (c->enable) { c->fraction += c->step; if (c->fraction & 0x0800000) sample += BASE_VOLUME; } } /* stash */ *buffer++ = sample; } }