summaryrefslogtreecommitdiffstats
path: root/services/audioflinger
diff options
context:
space:
mode:
authorAndy Hung <hunga@google.com>2014-04-08 18:44:38 -0700
committerAndy Hung <hunga@google.com>2014-04-09 14:30:31 -0700
commit771386e6e6e79697e2d839ef0f25a242946ba1e5 (patch)
treea96089d65f91b69e94dfa09c9a31ac6d9274f1cd /services/audioflinger
parentd549139155b20d7cbf6a4326133e06def465ef54 (diff)
downloadframeworks_av-771386e6e6e79697e2d839ef0f25a242946ba1e5.zip
frameworks_av-771386e6e6e79697e2d839ef0f25a242946ba1e5.tar.gz
frameworks_av-771386e6e6e79697e2d839ef0f25a242946ba1e5.tar.bz2
Add and enable floating point option for audio resampler
Can be tested with test-resample. Change-Id: I8339846d7c647444b6025d33cfa145d5d3658121 Signed-off-by: Andy Hung <hunga@google.com>
Diffstat (limited to 'services/audioflinger')
-rw-r--r--services/audioflinger/AudioResampler.cpp11
-rw-r--r--services/audioflinger/AudioResamplerDyn.cpp250
-rw-r--r--services/audioflinger/AudioResamplerDyn.h82
3 files changed, 179 insertions, 164 deletions
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index ca98f16..562c4ea 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -234,7 +234,16 @@ AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
case DYN_MED_QUALITY:
case DYN_HIGH_QUALITY:
ALOGV("Create dynamic Resampler = %d", quality);
- resampler = new AudioResamplerDyn(bitDepth, inChannelCount, sampleRate, quality);
+ if (bitDepth == 32) { /* bitDepth == 32 signals float precision */
+ resampler = new AudioResamplerDyn<float, float, float>(bitDepth, inChannelCount,
+ sampleRate, quality);
+ } else if (quality == DYN_HIGH_QUALITY) {
+ resampler = new AudioResamplerDyn<int32_t, int16_t, int32_t>(bitDepth, inChannelCount,
+ sampleRate, quality);
+ } else {
+ resampler = new AudioResamplerDyn<int16_t, int16_t, int32_t>(bitDepth, inChannelCount,
+ sampleRate, quality);
+ }
break;
}
diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp
index 173a243..3abe8fd 100644
--- a/services/audioflinger/AudioResamplerDyn.cpp
+++ b/services/audioflinger/AudioResamplerDyn.cpp
@@ -39,9 +39,9 @@
namespace android {
// generate a unique resample type compile-time constant (constexpr)
-#define RESAMPLETYPE(CHANNELS, LOCKED, STRIDE, COEFTYPE) \
- ((((CHANNELS)-1)&1) | !!(LOCKED)<<1 | (COEFTYPE)<<2 \
- | ((STRIDE)==8 ? 1 : (STRIDE)==16 ? 2 : 0)<<3)
+#define RESAMPLETYPE(CHANNELS, LOCKED, STRIDE) \
+ ((((CHANNELS)-1)&1) | !!(LOCKED)<<1 \
+ | ((STRIDE)==8 ? 1 : (STRIDE)==16 ? 2 : 0)<<2)
/*
* InBuffer is a type agnostic input buffer.
@@ -59,42 +59,46 @@ namespace android {
* r = extra space for implementing the ring buffer
*/
-template<typename TI>
-AudioResamplerDyn::InBuffer<TI>::InBuffer()
- : mState(NULL), mImpulse(NULL), mRingFull(NULL), mStateSize(0) {
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::InBuffer::InBuffer()
+ : mState(NULL), mImpulse(NULL), mRingFull(NULL), mStateCount(0)
+{
}
-template<typename TI>
-AudioResamplerDyn::InBuffer<TI>::~InBuffer() {
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::InBuffer::~InBuffer()
+{
init();
}
-template<typename TI>
-void AudioResamplerDyn::InBuffer<TI>::init() {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::init()
+{
free(mState);
mState = NULL;
mImpulse = NULL;
mRingFull = NULL;
- mStateSize = 0;
+ mStateCount = 0;
}
// resizes the state buffer to accommodate the appropriate filter length
-template<typename TI>
-void AudioResamplerDyn::InBuffer<TI>::resize(int CHANNELS, int halfNumCoefs) {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::resize(int CHANNELS, int halfNumCoefs)
+{
// calculate desired state size
- int stateSize = halfNumCoefs * CHANNELS * 2
- * kStateSizeMultipleOfFilterLength;
+ int stateCount = halfNumCoefs * CHANNELS * 2 * kStateSizeMultipleOfFilterLength;
// check if buffer needs resizing
if (mState
- && stateSize == mStateSize
- && mRingFull-mState == mStateSize-halfNumCoefs*CHANNELS) {
+ && stateCount == mStateCount
+ && mRingFull-mState == mStateCount-halfNumCoefs*CHANNELS) {
return;
}
// create new buffer
- TI* state = (int16_t*)memalign(32, stateSize*sizeof(*state));
- memset(state, 0, stateSize*sizeof(*state));
+ TI* state;
+ (void)posix_memalign(reinterpret_cast<void**>(&state), 32, stateCount*sizeof(*state));
+ memset(state, 0, stateCount*sizeof(*state));
// attempt to preserve state
if (mState) {
@@ -106,8 +110,8 @@ void AudioResamplerDyn::InBuffer<TI>::resize(int CHANNELS, int halfNumCoefs) {
dst += mState-srcLo;
srcLo = mState;
}
- if (srcHi > mState + mStateSize) {
- srcHi = mState + mStateSize;
+ if (srcHi > mState + mStateCount) {
+ srcHi = mState + mStateCount;
}
memcpy(dst, srcLo, (srcHi - srcLo) * sizeof(*srcLo));
free(mState);
@@ -115,27 +119,29 @@ void AudioResamplerDyn::InBuffer<TI>::resize(int CHANNELS, int halfNumCoefs) {
// set class member vars
mState = state;
- mStateSize = stateSize;
- mImpulse = mState + halfNumCoefs*CHANNELS; // actually one sample greater than needed
- mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS;
+ mStateCount = stateCount;
+ mImpulse = state + halfNumCoefs*CHANNELS; // actually one sample greater than needed
+ mRingFull = state + mStateCount - halfNumCoefs*CHANNELS;
}
// copy in the input data into the head (impulse+halfNumCoefs) of the buffer.
-template<typename TI>
+template<typename TC, typename TI, typename TO>
template<int CHANNELS>
-void AudioResamplerDyn::InBuffer<TI>::readAgain(TI*& impulse, const int halfNumCoefs,
- const TI* const in, const size_t inputIndex) {
- int16_t* head = impulse + halfNumCoefs*CHANNELS;
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::readAgain(TI*& impulse, const int halfNumCoefs,
+ const TI* const in, const size_t inputIndex)
+{
+ TI* head = impulse + halfNumCoefs*CHANNELS;
for (size_t i=0 ; i<CHANNELS ; i++) {
head[i] = in[inputIndex*CHANNELS + i];
}
}
// advance the impulse pointer, and load in data into the head (impulse+halfNumCoefs)
-template<typename TI>
+template<typename TC, typename TI, typename TO>
template<int CHANNELS>
-void AudioResamplerDyn::InBuffer<TI>::readAdvance(TI*& impulse, const int halfNumCoefs,
- const TI* const in, const size_t inputIndex) {
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::readAdvance(TI*& impulse, const int halfNumCoefs,
+ const TI* const in, const size_t inputIndex)
+{
impulse += CHANNELS;
if (CC_UNLIKELY(impulse >= mRingFull)) {
@@ -146,7 +152,8 @@ void AudioResamplerDyn::InBuffer<TI>::readAdvance(TI*& impulse, const int halfNu
readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
}
-void AudioResamplerDyn::Constants::set(
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::Constants::set(
int L, int halfNumCoefs, int inSampleRate, int outSampleRate)
{
int bits = 0;
@@ -159,10 +166,11 @@ void AudioResamplerDyn::Constants::set(
mHalfNumCoefs = halfNumCoefs;
}
-AudioResamplerDyn::AudioResamplerDyn(int bitDepth,
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::AudioResamplerDyn(int bitDepth,
int inChannelCount, int32_t sampleRate, src_quality quality)
: AudioResampler(bitDepth, inChannelCount, sampleRate, quality),
- mResampleType(0), mFilterSampleRate(0), mFilterQuality(DEFAULT_QUALITY),
+ mResampleFunc(0), mFilterSampleRate(0), mFilterQuality(DEFAULT_QUALITY),
mCoefBuffer(NULL)
{
mVolumeSimd[0] = mVolumeSimd[1] = 0;
@@ -173,33 +181,48 @@ AudioResamplerDyn::AudioResamplerDyn(int bitDepth,
mConstants.set(128, 8, mSampleRate, mSampleRate); // TODO: set better
}
-AudioResamplerDyn::~AudioResamplerDyn() {
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::~AudioResamplerDyn()
+{
free(mCoefBuffer);
}
-void AudioResamplerDyn::init() {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::init()
+{
mFilterSampleRate = 0; // always trigger new filter generation
mInBuffer.init();
}
-void AudioResamplerDyn::setVolume(int16_t left, int16_t right) {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::setVolume(int16_t left, int16_t right)
+{
AudioResampler::setVolume(left, right);
- mVolumeSimd[0] = static_cast<int32_t>(left)<<16;
- mVolumeSimd[1] = static_cast<int32_t>(right)<<16;
+ // volume is applied on the output type.
+ if (is_same<TO, float>::value || is_same<TO, double>::value) {
+ const TO scale = 1. / (1UL << 12);
+ mVolumeSimd[0] = static_cast<TO>(left) * scale;
+ mVolumeSimd[1] = static_cast<TO>(right) * scale;
+ } else {
+ mVolumeSimd[0] = static_cast<int32_t>(left) << 16;
+ mVolumeSimd[1] = static_cast<int32_t>(right) << 16;
+ }
}
-template <typename T> T max(T a, T b) {return a > b ? a : b;}
+template<typename T> T max(T a, T b) {return a > b ? a : b;}
-template <typename T> T absdiff(T a, T b) {return a > b ? a - b : b - a;}
+template<typename T> T absdiff(T a, T b) {return a > b ? a - b : b - a;}
-template<typename T>
-void AudioResamplerDyn::createKaiserFir(Constants &c, double stopBandAtten,
- int inSampleRate, int outSampleRate, double tbwCheat) {
- T* buf = reinterpret_cast<T*>(memalign(32, (c.mL+1)*c.mHalfNumCoefs*sizeof(T)));
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::createKaiserFir(Constants &c,
+ double stopBandAtten, int inSampleRate, int outSampleRate, double tbwCheat)
+{
+ TC* buf;
static const double atten = 0.9998; // to avoid ripple overflow
double fcr;
double tbw = firKaiserTbw(c.mHalfNumCoefs, stopBandAtten);
+ (void)posix_memalign(reinterpret_cast<void**>(&buf), 32, (c.mL+1)*c.mHalfNumCoefs*sizeof(TC));
if (inSampleRate < outSampleRate) { // upsample
fcr = max(0.5*tbwCheat - tbw/2, tbw/2);
} else { // downsample
@@ -207,7 +230,7 @@ void AudioResamplerDyn::createKaiserFir(Constants &c, double stopBandAtten,
}
// create and set filter
firKaiserGen(buf, c.mL, c.mHalfNumCoefs, stopBandAtten, fcr, atten);
- c.setBuf(buf);
+ c.mFirCoefs = buf;
if (mCoefBuffer) {
free(mCoefBuffer);
}
@@ -229,7 +252,8 @@ void AudioResamplerDyn::createKaiserFir(Constants &c, double stopBandAtten,
}
// recursive gcd. Using objdump, it appears the tail recursion is converted to a while loop.
-static int gcd(int n, int m) {
+static int gcd(int n, int m)
+{
if (m == 0) {
return n;
}
@@ -237,7 +261,8 @@ static int gcd(int n, int m) {
}
static bool isClose(int32_t newSampleRate, int32_t prevSampleRate,
- int32_t filterSampleRate, int32_t outSampleRate) {
+ int32_t filterSampleRate, int32_t outSampleRate)
+{
// different upsampling ratios do not need a filter change.
if (filterSampleRate != 0
@@ -254,7 +279,9 @@ static bool isClose(int32_t newSampleRate, int32_t prevSampleRate,
return pdiff < prevSampleRate>>4 && adiff < filterSampleRate>>3;
}
-void AudioResamplerDyn::setSampleRate(int32_t inSampleRate) {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::setSampleRate(int32_t inSampleRate)
+{
if (mInSampleRate == inSampleRate) {
return;
}
@@ -358,13 +385,8 @@ void AudioResamplerDyn::setSampleRate(int32_t inSampleRate) {
// create the filter
mConstants.set(phases, halfLength, inSampleRate, mSampleRate);
- if (useS32) {
- createKaiserFir<int32_t>(mConstants, stopBandAtten,
- inSampleRate, mSampleRate, tbwCheat);
- } else {
- createKaiserFir<int16_t>(mConstants, stopBandAtten,
- inSampleRate, mSampleRate, tbwCheat);
- }
+ createKaiserFir(mConstants, stopBandAtten,
+ inSampleRate, mSampleRate, tbwCheat);
} // End Kaiser filter
// update phase and state based on the new filter.
@@ -386,7 +408,7 @@ void AudioResamplerDyn::setSampleRate(int32_t inSampleRate) {
mPhaseFraction = mPhaseFraction >> c.mShift << c.mShift; // remove fractional phase
}
- mResampleType = RESAMPLETYPE(mChannelCount, locked, stride, !!useS32);
+ setResampler(RESAMPLETYPE(mChannelCount, locked, stride));
#ifdef DEBUG_RESAMPLER
printf("channels:%d %s stride:%d %s coef:%d shift:%d\n",
mChannelCount, locked ? "locked" : "interpolated",
@@ -394,78 +416,45 @@ void AudioResamplerDyn::setSampleRate(int32_t inSampleRate) {
#endif
}
-void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount,
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::resample(int32_t* out, size_t outFrameCount,
AudioBufferProvider* provider)
{
- // TODO:
- // 24 cases - this perhaps can be reduced later, as testing might take too long
- switch (mResampleType) {
+ (this->*mResampleFunc)(reinterpret_cast<TO*>(out), outFrameCount, provider);
+}
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::setResampler(unsigned resampleType)
+{
// stride 16 (falls back to stride 2 for machines that do not support NEON)
- case RESAMPLETYPE(1, true, 16, 0):
- return resample<1, true, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(2, true, 16, 0):
- return resample<2, true, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(1, false, 16, 0):
- return resample<1, false, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(2, false, 16, 0):
- return resample<2, false, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(1, true, 16, 1):
- return resample<1, true, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- case RESAMPLETYPE(2, true, 16, 1):
- return resample<2, true, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- case RESAMPLETYPE(1, false, 16, 1):
- return resample<1, false, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- case RESAMPLETYPE(2, false, 16, 1):
- return resample<2, false, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-#if 0
- // TODO: Remove these?
- // stride 8
- case RESAMPLETYPE(1, true, 8, 0):
- return resample<1, true, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(2, true, 8, 0):
- return resample<2, true, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(1, false, 8, 0):
- return resample<1, false, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(2, false, 8, 0):
- return resample<2, false, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(1, true, 8, 1):
- return resample<1, true, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- case RESAMPLETYPE(2, true, 8, 1):
- return resample<2, true, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- case RESAMPLETYPE(1, false, 8, 1):
- return resample<1, false, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- case RESAMPLETYPE(2, false, 8, 1):
- return resample<2, false, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- // stride 2 (can handle any filter length)
- case RESAMPLETYPE(1, true, 2, 0):
- return resample<1, true, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(2, true, 2, 0):
- return resample<2, true, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(1, false, 2, 0):
- return resample<1, false, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(2, false, 2, 0):
- return resample<2, false, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
- case RESAMPLETYPE(1, true, 2, 1):
- return resample<1, true, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- case RESAMPLETYPE(2, true, 2, 1):
- return resample<2, true, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- case RESAMPLETYPE(1, false, 2, 1):
- return resample<1, false, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
- case RESAMPLETYPE(2, false, 2, 1):
- return resample<2, false, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-#endif
+ switch (resampleType) {
+ case RESAMPLETYPE(1, true, 16):
+ mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>;
+ return;
+ case RESAMPLETYPE(2, true, 16):
+ mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>;
+ return;
+ case RESAMPLETYPE(1, false, 16):
+ mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>;
+ return;
+ case RESAMPLETYPE(2, false, 16):
+ mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>;
+ return;
default:
- ; // error
+ LOG_ALWAYS_FATAL("Invalid resampler type: %u", resampleType);
+ mResampleFunc = NULL;
+ return;
}
}
-template<int CHANNELS, bool LOCKED, int STRIDE, typename TC>
-void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount,
- const TC* const coefs, AudioBufferProvider* provider)
+template<typename TC, typename TI, typename TO>
+template<int CHANNELS, bool LOCKED, int STRIDE>
+void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
+ AudioBufferProvider* provider)
{
const Constants& c(mConstants);
- int16_t* impulse = mInBuffer.getImpulse();
+ const TC* const coefs = mConstants.mFirCoefs;
+ TI* impulse = mInBuffer.getImpulse();
size_t inputIndex = mInputIndex;
uint32_t phaseFraction = mPhaseFraction;
const uint32_t phaseIncrement = mPhaseIncrement;
@@ -491,8 +480,9 @@ void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount,
goto resample_exit;
}
if (phaseFraction >= phaseWrapLimit) { // read in data
- mInBuffer.readAdvance<CHANNELS>(
- impulse, c.mHalfNumCoefs, mBuffer.i16, inputIndex);
+ mInBuffer.template readAdvance<CHANNELS>(
+ impulse, c.mHalfNumCoefs,
+ reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
phaseFraction -= phaseWrapLimit;
while (phaseFraction >= phaseWrapLimit) {
inputIndex++;
@@ -501,20 +491,21 @@ void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount,
provider->releaseBuffer(&mBuffer);
break;
}
- mInBuffer.readAdvance<CHANNELS>(
- impulse, c.mHalfNumCoefs, mBuffer.i16, inputIndex);
+ mInBuffer.template readAdvance<CHANNELS>(
+ impulse, c.mHalfNumCoefs,
+ reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
phaseFraction -= phaseWrapLimit;
}
}
}
- const int16_t* const in = mBuffer.i16;
+ const TI* const in = reinterpret_cast<const TI*>(mBuffer.raw);
const size_t frameCount = mBuffer.frameCount;
const int coefShift = c.mShift;
const int halfNumCoefs = c.mHalfNumCoefs;
- const int32_t* const volumeSimd = mVolumeSimd;
+ const TO* const volumeSimd = mVolumeSimd;
// reread the last input in.
- mInBuffer.readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
+ mInBuffer.template readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
// main processing loop
while (CC_LIKELY(outputIndex < outputSampleCount)) {
@@ -537,7 +528,7 @@ void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount,
if (inputIndex >= frameCount) {
goto done; // need a new buffer
}
- mInBuffer.readAdvance<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
+ mInBuffer.template readAdvance<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
phaseFraction -= phaseWrapLimit;
}
}
@@ -556,5 +547,10 @@ resample_exit:
mPhaseFraction = phaseFraction;
}
+/* instantiate templates used by AudioResampler::create */
+template class AudioResamplerDyn<float, float, float>;
+template class AudioResamplerDyn<int16_t, int16_t, int32_t>;
+template class AudioResamplerDyn<int32_t, int16_t, int32_t>;
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/services/audioflinger/AudioResamplerDyn.h b/services/audioflinger/AudioResamplerDyn.h
index df1fdbe..8c56319 100644
--- a/services/audioflinger/AudioResamplerDyn.h
+++ b/services/audioflinger/AudioResamplerDyn.h
@@ -25,10 +25,24 @@
namespace android {
+/* AudioResamplerDyn
+ *
+ * This class template is used for floating point and integer resamplers.
+ *
+ * Type variables:
+ * TC = filter coefficient type (one of int16_t, int32_t, or float)
+ * TI = input data type (one of int16_t or float)
+ * TO = output data type (one of int32_t or float)
+ *
+ * For integer input data types TI, the coefficient type TC is either int16_t or int32_t.
+ * For float input data types TI, the coefficient type TC is float.
+ */
+
+template<typename TC, typename TI, typename TO>
class AudioResamplerDyn: public AudioResampler {
public:
- AudioResamplerDyn(int bitDepth, int inChannelCount, int32_t sampleRate,
- src_quality quality);
+ AudioResamplerDyn(int bitDepth, int inChannelCount,
+ int32_t sampleRate, src_quality quality);
virtual ~AudioResamplerDyn();
@@ -46,46 +60,38 @@ private:
class Constants { // stores the filter constants.
public:
Constants() :
- mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefsS16(NULL)
+ mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefs(NULL)
{}
void set(int L, int halfNumCoefs,
int inSampleRate, int outSampleRate);
- inline void setBuf(int16_t* buf) {
- mFirCoefsS16 = buf;
- }
- inline void setBuf(int32_t* buf) {
- mFirCoefsS32 = buf;
- }
- int mL; // interpolation phases in the filter.
- int mShift; // right shift to get polyphase index
+ int mL; // interpolation phases in the filter.
+ int mShift; // right shift to get polyphase index
unsigned int mHalfNumCoefs; // filter half #coefs
- union { // polyphase filter bank
- const int16_t* mFirCoefsS16;
- const int32_t* mFirCoefsS32;
- };
+ const TC* mFirCoefs; // polyphase filter bank
};
- // Input buffer management for a given input type TI, now (int16_t)
- // Is agnostic of the actual type, can work with int32_t and float.
- template<typename TI>
- class InBuffer {
+ class InBuffer { // buffer management for input type TI
public:
InBuffer();
~InBuffer();
void init();
+
void resize(int CHANNELS, int halfNumCoefs);
// used for direct management of the mImpulse pointer
inline TI* getImpulse() {
return mImpulse;
}
+
inline void setImpulse(TI *impulse) {
mImpulse = impulse;
}
+
template<int CHANNELS>
inline void readAgain(TI*& impulse, const int halfNumCoefs,
const TI* const in, const size_t inputIndex);
+
template<int CHANNELS>
inline void readAdvance(TI*& impulse, const int halfNumCoefs,
const TI* const in, const size_t inputIndex);
@@ -94,31 +100,35 @@ private:
// tuning parameter guidelines: 2 <= multiple <= 8
static const int kStateSizeMultipleOfFilterLength = 4;
- TI* mState; // base pointer for the input buffer storage
- TI* mImpulse; // current location of the impulse response (centered)
- TI* mRingFull; // mState <= mImpulse < mRingFull
// in general, mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS.
- size_t mStateSize; // in units of TI.
+ TI* mState; // base pointer for the input buffer storage
+ TI* mImpulse; // current location of the impulse response (centered)
+ TI* mRingFull; // mState <= mImpulse < mRingFull
+ size_t mStateCount; // size of state in units of TI.
};
- template<int CHANNELS, bool LOCKED, int STRIDE, typename TC>
- void resample(int32_t* out, size_t outFrameCount,
- const TC* const coefs, AudioBufferProvider* provider);
-
- template<typename T>
void createKaiserFir(Constants &c, double stopBandAtten,
int inSampleRate, int outSampleRate, double tbwCheat);
- InBuffer<int16_t> mInBuffer;
- Constants mConstants; // current set of coefficient parameters
- int32_t __attribute__ ((aligned (8))) mVolumeSimd[2];
- int32_t mResampleType; // contains the resample type.
- int32_t mFilterSampleRate; // designed filter sample rate.
- src_quality mFilterQuality; // designed filter quality.
- void* mCoefBuffer; // if a filter is created, this is not null
+ void setResampler(unsigned resampleType);
+
+ template<int CHANNELS, bool LOCKED, int STRIDE>
+ void resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider);
+
+ // declare a pointer to member function for resample
+ typedef void (AudioResamplerDyn<TC, TI, TO>::*resample_ABP_t)(TO* out,
+ size_t outFrameCount, AudioBufferProvider* provider);
+
+ // data - the contiguous storage and layout of these is important.
+ InBuffer mInBuffer;
+ Constants mConstants; // current set of coefficient parameters
+ TO __attribute__ ((aligned (8))) mVolumeSimd[2]; // must be aligned or NEON may crash
+ resample_ABP_t mResampleFunc; // called function for resampling
+ int32_t mFilterSampleRate; // designed filter sample rate.
+ src_quality mFilterQuality; // designed filter quality.
+ void* mCoefBuffer; // if a filter is created, this is not null
};
-// ----------------------------------------------------------------------------
}; // namespace android
#endif /*ANDROID_AUDIO_RESAMPLER_DYN_H*/