mirror of
https://github.com/holub/mame
synced 2025-10-05 16:50:57 +03:00
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
This commit is contained in:
parent
80a48d5229
commit
b9b2a6dd7d
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user