disound: Create m_specified_inputs_mask to track which inputs have been specified.

dac: Various improvements:
- Default to output range -1..1, by far the most common case
- Detect if inputs are specified and use those for output range

leland: Update to leverage new DAC capabilities.
This commit is contained in:
Aaron Giles 2020-10-18 00:07:26 -07:00
parent 52c739b434
commit eceffb4828
6 changed files with 75 additions and 72 deletions

View File

@ -91,8 +91,8 @@ dac_device_base::dac_device_base(const machine_config &mconfig, device_type type
m_bits(bits),
m_mapper(mapper),
m_gain(gain),
m_vref_base(0),
m_vref_range(0)
m_range_min(-1.0),
m_range_max(1.0)
{
}
@ -108,12 +108,10 @@ void dac_device_base::device_start()
m_value_map[code] = m_mapper(code, m_bits) * m_gain;
// determine the number of inputs
int inputs = 0;
if (m_vref_range == 0)
inputs += 2;
int inputs = (m_specified_inputs_mask == 0) ? 0 : 2;
// create the stream
m_stream = stream_alloc(inputs, 1, 48000 * 4, STREAM_DISABLE_INPUT_RESAMPLING);
m_stream = stream_alloc(inputs, 1, 48000 * 4);
// save data
save_item(NAME(m_curval));
@ -131,25 +129,31 @@ void dac_device_base::sound_stream_update(sound_stream &stream, std::vector<read
// rails are constant
if (inputs.size() == 0)
{
out.fill(m_vref_base + m_curval * m_vref_range);
out.fill(m_range_min + m_curval * (m_range_max - m_range_min));
return;
}
auto &pos = inputs[DAC_VREF_POS_INPUT];
auto &neg = inputs[DAC_VREF_NEG_INPUT];
auto &hi = inputs[DAC_INPUT_RANGE_HI];
auto &lo = inputs[DAC_INPUT_RANGE_LO];
// rails are streams but effectively constant
if (pos.sample_rate() == SAMPLE_RATE_MINIMUM && neg.sample_rate() == SAMPLE_RATE_MINIMUM)
out.fill(neg.get(0) + m_curval * (pos.get(0) - neg.get(0)));
// rails are streams matching our output rate
else if (pos.sample_rate() == out.sample_rate() && neg.sample_rate() == out.sample_rate())
// constant lo, streaming hi
if (!BIT(m_specified_inputs_mask, DAC_INPUT_RANGE_LO))
{
for (int sampindex = 0; sampindex < out.samples(); sampindex++)
out.put(sampindex, neg.get(sampindex) + m_curval * (pos.get(sampindex) - neg.get(sampindex)));
out.put(sampindex, m_range_min + m_curval * (hi.get(sampindex) - m_range_min));
}
// other cases not supported for now
// constant hi, streaming lo
else if (!BIT(m_specified_inputs_mask, DAC_INPUT_RANGE_HI))
{
for (int sampindex = 0; sampindex < out.samples(); sampindex++)
out.put(sampindex, lo.get(sampindex) + m_curval * (m_range_max - lo.get(sampindex)));
}
// both streams provided
else
throw emu_fatalerror("Unsupported case: DAC input rate does not match DAC output rate");
{
for (int sampindex = 0; sampindex < out.samples(); sampindex++)
out.put(sampindex, lo.get(sampindex) + m_curval * (hi.get(sampindex) - lo.get(sampindex)));
}
}

View File

@ -24,8 +24,11 @@
// CONSTANTS
//**************************************************************************
#define DAC_VREF_POS_INPUT (0)
#define DAC_VREF_NEG_INPUT (1)
#define DAC_INPUT_RANGE_HI (0)
#define DAC_INPUT_RANGE_LO (1)
#define DAC_VREF_POS_INPUT (DAC_INPUT_RANGE_HI)
#define DAC_VREF_NEG_INPUT (DAC_INPUT_RANGE_LO)
@ -100,14 +103,13 @@ protected:
public:
// configuration
dac_device_base &set_constant_vref(stream_buffer::sample_t vref1, stream_buffer::sample_t vref2)
dac_device_base &set_output_range(stream_buffer::sample_t range_min, stream_buffer::sample_t range_max)
{
if (vref1 > vref2)
std::swap(vref1, vref2);
m_vref_base = vref1;
m_vref_range = vref2 - vref1;
m_range_min = range_min;
m_range_max = range_max;
return *this;
}
dac_device_base &set_output_range(stream_buffer::sample_t vref) { return set_output_range(-vref, vref); }
private:
// internal state
@ -119,8 +121,8 @@ private:
u8 const m_bits;
dac_mapper_callback const m_mapper;
stream_buffer::sample_t const m_gain;
stream_buffer::sample_t m_vref_base;
stream_buffer::sample_t m_vref_range;
stream_buffer::sample_t m_range_min;
stream_buffer::sample_t m_range_max;
};
@ -128,11 +130,13 @@ private:
class dac_bit_device_base : public dac_device_base, public dac_bit_interface
{
public:
protected:
dac_bit_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bits, dac_mapper_callback mapper, stream_buffer::sample_t gain) :
dac_device_base(mconfig, type, tag, owner, clock, bits, mapper, gain)
{
}
public:
virtual WRITE_LINE_MEMBER(write) override { this->set_value(state); }
virtual void data_w(u8 data) override { this->set_value(data); }
};
@ -142,11 +146,13 @@ public:
class dac_byte_device_base : public dac_device_base, public dac_byte_interface
{
public:
protected:
dac_byte_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bits, dac_mapper_callback mapper, stream_buffer::sample_t gain) :
dac_device_base(mconfig, type, tag, owner, clock, bits, mapper, gain)
{
}
public:
virtual void write(u8 data) override { this->set_value(data); }
virtual void data_w(u8 data) override { this->set_value(data); }
};
@ -156,11 +162,13 @@ public:
class dac_word_device_base : public dac_device_base, public dac_word_interface
{
public:
protected:
dac_word_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bits, dac_mapper_callback mapper, stream_buffer::sample_t gain) :
dac_device_base(mconfig, type, tag, owner, clock, bits, mapper, gain)
{
}
public:
virtual void write(u16 data) override { this->set_value(data); }
virtual void data_w(u16 data) override { this->set_value(data); }
};

