summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine
diff options
context:
space:
mode:
author Aaron Giles <aaronsgiles@users.noreply.github.com>2020-09-13 10:18:44 -0700
committer GitHub <noreply@github.com>2020-09-13 10:18:44 -0700
commitc1bd56f0d318c71faac757d89c910c2682af6651 (patch)
tree9f4bbe78f74401a13603d89b6314c67fbd68a3f5 /src/devices/machine
parenta3572727bd862176aa7458a84e2e9664c9d3f918 (diff)
Significant internal changes to sound streams (#7169)
Significant internal changes to sound streams: Abstracted buffers of sound data into an internal stream_buffer class, with helper classes read_stream_view and write_stream_view which offer readable/writable "views" into the buffers Internal sound calculations are all done using stream_buffer::sample_t, which is a 32-bit float; existing callbacks are supported through an adapter that converts to/from signed 32-bit integers Improved behavior of dynamic stream sample rate changes to resample a short runway of data to preserve continuity across transitions Created a new stream update callback which passes a std::vector of read_stream_views for inputs, and a std::vector of write_stream_views for outputs Updated core mixer and speaker devices to the new stream update callback Updated the following sound cores to the new stream update callback: ay8910, dac, k054539, msm5205, namco, netlist, okim6295, pokey, samples, sn76496, sp0250, tms5220, tms57002, upd7759, vgm_visualizer, volt_reg Changed existing stream update callback to make inputs explicitly const and the output pointers const as well, since they are re-used across calls; fixed several engines that violated this rule Sound_manager::stream_alloc can no longer automatically connect to a device's sound_stream_update callback; instead, the stream_alloc() on the sound_device_interface should be called; updated many violators of this rule Streams can be created with SAMPLE_RATE_OUTPUT_ADAPTIVE, which dynamically tracks the sample rate of its first downstream output, or with SAMPLE_RATE_INPUT_ADAPTIVE, which tracks the sample rate of its first input Changed resampling to be a separate sound_stream that is invoked as needed, opening the path for selectable resampling implementations Added a flags parameter to the new stream allocation method that allows you to specify a that input streams should not be resampled Exposed stream_input and stream_output classes directly, simplifying access to user gains and stream names Added a simple dynamic compressor to sound_manager to provide nicer results when overdriven sound happens; compression does not affect speaker_report results Improved verbose speaker_report to print a graph of peaks over time More aggressive debugging enabled for now even in release builds (should be disabled prior to next release) via SOUND_DEBUG define in sound.h; report any assertions for fixing
Diffstat (limited to 'src/devices/machine')
-rw-r--r--src/devices/machine/8364_paula.cpp6
-rw-r--r--src/devices/machine/8364_paula.h2
-rw-r--r--src/devices/machine/acorn_vidc.cpp2
-rw-r--r--src/devices/machine/laserdsc.cpp6
-rw-r--r--src/devices/machine/laserdsc.h2
-rw-r--r--src/devices/machine/netlist.cpp60
-rw-r--r--src/devices/machine/netlist.h23
-rw-r--r--src/devices/machine/s2636.cpp6
-rw-r--r--src/devices/machine/s2636.h2
-rw-r--r--src/devices/machine/spg2xx_audio.cpp4
-rw-r--r--src/devices/machine/spg2xx_audio.h2
11 files changed, 61 insertions, 54 deletions
diff --git a/src/devices/machine/8364_paula.cpp b/src/devices/machine/8364_paula.cpp
index a340b5a523c..1e10ca55b3e 100644
--- a/src/devices/machine/8364_paula.cpp
+++ b/src/devices/machine/8364_paula.cpp
@@ -58,7 +58,7 @@ void paula_8364_device::device_start()
}
// create the stream
- m_stream = machine().sound().stream_alloc(*this, 0, 4, clock() / CLOCK_DIVIDER);
+ m_stream = stream_alloc_legacy(0, 4, clock() / CLOCK_DIVIDER);
}
//-------------------------------------------------
@@ -159,10 +159,10 @@ void paula_8364_device::dma_reload(audio_channel *chan)
}
//-------------------------------------------------
-// sound_stream_update - handle a stream update
+// sound_stream_update_legacy - handle a stream update
//-------------------------------------------------
-void paula_8364_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void paula_8364_device::sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples)
{
int channum, sampoffs = 0;
diff --git a/src/devices/machine/8364_paula.h b/src/devices/machine/8364_paula.h
index 0a7016c4496..a2ac2feab26 100644
--- a/src/devices/machine/8364_paula.h
+++ b/src/devices/machine/8364_paula.h
@@ -68,7 +68,7 @@ protected:
virtual void device_start() override;
// sound stream update overrides
- virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+ virtual void sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples) override;
private:
enum
diff --git a/src/devices/machine/acorn_vidc.cpp b/src/devices/machine/acorn_vidc.cpp
index 65487e2b63a..36733555e7d 100644
--- a/src/devices/machine/acorn_vidc.cpp
+++ b/src/devices/machine/acorn_vidc.cpp
@@ -416,7 +416,7 @@ inline void acorn_vidc10_device::refresh_stereo_image(u8 channel)
m_lspeaker->set_input_gain(channel,left_gain[m_stereo_image[channel]]*m_sound_input_gain);
m_rspeaker->set_input_gain(channel,right_gain[m_stereo_image[channel]]*m_sound_input_gain);
- //printf("%d %f %f\n",channel,m_lspeaker->input_gain(channel),m_rspeaker->input_gain(channel));
+ //printf("%d %f %f\n",channel,m_lspeaker->input(channel).gain(),m_rspeaker->input(channel).gain());
}
diff --git a/src/devices/machine/laserdsc.cpp b/src/devices/machine/laserdsc.cpp
index 8176ac14f29..ef3df359859 100644
--- a/src/devices/machine/laserdsc.cpp
+++ b/src/devices/machine/laserdsc.cpp
@@ -308,11 +308,11 @@ void laserdisc_device::device_timer(emu_timer &timer, device_timer_id id, int pa
//-------------------------------------------------
-// sound_stream_update - audio streamer for
+// sound_stream_update_legacy - audio streamer for
// laserdiscs
//-------------------------------------------------
-void laserdisc_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void laserdisc_device::sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples)
{
// compute AND values based on the squelch
int16_t leftand = (m_audiosquelch & 1) ? 0x0000 : 0xffff;
@@ -762,7 +762,7 @@ void laserdisc_device::init_audio()
m_audio_callback.resolve();
// allocate a stream
- m_stream = stream_alloc(0, 2, 48000);
+ m_stream = stream_alloc_legacy(0, 2, 48000);
// allocate audio buffers
m_audiomaxsamples = ((uint64_t)m_samplerate * 1000000 + m_fps_times_1million - 1) / m_fps_times_1million;
diff --git a/src/devices/machine/laserdsc.h b/src/devices/machine/laserdsc.h
index e2877a4a216..8ca3abad222 100644
--- a/src/devices/machine/laserdsc.h
+++ b/src/devices/machine/laserdsc.h
@@ -220,7 +220,7 @@ protected:
virtual void device_validity_check(validity_checker &valid) const override;
// device_sound_interface overrides
- virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+ virtual void sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples) override;
// subclass helpers
void set_audio_squelch(bool squelchleft, bool squelchright) { m_stream->update(); m_audiosquelch = (squelchleft ? 1 : 0) | (squelchright ? 2 : 0); }
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp
index 10208d8e357..988c21c33e1 100644
--- a/src/devices/machine/netlist.cpp
+++ b/src/devices/machine/netlist.cpp
@@ -263,7 +263,7 @@ plib::istream_uptr netlist_data_memregions_t::stream(const pstring &name)
// sound_in
// ----------------------------------------------------------------------------------------
-using sound_in_type = netlist::interface::NETLIB_NAME(buffered_param_setter)<stream_sample_t *>;
+using sound_in_type = netlist::interface::NETLIB_NAME(buffered_param_setter)<netlist_mame_sound_input_buffer>;
class NETLIB_NAME(sound_in) : public sound_in_type
{
@@ -820,17 +820,15 @@ void netlist_mame_stream_output_device::device_reset()
#endif
}
-void netlist_mame_stream_output_device::sound_update_fill(std::size_t samples, stream_sample_t *target)
+void netlist_mame_stream_output_device::sound_update_fill(write_stream_view &target)
{
- if (samples < m_buffer.size())
- osd_printf_warning("sound %s: samples %d less bufsize %d\n", name(), samples, m_buffer.size());
+ if (target.samples() < m_buffer.size())
+ osd_printf_warning("sound %s: samples %d less bufsize %d\n", name(), target.samples(), m_buffer.size());
- std::copy(m_buffer.begin(), m_buffer.end(), target);
- std::size_t pos = m_buffer.size();
- while (pos < samples)
- {
- target[pos++] = m_cur;
- }
+ int sampindex;
+ for (sampindex = 0; sampindex < m_buffer.size(); sampindex++)
+ target.put(sampindex, m_buffer[sampindex]);
+ target.fill(m_cur, sampindex);
}
@@ -868,19 +866,10 @@ void netlist_mame_stream_output_device::process(netlist::netlist_time_ext tim, n
// throw emu_fatalerror("sound %s: pos %d exceeded bufsize %d\n", name().c_str(), pos, m_bufsize);
while (m_buffer.size() < pos )
{
- m_buffer.push_back(static_cast<stream_sample_t>(m_cur));
+ m_buffer.push_back(static_cast<stream_buffer::sample_t>(m_cur));
}
- // clamp to avoid spikes, but not too hard, as downstream processing, volume
- // controls, etc may bring values above 32767 back down in range; some clamping
- // is still useful, however, as the mixing is done with integral values
- if (plib::abs(val) < 32767.0*256.0)
- m_cur = val;
- else if (val > 0.0)
- m_cur = 32767.0*256.0;
- else
- m_cur = -32767.0*256.0;
-
+ m_cur = val;
}
@@ -1409,8 +1398,10 @@ void netlist_mame_sound_device::device_start()
if (e.first < 0 || e.first >= m_in.size())
fatalerror("illegal input channel number %d", e.first);
}
+ m_inbuffer.resize(m_in.size());
+
/* initialize the stream(s) */
- m_stream = machine().sound().stream_alloc(*this, m_in.size(), m_out.size(), m_sound_clock);
+ m_stream = stream_alloc(m_in.size(), m_out.size(), m_sound_clock, STREAM_DISABLE_INPUT_RESAMPLING);
LOGDEVCALLS("sound device_start exit\n");
}
@@ -1453,26 +1444,25 @@ void netlist_mame_sound_device::update_to_current_time()
LOGTIMING("%s : %f us before machine time\n", this->name(), (cur - mtime).as_double() * 1000000.0);
}
-void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
- const auto mtime = machine().time();
- if (mtime < m_last_update_to_current_time)
- LOGTIMING("machine.time() decreased 1\n");
- m_last_update_to_current_time = mtime;
- LOGDEBUG("samples %d\n", samples);
-
for (auto &e : m_in)
{
- auto sample_time = netlist::netlist_time::from_raw(static_cast<netlist::netlist_time::internal_type>(nltime_from_attotime(m_attotime_per_clock).as_raw()));
- e.second->buffer_reset(sample_time, samples, &inputs[e.first]);
+ auto clock_period = inputs[e.first].sample_period();
+ auto sample_time = netlist::netlist_time::from_raw(static_cast<netlist::netlist_time::internal_type>(nltime_from_attotime(clock_period).as_raw()));
+ m_inbuffer[e.first] = netlist_mame_sound_input_buffer(inputs[e.first]);
+ e.second->buffer_reset(sample_time, m_inbuffer[e.first].samples(), &m_inbuffer[e.first]);
}
- m_cur_time += (samples * m_attotime_per_clock);
+ int samples = outputs[0].samples();
+ LOGDEBUG("samples %d\n", samples);
- auto nl_target_time = std::min(nltime_from_attotime(mtime), nltime_from_attotime(m_cur_time));
+ // end_time() is the time at the END of the last sample we're generating
+ // however, the sample value is the value at the START of that last sample,
+ // so subtract one sample period so that we only process up to the minimum
+ auto nl_target_time = nltime_from_attotime(outputs[0].end_time() - outputs[0].sample_period());
auto nltime(netlist().exec().time());
-
if (nltime < nl_target_time)
{
netlist().exec().process_queue(nl_target_time - nltime);
@@ -1480,7 +1470,7 @@ void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream
for (auto &e : m_out)
{
- e.second->sound_update_fill(samples, outputs[e.first]);
+ e.second->sound_update_fill(outputs[e.first]);
e.second->buffer_reset(nl_target_time);
}
diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h
index b7a78c0bd77..8b9e156adba 100644
--- a/src/devices/machine/netlist.h
+++ b/src/devices/machine/netlist.h
@@ -229,6 +229,22 @@ private:
};
// ----------------------------------------------------------------------------------------
+// netlist_mame_sound_input_buffer
+// ----------------------------------------------------------------------------------------
+
+class netlist_mame_sound_input_buffer : public read_stream_view
+{
+public:
+ netlist_mame_sound_input_buffer() :
+ read_stream_view() { }
+
+ netlist_mame_sound_input_buffer(read_stream_view const &src) :
+ read_stream_view(src) { }
+
+ stream_buffer::sample_t operator[](std::size_t index) { return get(index); }
+};
+
+// ----------------------------------------------------------------------------------------
// netlist_mame_sound_device
// ----------------------------------------------------------------------------------------
@@ -266,13 +282,14 @@ protected:
// device_t overrides
virtual void device_start() override;
// device_sound_interface overrides
- virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+ virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual void device_validity_check(validity_checker &valid) const override;
//virtual void device_reset() override;
private:
std::map<int, netlist_mame_stream_output_device *> m_out;
std::map<std::size_t, nld_sound_in *> m_in;
+ std::vector<netlist_mame_sound_input_buffer> m_inbuffer;
sound_stream *m_stream;
attotime m_cur_time;
uint32_t m_sound_clock;
@@ -593,7 +610,7 @@ public:
m_buffer.clear();
}
- void sound_update_fill(std::size_t samples, stream_sample_t *target);
+ void sound_update_fill(write_stream_view &target);
void set_sample_time(netlist::netlist_time t) { m_sample_time = t; }
@@ -608,7 +625,7 @@ private:
uint32_t m_channel;
const char * m_out_name;
- std::vector<stream_sample_t> m_buffer;
+ std::vector<stream_buffer::sample_t> m_buffer;
double m_cur;
netlist::netlist_time m_sample_time;
diff --git a/src/devices/machine/s2636.cpp b/src/devices/machine/s2636.cpp
index ddc46adf81c..bdf95dc69d0 100644
--- a/src/devices/machine/s2636.cpp
+++ b/src/devices/machine/s2636.cpp
@@ -203,7 +203,7 @@ void s2636_device::device_start()
save_item(NAME(m_intreq));
save_item(NAME(m_intack));
- m_stream = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate());
+ m_stream = stream_alloc_legacy(0, 1, machine().sample_rate());
save_item(NAME(m_sample_cnt));
save_item(NAME(m_sound_lvl));
@@ -447,10 +447,10 @@ void s2636_device::write_intack(int state)
//-------------------------------------------------
-// sound_stream_update - generate audio output
+// sound_stream_update_legacy - generate audio output
//-------------------------------------------------
-void s2636_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void s2636_device::sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples)
{
stream_sample_t *buffer = outputs[0];
while (samples--)
diff --git a/src/devices/machine/s2636.h b/src/devices/machine/s2636.h
index bc82ed68903..b5e41b83499 100644
--- a/src/devices/machine/s2636.h
+++ b/src/devices/machine/s2636.h
@@ -58,7 +58,7 @@ protected:
virtual void device_start() override;
// sound stream update overrides
- virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+ virtual void sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples) override;
private:
enum
diff --git a/src/devices/machine/spg2xx_audio.cpp b/src/devices/machine/spg2xx_audio.cpp
index f1ffd871f28..07d01e88be5 100644
--- a/src/devices/machine/spg2xx_audio.cpp
+++ b/src/devices/machine/spg2xx_audio.cpp
@@ -76,7 +76,7 @@ void spg2xx_audio_device::device_start()
m_audio_beat = timer_alloc(TIMER_BEAT);
m_audio_beat->adjust(attotime::never);
- m_stream = stream_alloc(0, 2, 281250/4);
+ m_stream = stream_alloc_legacy(0, 2, 281250/4);
m_channel_debug = -1;
@@ -887,7 +887,7 @@ void spg2xx_audio_device::audio_w(offs_t offset, uint16_t data)
}
}
-void spg2xx_audio_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void spg2xx_audio_device::sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples)
{
stream_sample_t *out_l = outputs[0];
stream_sample_t *out_r = outputs[1];
diff --git a/src/devices/machine/spg2xx_audio.h b/src/devices/machine/spg2xx_audio.h
index 30b001edfb2..59d7635198d 100644
--- a/src/devices/machine/spg2xx_audio.h
+++ b/src/devices/machine/spg2xx_audio.h
@@ -33,7 +33,7 @@ public:
protected:
// sound stream update overrides
- virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+ virtual void sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples) override;
void audio_beat_tick();
void audio_rampdown_tick(const uint32_t channel);