[Scummvm-cvs-logs] SF.net SVN: scummvm: [28008] scummvm/branches/gsoc2007-mixer/sound/rate.cpp
dogmatixman at users.sourceforge.net
dogmatixman at users.sourceforge.net
Tue Jul 10 16:23:48 CEST 2007
Revision: 28008
http://scummvm.svn.sourceforge.net/scummvm/?rev=28008&view=rev
Author: dogmatixman
Date: 2007-07-10 07:23:48 -0700 (Tue, 10 Jul 2007)
Log Message:
-----------
Added some gain control so that audio volumes from the filtering resampler are about the same as from the other ones.
Modified Paths:
--------------
scummvm/branches/gsoc2007-mixer/sound/rate.cpp
Modified: scummvm/branches/gsoc2007-mixer/sound/rate.cpp
===================================================================
--- scummvm/branches/gsoc2007-mixer/sound/rate.cpp 2007-07-10 13:25:54 UTC (rev 28007)
+++ scummvm/branches/gsoc2007-mixer/sound/rate.cpp 2007-07-10 14:23:48 UTC (rev 28008)
@@ -310,6 +310,15 @@
/* The number of channels of audio */
uint8 numChan;
+
+ /*
+ * Used to adjust the DC filter gain, for the case of positive
+ * reinforcement in the output when the filter coefficients are negative.
+ */
+ double kFudgeFactor;
+
+ /* The maximum DC gain across all subfilters */
+ double filtGain;
public:
FilteringRateConverter(st_rate_t inrate, st_rate_t outrate);
@@ -350,11 +359,39 @@
/* TODO: Fix this. */
/* At this point I don't have any code appending 0s in this case */
- assert((len % subLen) == 0);
+ assert((len % subLen) == 0);
+ /* Find the DC gain of each subfilter */
+ double *gain = (double *)calloc(numBanks, sizeof(double));
+
+ uint16 i;
+ for (i = 0; i < len; i++) {
+ /*
+ * Using the commented-out line and setting kFudgeFactor to 1 will
+ * ensure that no clipping will occur, but this makes output volumes
+ * softer than those of other resamplers using otherwise equal
+ * options.
+ */
+ //gain[i % numBanks] += fabs((filt->getCoeffs())[i]);
+ gain[i % numBanks] += (filt->getCoeffs())[i];
+ }
+
+ /* Find the maximum of these subfilter gains */
+ filtGain = 0;
+
+ for (i = 0; i < numBanks; i++) {
+ if (gain[i] > filtGain) {
+ filtGain = gain[i];
+ }
+ }
+
+ free(gain);
+
+ // TODO: Empirically determined -- is there some reasoned approximation?
+ kFudgeFactor = 0.75;
+
numChan = (stereo ? 2 : 1);
- /* Two channel of audio */
inBuf = (st_sample_t *)calloc(numChan * subLen, sizeof(st_sample_t));
inPos = 0;
@@ -406,14 +443,44 @@
}
}
- st_sample_t out0 = (st_sample_t)(accum0);
- st_sample_t out1 = (st_sample_t)(stereo ? accum1 : accum0);
+ /*
+ * Cancel out the gain effects of the filter (approximated -- if we
+ * ensure that there can be no clipping at all, the volume is far
+ * softer than the other resamplers produce)
+ */
+ double out0 = kFudgeFactor * accum0 / filtGain;
+ double out1 = kFudgeFactor * (stereo ? accum1 : accum0) / filtGain;
+ /* Check for clipping and clamp values in these cases */
+ if (fmax(out0, out1) > ST_SAMPLE_MAX) {
+ debug(1, "Clipping: sample value is %g (should be maximally %g)", fmax(out0, out1), (double)ST_SAMPLE_MAX);
+
+ if (out0 > ST_SAMPLE_MAX) {
+ out0 = ST_SAMPLE_MAX;
+ }
+ if (out1 > ST_SAMPLE_MAX) {
+ out1 = ST_SAMPLE_MAX;
+ }
+ }
+
+ if (fmin(out0, out1) < ST_SAMPLE_MIN) {
+ debug(1, "Clipping: sample value is %g (should be minimally %g)", fmin(out0, out1), (double)ST_SAMPLE_MIN);
+ if (out0 < ST_SAMPLE_MIN) {
+ out0 = ST_SAMPLE_MIN;
+ }
+ if (out1 < ST_SAMPLE_MIN) {
+ out1 = ST_SAMPLE_MIN;
+ }
+ }
+
+ assert(fmax(out0, out1) <= ST_SAMPLE_MAX);
+ assert(fmin(out0, out1) >= ST_SAMPLE_MIN);
+
/* Output left channel */
- clampedAdd(obuf[reverseStereo ], (out0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
+ clampedAdd(obuf[reverseStereo ], ((st_sample_t)out0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
/* output right channel */
- clampedAdd(obuf[reverseStereo ^ 1], (out1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
+ clampedAdd(obuf[reverseStereo ^ 1], ((st_sample_t)out1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
obuf += 2;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list