From b9b2a6dd7d64ebe072495b7c596862c3e7d50e6c Mon Sep 17 00:00:00 2001 From: cam900 Date: Sat, 30 Mar 2019 06:57:45 +0900 Subject: c6280.cpp : Fix LFO, Frequency behavior (#4822) * c6280.cpp : Fix LFO enable bit * c6280.cpp : Implement LFO reset bit behavior * c6280.cpp : Correct frequency behavior, Add notes --- src/devices/sound/c6280.cpp | 104 ++++++++++++++++++++------------------------ src/devices/sound/c6280.h | 9 ++-- 2 files changed, 51 insertions(+), 62 deletions(-) diff --git a/src/devices/sound/c6280.cpp b/src/devices/sound/c6280.cpp index 0e5873c86de..73ec3e821be 100644 --- a/src/devices/sound/c6280.cpp +++ b/src/devices/sound/c6280.cpp @@ -92,16 +92,16 @@ void c6280_device::sound_stream_update(sound_stream &stream, stream_sample_t **i if((ch >= 4) && (m_channel[ch].m_noise_control & 0x80)) { /* Noise mode */ - uint32_t step = m_noise_freq_tab[(m_channel[ch].m_noise_control & 0x1F) ^ 0x1F]; + uint32_t step = (m_channel[ch].m_noise_control & 0x1F) ^ 0x1F; for (int i = 0; i < samples; i += 1) { static int data = 0; - m_channel[ch].m_noise_counter += step; - if(m_channel[ch].m_noise_counter >= 0x800) + if(m_channel[ch].m_noise_counter <= 0) { + m_channel[ch].m_noise_counter = step << 2; data = (machine().rand() & 1) ? 0x1F : 0; } - m_channel[ch].m_noise_counter &= 0x7FF; + m_channel[ch].m_noise_counter--; outputs[0][i] += (int16_t)(vll * (data - 16)); outputs[1][i] += (int16_t)(vlr * (data - 16)); } @@ -118,28 +118,40 @@ void c6280_device::sound_stream_update(sound_stream &stream, stream_sample_t **i } else { - if ((m_lfo_control & 0x80) && (ch < 2)) + if ((m_lfo_control & 3) && (ch < 2)) { if (ch == 0) // CH 0 only, CH 1 is muted { /* Waveform mode with LFO */ - uint32_t step = m_channel[0].m_frequency; - uint16_t lfo_step = m_channel[1].m_frequency; + uint16_t lfo_step = m_channel[1].m_frequency ? m_channel[1].m_frequency : 0x1000; for (int i = 0; i < samples; i += 1) { - int offset, lfooffset; - int16_t data, lfo_data; - lfooffset = (m_channel[1].m_counter >> 12) & 0x1F; - m_channel[1].m_counter += m_wave_freq_tab[(lfo_step * m_lfo_frequency) & 0xfff]; // TODO : multiply? verify this from real hardware. - m_channel[1].m_counter &= 0x1FFFF; - lfo_data = m_channel[1].m_waveform[lfooffset]; - if (m_lfo_control & 3) + int32_t step = m_channel[0].m_frequency ? m_channel[0].m_frequency : 0x1000; + if (m_lfo_control & 0x80) // reset LFO + { + m_channel[1].m_tick = lfo_step * m_lfo_frequency; + m_channel[1].m_counter = 0; + } + else + { + int lfooffset = m_channel[1].m_counter; + m_channel[1].m_tick--; + if (m_channel[1].m_tick <= 0) + { + m_channel[1].m_tick = lfo_step * m_lfo_frequency; // TODO : multiply? verify this from real hardware. + m_channel[1].m_counter = (m_channel[1].m_counter + 1) & 0x1f; + } + int16_t lfo_data = m_channel[1].m_waveform[lfooffset]; step += ((lfo_data - 16) << (((m_lfo_control & 3)-1)<<1)); // verified from patent, TODO : same in real hardware? - - offset = (m_channel[0].m_counter >> 12) & 0x1F; - m_channel[0].m_counter += m_wave_freq_tab[step & 0xfff]; - m_channel[0].m_counter &= 0x1FFFF; - data = m_channel[0].m_waveform[offset]; + } + int offset = m_channel[0].m_counter; + m_channel[0].m_tick--; + if (m_channel[0].m_tick <= 0) + { + m_channel[0].m_tick = step; + m_channel[0].m_counter = (m_channel[0].m_counter + 1) & 0x1f; + } + int16_t data = m_channel[0].m_waveform[offset]; outputs[0][i] += (int16_t)(vll * (data - 16)); outputs[1][i] += (int16_t)(vlr * (data - 16)); } @@ -148,15 +160,17 @@ void c6280_device::sound_stream_update(sound_stream &stream, stream_sample_t **i else { /* Waveform mode */ - uint32_t step = m_wave_freq_tab[m_channel[ch].m_frequency]; + uint32_t step = m_channel[ch].m_frequency ? m_channel[ch].m_frequency : 0x1000; for (int i = 0; i < samples; i += 1) { - int offset; - int16_t data; - offset = (m_channel[ch].m_counter >> 12) & 0x1F; - m_channel[ch].m_counter += step; - m_channel[ch].m_counter &= 0x1FFFF; - data = m_channel[ch].m_waveform[offset]; + int offset = m_channel[0].m_counter; + m_channel[ch].m_tick--; + if (m_channel[ch].m_tick <= 0) + { + m_channel[ch].m_tick = step; + m_channel[ch].m_counter = (m_channel[ch].m_counter + 1) & 0x1f; + } + int16_t data = m_channel[ch].m_waveform[offset]; outputs[0][i] += (int16_t)(vll * (data - 16)); outputs[1][i] += (int16_t)(vlr * (data - 16)); } @@ -205,6 +219,10 @@ WRITE8_MEMBER( c6280_device::c6280_w ) { chan->m_index = 0; } + if(((chan->m_control & 0x80) == 0) && (data & 0x80)) + { + chan->m_tick = chan->m_frequency; + } chan->m_control = data; break; @@ -261,38 +279,9 @@ c6280_device::c6280_device(const machine_config &mconfig, const char *tag, devic { } -//------------------------------------------------- -// calculate_clocks - (re)calculate clock-derived -// members -//------------------------------------------------- - -void c6280_device::calculate_clocks() -{ - int rate = clock() / 16; - - /* Make waveform frequency table */ - for (int i = 0; i < 4096; i += 1) - { - double step = (16 * 4096) / (i + 1); - m_wave_freq_tab[(1 + i) & 0xFFF] = (uint32_t)step; - } - - /* Make noise frequency table */ - for (int i = 0; i < 32; i += 1) - { - double step = (16 * 32) / (i+1); - m_noise_freq_tab[i] = (uint32_t)step; - } - - if (m_stream != nullptr) - m_stream->set_sample_rate(rate); - else - m_stream = machine().sound().stream_alloc(*this, 0, 2, rate); -} - void c6280_device::device_clock_changed() { - calculate_clocks(); + m_stream->set_sample_rate(clock()); } //------------------------------------------------- @@ -311,7 +300,7 @@ void c6280_device::device_start() m_lfo_control = 0; memset(m_channel, 0, sizeof(channel) * 8); - calculate_clocks(); + m_stream = machine().sound().stream_alloc(*this, 0, 2, clock()); /* Make volume table */ /* PSG has 48dB volume range spread over 32 steps */ @@ -338,5 +327,6 @@ void c6280_device::device_start() save_item(NAME(m_channel[chan].m_noise_control), chan); save_item(NAME(m_channel[chan].m_noise_counter), chan); save_item(NAME(m_channel[chan].m_counter), chan); + save_item(NAME(m_channel[chan].m_tick), chan); } } diff --git a/src/devices/sound/c6280.h b/src/devices/sound/c6280.h index 5b7f94bce7f..0cfdc34799b 100644 --- a/src/devices/sound/c6280.h +++ b/src/devices/sound/c6280.h @@ -8,6 +8,8 @@ class c6280_device : public device_t, public device_sound_interface { public: + static constexpr feature_type imperfect_features() { return feature::SOUND; } // Incorrect / Not verified noise / LFO output + c6280_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // write only @@ -22,8 +24,6 @@ protected: virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; private: - void calculate_clocks(); - struct channel { uint16_t m_frequency; uint8_t m_control; @@ -32,8 +32,9 @@ private: uint8_t m_index; int16_t m_dda; uint8_t m_noise_control; - uint32_t m_noise_counter; + int32_t m_noise_counter; uint32_t m_counter; + int32_t m_tick; }; // internal state @@ -44,8 +45,6 @@ private: uint8_t m_lfo_control; channel m_channel[8]; int16_t m_volume_table[32]; - uint32_t m_noise_freq_tab[32]; - uint32_t m_wave_freq_tab[4096]; }; DECLARE_DEVICE_TYPE(C6280, c6280_device) -- cgit v1.2.3