diff options
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 |
commit | c1bd56f0d318c71faac757d89c910c2682af6651 (patch) | |
tree | 9f4bbe78f74401a13603d89b6314c67fbd68a3f5 /src/devices/machine | |
parent | a3572727bd862176aa7458a84e2e9664c9d3f918 (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.cpp | 6 | ||||
-rw-r--r-- | src/devices/machine/8364_paula.h | 2 | ||||
-rw-r--r-- | src/devices/machine/acorn_vidc.cpp | 2 | ||||
-rw-r--r-- | src/devices/machine/laserdsc.cpp | 6 | ||||
-rw-r--r-- | src/devices/machine/laserdsc.h | 2 | ||||
-rw-r--r-- | src/devices/machine/netlist.cpp | 60 | ||||
-rw-r--r-- | src/devices/machine/netlist.h | 23 | ||||
-rw-r--r-- | src/devices/machine/s2636.cpp | 6 | ||||
-rw-r--r-- | src/devices/machine/s2636.h | 2 | ||||
-rw-r--r-- | src/devices/machine/spg2xx_audio.cpp | 4 | ||||
-rw-r--r-- | src/devices/machine/spg2xx_audio.h | 2 |
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); |