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