Skip to content

Commit

Permalink
Merge branch 'gingerbread' of git://github.com/CyanogenMod/android_fr…
Browse files Browse the repository at this point in the history
…ameworks_base into gingerbread
  • Loading branch information
jt1134 committed Jun 23, 2011
2 parents e6eada7 + 2122f6e commit 988c03c
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 46 deletions.
32 changes: 17 additions & 15 deletions media/libeffects/cyanogen-dsp/EffectCompression.cpp
Expand Up @@ -51,8 +51,10 @@ int32_t EffectCompression::command(uint32_t cmdCode, uint32_t cmdSize, void* pCm
return 0;
}

mWeighter[0].setBandPass(1700, mSamplingRate, sqrtf(2)/2);
mWeighter[1].setBandPass(1700, mSamplingRate, sqrtf(2)/2);
/* This filter gives a reasonable approximation of A- and C-weighting
* which is close to correct for 100 - 10 kHz. 10 dB gain must be added to result. */
mWeigherBP[0].setBandPass(2200, mSamplingRate, 0.33);
mWeigherBP[1].setBandPass(2200, mSamplingRate, 0.33);

*replyData = 0;
return 0;
Expand Down Expand Up @@ -105,15 +107,16 @@ int32_t EffectCompression::command(uint32_t cmdCode, uint32_t cmdSize, void* pCm
}

