Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions src/devices/sound/cem3394.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ static constexpr double TRIANGLE_VOLUME = SAWTOOTH_VOLUME * 1.27f;
// external input is unknown but let's make it the same as the pulse
static constexpr double EXTERNAL_VOLUME = PULSE_VOLUME;

// filter volume when self-oscillating unknown, using PULSE_VOLUME arbitrarily
static constexpr double FILTER_OSC_VOLUME = PULSE_VOLUME;


// waveform generation parameters
#define ENABLE_PULSE 1
Expand Down Expand Up @@ -156,6 +159,7 @@ cem3394_device::cem3394_device(const machine_config &mconfig, const char *tag, d
m_filter_frequency(1300),
m_filter_modulation(0),
m_filter_resonance(0),
m_filter_osc_position(0),
m_filter_in{0},
m_filter_out{0},
m_pulse_width(0),
Expand Down Expand Up @@ -420,10 +424,31 @@ void cem3394_device::sound_stream_update(sound_stream &stream)
if (ENABLE_EXTERNAL && BIT(input_mask, AUDIO_INPUT))
result += EXTERNAL_VOLUME * m_mixer_external * stream.get(AUDIO_INPUT, sampindex);

// compute the modulated filter frequency and apply the filter
// modulation tracks the VCO triangle
double filter_freq = m_filter_frequency * (1 + m_filter_modulation * triangle);
result = filter(result, filter_freq);
if (FILTER_TYPE)
{
// compute the modulated filter frequency and apply the filter
// modulation tracks the VCO triangle
const double filter_freq = m_filter_frequency * (1 + m_filter_modulation * triangle);
// need to call filter() and advance the filter's state, even if we don't use the result
const double filter_result = filter(result, filter_freq);

// advance the position of the oscillator used when the filter is self-oscillating
m_filter_osc_position += filter_freq * m_inv_sample_rate;
if (m_filter_osc_position >= 1.0)
m_filter_osc_position -= floor(m_filter_osc_position);

if (!m_wave_select && m_filter_resonance >= 1.0)
{
// when no waveform is selected and the filter is configured to self-oscilate,
// use a sine wave oscillator.
const double angle = 2 * M_PI * m_filter_osc_position - M_PI;
result = FILTER_OSC_VOLUME * sin(angle);
}
else
{
result = filter_result;
}
}

// apply AC coupling
if (ENABLE_AC_COUPLING)
Expand Down Expand Up @@ -460,6 +485,7 @@ void cem3394_device::device_start()
save_item(NAME(m_filter_frequency));
save_item(NAME(m_filter_modulation));
save_item(NAME(m_filter_resonance));
save_item(NAME(m_filter_osc_position));
save_item(NAME(m_filter_in));
save_item(NAME(m_filter_out));

Expand Down Expand Up @@ -578,7 +604,7 @@ void cem3394_device::set_voltage_internal(int input, double voltage)
}
else if (voltage > 2.0)
{
m_pulse_width = 100;
m_pulse_width = 1;
m_wave_select &= ~WAVE_PULSE;
}
else
Expand Down
1 change: 1 addition & 0 deletions src/devices/sound/cem3394.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class cem3394_device : public device_t, public device_sound_interface
double m_filter_frequency; // baseline filter frequency
double m_filter_modulation; // depth of modulation (up to 1.0)
double m_filter_resonance; // depth of modulation (up to 1.0)
double m_filter_osc_position; // current filter self-oscillation position (always < 1.0)
double m_filter_in[4]; // filter input history
double m_filter_out[4]; // filter output history

Expand Down
Loading