summaryrefslogtreecommitdiffstats
path: root/libs/audioflinger
diff options
context:
space:
mode:
Diffstat (limited to 'libs/audioflinger')
-rw-r--r--libs/audioflinger/AudioDSP.cpp30
-rw-r--r--libs/audioflinger/AudioDSP.h2
2 files changed, 25 insertions, 7 deletions
diff --git a/libs/audioflinger/AudioDSP.cpp b/libs/audioflinger/AudioDSP.cpp
index d6b85ca..2a21d85 100644
--- a/libs/audioflinger/AudioDSP.cpp
+++ b/libs/audioflinger/AudioDSP.cpp
@@ -406,7 +406,8 @@ void EffectHeadphone::configure(const float samplingFrequency) {
mReverbDelayL.setParameters(mSamplingFrequency, 0.030f);
mReverbDelayR.setParameters(mSamplingFrequency, 0.030f);
/* the -3 dB point is around 650 Hz, giving about 300 us to work with */
- mLowpass.setHighShelf(850.0f, mSamplingFrequency, -10.0f, 0.72f);
+ mLocalizationL.setHighShelf(800.0f, mSamplingFrequency, -11.0f, 0.72f);
+ mLocalizationR.setHighShelf(800.0f, mSamplingFrequency, -11.0f, 0.72f);
/* Rockbox has a 0.3 ms delay line (13 samples at 44100 Hz), but
* I think it makes the whole effect sound pretty bad so I skipped it! */
}
@@ -437,6 +438,7 @@ void EffectHeadphone::process(int32_t* inout, int32_t frames)
/* 28 bits */
if (mDeep) {
+ /* Note: a pinking filter here would be good. */
dataL += mDelayDataR;
dataR += mDelayDataL;
}
@@ -460,13 +462,29 @@ void EffectHeadphone::process(int32_t* inout, int32_t frames)
dataL += dryL;
dataR += dryR;
- /* Lowpass filter difference to estimate head shadow. */
- int32_t diff = mLowpass.process((dataL - dataR) >> fixedPointDecimals);
+ /* In matrix decoding, center channel is mixed at 0.7 and the main channel at 1.
+ * It follows that the sum of them is 1.7, and the proportion of the main channel
+ * must be 1 / 1.7, or about 6/10. Assuming it is so, 4/10 is the contribution
+ * of center, and when 2 channels are combined, the scaler is 2/10 or 1/5.
+ *
+ * We could try to dynamically adjust this divisor based on cross-correlation
+ * between left/right channels, which would allow us to recover a reasonable
+ * estimate of the music's original center channel. */
+ int32_t center = (dataL + dataR) / 5;
+ int32_t directL = (dataL - center);
+ int32_t directR = (dataR - center);
+
+ /* We assume center channel reaches both ears with no coloration required.
+ * We could also handle it differently at reverb stage... */
+
+ /* Apply localization filter. */
+ int32_t localizedL = mLocalizationL.process(directL >> fixedPointDecimals);
+ int32_t localizedR = mLocalizationR.process(directR >> fixedPointDecimals);
/* 28 bits */
- /* Mix difference between channels. */
- inout[0] = dataL - (diff >> 1);
- inout[1] = dataR + (diff >> 1);
+ /* Mix difference between channels. dataX = directX + center. */
+ inout[0] = dataL + localizedR;
+ inout[1] = dataR + localizedL;
inout += 2;
}
}
diff --git a/libs/audioflinger/AudioDSP.h b/libs/audioflinger/AudioDSP.h
index a962ba7..2fed833 100644
--- a/libs/audioflinger/AudioDSP.h
+++ b/libs/audioflinger/AudioDSP.h
@@ -120,7 +120,7 @@ class EffectHeadphone : public Effect {
Delay mReverbDelayL, mReverbDelayR;
int32_t mDelayDataL, mDelayDataR;
- Biquad mLowpass;
+ Biquad mLocalizationL, mLocalizationR;
public:
EffectHeadphone();