summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaronsgiles@users.noreply.github.com>2020-10-17 05:22:58 -0700
committer GitHub <noreply@github.com>2020-10-17 08:22:58 -0400
commit522dc72d2cdedaac147cac239d93112050d15e5c (patch)
tree2b722357456c949f3c02cdee84750fc063b821af
parentf9deebb78103f9c3ab6d2688b21ed9ca4f92ff5f (diff)
dac/volt_reg: improve performance (#7274)
* dac/volt_reg: improve performance * modify dac to accept streams of any input rate to avoid resampling * modify dac to assume input voltage streams are constant by only grabbing the first input sample * modify volt_reg to output at the minimum sample rate * dac: Restructure the DAC sound devices a bit * centralize implementation based on lookup tables * add set_constant_vref() method for the common case where references are constant, thus avoiding the need for voltage regulator devices * convert williams.cpp to using this new method as a test
-rw-r--r--src/devices/sound/dac.cpp135
-rw-r--r--src/devices/sound/dac.h365
-rw-r--r--src/devices/sound/volt_reg.cpp2
-rw-r--r--src/emu/sound.cpp1
-rw-r--r--src/mame/audio/leland.h2
-rw-r--r--src/mame/drivers/williams.cpp19
6 files changed, 287 insertions, 237 deletions
diff --git a/src/devices/sound/dac.cpp b/src/devices/sound/dac.cpp
index c2dfe37ce0a..d6f40cff3ab 100644
--- a/src/devices/sound/dac.cpp
+++ b/src/devices/sound/dac.cpp
@@ -18,3 +18,138 @@
DEFINE_DEVICE_TYPE(_dac_type, _dac_class, _dac_shortname, _dac_description)
#include "dac.h"
+
+
+//-------------------------------------------------
+// dac_mapper_unsigned - map an unsigned value of
+// the given number of bits to a sample value
+//-------------------------------------------------
+
+stream_buffer::sample_t dac_mapper_unsigned(u32 input, u8 bits)
+{
+ stream_buffer::sample_t scale = 1.0 / stream_buffer::sample_t((bits > 1) ? (1 << bits) : 1);
+ input &= (1 << bits) - 1;
+ return stream_buffer::sample_t(input) * scale;
+}
+
+
+//-------------------------------------------------
+// dac_mapper_signed - map a signed value of
+// the given number of bits to a sample value
+//-------------------------------------------------
+
+stream_buffer::sample_t dac_mapper_signed(u32 input, u8 bits)
+{
+ return dac_mapper_unsigned(input ^ (1 << (bits - 1)), bits);
+}
+
+
+//-------------------------------------------------
+// dac_mapper_ones_complement - map a value where
+// the top bit indicates the lower bits should be
+// treated as a negative 1s complement
+//-------------------------------------------------
+
+stream_buffer::sample_t dac_mapper_ones_complement(u32 input, u8 bits)
+{
+ // this mapping assumes symmetric reference voltages,
+ // which is true for all existing cases
+ if (BIT(input, bits - 1))
+ return 0.5 - 0.5 * dac_mapper_unsigned(~input, bits - 1);
+ else
+ return 0.5 + 0.5 * dac_mapper_unsigned(input, bits - 1);
+}
+
+
+//-------------------------------------------------
+// dac_mapper_ones_complement - map a value where
+// the top bit is a sign bit and the lower bits
+// are absolute magnitude
+//-------------------------------------------------
+
+stream_buffer::sample_t dac_mapper_sign_magnitude(u32 input, u8 bits)
+{
+ // this mapping assumes symmetric reference voltages,
+ // which is true for all existing cases
+ if (BIT(input, bits - 1))
+ return 0.5 - 0.5 * dac_mapper_unsigned(input, bits - 1);
+ else
+ return 0.5 + 0.5 * dac_mapper_unsigned(input, bits - 1);
+}
+
+
+//-------------------------------------------------
+// dac_device_base - constructor
+//-------------------------------------------------
+
+dac_device_base::dac_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u8 bits, dac_mapper_callback mapper, stream_buffer::sample_t gain) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_sound_interface(mconfig, *this),
+ m_stream(nullptr),
+ m_curval(0),
+ m_value_map(1 << bits),
+ m_bits(bits),
+ m_mapper(mapper),
+ m_gain(gain),
+ m_vref_base(0),
+ m_vref_range(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device startup
+//-------------------------------------------------
+
+void dac_device_base::device_start()
+{
+ // precompute all gain-applied values
+ for (s32 code = 0; code < m_value_map.size(); code++)
+ 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;
+
+ // create the stream
+ m_stream = stream_alloc(inputs, 1, 48000 * 4, STREAM_DISABLE_INPUT_RESAMPLING);
+
+ // save data
+ save_item(NAME(m_curval));
+}
+
+
+//-------------------------------------------------
+// sound_stream_update - stream updates
+//-------------------------------------------------
+
+void dac_device_base::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
+{
+ auto &out = outputs[0];
+
+ // rails are constant
+ if (inputs.size() == 0)
+ {
+ out.fill(m_vref_base + m_curval * m_vref_range);
+ return;
+ }
+
+ auto &pos = inputs[DAC_VREF_POS_INPUT];
+ auto &neg = inputs[DAC_VREF_NEG_INPUT];
+
+ // 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())
+ {
+ for (int sampindex = 0; sampindex < out.samples(); sampindex++)
+ out.put(sampindex, neg.get(sampindex) + m_curval * (pos.get(sampindex) - neg.get(sampindex)));
+ }
+
+ // other cases not supported for now
+ else
+ throw emu_fatalerror("Unsupported case: DAC input rate does not match DAC output rate");
+}
diff --git a/src/devices/sound/dac.h b/src/devices/sound/dac.h
index 7a48ba80998..40e5315fc92 100644
--- a/src/devices/sound/dac.h
+++ b/src/devices/sound/dac.h
@@ -20,296 +20,221 @@
#include <type_traits>
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
#define DAC_VREF_POS_INPUT (0)
#define DAC_VREF_NEG_INPUT (1)
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+constexpr stream_buffer::sample_t dac_gain_r2r = 1.0;
+constexpr stream_buffer::sample_t dac_gain_bw = 2.0;
+
+
+// ======================> dac_mapper_callback
+
+using dac_mapper_callback = stream_buffer::sample_t (*)(u32 input, u8 bits);
+
+stream_buffer::sample_t dac_mapper_unsigned(u32 input, u8 bits);
+stream_buffer::sample_t dac_mapper_signed(u32 input, u8 bits);
+stream_buffer::sample_t dac_mapper_ones_complement(u32 input, u8 bits);
+stream_buffer::sample_t dac_mapper_sign_magnitude(u32 input, u8 bits);
+
+
+// ======================> dac_bit_interface
+
class dac_bit_interface
{
public:
virtual DECLARE_WRITE_LINE_MEMBER(write) = 0;
- virtual void data_w(uint8_t data) = 0;
+ virtual void data_w(u8 data) = 0;
};
+
+// ======================> dac_byte_interface
+
class dac_byte_interface
{
public:
- virtual void write(unsigned char data) = 0;
- virtual void data_w(uint8_t data) = 0;
+ virtual void write(u8 data) = 0;
+ virtual void data_w(u8 data) = 0;
};
+
+// ======================> dac_word_interface
+
class dac_word_interface
{
public:
- virtual void write(unsigned short data) = 0;
- virtual void data_w(uint16_t data) = 0;
+ virtual void write(u16 data) = 0;
+ virtual void data_w(u16) = 0;
};
-template <unsigned bits>
-constexpr stream_buffer::sample_t dac_multiply(const double vref, const s32 code)
-{
- constexpr stream_buffer::sample_t scale = 1.0 / stream_buffer::sample_t((bits > 1) ? (1 << (bits)) : 1);
- return vref * scale * stream_buffer::sample_t(code);
-}
-
-template <unsigned bits>
-class dac_code
-{
-protected:
- dac_code(double gain) :
- m_stream(nullptr),
- m_code(0),
- m_gain(gain)
- {
- }
-
- sound_stream * m_stream;
- s32 m_code;
- const double m_gain;
-
- inline void setCode(s32 code)
- {
- code &= ~(~u32(0) << bits);
- if (m_code != code)
- {
- m_stream->update();
- m_code = code;
- }
- }
- virtual void sound_stream_update_tag(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) = 0;
-};
+// ======================> dac_device_base
-template <unsigned bits>
-class dac_code_binary : protected dac_code<bits>
+class dac_device_base : public device_t, public device_sound_interface
{
protected:
- using dac_code<bits>::dac_code;
+ // constructor
+ dac_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u8 bits, dac_mapper_callback mapper, stream_buffer::sample_t gain);
- virtual void sound_stream_update_tag(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override
- {
- for (int samp = 0; samp < outputs[0].samples(); samp++)
- {
- double const vref_pos = inputs[DAC_VREF_POS_INPUT].get(samp) * this->m_gain;
- double const vref_neg = inputs[DAC_VREF_NEG_INPUT].get(samp) * this->m_gain;
- stream_buffer::sample_t const vout = vref_neg + dac_multiply<bits>(vref_pos - vref_neg, this->m_code);
- outputs[0].put(samp, vout);
- }
- }
-};
+ // device startup
+ virtual void device_start() override;
-template <unsigned bits>
-class dac_code_ones_complement : protected dac_code<bits>
-{
-protected:
- using dac_code<bits>::dac_code;
+ // stream generation
+ virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
- virtual void sound_stream_update_tag(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override
+ // set the current value
+ void set_value(u32 value)
{
- if (this->m_code & (1 << (bits - 1)))
- {
- for (int samp = 0; samp < outputs[0].samples(); samp++)
- {
- double const vref_neg = inputs[DAC_VREF_NEG_INPUT].get(samp) * this->m_gain;
- stream_buffer::sample_t const vout = dac_multiply<bits - 1>(vref_neg, this->m_code ^ ~(~0U << bits));
- outputs[0].put(samp, vout);
- }
- }
- else
- {
- for (int samp = 0; samp < outputs[0].samples(); samp++)
- {
- double const vref_pos = inputs[DAC_VREF_POS_INPUT].get(samp) * this->m_gain;
- stream_buffer::sample_t const vout = dac_multiply<bits - 1>(vref_pos, this->m_code);
- outputs[0].put(samp, vout);
- }
- }
+ m_stream->update();
+ m_curval = m_value_map[value & (m_value_map.size() - 1)];
}
-};
-template <unsigned bits>
-class dac_code_twos_complement : protected dac_code<bits>
-{
-protected:
- using dac_code<bits>::dac_code;
-
- virtual void sound_stream_update_tag(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override
+public:
+ // configuration
+ dac_device_base &set_constant_vref(stream_buffer::sample_t vref1, stream_buffer::sample_t vref2)
{
- for (int samp = 0; samp < outputs[0].samples(); samp++)
- {
- double const vref_pos = inputs[DAC_VREF_POS_INPUT].get(samp) * this->m_gain;
- double const vref_neg = inputs[DAC_VREF_NEG_INPUT].get(samp) * this->m_gain;
- stream_buffer::sample_t const vout = vref_neg + dac_multiply<bits>(vref_pos - vref_neg, this->m_code ^ (1 << (bits - 1)));
- outputs[0].put(samp, vout);
- }
+ if (vref1 > vref2)
+ std::swap(vref1, vref2);
+ m_vref_base = vref1;
+ m_vref_range = vref2 - vref1;
+ return *this;
}
-};
-
-template <unsigned bits>
-class dac_code_sign_magntitude : protected dac_code<bits>
-{
-protected:
- using dac_code<bits>::dac_code;
- virtual void sound_stream_update_tag(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override
- {
- if (this->m_code & (1 << (bits - 1)))
- {
- for (int samp = 0; samp < outputs[0].samples(); samp++)
- {
- double const vref_neg = inputs[DAC_VREF_NEG_INPUT].get(samp) * this->m_gain;
- stream_buffer::sample_t const vout = dac_multiply<bits - 1>(vref_neg, this->m_code ^ (1 << (bits - 1)));
- outputs[0].put(samp, vout);
- }
- }
- else
- {
- for (int samp = 0; samp < outputs[0].samples(); samp++)
- {
- double const vref_pos = inputs[DAC_VREF_POS_INPUT].get(samp) * this->m_gain;
- stream_buffer::sample_t const vout = dac_multiply<bits - 1>(vref_pos, this->m_code);
- outputs[0].put(samp, vout);
- }
- }
- }
+private:
+ // internal state
+ sound_stream *m_stream;
+ stream_buffer::sample_t m_curval;
+ std::vector<stream_buffer::sample_t> m_value_map;
+
+ // configuration state
+ 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;
};
-template <typename _dac_code>
-class dac_device : public device_t,
- public device_sound_interface,
- protected _dac_code
-{
-protected:
- dac_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, double gain) :
- device_t(mconfig, type, tag, owner, clock),
- device_sound_interface(mconfig, *this),
- _dac_code(gain)
- {
- }
-
- virtual void device_start() override
- {
- this->m_stream = stream_alloc(2, 1, 48000 * 4);
+// ======================> dac_bit_device_base
- save_item(NAME(this->m_code));
- }
-
- virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override
+class dac_bit_device_base : public dac_device_base, public dac_bit_interface
+{
+public:
+ 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)
{
- _dac_code::sound_stream_update_tag(stream, inputs, outputs);
}
+ virtual WRITE_LINE_MEMBER(write) override { this->set_value(state); }
+ virtual void data_w(u8 data) override { this->set_value(data); }
};
-template <typename dac_interface, typename _dac_code> class dac_generator;
-template <typename _dac_code>
-class dac_generator<dac_bit_interface, _dac_code> :
- public dac_bit_interface,
- public dac_device<_dac_code>
+// ======================> dac_byte_device_base
+
+class dac_byte_device_base : public dac_device_base, public dac_byte_interface
{
public:
- dac_generator(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, double gain) :
- dac_device<_dac_code>(mconfig, type, tag, owner, clock, gain)
+ 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)
{
}
-
- virtual WRITE_LINE_MEMBER(write) override { this->setCode(state); }
- virtual void data_w(uint8_t data) override { this->setCode(data); }
+ virtual void write(u8 data) override { this->set_value(data); }
+ virtual void data_w(u8 data) override { this->set_value(data); }
};
-template <typename _dac_code>
-class dac_generator<dac_byte_interface, _dac_code> :
- public dac_byte_interface,
- public dac_device<_dac_code>
-{
-public:
- dac_generator(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, double gain) :
- dac_device<_dac_code>(mconfig, type, tag, owner, clock, gain)
- {
- }
- virtual void write(unsigned char data) override { this->setCode(data); }
- virtual void data_w(uint8_t data) override { this->setCode(data); }
-};
+// ======================> dac_word_device_base
-template <typename _dac_code>
-class dac_generator<dac_word_interface, _dac_code> :
- public dac_word_interface,
- public dac_device<_dac_code>
+class dac_word_device_base : public dac_device_base, public dac_word_interface
{
public:
- dac_generator(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, double gain) :
- dac_device<_dac_code>(mconfig, type, tag, owner, clock, gain)
+ 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)
{
}
-
- virtual void write(unsigned short data) override { this->setCode(data); }
- virtual void data_w(uint16_t data) override { this->setCode(data); }
+ virtual void write(u16 data) override { this->set_value(data); }
+ virtual void data_w(u16 data) override { this->set_value(data); }
};
-constexpr double dac_gain_r2r = 1.0;
-constexpr double dac_gain_binary_weighted = 2.0;
+
+//**************************************************************************
+// DAC GENERATORS
+//**************************************************************************
+
+// epilog only defined in dac.cpp
#ifndef DAC_GENERATOR_EPILOG
#define DAC_GENERATOR_EPILOG(_dac_type, _dac_class, _dac_description, _dac_shortname)
#endif
-#define DAC_GENERATOR(_dac_type, _dac_class, _dac_interface, _dac_coding, _dac_gain, _dac_description, _dac_shortname) \
+#define DAC_GENERATOR(_dac_type, _dac_class, _dac_base_class, _dac_mapper, _dac_bits, _dac_gain, _dac_description, _dac_shortname) \
DECLARE_DEVICE_TYPE(_dac_type, _dac_class) \
-class _dac_class : public dac_generator<_dac_interface, _dac_coding> \
+class _dac_class : public _dac_base_class \
{\
public: \
_dac_class(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) : \
- dac_generator(mconfig, _dac_type, tag, owner, clock, _dac_gain) {} \
+ _dac_base_class(mconfig, _dac_type, tag, owner, clock, _dac_bits, _dac_mapper, _dac_gain) {} \
}; \
DAC_GENERATOR_EPILOG(_dac_type, _dac_class, _dac_description, _dac_shortname)
// DAC chips
-DAC_GENERATOR(AD557, ad557_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "AD557", "ad557")
-DAC_GENERATOR(AD558, ad558_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "AD558", "ad558")
-DAC_GENERATOR(AD7224, ad7224_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "AD7224", "ad7224")
-DAC_GENERATOR(AD7521, ad7521_device, dac_word_interface, dac_code_binary<12>, dac_gain_r2r, "AD7521", "ad7521")
-DAC_GENERATOR(AD7523, ad7523_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "AD7523", "ad7523")
-DAC_GENERATOR(AD7524, ad7524_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "AD7524", "ad7524")
-DAC_GENERATOR(AD7528, ad7528_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "AD7528", "ad7528") /// 2 x vin + 2 x vout
-DAC_GENERATOR(AD7533, ad7533_device, dac_word_interface, dac_code_binary<10>, dac_gain_r2r, "AD7533", "ad7533")
-DAC_GENERATOR(AD7541, ad7541_device, dac_word_interface, dac_code_binary<12>, dac_gain_r2r, "AD7541", "ad7541")
-DAC_GENERATOR(AM6012, am6012_device, dac_word_interface, dac_code_binary<12>, dac_gain_r2r, "AM6012", "am6012")
-DAC_GENERATOR(DAC08, dac08_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "DAC08", "dac08")
-DAC_GENERATOR(DAC0800, dac0800_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "DAC0800", "dac0800")
-DAC_GENERATOR(DAC0832, dac0832_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "DAC0832", "dac0832") // should be double-buffered?
-DAC_GENERATOR(DAC1200, dac1200_device, dac_word_interface, dac_code_binary<12>, dac_gain_r2r, "DAC1200", "dac1200")
-DAC_GENERATOR(MC1408, mc1408_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "MC1408", "mc1408")
-DAC_GENERATOR(MC3408, mc3408_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "MC3408", "mc3408")
-DAC_GENERATOR(MC3410, mc3410_device, dac_word_interface, dac_code_binary<10>, dac_gain_r2r, "MC3410", "mc3410")
-DAC_GENERATOR(MP1210, mp1210_device, dac_word_interface, dac_code_twos_complement<12>, dac_gain_r2r, "MP1210", "mp1210") // also addressable with separate 8-bit and 4-bit input latches
-DAC_GENERATOR(PCM54HP, pcm54hp_device, dac_word_interface, dac_code_binary<16>, dac_gain_r2r, "PCM54HP", "pcm54hp")
-DAC_GENERATOR(UDA1341TS, uda1341ts_device, dac_word_interface, dac_code_twos_complement<16>, dac_gain_r2r, "UDA1341TS", "uda1341ts") // I2C stereo audio codec
-DAC_GENERATOR(ZN425E, zn425e_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "ZN425E", "zn425e")
-DAC_GENERATOR(ZN426E, zn426e_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "ZN426E-8", "zn426e")
-DAC_GENERATOR(ZN428E, zn428e_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "ZN428E-8", "zn428e")
-DAC_GENERATOR(ZN429E, zn429e_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "ZN429E-8", "zn429e")
+DAC_GENERATOR(AD557, ad557_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "AD557 DAC", "ad557")
+DAC_GENERATOR(AD558, ad558_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "AD558 DAC", "ad558")
+DAC_GENERATOR(AD7224, ad7224_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "AD7224 DAC", "ad7224")
+DAC_GENERATOR(AD7521, ad7521_device, dac_word_device_base, dac_mapper_unsigned, 12, dac_gain_r2r, "AD7521 DAC", "ad7521")
+DAC_GENERATOR(AD7523, ad7523_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "AD7523 DAC", "ad7523")
+DAC_GENERATOR(AD7524, ad7524_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "AD7524 DAC", "ad7524")
+DAC_GENERATOR(AD7528, ad7528_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "AD7528 DAC", "ad7528") // 2 x vin + 2 x vout
+DAC_GENERATOR(AD7533, ad7533_device, dac_word_device_base, dac_mapper_unsigned, 10, dac_gain_r2r, "AD7533 DAC", "ad7533")
+DAC_GENERATOR(AD7541, ad7541_device, dac_word_device_base, dac_mapper_unsigned, 12, dac_gain_r2r, "AD7541 DAC", "ad7541")
+DAC_GENERATOR(AM6012, am6012_device, dac_word_device_base, dac_mapper_unsigned, 12, dac_gain_r2r, "AM6012 DAC", "am6012")
+DAC_GENERATOR(DAC08, dac08_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "DAC08 DAC", "dac08")
+DAC_GENERATOR(DAC0800, dac0800_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "DAC0800 DAC", "dac0800")
+DAC_GENERATOR(DAC0832, dac0832_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "DAC0832 DAC", "dac0832") // should be double-buffered?
+DAC_GENERATOR(DAC1200, dac1200_device, dac_word_device_base, dac_mapper_unsigned, 12, dac_gain_r2r, "DAC1200 DAC", "dac1200")
+DAC_GENERATOR(MC1408, mc1408_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "MC1408 DAC", "mc1408")
+DAC_GENERATOR(MC3408, mc3408_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "MC3408 DAC", "mc3408")
+DAC_GENERATOR(MC3410, mc3410_device, dac_word_device_base, dac_mapper_unsigned, 10, dac_gain_r2r, "MC3410 DAC", "mc3410")
+DAC_GENERATOR(MP1210, mp1210_device, dac_word_device_base, dac_mapper_signed, 12, dac_gain_r2r, "MP1210 DAC", "mp1210") // also addressable with separate 8-bit and 4-bit input latches
+DAC_GENERATOR(PCM54HP, pcm54hp_device, dac_word_device_base, dac_mapper_unsigned, 16, dac_gain_r2r, "PCM54HP DAC", "pcm54hp")
+DAC_GENERATOR(UDA1341TS, uda1341ts_device, dac_word_device_base, dac_mapper_signed, 16, dac_gain_r2r, "UDA1341TS DAC", "uda1341ts") // I2C stereo audio codec
+DAC_GENERATOR(ZN425E, zn425e_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "ZN425E DAC", "zn425e")
+DAC_GENERATOR(ZN426E, zn426e_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "ZN426E-8 DAC", "zn426e")
+DAC_GENERATOR(ZN428E, zn428e_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "ZN428E-8 DAC", "zn428e")
+DAC_GENERATOR(ZN429E, zn429e_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "ZN429E-8 DAC", "zn429e")
// DAC circuits/unidentified chips
-DAC_GENERATOR(DAC_1BIT, dac_1bit_device, dac_bit_interface, dac_code_binary<1>, 1.0, "1-Bit DAC", "dac")
-DAC_GENERATOR(DAC_2BIT_BINARY_WEIGHTED, dac_2bit_binary_weighted_device, dac_byte_interface, dac_code_binary<2>, dac_gain_binary_weighted, "2-Bit Binary Weighted DAC", "dac_2bit_bw")
-DAC_GENERATOR(DAC_2BIT_BINARY_WEIGHTED_ONES_COMPLEMENT, dac_2bit_binary_weighted_ones_complement_device, dac_byte_interface, dac_code_ones_complement<2>, dac_gain_binary_weighted, "2-Bit Binary Weighted Ones Complement DAC", "dac_2bit_bw_oc")
-DAC_GENERATOR(DAC_2BIT_R2R, dac_2bit_r2r_device, dac_byte_interface, dac_code_binary<2>, dac_gain_r2r, "2-Bit R-2R DAC", "dac_2bit_r2r")
-DAC_GENERATOR(DAC_3BIT_BINARY_WEIGHTED, dac_3bit_binary_weighted_device, dac_byte_interface, dac_code_binary<3>, dac_gain_binary_weighted, "3-Bit Binary Weighted DAC", "dac_3bit_bw")
-DAC_GENERATOR(DAC_4BIT_BINARY_WEIGHTED, dac_4bit_binary_weighted_device, dac_byte_interface, dac_code_binary<4>, dac_gain_binary_weighted, "4-Bit Binary Weighted DAC", "dac_4bit_bw")
-DAC_GENERATOR(DAC_4BIT_BINARY_WEIGHTED_SIGN_MAGNITUDE, dac_4bit_binary_weighted_sign_magnitude_device, dac_byte_interface, dac_code_sign_magntitude<4>, dac_gain_binary_weighted, "4-Bit Binary Weighted Sign Magnitude DAC", "dac_4bit_bw_sm")
-DAC_GENERATOR(DAC_4BIT_R2R, dac_4bit_r2r_device, dac_byte_interface, dac_code_binary<4>, dac_gain_r2r, "4-Bit R-2R DAC", "dac_4bit_r2r")
-DAC_GENERATOR(DAC_6BIT_BINARY_WEIGHTED, dac_6bit_binary_weighted_device, dac_byte_interface, dac_code_binary<6>, dac_gain_binary_weighted, "6-Bit Binary Weighted DAC", "dac_6bit_bw")
-DAC_GENERATOR(DAC_6BIT_R2R, dac_6bit_r2r_device, dac_byte_interface, dac_code_binary<6>, dac_gain_r2r, "6-Bit R-2R DAC", "dac_6bit_r2r")
-DAC_GENERATOR(DAC_8BIT_BINARY_WEIGHTED, dac_binary_weighted_8bit_device, dac_byte_interface, dac_code_binary<8>, dac_gain_binary_weighted, "8-Bit Binary Weighted DAC", "dac_8bit_bw")
-DAC_GENERATOR(DAC_8BIT_PWM, dac_8bit_pwm_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "8-Bit PWM DAC", "dac_8bit_pwm")
-DAC_GENERATOR(DAC_8BIT_R2R, dac_8bit_r2r_device, dac_byte_interface, dac_code_binary<8>, dac_gain_r2r, "8-Bit R-2R DAC", "dac_8bit_r2r")
-DAC_GENERATOR(DAC_8BIT_R2R_TWOS_COMPLEMENT, dac_8bit_r2r_twos_complement_device, dac_byte_interface, dac_code_twos_complement<8>, dac_gain_r2r, "8-Bit R-2R Twos Complement DAC", "dac_8bit_r2r_tc")
-DAC_GENERATOR(DAC_10BIT_R2R, dac_10bit_r2r_device, dac_word_interface, dac_code_binary<10>, dac_gain_r2r, "10-Bit R-2R DAC", "dac_10bit_r2r")
-DAC_GENERATOR(DAC_12BIT_R2R, dac_12bit_r2r_device, dac_word_interface, dac_code_binary<12>, dac_gain_r2r, "12-Bit R-2R DAC", "dac_12bit_r2r")
-DAC_GENERATOR(DAC_12BIT_R2R_TWOS_COMPLEMENT, dac_12bit_r2r_twos_complement_device, dac_word_interface, dac_code_twos_complement<12>, dac_gain_r2r, "12-Bit R-2R Twos Complement DAC", "dac_12bit_r2r_tc")
-DAC_GENERATOR(DAC_16BIT_R2R, dac_16bit_r2r_device, dac_word_interface, dac_code_binary<16>, dac_gain_r2r, "16-Bit R-2R DAC", "dac_16bit_r2r")
-DAC_GENERATOR(DAC_16BIT_R2R_TWOS_COMPLEMENT, dac_16bit_r2r_twos_complement_device, dac_word_interface, dac_code_twos_complement<16>, dac_gain_r2r, "16-Bit R-2R Twos Complement DAC", "dac_16bit_r2r_tc")
+DAC_GENERATOR(DAC_1BIT, dac_1bit_device, dac_bit_device_base, dac_mapper_unsigned, 1, 1.0, "1-Bit DAC", "dac")
+DAC_GENERATOR(DAC_2BIT_BINARY_WEIGHTED, dac_2bit_binary_weighted_device, dac_byte_device_base, dac_mapper_unsigned, 2, dac_gain_bw, "2-Bit Binary Weighted DAC", "dac_2bit_bw")
+DAC_GENERATOR(DAC_2BIT_R2R, dac_2bit_r2r_device, dac_byte_device_base, dac_mapper_unsigned, 2, dac_gain_r2r, "2-Bit R-2R DAC", "dac_2bit_r2r")
+DAC_GENERATOR(DAC_3BIT_BINARY_WEIGHTED, dac_3bit_binary_weighted_device, dac_byte_device_base, dac_mapper_unsigned, 3, dac_gain_bw, "3-Bit Binary Weighted DAC", "dac_3bit_bw")
+DAC_GENERATOR(DAC_4BIT_BINARY_WEIGHTED, dac_4bit_binary_weighted_device, dac_byte_device_base, dac_mapper_unsigned, 4, dac_gain_bw, "4-Bit Binary Weighted DAC", "dac_4bit_bw")
+DAC_GENERATOR(DAC_4BIT_R2R, dac_4bit_r2r_device, dac_byte_device_base, dac_mapper_unsigned, 4, dac_gain_r2r, "4-Bit R-2R DAC", "dac_4bit_r2r")
+DAC_GENERATOR(DAC_6BIT_BINARY_WEIGHTED, dac_6bit_binary_weighted_device, dac_byte_device_base, dac_mapper_unsigned, 6, dac_gain_bw, "6-Bit Binary Weighted DAC", "dac_6bit_bw")
+DAC_GENERATOR(DAC_6BIT_R2R, dac_6bit_r2r_device, dac_byte_device_base, dac_mapper_unsigned, 6, dac_gain_r2r, "6-Bit R-2R DAC", "dac_6bit_r2r")
+DAC_GENERATOR(DAC_8BIT_BINARY_WEIGHTED, dac_8bit_binary_weighted_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_bw, "8-Bit Binary Weighted DAC", "dac_8bit_bw")
+DAC_GENERATOR(DAC_8BIT_PWM, dac_8bit_pwm_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "8-Bit PWM DAC", "dac_8bit_pwm")
+DAC_GENERATOR(DAC_8BIT_R2R, dac_8bit_r2r_device, dac_byte_device_base, dac_mapper_unsigned, 8, dac_gain_r2r, "8-Bit R-2R DAC", "dac_8bit_r2r")
+DAC_GENERATOR(DAC_8BIT_R2R_TWOS_COMPLEMENT, dac_8bit_r2r_twos_complement_device, dac_byte_device_base, dac_mapper_signed, 8, dac_gain_r2r, "8-Bit R-2R Twos Complement DAC", "dac_8bit_r2r_tc")
+DAC_GENERATOR(DAC_10BIT_R2R, dac_10bit_r2r_device, dac_word_device_base, dac_mapper_unsigned, 10, dac_gain_r2r, "10-Bit R-2R DAC", "dac_10bit_r2r")
+DAC_GENERATOR(DAC_12BIT_R2R, dac_12bit_r2r_device, dac_word_device_base, dac_mapper_unsigned, 12, dac_gain_r2r, "12-Bit R-2R DAC", "dac_12bit_r2r")
+DAC_GENERATOR(DAC_12BIT_R2R_TWOS_COMPLEMENT, dac_12bit_r2r_twos_complement_device, dac_word_device_base, dac_mapper_signed, 12, dac_gain_r2r, "12-Bit R-2R Twos Complement DAC", "dac_12bit_r2r_tc")
+DAC_GENERATOR(DAC_16BIT_R2R, dac_16bit_r2r_device, dac_word_device_base, dac_mapper_unsigned, 16, dac_gain_r2r, "16-Bit R-2R DAC", "dac_16bit_r2r")
+DAC_GENERATOR(DAC_16BIT_R2R_TWOS_COMPLEMENT, dac_16bit_r2r_twos_complement_device, dac_word_device_base, dac_mapper_signed, 16, dac_gain_r2r, "16-Bit R-2R Twos Complement DAC", "dac_16bit_r2r_tc")
+
+// special odd cases -- are these real?
+DAC_GENERATOR(DAC_2BIT_BINARY_WEIGHTED_ONES_COMPLEMENT, dac_2bit_binary_weighted_ones_complement_device, dac_byte_device_base, dac_mapper_ones_complement, 2, dac_gain_bw, "2-Bit Binary Weighted Ones Complement DAC", "dac_2bit_bw_oc")
+DAC_GENERATOR(DAC_4BIT_BINARY_WEIGHTED_SIGN_MAGNITUDE, dac_4bit_binary_weighted_sign_magnitude_device, dac_byte_device_base, dac_mapper_sign_magnitude, 4, dac_gain_bw, "4-Bit Binary Weighted Sign Magnitude DAC", "dac_4bit_bw_sm")
+
#undef DAC_GENERATOR
#undef DAC_GENERATOR_EPILOG
diff --git a/src/devices/sound/volt_reg.cpp b/src/devices/sound/volt_reg.cpp
index 48693204e46..14ccdfaab16 100644
--- a/src/devices/sound/volt_reg.cpp
+++ b/src/devices/sound/volt_reg.cpp
@@ -27,7 +27,7 @@ voltage_regulator_device::voltage_regulator_device(const machine_config &mconfig
void voltage_regulator_device::device_start()
{
- m_stream = stream_alloc(0, 1, SAMPLE_RATE_OUTPUT_ADAPTIVE);
+ m_stream = stream_alloc(0, 1, SAMPLE_RATE_MINIMUM);
}
void voltage_regulator_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
diff --git a/src/emu/sound.cpp b/src/emu/sound.cpp
index 8063db03959..eaf640a3e57 100644
--- a/src/emu/sound.cpp
+++ b/src/emu/sound.cpp
@@ -744,6 +744,7 @@ read_stream_view sound_stream::update_view(attotime start, attotime end, u32 out
m_input_view[inputnum] = m_input[inputnum].update(update_start, end);
else
m_input_view[inputnum] = empty_view(update_start, end);
+ sound_assert(m_input_view[inputnum].samples() > 0);
sound_assert(m_resampling_disabled || m_input_view[inputnum].sample_rate() == m_sample_rate);
}
diff --git a/src/mame/audio/leland.h b/src/mame/audio/leland.h
index d6dd4176dae..09eb3b96319 100644
--- a/src/mame/audio/leland.h
+++ b/src/mame/audio/leland.h
@@ -61,7 +61,7 @@ protected:
required_device<generic_latch_16_device> m_soundlatch;
optional_device_array<dac_byte_interface, 8> m_dac;
optional_device<dac_word_interface> m_dac9;
- optional_device_array<dac_binary_weighted_8bit_device, 8> m_dacvol;
+ optional_device_array<dac_8bit_binary_weighted_device, 8> m_dacvol;
optional_device_array<pit8254_device, 3> m_pit;
optional_device<i80186_cpu_device> m_audiocpu;
optional_device<ym2151_device> m_ymsnd;
diff --git a/src/mame/drivers/williams.cpp b/src/mame/drivers/williams.cpp
index a47f2195678..4d11cae9d88 100644
--- a/src/mame/drivers/williams.cpp
+++ b/src/mame/drivers/williams.cpp
@@ -496,7 +496,6 @@ Reference videos: https://www.youtube.com/watch?v=R5OeC6Wc_yI
#include "machine/input_merger.h"
#include "machine/nvram.h"
#include "sound/dac.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
@@ -1561,10 +1560,7 @@ void williams_state::williams_base(machine_config &config)
// sound hardware
SPEAKER(config, "speaker").front_center();
- MC1408(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25); // mc1408.ic6
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
+ MC1408(config, "dac", 0).set_constant_vref(-1.0, 1.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);
@@ -1769,15 +1765,11 @@ void blaster_state::blaster(machine_config &config)
// sound hardware
config.device_remove("speaker");
config.device_remove("dac");
- config.device_remove("vref");
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
- 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
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "ldac", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "ldac", -1.0, DAC_VREF_NEG_INPUT);
- vref.add_route(0, "rdac", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "rdac", -1.0, DAC_VREF_NEG_INPUT);
+ 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
}
@@ -1812,10 +1804,7 @@ void williams2_state::williams2_base(machine_config &config)
// sound hardware
SPEAKER(config, "speaker").front_center();
- MC1408(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
+ MC1408(config, "dac", 0).set_constant_vref(-1.0, 1.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);