summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/spkrdev.cpp
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2021-04-04 21:38:26 +0200
committer hap <happppp@users.noreply.github.com>2021-04-04 21:38:38 +0200
commit17c64fa3727e728bf0c3ebb3cc9722e70601a1e1 (patch)
tree8a8a50cf4e7bfb4a806f5cbc3d86ef69c5457d24 /src/devices/sound/spkrdev.cpp
parent5a63d0e7380985786e87a49704761b1f6226983e (diff)
spkrdev: fix regression with filtering
Diffstat (limited to 'src/devices/sound/spkrdev.cpp')
-rw-r--r--src/devices/sound/spkrdev.cpp64
1 files changed, 27 insertions, 37 deletions
diff --git a/src/devices/sound/spkrdev.cpp b/src/devices/sound/spkrdev.cpp
index b33e4ee5520..03694c84b3e 100644
--- a/src/devices/sound/spkrdev.cpp
+++ b/src/devices/sound/spkrdev.cpp
@@ -53,11 +53,11 @@
* Virtual stream 2: Intermediate representation.
* Sample rate = RATE_MULTIPLIER * stream 3 sample rate.
* If effective rate of stream 1 exceeds rate of stream 2,
- * some aliasing distorsion is introduced in this step because the average filtering is a compromise.
- * The distorsion is however mostly in the higher frequencies.
+ * some aliasing distortion is introduced in this step because the average filtering is a compromise.
+ * The distortion is however mostly in the higher frequencies.
* -> low-pass anti-alias filtering with kernel ampl[] ->
* -> down-sampling ->
- * Actual stream 3: channel output generated by speaker_sound_update().
+ * Actual stream 3: channel output generated by sound_stream_update().
* Sample rate = device sample rate = configured "-samplerate".
*
* In the speaker_state data structure,
@@ -77,7 +77,7 @@
static constexpr double default_levels[2] = {0.0, 1.0};
-// Internal oversampling factor (interm. samples vs stream samples)
+// Internal oversampling factor (intermediate samples vs stream samples)
static constexpr int RATE_MULTIPLIER = 4;
@@ -109,16 +109,17 @@ void speaker_sound_device::device_start()
m_composed_volume[i] = 0;
m_composed_sample_index = 0;
+ m_interm_sample_index = 0;
+ m_prevx = m_prevy = 0.0;
+
m_last_update_time = machine().time();
m_channel_sample_period = HZ_TO_ATTOSECONDS(machine().sample_rate());
m_channel_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_channel_sample_period);
m_interm_sample_period = m_channel_sample_period / RATE_MULTIPLIER;
m_interm_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_interm_sample_period);
- m_channel_last_sample_time = m_channel->sample_time();
+ m_channel_last_sample_time = m_last_update_time;
m_channel_next_sample_time = m_channel_last_sample_time + attotime(0, m_channel_sample_period);
m_next_interm_sample_time = m_channel_last_sample_time + attotime(0, m_interm_sample_period);
- m_interm_sample_index = 0;
- m_prevx = m_prevy = 0.0;
/* Note: To avoid time drift due to floating point inaccuracies,
* it is good if the speaker time synchronizes itself with the stream timing regularly.
@@ -172,23 +173,7 @@ void speaker_sound_device::device_start()
void speaker_sound_device::device_reset()
{
- int i;
-
m_level = 0;
- for (i = 0; i < FILTER_LENGTH; i++)
- m_composed_volume[i] = 0;
-
- m_composed_sample_index = 0;
- m_last_update_time = machine().time();
- m_channel_sample_period = HZ_TO_ATTOSECONDS(machine().sample_rate());
- m_channel_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_channel_sample_period);
- m_interm_sample_period = m_channel_sample_period / RATE_MULTIPLIER;
- m_interm_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_interm_sample_period);
- m_channel_last_sample_time = m_channel->sample_time();
- m_channel_next_sample_time = m_channel_last_sample_time + attotime(0, m_channel_sample_period);
- m_next_interm_sample_time = m_channel_last_sample_time + attotime(0, m_interm_sample_period);
- m_interm_sample_index = 0;
- m_prevx = m_prevy = 0.0;
}
void speaker_sound_device::device_post_load()
@@ -224,7 +209,7 @@ void speaker_sound_device::sound_stream_update(sound_stream &stream, std::vector
for (int sampindex = 0; sampindex < buffer.samples(); )
{
- /* Note that first interm. sample may be composed... */
+ /* Note that first intermediate sample may be composed... */
filtered_volume = update_interm_samples_get_filtered_volume(volume);
/* Composite volume is now quantized to the stream resolution */
@@ -249,7 +234,7 @@ void speaker_sound_device::sound_stream_update(sound_stream &stream, std::vector
void speaker_sound_device::level_w(int new_level)
{
- int volume;
+ double volume;
attotime time;
if (new_level == m_level)
@@ -266,7 +251,7 @@ void speaker_sound_device::level_w(int new_level)
if (time < m_channel_next_sample_time)
{
- /* Stream sample is yet unfinished, but we may have one or more interm. samples */
+ /* Stream sample is yet unfinished, but we may have one or more intermediate samples */
update_interm_samples(time, volume);
/* Do not forget to update speaker state before returning! */
@@ -275,23 +260,28 @@ void speaker_sound_device::level_w(int new_level)
}
/* Reaching here means such time has passed since last stream update
* that we can add at least one complete sample to the stream.
- * The details have to be handled by speaker_sound_update()
+ * The details have to be handled by sound_stream_update()
*/
- /* Force streams.c to update sound until this point in time now */
+ /* Force stream to update sound until this point in time now */
m_channel->update();
- /* This is redundant because time update has to be done within speaker_sound_update() anyway,
+ /* This is redundant because time update has to be done within sound_stream_update() anyway,
* however this ensures synchronization between the speaker and stream timing:
*/
m_channel_last_sample_time = m_channel->sample_time();
+
+ /* sample_time() may be ahead of us */
+ if (m_channel_last_sample_time > time)
+ m_channel_last_sample_time -= attotime(0, m_channel_sample_period);
+
m_channel_next_sample_time = m_channel_last_sample_time + attotime(0, m_channel_sample_period);
m_next_interm_sample_time = m_channel_last_sample_time + attotime(0, m_interm_sample_period);
m_last_update_time = m_channel_last_sample_time;
/* Assertion: time - last_update_time < channel_sample_period, i.e. time < channel_next_sample_time */
- /* The overshooting fraction of time will make zero, one or more interm. samples: */
+ /* The overshooting fraction of time will make zero, one or more intermediate samples: */
update_interm_samples(time, volume);
/* Finally update speaker state before returning */
@@ -299,14 +289,14 @@ void speaker_sound_device::level_w(int new_level)
}
-void speaker_sound_device::update_interm_samples(const attotime &time, int volume)
+void speaker_sound_device::update_interm_samples(const attotime &time, double volume)
{
double fraction;
- /* We may have completed zero, one or more interm. samples: */
+ /* We may have completed zero, one or more intermediate samples: */
while (time >= m_next_interm_sample_time)
{
- /* First interm. sample may be composed, subsequent samples will be homogeneous. */
+ /* First intermediate sample may be composed, subsequent samples will be homogeneous. */
/* Treat all the same general way. */
finalize_interm_sample(volume);
init_next_interm_sample();
@@ -325,20 +315,20 @@ double speaker_sound_device::update_interm_samples_get_filtered_volume(double vo
{
double filtered_volume, tempx;
- /* We may have one or more interm. samples to go */
+ /* We may have one or more intermediate samples to go */
if (m_interm_sample_index < RATE_MULTIPLIER)
{
- /* First interm. sample may be composed. */
+ /* First intermediate sample may be composed. */
finalize_interm_sample(volume);
- /* Subsequent interm. samples will be homogeneous. */
+ /* Subsequent intermediate samples will be homogeneous. */
while (m_interm_sample_index + 1 < RATE_MULTIPLIER)
{
init_next_interm_sample();
m_composed_volume[m_composed_sample_index] = volume;
}
}
- /* Important: next interm. sample not initialised yet, so that no data is destroyed before filtering... */
+ /* Important: next intermediate sample not initialised yet, so that no data is destroyed before filtering... */
filtered_volume = get_filtered_volume();
init_next_interm_sample();
/* Reset counter to next stream sample: */