AudioResamplerDyn.cpp revision 5e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2013 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "AudioResamplerDyn"
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define LOG_NDEBUG 0
19098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
20c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani#include <malloc.h>
21c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani#include <string.h>
22c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani#include <stdlib.h>
23c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani#include <dlfcn.h>
24fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten#include <math.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn#include <cutils/compiler.h>
276243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani#include <cutils/properties.h>
2882aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh#include <utils/Debug.h>
2982aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh#include <utils/Log.h>
3082aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh#include <audio_utils/primitives.h>
3182aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh
3282aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh#include "AudioResamplerFirOps.h" // USE_NEON and USE_INLINE_ASSEMBLY defined here
3382aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh#include "AudioResamplerFirProcess.h"
34bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly#include "AudioResamplerFirProcessNeon.h"
35d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi#include "AudioResamplerFirGen.h" // requires math.h
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "AudioResamplerDyn.h"
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define DEBUG_RESAMPLER
39a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
41f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi
42e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent/*
43e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent * InBuffer is a type agnostic input buffer.
44b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh *
4541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang * Layout of the state buffer for halfNumCoefs=8.
46212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent *
4741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang * [rrrrrrppppppppnnnnnnnnrrrrrrrrrrrrrrrrrrr.... rrrrrrr]
48c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean *  S            I                                R
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * S = mState
518fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi * I = mImpulse
52958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi * R = mRingFull
53a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * p = past samples, convoluted with the (p)ositive side of sinc()
540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * n = future samples, convoluted with the (n)egative side of sinc()
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * r = extra space for implementing the ring buffer
56c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent */
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate<typename TC, typename TI, typename TO>
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioResamplerDyn<TC, TI, TO>::InBuffer::InBuffer()
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mState(NULL), mImpulse(NULL), mRingFull(NULL), mStateCount(0)
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
62c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi}
63632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate<typename TC, typename TI, typename TO>
6533f4e04e32fac42f158733d6a731e50490fa9951John SpurlockAudioResamplerDyn<TC, TI, TO>::InBuffer::~InBuffer()
6682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh{
675ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn    init();
68bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent}
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate<typename TC, typename TI, typename TO>
71ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunnvoid AudioResamplerDyn<TC, TI, TO>::InBuffer::init()
72632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn{
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    free(mState);
74aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock    mState = NULL;
75a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    mImpulse = NULL;
76d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi    mRingFull = NULL;
77519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik    mStateCount = 0;
78bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi}
79bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi
80873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi// resizes the state buffer to accommodate the appropriate filter length
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate<typename TC, typename TI, typename TO>
82e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentvoid AudioResamplerDyn<TC, TI, TO>::InBuffer::resize(int CHANNELS, int halfNumCoefs)
830dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik{
84e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent    // calculate desired state size
85e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent    int stateCount = halfNumCoefs * CHANNELS * 2 * kStateSizeMultipleOfFilterLength;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
87d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi    // check if buffer needs resizing
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mState
89d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi            && stateCount == mStateCount
90e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent            && mRingFull-mState == mStateCount-halfNumCoefs*CHANNELS) {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
92c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent    }
93c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent
945a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganesh    // create new buffer
95c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent    TI* state;
9682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh    (void)posix_memalign(reinterpret_cast<void**>(&state), 32, stateCount*sizeof(*state));
97d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik    memset(state, 0, stateCount*sizeof(*state));
98c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent
99519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik    // attempt to preserve state
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mState) {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TI* srcLo = mImpulse - halfNumCoefs*CHANNELS;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TI* srcHi = mImpulse + halfNumCoefs*CHANNELS;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TI* dst = state;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (srcLo < mState) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dst += mState-srcLo;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            srcLo = mState;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (srcHi > mState + mStateCount) {
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            srcHi = mState + mStateCount;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(dst, srcLo, (srcHi - srcLo) * sizeof(*srcLo));
113fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        free(mState);
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // set class member vars
117339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi    mState = state;
118339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi    mStateCount = stateCount;
1198fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    mImpulse = state + halfNumCoefs*CHANNELS; // actually one sample greater than needed
1208fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    mRingFull = state + mStateCount - halfNumCoefs*CHANNELS;
1218fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi}
1228fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
1233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi// copy in the input data into the head (impulse+halfNumCoefs) of the buffer.
124ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlocktemplate<typename TC, typename TI, typename TO>
12518e7bce52318f00b5023f33933a571c477f2b61cJean-Michel Trivitemplate<int CHANNELS>
126430fc48865e5a371b08f180390946b96d73848feRoboErikvoid AudioResamplerDyn<TC, TI, TO>::InBuffer::readAgain(TI*& impulse, const int halfNumCoefs,
127ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        const TI* const in, const size_t inputIndex)
1288a2cfc309ab9126e90022916967c65a793c034f0RoboErik{
1298600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    TI* head = impulse + halfNumCoefs*CHANNELS;
1308600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    for (size_t i=0 ; i<CHANNELS ; i++) {
1318600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        head[i] = in[inputIndex*CHANNELS + i];
132a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock    }
133a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock}
134a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// advance the impulse pointer, and load in data into the head (impulse+halfNumCoefs)
13645edba1b8b0377dfe70a4f2b0afb0f04dd8e1ee9RoboEriktemplate<typename TC, typename TI, typename TO>
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate<int CHANNELS>
1383346a802087f621c6441bc512dfcc17b07143fc6John Spurlockvoid AudioResamplerDyn<TC, TI, TO>::InBuffer::readAdvance(TI*& impulse, const int halfNumCoefs,
1393346a802087f621c6441bc512dfcc17b07143fc6John Spurlock        const TI* const in, const size_t inputIndex)
1403346a802087f621c6441bc512dfcc17b07143fc6John Spurlock{
1413346a802087f621c6441bc512dfcc17b07143fc6John Spurlock    impulse += CHANNELS;
1423346a802087f621c6441bc512dfcc17b07143fc6John Spurlock
1433346a802087f621c6441bc512dfcc17b07143fc6John Spurlock    if (CC_UNLIKELY(impulse >= mRingFull)) {
1443346a802087f621c6441bc512dfcc17b07143fc6John Spurlock        const size_t shiftDown = mRingFull - mState - halfNumCoefs*CHANNELS;
1453346a802087f621c6441bc512dfcc17b07143fc6John Spurlock        memcpy(mState, mState+shiftDown, halfNumCoefs*CHANNELS*2*sizeof(TI));
146a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock        impulse -= shiftDown;
147a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock    }
148a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock    readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
149a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock}
150a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock
151ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborntemplate<typename TC, typename TI, typename TO>
152ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackbornvoid AudioResamplerDyn<TC, TI, TO>::Constants::set(
153ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn        int L, int halfNumCoefs, int inSampleRate, int outSampleRate)
154212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent{
155212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    int bits = 0;
156212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    int lscale = inSampleRate/outSampleRate < 2 ? L - 1 :
157212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent            static_cast<int>(static_cast<uint64_t>(L)*inSampleRate/outSampleRate);
158212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    for (int i=lscale; i; ++bits, i>>=1)
159212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        ;
160212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    mL = L;
161212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    mShift = kNumPhaseBits - bits;
162212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    mHalfNumCoefs = halfNumCoefs;
163212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent}
164212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent
165212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurenttemplate<typename TC, typename TI, typename TO>
166212532b58e3b17d7e9d6e1361946d909d4e372c2Eric LaurentAudioResamplerDyn<TC, TI, TO>::AudioResamplerDyn(
167212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        int inChannelCount, int32_t sampleRate, src_quality quality)
168212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    : AudioResampler(inChannelCount, sampleRate, quality),
169212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent      mResampleFunc(0), mFilterSampleRate(0), mFilterQuality(DEFAULT_QUALITY),
170212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    mCoefBuffer(NULL)
171d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi{
1723346a802087f621c6441bc512dfcc17b07143fc6John Spurlock    mVolumeSimd[0] = mVolumeSimd[1] = 0;
1733346a802087f621c6441bc512dfcc17b07143fc6John Spurlock    // The AudioResampler base class assumes we are always ready for 1:1 resampling.
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // We reset mInSampleRate to 0, so setSampleRate() will calculate filters for
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // setSampleRate() for 1:1. (May be removed if precalculated filters are used.)
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mInSampleRate = 0;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mConstants.set(128, 8, mSampleRate, mSampleRate); // TODO: set better
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttemplate<typename TC, typename TI, typename TO>
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioResamplerDyn<TC, TI, TO>::~AudioResamplerDyn()
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1833114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi    free(mCoefBuffer);
1849bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent}
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1865c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwoodtemplate<typename TC, typename TI, typename TO>
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioResamplerDyn<TC, TI, TO>::init()
188bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent{
189dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent    mFilterSampleRate = 0; // always trigger new filter generation
190dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent    mInBuffer.init();
191dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent}
192dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent
193dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurenttemplate<typename TC, typename TI, typename TO>
194dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurentvoid AudioResamplerDyn<TC, TI, TO>::setVolume(float left, float right)
195dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent{
196dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent    AudioResampler::setVolume(left, right);
197dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent    if (is_same<TO, float>::value || is_same<TO, double>::value) {
198dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent        mVolumeSimd[0] = static_cast<TO>(left);
199dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent        mVolumeSimd[1] = static_cast<TO>(right);
200dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent    } else {  // integer requires scaling to U4_28 (rounding down)
201dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent        // integer volumes are clamped to 0 to UNITY_GAIN so there
202dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent        // are no issues with signed overflow.
203dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent        mVolumeSimd[0] = u4_28_from_float(clampFloatVol(left));
204dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent        mVolumeSimd[1] = u4_28_from_float(clampFloatVol(right));
2054a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent    }
206aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock}
207b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds
2083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivitemplate<typename T> T max(T a, T b) {return a > b ? a : b;}
2093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi
210e12c39bb9cedb8b363658979872694eb55b1386eJean-Michel Trivitemplate<typename T> T absdiff(T a, T b) {return a > b ? a - b : b - a;}
211fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
2120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwoodtemplate<typename TC, typename TI, typename TO>
2130a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwoodvoid AudioResamplerDyn<TC, TI, TO>::createKaiserFir(Constants &c,
2143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi        double stopBandAtten, int inSampleRate, int outSampleRate, double tbwCheat)
215afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent{
2164c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi    TC* buf;
217dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent    static const double atten = 0.9998;   // to avoid ripple overflow
218dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent    double fcr;
219dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent    double tbw = firKaiserTbw(c.mHalfNumCoefs, stopBandAtten);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    (void)posix_memalign(reinterpret_cast<void**>(&buf), 32, (c.mL+1)*c.mHalfNumCoefs*sizeof(TC));
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (inSampleRate < outSampleRate) { // upsample
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fcr = max(0.5*tbwCheat - tbw/2, tbw/2);
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else { // downsample
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fcr = max(0.5*tbwCheat*outSampleRate/inSampleRate - tbw/2, tbw/2);
226b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh    }
227a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent    // create and set filter
228fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    firKaiserGen(buf, c.mL, c.mHalfNumCoefs, stopBandAtten, fcr, atten);
229ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten    c.mFirCoefs = buf;
230ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten    if (mCoefBuffer) {
23145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent        free(mCoefBuffer);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23330c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten    mCoefBuffer = buf;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef DEBUG_RESAMPLER
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // print basic filter stats
2364767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood    printf("L:%d  hnc:%d  stopBandAtten:%lf  fcr:%lf  atten:%lf  tbw:%lf\n",
2374767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood            c.mL, c.mHalfNumCoefs, stopBandAtten, fcr, atten, tbw);
2384767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood    // test the filter and report results
2394767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood    double fp = (fcr - tbw/2)/c.mL;
2406c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang    double fs = (fcr + tbw/2)/c.mL;
2416c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang    double passMin, passMax, passRipple;
2426c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang    double stopMax, stopRipple;
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    testFir(buf, c.mL, c.mHalfNumCoefs, fp, fs, /*passSteps*/ 1000, /*stopSteps*/ 100000,
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            passMin, passMax, passRipple, stopMax, stopRipple);
245e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent    printf("passband(%lf, %lf): %.8lf %.8lf %.8lf\n", 0., fp, passMin, passMax, passRipple);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("stopband(%lf, %lf): %.8lf %.3lf\n", fs, 0.5, stopMax, stopRipple);
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
250e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent// recursive gcd. Using objdump, it appears the tail recursion is converted to a while loop.
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int gcd(int n, int m)
2525982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles{
25391377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent    if (m == 0) {
2546ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent        return n;
2556ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent    }
2566ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent    return gcd(m, n % m);
2576ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent}
2586ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent
2596ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurentstatic bool isClose(int32_t newSampleRate, int32_t prevSampleRate,
2606ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent        int32_t filterSampleRate, int32_t outSampleRate)
2616ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent{
2626ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent
2636ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent    // different upsampling ratios do not need a filter change.
2645982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles    if (filterSampleRate != 0
26591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            && filterSampleRate < outSampleRate
26691377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            && newSampleRate < outSampleRate)
26791377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent        return true;
26891377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent
26991377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent    // check design criteria again if downsampling is detected.
27091377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent    int pdiff = absdiff(newSampleRate, prevSampleRate);
27191377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent    int adiff = absdiff(newSampleRate, filterSampleRate);
27291377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent
27391377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent    // allow up to 6% relative change increments.
27491377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent    // allow up to 12% absolute change increments (from filter design)
27591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent    return pdiff < prevSampleRate>>4 && adiff < filterSampleRate>>3;
27691377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent}
27791377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent
27891377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurenttemplate<typename TC, typename TI, typename TO>
2796d5176638c2189595cede38fb92c3e7e8700e221Eric Laurentvoid AudioResamplerDyn<TC, TI, TO>::setSampleRate(int32_t inSampleRate)
280a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent{
281a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent    if (mInSampleRate == inSampleRate) {
2826d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent        return;
2836d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent    }
28424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent    int32_t oldSampleRate = mInSampleRate;
285212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    int32_t oldHalfNumCoefs = mConstants.mHalfNumCoefs;
286212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    uint32_t oldPhaseWrapLimit = mConstants.mL << mConstants.mShift;
287212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    bool useS32 = false;
288212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent
2896d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent    mInSampleRate = inSampleRate;
2906d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent
2916d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent    // TODO: Add precalculated Equiripple filters
2926d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent
2936d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent    if (mFilterQuality != getQuality() ||
2946d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent            !isClose(inSampleRate, oldSampleRate, mFilterSampleRate, mSampleRate)) {
2956d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent        mFilterSampleRate = inSampleRate;
2966d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent        mFilterQuality = getQuality();
2976d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent
2986d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent        // Begin Kaiser Filter computation
299a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent        //
300212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        // The quantization floor for S16 is about 96db - 10*log_10(#length) + 3dB.
301212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        // Keep the stop band attenuation no greater than 84-85dB for 32 length S16 filters
302212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        //
303212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        // For s32 we keep the stop band attenuation at the same as 16b resolution, about
304212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        // 96-98dB
305212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        //
306212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent
307212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        double stopBandAtten;
308212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        double tbwCheat = 1.; // how much we "cheat" into aliasing
309212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        int halfLength;
310212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        if (mFilterQuality == DYN_HIGH_QUALITY) {
311212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent            // 32b coefficients, 64 length
312212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent            useS32 = true;
3136d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent            stopBandAtten = 98.;
3144f0f120316cfcee5880191264885772677fff921John Spurlock            if (inSampleRate >= mSampleRate * 4) {
3156d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent                halfLength = 48;
3166d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent            } else if (inSampleRate >= mSampleRate * 2) {
3176d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent                halfLength = 40;
3186d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent            } else {
3196d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent                halfLength = 32;
3204f0f120316cfcee5880191264885772677fff921John Spurlock            }
3214f0f120316cfcee5880191264885772677fff921John Spurlock        } else if (mFilterQuality == DYN_LOW_QUALITY) {
3226d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent            // 16b coefficients, 16-32 length
3236d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent            useS32 = false;
3246d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent            stopBandAtten = 80.;
325a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent            if (inSampleRate >= mSampleRate * 4) {
326ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn                halfLength = 24;
327ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            } else if (inSampleRate >= mSampleRate * 2) {
328ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn                halfLength = 16;
329ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            } else {
330ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn                halfLength = 8;
331ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            }
332ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            if (inSampleRate <= mSampleRate) {
333ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn                tbwCheat = 1.05;
334ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            } else {
335ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn                tbwCheat = 1.03;
336ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            }
337ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn        } else { // DYN_MED_QUALITY
338ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            // 16b coefficients, 32-64 length
339ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            // note: > 64 length filters with 16b coefs can have quantization noise problems
340ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            useS32 = false;
341ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            stopBandAtten = 84.;
342ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn            if (inSampleRate >= mSampleRate * 4) {
34383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent                halfLength = 32;
34483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent            } else if (inSampleRate >= mSampleRate * 2) {
345bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent                halfLength = 24;
3461af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            } else {
347bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent                halfLength = 16;
348bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent            }
349bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent            if (inSampleRate <= mSampleRate) {
350bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent                tbwCheat = 1.03;
351bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent            } else {
352bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent                tbwCheat = 1.01;
353bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent            }
354bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent        }
355bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent
356bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent        // determine the number of polyphases in the filterbank.
357bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent        // for 16b, it is desirable to have 2^(16/2) = 256 phases.
358bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent        // https://ccrma.stanford.edu/~jos/resample/Relation_Interpolation_Error_Quantization.html
35930c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten        //
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We are a bit more lax on this.
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int phases = mSampleRate / gcd(mSampleRate, inSampleRate);
363dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent
364dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent        // TODO: Once dynamic sample rate change is an option, the code below
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // should be modified to execute only when dynamic sample rate change is enabled.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // as above, #phases less than 63 is too few phases for accurate linear interpolation.
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // we increase the phases to compensate, but more phases means more memory per
369dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent        // filter and more time to compute the filter.
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // if we know that the filter will be used for dynamic sample rate changes,
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // that would allow us skip this part for fixed sample rate resamplers.
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (phases<63) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            phases *= 2; // this code only needed to support dynamic rate changes
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
377ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten
378661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock        if (phases>=256) {  // too many phases, always interpolate
379661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock            phases = 127;
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3819bcf401d13d47416043a704430388abd59aef7cdEric Laurent
38224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent        // create the filter
3839bcf401d13d47416043a704430388abd59aef7cdEric Laurent        mConstants.set(phases, halfLength, inSampleRate, mSampleRate);
3845b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent        createKaiserFir(mConstants, stopBandAtten,
3855b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent                inSampleRate, mSampleRate, tbwCheat);
3865b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent    } // End Kaiser filter
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // update phase and state based on the new filter.
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const Constants& c(mConstants);
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mInBuffer.resize(mChannelCount, c.mHalfNumCoefs);
391bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent    const uint32_t phaseWrapLimit = c.mL << c.mShift;
392bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent    // try to preserve as much of the phase fraction as possible for on-the-fly changes
393bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent    mPhaseFraction = static_cast<unsigned long long>(mPhaseFraction)
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            * phaseWrapLimit / oldPhaseWrapLimit;
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mPhaseFraction %= phaseWrapLimit; // should not do anything, but just in case.
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mPhaseIncrement = static_cast<uint32_t>(static_cast<double>(phaseWrapLimit)
397bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent            * inSampleRate / mSampleRate);
398bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent
399bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent    // determine which resampler to use
400a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent    // check if locked phase (works only if mPhaseIncrement has no "fractional phase bits")
401a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent    int locked = (mPhaseIncrement << (sizeof(mPhaseIncrement)*8 - c.mShift)) == 0;
402a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent    if (locked) {
403c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent        mPhaseFraction = mPhaseFraction >> c.mShift << c.mShift; // remove fractional phase
40430c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten    }
405c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent
406c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent    // stride is the minimum number of filter coefficients processed per loop iteration.
407c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent    // We currently only allow a stride of 16 to match with SIMD processing.
408c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent    // This means that the filter length must be a multiple of 16,
4090dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood    // or half the filter length (mHalfNumCoefs) must be a multiple of 8.
4100dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood    //
4110dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood    // Note: A stride of 2 is achieved with non-SIMD processing.
4129760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood    int stride = ((c.mHalfNumCoefs & 7) == 0) ? 16 : 2;
4139760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood    LOG_ALWAYS_FATAL_IF(stride < 16, "Resampler stride must be 16 or more");
4149272b4b4a44fe1f33e3030810618194f817caaecEric Laurent    LOG_ALWAYS_FATAL_IF(mChannelCount < 1 || mChannelCount > 8,
4159272b4b4a44fe1f33e3030810618194f817caaecEric Laurent            "Resampler channels(%d) must be between 1 to 8", mChannelCount);
41630c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten    // stride 16 (falls back to stride 2 for machines that do not support NEON)
417eb14a783be073b5fd6e8c8c9bc87d2d1919f2c9eEric Laurent    if (locked) {
4183def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent        switch (mChannelCount) {
41930c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten        case 1:
4203def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>;
4213def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent            break;
4223def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent        case 2:
4233def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>;
42482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh            break;
42582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh        case 3:
4263def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, true, 16>;
42762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent            break;
42862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent        case 4:
42962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, true, 16>;
43062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent            break;
43162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent        case 5:
432dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, true, 16>;
433dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent            break;
43425fc29b3691a1d2a84164988dc74b2e7d301868eEric Laurent        case 6:
435dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, true, 16>;
436dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent            break;
437dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent        case 7:
438dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, true, 16>;
43962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent            break;
44062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent        case 8:
44162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, true, 16>;
442dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent            break;
443dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent        }
444dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent    } else {
445dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent        switch (mChannelCount) {
446c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent        case 1:
447c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>;
448c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent            break;
449f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao        case 2:
450f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>;
451c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent            break;
452c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent        case 3:
453c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, false, 16>;
454c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent            break;
455f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao        case 4:
456f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, false, 16>;
457f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao            break;
458f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao        case 5:
459c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, false, 16>;
460dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent            break;
461dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent        case 6:
46262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, false, 16>;
463a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent            break;
4644a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent        case 7:
465a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, false, 16>;
466a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent            break;
467a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent        case 8:
468a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, false, 16>;
469a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent            break;
470a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent        }
471c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi    }
472f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi#ifdef DEBUG_RESAMPLER
47325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent    printf("channels:%d  %s  stride:%d  %s  coef:%d  shift:%d\n",
47425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent            mChannelCount, locked ? "locked" : "interpolated",
4756243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani            stride, useS32 ? "S32" : "S16", 2*c.mHalfNumCoefs, c.mShift);
4766243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani#endif
47745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent}
47845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent
47945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurenttemplate<typename TC, typename TI, typename TO>
48045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurentvoid AudioResamplerDyn<TC, TI, TO>::resample(int32_t* out, size_t outFrameCount,
48145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent            AudioBufferProvider* provider)
48245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent{
48345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent    (this->*mResampleFunc)(reinterpret_cast<TO*>(out), outFrameCount, provider);
48445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent}
485098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey
486098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeytemplate<typename TC, typename TI, typename TO>
4879bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurenttemplate<int CHANNELS, bool LOCKED, int STRIDE>
488f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivivoid AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
489bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi        AudioBufferProvider* provider)
490f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi{
4917847211fb4699bf6018e29d214a918ed6657319bEric Laurent    // TODO Mono -> Mono is not supported. OUTPUT_CHANNELS reflects minimum of stereo out.
4927847211fb4699bf6018e29d214a918ed6657319bEric Laurent    const int OUTPUT_CHANNELS = (CHANNELS < 2) ? 2 : CHANNELS;
4937847211fb4699bf6018e29d214a918ed6657319bEric Laurent    const Constants& c(mConstants);
4947847211fb4699bf6018e29d214a918ed6657319bEric Laurent    const TC* const coefs = mConstants.mFirCoefs;
495632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn    TI* impulse = mInBuffer.getImpulse();
496632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn    size_t inputIndex = 0;
497632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn    uint32_t phaseFraction = mPhaseFraction;
498632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn    const uint32_t phaseIncrement = mPhaseIncrement;
499632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn    size_t outputIndex = 0;
5004bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent    size_t outputSampleCount = outFrameCount * OUTPUT_CHANNELS;
501212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    const uint32_t phaseWrapLimit = c.mL << c.mShift;
5024bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent    size_t inFrameCount = (phaseIncrement * (uint64_t)outFrameCount + phaseFraction)
503212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent            / phaseWrapLimit;
504212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    // sanity check that inFrameCount is in signed 32 bit integer range.
505212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent    ALOG_ASSERT(0 <= inFrameCount && inFrameCount < (1U << 31));
506212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent
507ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi    //ALOGV("inFrameCount:%d  outFrameCount:%d"
5084bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent    //        "  phaseIncrement:%u  phaseFraction:%u  phaseWrapLimit:%u",
509bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi    //        inFrameCount, outFrameCount, phaseIncrement, phaseFraction, phaseWrapLimit);
510d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent
511bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi    // NOTE: be very careful when modifying the code here. register
512d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent    // pressure is very high and a small change might cause the compiler
5137ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent    // to generate far less efficient code.
5147ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent    // Always sanity check the result with objdump or test-resample.
51508ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent
51608ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent    // the following logic is a bit convoluted to keep the main processing loop
517fde16d5879ea88a971004c984093409468b6139cEric Laurent    // as tight as possible with register allocation.
518fde16d5879ea88a971004c984093409468b6139cEric Laurent    while (outputIndex < outputSampleCount) {
519fde16d5879ea88a971004c984093409468b6139cEric Laurent        //ALOGV("LOOP: inFrameCount:%d  outputIndex:%d  outFrameCount:%d"
520fde16d5879ea88a971004c984093409468b6139cEric Laurent        //        "  phaseFraction:%u  phaseWrapLimit:%u",
521fde16d5879ea88a971004c984093409468b6139cEric Laurent        //        inFrameCount, outputIndex, outFrameCount, phaseFraction, phaseWrapLimit);
522fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
523fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        // check inputIndex overflow
524fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        ALOG_ASSERT(inputIndex <= mBuffer.frameCount, "inputIndex%d > frameCount%d",
525fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                inputIndex, mBuffer.frameCount);
5265a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        // Buffer is empty, fetch a new one if necessary (inFrameCount > 0).
5275a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        // We may not fetch a new buffer if the existing data is sufficient.
5285a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du        while (mBuffer.frameCount == 0 && inFrameCount > 0) {
5295a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            mBuffer.frameCount = inFrameCount;
5305a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du            provider->getNextBuffer(&mBuffer,
5315a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du                    calculateOutputPTS(outputIndex / OUTPUT_CHANNELS));
532318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund            if (mBuffer.raw == NULL) {
533318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund                goto resample_exit;
534adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent            }
535adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent            inFrameCount -= mBuffer.frameCount;
536661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock            if (phaseFraction >= phaseWrapLimit) { // read in data
537661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock                mInBuffer.template readAdvance<CHANNELS>(
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        impulse, c.mHalfNumCoefs,
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                inputIndex++;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                phaseFraction -= phaseWrapLimit;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (phaseFraction >= phaseWrapLimit) {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (inputIndex >= mBuffer.frameCount) {
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        inputIndex = 0;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        provider->releaseBuffer(&mBuffer);
546ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn                        break;
547212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent                    }
548212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent                    mInBuffer.template readAdvance<CHANNELS>(
549212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent                            impulse, c.mHalfNumCoefs,
550212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent                            reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
551212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent                    inputIndex++;
5520b03f9909be438f45b32ce2a6a2c2c5208a82cc9Eric Laurent                    phaseFraction -= phaseWrapLimit;
553212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent                }
554212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent            }
555212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        }
556212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent        const TI* const in = reinterpret_cast<const TI*>(mBuffer.raw);
5575982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles        const size_t frameCount = mBuffer.frameCount;
558c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi        const int coefShift = c.mShift;
559fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        const int halfNumCoefs = c.mHalfNumCoefs;
560c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi        const TO* const volumeSimd = mVolumeSimd;
561bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent
562bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent        // main processing loop
563bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent        while (CC_LIKELY(outputIndex < outputSampleCount)) {
5645982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles            // caution: fir() is inlined and may be large.
56591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            // output will be loaded with the appropriate values
56691377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            //
56791377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            // from the input samples in impulse[-halfNumCoefs+1]... impulse[halfNumCoefs]
56891377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            // from the polyphase filter of (phaseFraction / phaseWrapLimit) in coefs.
56991377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            //
57091377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            //ALOGV("LOOP2: inFrameCount:%d  outputIndex:%d  outFrameCount:%d"
57191377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            //        "  phaseFraction:%u  phaseWrapLimit:%u",
57291377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            //        inFrameCount, outputIndex, outFrameCount, phaseFraction, phaseWrapLimit);
57391377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            ALOG_ASSERT(phaseFraction < phaseWrapLimit);
57491377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent            fir<CHANNELS, LOCKED, STRIDE>(
57591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent                    &out[outputIndex],
57691377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent                    phaseFraction, phaseWrapLimit,
5775982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles                    coefShift, halfNumCoefs, coefs,
578f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi                    impulse, volumeSimd);
579c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi
58025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent            outputIndex += OUTPUT_CHANNELS;
581c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent
582dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent            phaseFraction += phaseIncrement;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (phaseFraction >= phaseWrapLimit) {
584dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent                if (inputIndex >= frameCount) {
585fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                    goto done;  // need a new buffer
5863346a802087f621c6441bc512dfcc17b07143fc6John Spurlock                }
587fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                mInBuffer.template readAdvance<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
588dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent                inputIndex++;
589dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent                phaseFraction -= phaseWrapLimit;
590dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent            }
591dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent        }
592dd45d01128423a82652a3c9d77fa393631d95229Eric Laurentdone:
593dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent        // We arrive here when we're finished or when the input buffer runs out.
594dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent        // Regardless we need to release the input buffer if we've acquired it.
595dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent        if (inputIndex > 0) {  // we've acquired a buffer (alternatively could check frameCount)
596dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent            ALOG_ASSERT(inputIndex == frameCount, "inputIndex(%d) != frameCount(%d)",
597dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent                    inputIndex, frameCount);  // must have been fully read.
598dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent            inputIndex = 0;
599dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent            provider->releaseBuffer(&mBuffer);
600dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent            ALOG_ASSERT(mBuffer.frameCount == 0);
601dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent        }
60205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent    }
60305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent
60405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurentresample_exit:
60505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent    // inputIndex must be zero in all three cases:
60605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent    // (1) the buffer never was been acquired; (2) the buffer was
60705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent    // released at "done:"; or (3) getNextBuffer() failed.
60805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent    ALOG_ASSERT(inputIndex == 0, "Releasing: inputindex:%d frameCount:%d  phaseFraction:%u",
60905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent            inputIndex, mBuffer.frameCount, phaseFraction);
61083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent    ALOG_ASSERT(mBuffer.frameCount == 0); // there must be no frames in the buffer
61183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent    mInBuffer.setImpulse(impulse);
612da39290460b30e5080769f039d6dff352b3c7808Wally Yau    mPhaseFraction = phaseFraction;
613da39290460b30e5080769f039d6dff352b3c7808Wally Yau}
614da39290460b30e5080769f039d6dff352b3c7808Wally Yau
615da39290460b30e5080769f039d6dff352b3c7808Wally Yau/* instantiate templates used by AudioResampler::create */
61683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurenttemplate class AudioResamplerDyn<float, float, float>;
61724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurenttemplate class AudioResamplerDyn<int16_t, int16_t, int32_t>;
61824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurenttemplate class AudioResamplerDyn<int32_t, int16_t, int32_t>;
61924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
621c1d4166289ce016965d1147f7e8d37862ee347ecEric Laurent}; // namespace android
622a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent