diff options
Diffstat (limited to 'src/emu/sound/speaker.c')
| -rw-r--r-- | src/emu/sound/speaker.c | 74 |
1 files changed, 37 insertions, 37 deletions
diff --git a/src/emu/sound/speaker.c b/src/emu/sound/speaker.c index 67b3e24b0f8..deb1ebc55e6 100644 --- a/src/emu/sound/speaker.c +++ b/src/emu/sound/speaker.c @@ -6,16 +6,16 @@ driven by one or more output bits Original author: (unsigned) - Filtering: Anders Hallström + Filtering: Anders Hallstr?m ****************************************************************************/ -/* Discussion of oversampling and anti-alias filtering: (Anders Hallström) +/* Discussion of oversampling and anti-alias filtering: (Anders Hallstr?m) * * This driver is for machines that directly control * one or more simple digital-to-analog converters (DAC) * connected to one or more audio outputs (such as analog amp + speaker). * Currently only 1-bit DAC is supported via the interface to this module. - * + * * Frequently such machines would oversample the DAC * in order to overcome the limited DAC resolution. * For faithful reproduction of the sound, this must be carefully handled @@ -94,9 +94,9 @@ struct _speaker_state int level; /* The volume of a composed sample grows incrementally each time the speaker is over-sampled. - * That is in effect a basic average filter. - * Another filter can and will be applied to the array of composed samples. - */ + * That is in effect a basic average filter. + * Another filter can and will be applied to the array of composed samples. + */ double composed_volume[FILTER_LENGTH]; /* integrator(s) */ int composed_sample_index; /* array index for composed_volume */ attoseconds_t channel_sample_period; /* in as */ @@ -159,25 +159,25 @@ static DEVICE_START( speaker ) sp->next_interm_sample_time = attotime_add_attoseconds(sp->channel_last_sample_time, sp->interm_sample_period); sp->interm_sample_index = 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. - */ + * it is good if the speaker time synchronizes itself with the stream timing regularly. + */ /* Compute filter kernel; */ /* (Done for each device though the data is shared... - * No problem really, but should be done as part of system init if I knew how) - */ + * No problem really, but should be done as part of system init if I knew how) + */ #if 1 /* This is an approximated sinc (a perfect sinc makes an ideal low-pass filter). - * FILTER_STEP determines the cutoff frequency, - * which should be below the Nyquist freq, i.e. half the sample rate. - * Smaller step => kernel extends in time domain => lower cutoff freq - * In this case, with sinc, filter step PI corresponds to the Nyq. freq. - * Since we do not get a perfect filter => must lower the cutoff freq some more. - * For example, step PI/(2*RATE_MULTIPLIER) corresponds to cutoff freq = sample rate / 4; - * With -samplerate 48000, cutoff freq is ca 12kHz while the Nyq. freq is 24kHz. - * With -samplerate 96000, cutoff freq is ca 24kHz while the Nyq. freq is 48kHz. - * For a steeper, more efficient filter, increase FILTER_LENGTH at the expense of CPU usage. - */ + * FILTER_STEP determines the cutoff frequency, + * which should be below the Nyquist freq, i.e. half the sample rate. + * Smaller step => kernel extends in time domain => lower cutoff freq + * In this case, with sinc, filter step PI corresponds to the Nyq. freq. + * Since we do not get a perfect filter => must lower the cutoff freq some more. + * For example, step PI/(2*RATE_MULTIPLIER) corresponds to cutoff freq = sample rate / 4; + * With -samplerate 48000, cutoff freq is ca 12kHz while the Nyq. freq is 24kHz. + * With -samplerate 96000, cutoff freq is ca 24kHz while the Nyq. freq is 48kHz. + * For a steeper, more efficient filter, increase FILTER_LENGTH at the expense of CPU usage. + */ #define FILTER_STEP (M_PI / 2 / RATE_MULTIPLIER) /* Distribute symmetrically on x axis; center has x=0 if length is odd */ for (i = 0, x = (0.5 - FILTER_LENGTH / 2.) * FILTER_STEP; @@ -191,9 +191,9 @@ static DEVICE_START( speaker ) } #else /* Trivial average filter with poor frequency cutoff properties; - * First zero (frequency where amplification=0) = sample rate / filter length - * Cutoff frequency approx <= first zero / 2 - */ + * First zero (frequency where amplification=0) = sample rate / filter length + * Cutoff frequency approx <= first zero / 2 + */ for (i = 0, i < FILTER_LENGTH; i++) ampl[i] = 1; #endif @@ -219,9 +219,9 @@ static STREAM_UPDATE( speaker_sound_update ) sampled_time = attotime_mul(sampled_time, samples); /* Note: since the stream is in the process of being updated, - * stream_get_time() will return the time before the update! (MAME 0.130) - * Avoid using it here in order to avoid a subtle dependence on the stream implementation. - */ + * stream_get_time() will return the time before the update! (MAME 0.130) + * Avoid using it here in order to avoid a subtle dependence on the stream implementation. + */ } if (samples-- > 0) @@ -277,16 +277,16 @@ void speaker_level_w(const device_config *device, int new_level) return; } /* 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() - */ + * that we can add at least one complete sample to the stream. + * The details have to be handled by speaker_sound_update() + */ /* Force streams.c to update sound until this point in time now */ stream_update(sp->channel); /* This is redundant because time update has to be done within speaker_sound_update() anyway, - * however this ensures synchronization between the speaker and stream timing: - */ + * however this ensures synchronization between the speaker and stream timing: + */ sp->channel_last_sample_time = stream_get_time(sp->channel); sp->channel_next_sample_time = attotime_add_attoseconds(sp->channel_last_sample_time, sp->channel_sample_period); sp->next_interm_sample_time = attotime_add_attoseconds(sp->channel_last_sample_time, sp->interm_sample_period); @@ -316,9 +316,9 @@ static void update_interm_samples(speaker_state *sp, attotime time, int volume) init_next_interm_sample(sp); } /* Depending on status above: - * a) Add latest fraction to unfinished composed sample - * b) The overshooting fraction of time will start a new composed sample - */ + * a) Add latest fraction to unfinished composed sample + * b) The overshooting fraction of time will start a new composed sample + */ fraction = make_fraction(time, sp->last_update_time, sp->interm_sample_period_secfrac); sp->composed_volume[sp->composed_sample_index] += volume * fraction; sp->last_update_time = time; @@ -357,8 +357,8 @@ static void finalize_interm_sample(speaker_state *sp, int volume) double fraction; /* Fill the composed sample up if it was incomplete */ - fraction = make_fraction(sp->next_interm_sample_time, - sp->last_update_time, + fraction = make_fraction(sp->next_interm_sample_time, + sp->last_update_time, sp->interm_sample_period_secfrac); sp->composed_volume[sp->composed_sample_index] += volume * fraction; /* Update time state */ @@ -395,7 +395,7 @@ static double get_filtered_volume(speaker_state *sp) double filtered_volume = 0; double ampsum = 0; int i, c; - + /* Filter over composed samples (each composed sample is already average filtered) */ for (i = sp->composed_sample_index + 1, c = 0; c < FILTER_LENGTH; i++, c++) { |
