diff options
author | 2013-02-19 06:33:21 +0000 | |
---|---|---|
committer | 2013-02-19 06:33:21 +0000 | |
commit | 7f4a3d4b5e234b03f6538a4c4ea356a0b2068315 (patch) | |
tree | 04d3f82fc1862507dd6277f95cf0ac38eb604f59 /src/emu/sound/k051649.c | |
parent | 1d9b72e13e80f6b430e21823133cf65d7273bd92 (diff) |
Modernized tms3615, es8712, cem3394, k051649, and rf5c400 sound devices. [Andrew
Gardner]
Diffstat (limited to 'src/emu/sound/k051649.c')
-rw-r--r-- | src/emu/sound/k051649.c | 330 |
1 files changed, 145 insertions, 185 deletions
diff --git a/src/emu/sound/k051649.c b/src/emu/sound/k051649.c index e3503a1eb52..44465fc604e 100644 --- a/src/emu/sound/k051649.c +++ b/src/emu/sound/k051649.c @@ -29,86 +29,101 @@ #define DEF_GAIN 8 -/* this structure defines the parameters for a channel */ -struct k051649_sound_channel -{ - unsigned long counter; - int frequency; - int volume; - int key; - signed char waveram[32]; -}; - -struct k051649_state -{ - k051649_sound_channel channel_list[5]; +// device type definition +const device_type K051649 = &device_creator<k051649_device>; - /* global sound parameters */ - sound_stream * stream; - int mclock,rate; - /* mixer tables and internal buffers */ - INT16 *mixer_table; - INT16 *mixer_lookup; - short *mixer_buffer; +//************************************************************************** +// LIVE DEVICE +//************************************************************************** - /* chip registers */ - UINT8 test; -}; +//------------------------------------------------- +// k051649_device - constructor +//------------------------------------------------- -INLINE k051649_state *get_safe_token(device_t *device) +k051649_device::k051649_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, K051649, "K051649", tag, owner, clock), + device_sound_interface(mconfig, *this), + m_stream(NULL), + m_mclock(0), + m_rate(0), + m_mixer_table(NULL), + m_mixer_lookup(NULL), + m_mixer_buffer(NULL), + m_test(0) { - assert(device != NULL); - assert(device->type() == K051649); - return (k051649_state *)downcast<k051649_device *>(device)->token(); } -/* build a table to divide by the number of voices */ -static void make_mixer_table(running_machine &machine, k051649_state *info, int voices) + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void k051649_device::device_start() { - int i; + // get stream channels + m_rate = clock()/16; + m_stream = stream_alloc(0, 1, m_rate); + m_mclock = clock(); - /* allocate memory */ - info->mixer_table = auto_alloc_array(machine, INT16, 512 * voices); + // allocate a buffer to mix into - 1 second's worth should be more than enough + m_mixer_buffer = auto_alloc_array(machine(), short, 2 * m_rate); - /* find the middle of the table */ - info->mixer_lookup = info->mixer_table + (256 * voices); + // build the mixer table + make_mixer_table(5); +} - /* fill in the table - 16 bit case */ - for (i = 0; i < (voices * 256); i++) - { - int val = i * DEF_GAIN * 16 / voices; - if (val > 32767) val = 32767; - info->mixer_lookup[ i] = val; - info->mixer_lookup[-i] = -val; + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void k051649_device::device_reset() +{ + k051649_sound_channel *voice = m_channel_list; + int i; + + // reset all the voices + for (i = 0; i < 5; i++) + { + voice[i].frequency = 0; + voice[i].volume = 0xf; + voice[i].counter = 0; + voice[i].key = 0; } + + // other parameters + m_test = 0; } -/* generate sound to the mix buffer */ -static STREAM_UPDATE( k051649_update ) +//------------------------------------------------- +// sound_stream_update - handle a stream update +//------------------------------------------------- + +void k051649_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { - k051649_state *info = (k051649_state *)param; - k051649_sound_channel *voice=info->channel_list; + k051649_sound_channel *voice=m_channel_list; stream_sample_t *buffer = outputs[0]; short *mix; int i,j; - /* zap the contents of the mixer buffer */ - memset(info->mixer_buffer, 0, samples * sizeof(short)); + // zap the contents of the mixer buffer + memset(m_mixer_buffer, 0, samples * sizeof(short)); - for (j = 0; j < 5; j++) { - /* channel is halted for freq < 9 */ + for (j = 0; j < 5; j++) + { + // channel is halted for freq < 9 if (voice[j].frequency > 8) { const signed char *w = voice[j].waveram; int v=voice[j].volume * voice[j].key; int c=voice[j].counter; - int step = ((INT64)info->mclock * (1 << FREQ_BITS)) / (float)((voice[j].frequency + 1) * 16 * (info->rate / 32)) + 0.5; + int step = ((INT64)m_mclock * (1 << FREQ_BITS)) / (float)((voice[j].frequency + 1) * 16 * (m_rate / 32)) + 0.5; - mix = info->mixer_buffer; + mix = m_mixer_buffer; - /* add our contribution */ + // add our contribution for (i = 0; i < samples; i++) { int offs; @@ -118,211 +133,156 @@ static STREAM_UPDATE( k051649_update ) *mix++ += (w[offs] * v)>>3; } - /* update the counter for this voice */ + // update the counter for this voice voice[j].counter = c; } } - /* mix it down */ - mix = info->mixer_buffer; + // mix it down + mix = m_mixer_buffer; for (i = 0; i < samples; i++) - *buffer++ = info->mixer_lookup[*mix++]; -} - -static DEVICE_START( k051649 ) -{ - k051649_state *info = get_safe_token(device); - - /* get stream channels */ - info->rate = device->clock()/16; - info->stream = device->machine().sound().stream_alloc(*device, 0, 1, info->rate, info, k051649_update); - info->mclock = device->clock(); - - /* allocate a buffer to mix into - 1 second's worth should be more than enough */ - info->mixer_buffer = auto_alloc_array(device->machine(), short, 2 * info->rate); - - /* build the mixer table */ - make_mixer_table(device->machine(), info, 5); + *buffer++ = m_mixer_lookup[*mix++]; } -static DEVICE_RESET( k051649 ) -{ - k051649_state *info = get_safe_token(device); - k051649_sound_channel *voice = info->channel_list; - int i; - - /* reset all the voices */ - for (i = 0; i < 5; i++) { - voice[i].frequency = 0; - voice[i].volume = 0xf; - voice[i].counter = 0; - voice[i].key = 0; - } - - /* other parameters */ - info->test = 0; -} /********************************************************************************/ -WRITE8_DEVICE_HANDLER( k051649_waveform_w ) -{ - k051649_state *info = get_safe_token(device); - /* waveram is read-only? */ - if (info->test & 0x40 || (info->test & 0x80 && offset >= 0x60)) +WRITE8_MEMBER( k051649_device::k051649_waveform_w ) +{ + // waveram is read-only? + if (m_test & 0x40 || (m_test & 0x80 && offset >= 0x60)) return; - info->stream->update(); + m_stream->update(); if (offset >= 0x60) { - /* channel 5 shares waveram with channel 4 */ - info->channel_list[3].waveram[offset&0x1f]=data; - info->channel_list[4].waveram[offset&0x1f]=data; + // channel 5 shares waveram with channel 4 + m_channel_list[3].waveram[offset&0x1f]=data; + m_channel_list[4].waveram[offset&0x1f]=data; } else - info->channel_list[offset>>5].waveram[offset&0x1f]=data; + m_channel_list[offset>>5].waveram[offset&0x1f]=data; } -READ8_DEVICE_HANDLER ( k051649_waveform_r ) -{ - k051649_state *info = get_safe_token(device); - /* test-register bits 6/7 expose the internal counter */ - if (info->test & 0xc0) +READ8_MEMBER ( k051649_device::k051649_waveform_r ) +{ + // test-register bits 6/7 expose the internal counter + if (m_test & 0xc0) { - info->stream->update(); + m_stream->update(); if (offset >= 0x60) - offset += (info->channel_list[3 + (info->test >> 6 & 1)].counter >> FREQ_BITS); - else if (info->test & 0x40) - offset += (info->channel_list[offset>>5].counter >> FREQ_BITS); + offset += (m_channel_list[3 + (m_test >> 6 & 1)].counter >> FREQ_BITS); + else if (m_test & 0x40) + offset += (m_channel_list[offset>>5].counter >> FREQ_BITS); } - return info->channel_list[offset>>5].waveram[offset&0x1f]; + return m_channel_list[offset>>5].waveram[offset&0x1f]; } -WRITE8_DEVICE_HANDLER( k052539_waveform_w ) -{ - k051649_state *info = get_safe_token(device); - /* waveram is read-only? */ - if (info->test & 0x40) +WRITE8_MEMBER( k051649_device::k052539_waveform_w ) +{ + // waveram is read-only? + if (m_test & 0x40) return; - info->stream->update(); - info->channel_list[offset>>5].waveram[offset&0x1f]=data; + m_stream->update(); + m_channel_list[offset>>5].waveram[offset&0x1f]=data; } -READ8_DEVICE_HANDLER ( k052539_waveform_r ) -{ - k051649_state *info = get_safe_token(device); - /* test-register bit 6 exposes the internal counter */ - if (info->test & 0x40) +READ8_MEMBER ( k051649_device::k052539_waveform_r ) +{ + // test-register bit 6 exposes the internal counter + if (m_test & 0x40) { - info->stream->update(); - offset += (info->channel_list[offset>>5].counter >> FREQ_BITS); + m_stream->update(); + offset += (m_channel_list[offset>>5].counter >> FREQ_BITS); } - return info->channel_list[offset>>5].waveram[offset&0x1f]; + return m_channel_list[offset>>5].waveram[offset&0x1f]; } -WRITE8_DEVICE_HANDLER( k051649_volume_w ) + +WRITE8_MEMBER( k051649_device::k051649_volume_w ) { - k051649_state *info = get_safe_token(device); - info->stream->update(); - info->channel_list[offset&0x7].volume=data&0xf; + m_stream->update(); + m_channel_list[offset&0x7].volume=data&0xf; } -WRITE8_DEVICE_HANDLER( k051649_frequency_w ) + +WRITE8_MEMBER( k051649_device::k051649_frequency_w ) { - k051649_state *info = get_safe_token(device); int freq_hi = offset & 1; offset >>= 1; - info->stream->update(); + m_stream->update(); - /* test-register bit 5 resets the internal counter */ - if (info->test & 0x20) - info->channel_list[offset].counter = ~0; - else if (info->channel_list[offset].frequency < 9) - info->channel_list[offset].counter |= ((1 << FREQ_BITS) - 1); + // test-register bit 5 resets the internal counter + if (m_test & 0x20) + m_channel_list[offset].counter = ~0; + else if (m_channel_list[offset].frequency < 9) + m_channel_list[offset].counter |= ((1 << FREQ_BITS) - 1); - /* update frequency */ + // update frequency if (freq_hi) - info->channel_list[offset].frequency = (info->channel_list[offset].frequency & 0x0ff) | (data << 8 & 0xf00); + m_channel_list[offset].frequency = (m_channel_list[offset].frequency & 0x0ff) | (data << 8 & 0xf00); else - info->channel_list[offset].frequency = (info->channel_list[offset].frequency & 0xf00) | data; + m_channel_list[offset].frequency = (m_channel_list[offset].frequency & 0xf00) | data; } -WRITE8_DEVICE_HANDLER( k051649_keyonoff_w ) + +WRITE8_MEMBER( k051649_device::k051649_keyonoff_w ) { int i; - k051649_state *info = get_safe_token(device); - info->stream->update(); + m_stream->update(); - for (i = 0; i < 5; i++) { - info->channel_list[i].key=data&1; + for (i = 0; i < 5; i++) + { + m_channel_list[i].key=data&1; data >>= 1; } } -WRITE8_DEVICE_HANDLER( k051649_test_w ) -{ - k051649_state *info = get_safe_token(device); - info->test = data; -} -READ8_DEVICE_HANDLER ( k051649_test_r ) +WRITE8_MEMBER( k051649_device::k051649_test_w ) { - /* reading the test register sets it to $ff! */ - k051649_test_w(device, space, offset, 0xff); - return 0xff; + m_test = data; } -const device_type K051649 = &device_creator<k051649_device>; -k051649_device::k051649_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, K051649, "K051649", tag, owner, clock), - device_sound_interface(mconfig, *this) +READ8_MEMBER ( k051649_device::k051649_test_r ) { - m_token = global_alloc_clear(k051649_state); + // reading the test register sets it to $ff! + k051649_test_w(space, offset, 0xff); + return 0xff; } -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void k051649_device::device_config_complete() -{ -} //------------------------------------------------- -// device_start - device-specific startup +// build a table to divide by the number of voices //------------------------------------------------- -void k051649_device::device_start() +void k051649_device::make_mixer_table(int voices) { - DEVICE_START_NAME( k051649 )(this); -} + int i; -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- + // allocate memory + m_mixer_table = auto_alloc_array(machine(), INT16, 512 * voices); -void k051649_device::device_reset() -{ - DEVICE_RESET_NAME( k051649 )(this); + // find the middle of the table + m_mixer_lookup = m_mixer_table + (256 * voices); + + // fill in the table - 16 bit case + for (i = 0; i < (voices * 256); i++) + { + int val = i * DEF_GAIN * 16 / voices; + if (val > 32767) val = 32767; + m_mixer_lookup[ i] = val; + m_mixer_lookup[-i] = -val; + } } -//------------------------------------------------- -// sound_stream_update - handle a stream update -//------------------------------------------------- -void k051649_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) -{ - // should never get here - fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); -} |