summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/AudioResampler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger/AudioResampler.cpp')
-rw-r--r--services/audioflinger/AudioResampler.cpp135
1 files changed, 106 insertions, 29 deletions
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index e5cceb1..1f7a613 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -22,9 +22,11 @@
#include <sys/types.h>
#include <cutils/log.h>
#include <cutils/properties.h>
+#include <audio_utils/primitives.h>
#include "AudioResampler.h"
#include "AudioResamplerSinc.h"
#include "AudioResamplerCubic.h"
+#include "AudioResamplerDyn.h"
#ifdef __arm__
#include <machine/cpu-features.h>
@@ -39,8 +41,8 @@ namespace android {
class AudioResamplerOrder1 : public AudioResampler {
public:
- AudioResamplerOrder1(int bitDepth, int inChannelCount, int32_t sampleRate) :
- AudioResampler(bitDepth, inChannelCount, sampleRate, LOW_QUALITY), mX0L(0), mX0R(0) {
+ AudioResamplerOrder1(int inChannelCount, int32_t sampleRate) :
+ AudioResampler(inChannelCount, sampleRate, LOW_QUALITY), mX0L(0), mX0R(0) {
}
virtual void resample(int32_t* out, size_t outFrameCount,
AudioBufferProvider* provider);
@@ -77,6 +79,9 @@ private:
int mX0R;
};
+/*static*/
+const double AudioResampler::kPhaseMultiplier = 1L << AudioResampler::kNumPhaseBits;
+
bool AudioResampler::qualityIsSupported(src_quality quality)
{
switch (quality) {
@@ -85,6 +90,9 @@ bool AudioResampler::qualityIsSupported(src_quality quality)
case MED_QUALITY:
case HIGH_QUALITY:
case VERY_HIGH_QUALITY:
+ case DYN_LOW_QUALITY:
+ case DYN_MED_QUALITY:
+ case DYN_HIGH_QUALITY:
return true;
default:
return false;
@@ -105,7 +113,7 @@ void AudioResampler::init_routine()
if (*endptr == '\0') {
defaultQuality = (src_quality) l;
ALOGD("forcing AudioResampler quality to %d", defaultQuality);
- if (defaultQuality < DEFAULT_QUALITY || defaultQuality > VERY_HIGH_QUALITY) {
+ if (defaultQuality < DEFAULT_QUALITY || defaultQuality > DYN_HIGH_QUALITY) {
defaultQuality = DEFAULT_QUALITY;
}
}
@@ -125,6 +133,12 @@ uint32_t AudioResampler::qualityMHz(src_quality quality)
return 20;
case VERY_HIGH_QUALITY:
return 34;
+ case DYN_LOW_QUALITY:
+ return 4;
+ case DYN_MED_QUALITY:
+ return 6;
+ case DYN_HIGH_QUALITY:
+ return 12;
}
}
@@ -132,7 +146,7 @@ static const uint32_t maxMHz = 130; // an arbitrary number that permits 3 VHQ, s
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static uint32_t currentMHz = 0;
-AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
+AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount,
int32_t sampleRate, src_quality quality) {
bool atFinalQuality;
@@ -148,6 +162,16 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
atFinalQuality = true;
}
+ /* if the caller requests DEFAULT_QUALITY and af.resampler.property
+ * has not been set, the target resampler quality is set to DYN_MED_QUALITY,
+ * and allowed to "throttle" down to DYN_LOW_QUALITY if necessary
+ * due to estimated CPU load of having too many active resamplers
+ * (the code below the if).
+ */
+ if (quality == DEFAULT_QUALITY) {
+ quality = DYN_MED_QUALITY;
+ }
+
// naive implementation of CPU load throttling doesn't account for whether resampler is active
pthread_mutex_lock(&mutex);
for (;;) {
@@ -162,7 +186,6 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
// not enough CPU available for proposed quality level, so try next lowest level
switch (quality) {
default:
- case DEFAULT_QUALITY:
case LOW_QUALITY:
atFinalQuality = true;
break;
@@ -175,6 +198,15 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
case VERY_HIGH_QUALITY:
quality = HIGH_QUALITY;
break;
+ case DYN_LOW_QUALITY:
+ atFinalQuality = true;
+ break;
+ case DYN_MED_QUALITY:
+ quality = DYN_LOW_QUALITY;
+ break;
+ case DYN_HIGH_QUALITY:
+ quality = DYN_MED_QUALITY;
+ break;
}
}
pthread_mutex_unlock(&mutex);
@@ -183,22 +215,43 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
switch (quality) {
default:
- case DEFAULT_QUALITY:
case LOW_QUALITY:
ALOGV("Create linear Resampler");
- resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate);
+ LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
+ resampler = new AudioResamplerOrder1(inChannelCount, sampleRate);
break;
case MED_QUALITY:
ALOGV("Create cubic Resampler");
- resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate);
+ LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
+ resampler = new AudioResamplerCubic(inChannelCount, sampleRate);
break;
case HIGH_QUALITY:
ALOGV("Create HIGH_QUALITY sinc Resampler");
- resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate);
+ LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
+ resampler = new AudioResamplerSinc(inChannelCount, sampleRate);
break;
case VERY_HIGH_QUALITY:
ALOGV("Create VERY_HIGH_QUALITY sinc Resampler = %d", quality);
- resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate, quality);
+ LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
+ resampler = new AudioResamplerSinc(inChannelCount, sampleRate, quality);
+ break;
+ case DYN_LOW_QUALITY:
+ case DYN_MED_QUALITY:
+ case DYN_HIGH_QUALITY:
+ ALOGV("Create dynamic Resampler = %d", quality);
+ if (format == AUDIO_FORMAT_PCM_FLOAT) {
+ resampler = new AudioResamplerDyn<float, float, float>(inChannelCount,
+ sampleRate, quality);
+ } else {
+ LOG_ALWAYS_FATAL_IF(format != AUDIO_FORMAT_PCM_16_BIT);
+ if (quality == DYN_HIGH_QUALITY) {
+ resampler = new AudioResamplerDyn<int32_t, int16_t, int32_t>(inChannelCount,
+ sampleRate, quality);
+ } else {
+ resampler = new AudioResamplerDyn<int16_t, int16_t, int32_t>(inChannelCount,
+ sampleRate, quality);
+ }
+ }
break;
}
@@ -207,26 +260,26 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
return resampler;
}
-AudioResampler::AudioResampler(int bitDepth, int inChannelCount,
+AudioResampler::AudioResampler(int inChannelCount,
int32_t sampleRate, src_quality quality) :
- mBitDepth(bitDepth), mChannelCount(inChannelCount),
- mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0),
- mPhaseFraction(0), mLocalTimeFreq(0),
- mPTS(AudioBufferProvider::kInvalidPTS), mQuality(quality) {
- // sanity check on format
- if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) {
- ALOGE("Unsupported sample format, %d bits, %d channels", bitDepth,
- inChannelCount);
- // ALOG_ASSERT(0);
+ mChannelCount(inChannelCount),
+ mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0),
+ mPhaseFraction(0), mLocalTimeFreq(0),
+ mPTS(AudioBufferProvider::kInvalidPTS), mQuality(quality) {
+
+ const int maxChannels = quality < DYN_LOW_QUALITY ? 2 : 8;
+ if (inChannelCount < 1
+ || inChannelCount > maxChannels) {
+ LOG_ALWAYS_FATAL("Unsupported sample format %d quality %d channels",
+ quality, inChannelCount);
}
if (sampleRate <= 0) {
- ALOGE("Unsupported sample rate %d Hz", sampleRate);
+ LOG_ALWAYS_FATAL("Unsupported sample rate %d Hz", sampleRate);
}
// initialize common members
mVolume[0] = mVolume[1] = 0;
mBuffer.frameCount = 0;
-
}
AudioResampler::~AudioResampler() {
@@ -246,10 +299,12 @@ void AudioResampler::setSampleRate(int32_t inSampleRate) {
mPhaseIncrement = (uint32_t)((kPhaseMultiplier * inSampleRate) / mSampleRate);
}
-void AudioResampler::setVolume(int16_t left, int16_t right) {
+void AudioResampler::setVolume(float left, float right) {
// TODO: Implement anti-zipper filter
- mVolume[0] = left;
- mVolume[1] = right;
+ // convert to U4.12 for internal integer use (round down)
+ // integer volume values are clamped to 0 to UNITY_GAIN.
+ mVolume[0] = u4_12_from_float(clampFloatVol(left));
+ mVolume[1] = u4_12_from_float(clampFloatVol(right));
}
void AudioResampler::setLocalTimeFreq(uint64_t freq) {
@@ -305,7 +360,7 @@ void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,
uint32_t phaseIncrement = mPhaseIncrement;
size_t outputIndex = 0;
size_t outputSampleCount = outFrameCount * 2;
- size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+ size_t inFrameCount = getInFrameCountRequired(outFrameCount);
// ALOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d",
// outFrameCount, inputIndex, phaseFraction, phaseIncrement);
@@ -339,8 +394,9 @@ void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,
out[outputIndex++] += vl * Interp(mX0L, in[0], phaseFraction);
out[outputIndex++] += vr * Interp(mX0R, in[1], phaseFraction);
Advance(&inputIndex, &phaseFraction, phaseIncrement);
- if (outputIndex == outputSampleCount)
+ if (outputIndex == outputSampleCount) {
break;
+ }
}
// process input samples
@@ -402,7 +458,7 @@ void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount,
uint32_t phaseIncrement = mPhaseIncrement;
size_t outputIndex = 0;
size_t outputSampleCount = outFrameCount * 2;
- size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+ size_t inFrameCount = getInFrameCountRequired(outFrameCount);
// ALOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d",
// outFrameCount, inputIndex, phaseFraction, phaseIncrement);
@@ -434,8 +490,9 @@ void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount,
out[outputIndex++] += vl * sample;
out[outputIndex++] += vr * sample;
Advance(&inputIndex, &phaseFraction, phaseIncrement);
- if (outputIndex == outputSampleCount)
+ if (outputIndex == outputSampleCount) {
break;
+ }
}
// process input samples
@@ -514,6 +571,16 @@ void AudioResamplerOrder1::AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t
size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
uint32_t &phaseFraction, uint32_t phaseIncrement)
{
+ (void)maxOutPt; // remove unused parameter warnings
+ (void)maxInIdx;
+ (void)outputIndex;
+ (void)out;
+ (void)inputIndex;
+ (void)vl;
+ (void)vr;
+ (void)phaseFraction;
+ (void)phaseIncrement;
+ (void)in;
#define MO_PARAM5 "36" // offset of parameter 5 (outputIndex)
asm(
@@ -625,6 +692,16 @@ void AudioResamplerOrder1::AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32
size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
uint32_t &phaseFraction, uint32_t phaseIncrement)
{
+ (void)maxOutPt; // remove unused parameter warnings
+ (void)maxInIdx;
+ (void)outputIndex;
+ (void)out;
+ (void)inputIndex;
+ (void)vl;
+ (void)vr;
+ (void)phaseFraction;
+ (void)phaseIncrement;
+ (void)in;
#define ST_PARAM5 "40" // offset of parameter 5 (outputIndex)
asm(
"stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"