View File

@ -21,10 +21,11 @@
// device_sound_interface - constructor
//-------------------------------------------------
device_sound_interface::device_sound_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "sound")
, m_outputs(0)
, m_auto_allocated_inputs(0)
device_sound_interface::device_sound_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "sound"),
m_outputs(0),
m_auto_allocated_inputs(0),
m_specified_inputs_mask(0)
{
}
@ -292,10 +293,15 @@ void device_sound_interface::interface_pre_start()
// scan each route on the device
for (sound_route const &route : sound.routes())
{
// see if we are the target of this route; if we are, make sure the source device is started
device_t *const target_device = route.m_base.get().subdevice(route.m_target.c_str());
if ((target_device == &device()) && !sound.device().started())
throw device_missing_dependencies();
if (target_device == &device())
{
// see if we are the target of this route; if we are, make sure the source device is started
if (!sound.device().started())
throw device_missing_dependencies();
if (route.m_input != AUTO_ALLOC_INPUT)
m_specified_inputs_mask |= 1 << route.m_input;
}
}
}
@ -308,7 +314,7 @@ void device_sound_interface::interface_pre_start()
{
// see if we are the target of this route
device_t *const target_device = route.m_base.get().subdevice(route.m_target.c_str());
if ((target_device == &device()) && (route.m_input == AUTO_ALLOC_INPUT))
if (target_device == &device() && route.m_input == AUTO_ALLOC_INPUT)
{
route.m_input = m_auto_allocated_inputs;
m_auto_allocated_inputs += (route.m_output == ALL_OUTPUTS) ? sound.outputs() : 1;
@ -339,7 +345,7 @@ void device_sound_interface::interface_post_start()
int inputnum = route.m_input;
int const numoutputs = sound.outputs();
for (int outputnum = 0; outputnum < numoutputs; outputnum++)
if ((route.m_output == outputnum) || (route.m_output == ALL_OUTPUTS))
if (route.m_output == outputnum || route.m_output == ALL_OUTPUTS)
{
// find the output stream to connect from
int streamoutputnum;
@ -440,7 +446,7 @@ void device_mixer_interface::interface_pre_start()
{
// see if we are the target of this route
device_t *const target_device = route.m_base.get().subdevice(route.m_target.c_str());
if ((target_device == &device()) && (route.m_input < m_auto_allocated_inputs))
if (target_device == &device() && route.m_input < m_auto_allocated_inputs)
{
int const count = (route.m_output == ALL_OUTPUTS) ? sound.outputs() : 1;
for (int output = 0; output < count; output++)

View File

@ -109,6 +109,7 @@ protected:
std::vector<sound_route> m_route_list; // list of sound routes
int m_outputs; // number of outputs from this instance
int m_auto_allocated_inputs; // number of auto-allocated inputs targeting us
u32 m_specified_inputs_mask; // mask of inputs explicitly specified (not counting auto-allocated)
};
// iterator

View File

@ -145,20 +145,15 @@ void leland_80186_sound_device::device_add_mconfig(machine_config &config)
m_audiocpu->tmrout0_handler().set(FUNC(leland_80186_sound_device::i80186_tmr0_w));
SPEAKER(config, "speaker").front_center();
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
for (int i = 0; i < 6; i++)
{
AD7524(config, m_dac[i], 0).add_route(ALL_OUTPUTS, "speaker", 0.2); // 74hc374.u31..6 + ad7524.u46..51
DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0); // 74hc374.u17..22 + rX2-rX9 (24k,12k,6.2k,3k,1.5k,750,360,160) where X is 0..5
m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_VREF_POS_INPUT);
m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, m_dacvol[i], 1.0, DAC_VREF_POS_INPUT);
DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0).set_output_range(0, 1); // 74hc374.u17..22 + rX2-rX9 (24k,12k,6.2k,3k,1.5k,750,360,160) where X is 0..5
m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_INPUT_RANGE_HI);
m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_INPUT_RANGE_LO);
}
AD7533(config, "dac9", 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // ad7533.u64
vref.add_route(0, "dac9", 1.0, DAC_VREF_POS_INPUT);
vref.add_route(0, "dac9", -1.0, DAC_VREF_NEG_INPUT);
PIT8254(config, m_pit[0], 0);
m_pit[0]->set_clk<0>(4000000);
m_pit[0]->out_handler<0>().set(m_audiocpu, FUNC(i80186_cpu_device::drq0_w));
@ -186,14 +181,12 @@ void redline_80186_sound_device::device_add_mconfig(machine_config &config)
m_audiocpu->chip_select_callback().set(FUNC(leland_80186_sound_device::peripheral_ctrl));
SPEAKER(config, "speaker").front_center();
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
for (int i = 0; i < 8; i++)
{
AD7524(config, m_dac[i], 0).add_route(ALL_OUTPUTS, "speaker", 0.2); // unknown DAC
DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0);
m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_VREF_POS_INPUT);
m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_VREF_NEG_INPUT); // unknown DAC
vref.add_route(0, m_dacvol[i], 1.0, DAC_VREF_POS_INPUT);
DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0).set_output_range(0, 1);
m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_INPUT_RANGE_HI);
m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_INPUT_RANGE_LO); // unknown DAC
}
PIT8254(config, m_pit[0], 0);
@ -229,20 +222,15 @@ void ataxx_80186_sound_device::device_add_mconfig(machine_config &config)
m_audiocpu->tmrout0_handler().set(FUNC(leland_80186_sound_device::i80186_tmr0_w));
SPEAKER(config, "speaker").front_center();
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
for (int i = 0; i < 4; i++)
{
AD7524(config, m_dac[i], 0).add_route(ALL_OUTPUTS, "speaker", 0.2); // unknown DAC
DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0); // unknown DAC
m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_VREF_POS_INPUT);
m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_VREF_NEG_INPUT);
vref.add_route(0, m_dacvol[i], 1.0, DAC_VREF_POS_INPUT);
DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0).set_output_range(0, 1); // unknown DAC
m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_INPUT_RANGE_HI);
m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_INPUT_RANGE_LO);
}
AD7533(config, "dac9", 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // unknown DAC
vref.add_route(0, "dac9", 1.0, DAC_VREF_POS_INPUT);
vref.add_route(0, "dac9", -1.0, DAC_VREF_NEG_INPUT);
PIT8254(config, m_pit[0], 0);
m_pit[0]->set_clk<0>(4000000);
m_pit[0]->out_handler<0>().set(m_audiocpu, FUNC(i80186_cpu_device::drq0_w));
@ -264,18 +252,14 @@ void wsf_80186_sound_device::device_add_mconfig(machine_config &config)
m_audiocpu->tmrout1_handler().set(FUNC(leland_80186_sound_device::i80186_tmr1_w));
SPEAKER(config, "speaker").front_center();
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
for (int i = 0; i < 4; i++)
{
AD7524(config, m_dac[i], 0).add_route(ALL_OUTPUTS, "speaker", 0.2); // unknown DAC
DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0); // unknown DAC
m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_VREF_POS_INPUT);
m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_VREF_NEG_INPUT); // unknown DAC
vref.add_route(0, m_dacvol[i], 1.0, DAC_VREF_POS_INPUT);
DAC_8BIT_BINARY_WEIGHTED(config, m_dacvol[i], 0).set_output_range(0, 1); // unknown DAC
m_dacvol[i]->add_route(0, m_dac[i], 1.0, DAC_INPUT_RANGE_HI);
m_dacvol[i]->add_route(0, m_dac[i], -1.0, DAC_INPUT_RANGE_LO); // unknown DAC
}
AD7533(config, "dac9", 0).add_route(ALL_OUTPUTS, "speaker", 1.0); // unknown DAC
vref.add_route(0, "dac9", 1.0, DAC_VREF_POS_INPUT);
vref.add_route(0, "dac9", -1.0, DAC_VREF_NEG_INPUT);
/* sound hardware */
YM2151(config, m_ymsnd, 4000000);