/* Return fixed point 16.48 */
uint64_t EffectCompression::estimateOneChannelLevel(audio_buffer_t *in, int32_t interleave, int32_t offset, Biquad& weighter)
uint64_t EffectCompression::estimateOneChannelLevel(audio_buffer_t *in, int32_t interleave, int32_t offset, Biquad& weigherBP)
{
uint64_t power = 0;
for (uint32_t i = 0; i < in->frameCount; i ++) {
int32_t tmp = read(in, offset);
offset += interleave;
int64_t out = weighter.process(tmp);
tmp = weigherBP.process(tmp);

/* 2^24 * 2^24 = 48 */
power += out * out;
power += int64_t(tmp) * int64_t(tmp);
offset += interleave;
}

return (power / in->frameCount);
Expand All @@ -124,7 +127,7 @@ int32_t EffectCompression::process_effect(audio_buffer_t *in, audio_buffer_t *ou
/* Analyze both channels separately, pick the maximum power measured. */
uint64_t maximumPowerSquared = 0;
for (uint32_t i = 0; i < mChannels; i ++) {
uint64_t candidatePowerSquared = estimateOneChannelLevel(in, mChannels, i, mWeighter[i]);
uint64_t candidatePowerSquared = estimateOneChannelLevel(in, mChannels, i, mWeigherBP[i]);
if (candidatePowerSquared > maximumPowerSquared) {
maximumPowerSquared = candidatePowerSquared;
}
Expand All @@ -133,9 +136,8 @@ int32_t EffectCompression::process_effect(audio_buffer_t *in, audio_buffer_t *ou
/* -100 .. 0 dB. */
float signalPowerDb = logf(maximumPowerSquared / float(int64_t(1) << 48) + 1e-10f) / logf(10.0f) * 10.0f;

/* target 83 dB SPL, and add 6 dB to compensate for the weighter, whose
* peak is at -3 dB. */
signalPowerDb += 96.0f - 83.0f + 6.0f;
/* Target 83 dB SPL */
signalPowerDb += 96.0f - 83.0f + 10.0f;

/* now we have an estimate of the signal power, with 0 level around 83 dB.
* we now select the level to boost to. */
Expand All @@ -159,14 +161,14 @@ int32_t EffectCompression::process_effect(audio_buffer_t *in, audio_buffer_t *ou
/* 8.24 */
int32_t volAdj = desiredLevel - mCurrentLevel[i];

/* I want volume adjustments to occur in about 0.05 seconds.
/* I want volume adjustments to occur in about 0.025 seconds.
* However, if the input buffer would happen to be longer than
* this, I'll just make sure that I am done with the adjustment
* by the end of it. */
int32_t adjLen = mSamplingRate / 20;
/* Note: this adjustment should probably be piecewise linear
* approximation of an exponential to keep perceptibly linear
* correction rate. */
int32_t adjLen = mSamplingRate / 40; // in practice, about 1100 frames
/* This formulation results in piecewise linear approximation of
* exponential because the rate of adjustment decreases from granule
* to granule. */
volAdj /= max(adjLen, in->frameCount);

/* Additionally, I want volume to increase only very slowly.
Expand Down
5 changes: 3 additions & 2 deletions media/libeffects/cyanogen-dsp/EffectCompression.h
Expand Up @@ -9,9 +9,10 @@ class EffectCompression : public Effect {
float mCompressionRatio;

int32_t mCurrentLevel[2];
Biquad mWeighter[2];

uint64_t estimateOneChannelLevel(audio_buffer_t *in, int32_t interleave, int32_t offset, Biquad& weighter);
Biquad mWeigherBP[2];

uint64_t estimateOneChannelLevel(audio_buffer_t *in, int32_t interleave, int32_t offset, Biquad& WeigherBP);

public:
EffectCompression();
Expand Down
64 changes: 35 additions & 29 deletions media/libeffects/cyanogen-dsp/EffectEqualizer.cpp
Expand Up @@ -61,7 +61,7 @@ static int64_t toFixedPoint(float in) {
}

EffectEqualizer::EffectEqualizer()
: mLoudnessAdjustment(10000.f), mLoudness(0.f)
: mLoudnessAdjustment(10000.f), mLoudness(50.f), mNextUpdate(0), mNextUpdateInterval(1000), mPowerSquared(0)
{
for (int32_t i = 0; i < 5; i ++) {
mBand[i] = 0;
Expand All @@ -79,9 +79,10 @@ int32_t EffectEqualizer::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdD
return 0;
}

/* Weigher for estimating bass compensation. Our adjustments have range from 62.5 to 4000 Hz.
* Most of the adjustment is at the 62.5 Hz band, so we must concentrate on bass region. */
mWeigher.setLowPass(1000.0, mSamplingRate, sqrtf(2)/2.);
/* Weigher for estimating bass compensation. */
mWeigher.setBandPass(2200.0, mSamplingRate, 0.33);
/* 100 updates per second. */
mNextUpdateInterval = int32_t(mSamplingRate / 100.);

int32_t *replyData = (int32_t *) pReplyData;
*replyData = 0;
Expand Down Expand Up @@ -195,18 +196,20 @@ int32_t EffectEqualizer::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdD
* sound pressure level.
*
* The boost can be calculated as linear scaling of the following adjustment:
* 62.5 Hz +24 dB
* 250 Hz +10 dB
* 1000 Hz 0 dB
* 4000 Hz -6 dB
* 20 Hz +40 dB (unmodeled)
* 62.5 Hz +20 dB
* 250 Hz +8 dB
* 1000 Hz 0 dB
* 4000 Hz -3 dB
* 16000 Hz +6 dB
*
* The boost will be applied maximally for signals of 20 dB and less,
* and linearly decreased for signals 20 dB ... 100 dB, and no adjustment is
* made for 100 dB or higher. User must configure a reference level that maps the
* digital sound level against the audio.
*/
float EffectEqualizer::getAdjustedBand(int32_t band) {
const float adj[5] = { 24.0, 10.0, 0.0, -6.0, 0.0 };
const float adj[5] = { 20.0, 8.0, 0.0, -3.0, 6.0 };

float loudnessLevel = mLoudness + mLoudnessAdjustment;
if (loudnessLevel > 100.f) {
Expand Down Expand Up @@ -236,16 +239,35 @@ void EffectEqualizer::refreshBands()

int32_t EffectEqualizer::process_effect(audio_buffer_t *in, audio_buffer_t *out)
{
refreshBands();

int64_t maximumPowerSquared = 0;
for (uint32_t i = 0; i < in->frameCount; i ++) {
if (mNextUpdate == 0) {
float signalPowerDb = logf(mPowerSquared / mNextUpdateInterval / float(int64_t(1) << 48) + 1e-10f) / logf(10.0f) * 10.0f;
signalPowerDb += 96.0f + 10.0f;

/* Limit automatic EQ to sub-dB adjustments to limit the noise
* introduced by updates. */
if (mLoudness < signalPowerDb - .5) {
mLoudness += .5;
} else if (mLoudness > signalPowerDb + .5) {
mLoudness -= .5;
} else {
mLoudness = signalPowerDb;
}

/* Update EQ. */
refreshBands();

mNextUpdate = mNextUpdateInterval;
mPowerSquared = 0;
}
mNextUpdate --;

int32_t tmpL = read(in, i * 2);
int32_t tmpR = read(in, i * 2 + 1);

/* Calculate signal loudness estimate */
int64_t weight = mWeigher.process(tmpL + tmpR);
maximumPowerSquared += weight * weight;
mPowerSquared += weight * weight;

/* first "shelve" is just gain */
tmpL = tmpL * mGain >> 32;
Expand All @@ -260,22 +282,6 @@ int32_t EffectEqualizer::process_effect(audio_buffer_t *in, audio_buffer_t *out)
write(out, i * 2, tmpL);
write(out, i * 2 + 1, tmpR);
}
maximumPowerSquared /= in->frameCount;

float signalPowerDb = logf(maximumPowerSquared / float(int64_t(1) << 48) + 1e-10f) / logf(10.0f) * 10.0f;
signalPowerDb += 96.0f;

/* Limit automatic EQ to maximum of 10 dB adjustment rate per second.
* a frame-to-frame adjusted should not be very large because adjustments do cause
* small glitches at the output. These may be audible if single step is too large. */
float maxAdj = in->frameCount / mSamplingRate * 10.f;
if (mLoudness < signalPowerDb - maxAdj) {
mLoudness += maxAdj;
} else if (mLoudness > signalPowerDb + maxAdj) {
mLoudness -= maxAdj;
} else {
mLoudness = signalPowerDb;
}

return 0;
}
Expand Down
3 changes: 3 additions & 0 deletions media/libeffects/cyanogen-dsp/EffectEqualizer.h
Expand Up @@ -20,6 +20,9 @@ class EffectEqualizer : public Effect {

Biquad mWeigher;
float mLoudness;
int32_t mNextUpdate;
int32_t mNextUpdateInterval;
int64_t mPowerSquared;

void setBand(int32_t idx, float dB);
float getAdjustedBand(int32_t idx);
Expand Down

0 comments on commit 988c03c

Please sign in to comment.