View File

@ -1560,7 +1560,7 @@ void williams_state::williams_base(machine_config &config)
// sound hardware
SPEAKER(config, "speaker").front_center();
MC1408(config, "dac", 0).set_constant_vref(-1.0, 1.0).add_route(ALL_OUTPUTS, "speaker", 0.25); // mc1408.ic6
MC1408(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25); // mc1408.ic6
// pia
INPUT_MERGER_ANY_HIGH(config, "mainirq").output_handler().set_inputline(m_maincpu, M6809_IRQ_LINE);
@ -1768,8 +1768,8 @@ void blaster_state::blaster(machine_config &config)
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
MC1408(config, "ldac", 0).set_constant_vref(-1.0, 1.0).add_route(ALL_OUTPUTS, "lspeaker", 0.25); // unknown DAC
MC1408(config, "rdac", 0).set_constant_vref(-1.0, 1.0).add_route(ALL_OUTPUTS, "rspeaker", 0.25); // unknown DAC
MC1408(config, "ldac", 0).add_route(ALL_OUTPUTS, "lspeaker", 0.25); // unknown DAC
MC1408(config, "rdac", 0).add_route(ALL_OUTPUTS, "rspeaker", 0.25); // unknown DAC
}
@ -1804,7 +1804,7 @@ void williams2_state::williams2_base(machine_config &config)
// sound hardware
SPEAKER(config, "speaker").front_center();
MC1408(config, "dac", 0).set_constant_vref(-1.0, 1.0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
MC1408(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
INPUT_MERGER_ANY_HIGH(config, "mainirq").output_handler().set_inputline(m_maincpu, M6809_IRQ_LINE);
INPUT_MERGER_ANY_HIGH(config, "soundirq").output_handler().set_inputline(m_soundcpu, M6808_IRQ_LINE);