AudioResamplerSinc.cpp revision 54c3b66444ebfb9f2265ee70ac3b76ccefa0506a
165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/* 265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Copyright (C) 2007 The Android Open Source Project 365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License"); 565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * you may not use this file except in compliance with the License. 665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * You may obtain a copy of the License at 765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * http://www.apache.org/licenses/LICENSE-2.0 965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 1065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Unless required by applicable law or agreed to in writing, software 1165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS, 1265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * See the License for the specific language governing permissions and 1465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * limitations under the License. 1565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 1665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <string.h> 1865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "AudioResamplerSinc.h" 1965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace android { 2165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 2265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/* 2565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * These coeficients are computed with the "fir" utility found in 2665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * tools/resampler_tools 2765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * TODO: A good optimization would be to transpose this matrix, to take 2865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * better advantage of the data-cache. 2965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 3065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianconst int32_t AudioResamplerSinc::mFirCoefsUp[] = { 3165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x7fffffff, 0x7f15d078, 0x7c5e0da6, 0x77ecd867, 0x71e2e251, 0x6a6c304a, 0x61be7269, 0x58170412, 0x4db8ab05, 0x42e92ea6, 0x37eee214, 0x2d0e3bb1, 0x22879366, 0x18951e95, 0x0f693d0d, 0x072d2621, 3265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xf9f66655, 0xf51a5fd7, 0xf16bbd84, 0xeee0d9ac, 0xed67a922, 0xece70de6, 0xed405897, 0xee50e505, 0xeff3be30, 0xf203370f, 0xf45a6741, 0xf6d67d53, 0xf957db66, 0xfbc2f647, 0xfe00f2b9, 3365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0x01b37218, 0x0313a0c6, 0x041d930d, 0x04d28057, 0x053731b0, 0x05534dff, 0x05309bfd, 0x04da440d, 0x045c1aee, 0x03c1fcdd, 0x03173ef5, 0x02663ae8, 0x01b7f736, 0x0113ec79, 0x007fe6a9, 3465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xff96b229, 0xff44f99f, 0xff0a86be, 0xfee5f803, 0xfed518fd, 0xfed521fd, 0xfee2f4fd, 0xfefb54f8, 0xff1b159b, 0xff3f4203, 0xff6539e0, 0xff8ac502, 0xffae1ddd, 0xffcdf3f9, 0xffe96798, 3565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0x00119de6, 0x001e6b7e, 0x0026cb7a, 0x002b4830, 0x002c83d6, 0x002b2a82, 0x0027e67a, 0x002356f9, 0x001e098e, 0x001875e4, 0x0012fbbe, 0x000de2d1, 0x00095c10, 0x00058414, 0x00026636, 3665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xfffe44a9, 0xfffd206d, 0xfffc7b7f, 0xfffc3c8f, 0xfffc4ac2, 0xfffc8f2b, 0xfffcf5c4, 0xfffd6df3, 0xfffdeab2, 0xfffe6275, 0xfffececf, 0xffff2c07, 0xffff788c, 0xffffb471, 0xffffe0f2, 3765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0x000013e6, 0x00001f03, 0x00002396, 0x00002399, 0x000020b6, 0x00001c3c, 0x00001722, 0x00001216, 0x00000d81, 0x0000099c, 0x0000067c, 0x00000419, 0x0000025f, 0x00000131, 0x00000070, 3865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xffffffc7, 0xffffffb3, 0xffffffb3, 0xffffffbe, 0xffffffcd, 0xffffffdb, 0xffffffe7, 0xfffffff0, 0xfffffff7, 0xfffffffb, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 3965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000 // this one is needed for lerping the last coefficient 4065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; 4165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 4265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/* 4365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * These coefficients are optimized for 48KHz -> 44.1KHz (stop-band at 22.050KHz) 4465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * It's possible to use the above coefficient for any down-sampling 4565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * at the expense of a slower processing loop (we can interpolate 4665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * these coefficient from the above by "Stretching" them in time). 4765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 4865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianconst int32_t AudioResamplerSinc::mFirCoefsDown[] = { 4965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x7fffffff, 0x7f55e46d, 0x7d5b4c60, 0x7a1b4b98, 0x75a7fb14, 0x7019f0bd, 0x698f875a, 0x622bfd59, 0x5a167256, 0x5178cc54, 0x487e8e6c, 0x3f53aae8, 0x36235ad4, 0x2d17047b, 0x245539ab, 0x1c00d540, 5065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x14383e57, 0x0d14d5ca, 0x06aa910b, 0x0107c38b, 0xfc351654, 0xf835abae, 0xf5076b45, 0xf2a37202, 0xf0fe9faa, 0xf00a3bbd, 0xefb4aa81, 0xefea2b05, 0xf0959716, 0xf1a11e83, 0xf2f6f7a0, 0xf481fff4, 5165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0xf62e48ce, 0xf7e98ca5, 0xf9a38b4c, 0xfb4e4bfa, 0xfcde456f, 0xfe4a6d30, 0xff8c2fdf, 0x009f5555, 0x0181d393, 0x0233940f, 0x02b62f06, 0x030ca07d, 0x033afa62, 0x03461725, 0x03334f83, 0x030835fa, 5265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x02ca59cc, 0x027f12d1, 0x022b570d, 0x01d39a49, 0x017bb78f, 0x0126e414, 0x00d7aaaf, 0x008feec7, 0x0050f584, 0x001b73e3, 0xffefa063, 0xffcd46ed, 0xffb3ddcd, 0xffa29aaa, 0xff988691, 0xff949066, 5365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0xff959d24, 0xff9a959e, 0xffa27195, 0xffac4011, 0xffb72d2b, 0xffc28569, 0xffcdb706, 0xffd85171, 0xffe20364, 0xffea97e9, 0xfff1f2b2, 0xfff80c06, 0xfffcec92, 0x0000a955, 0x00035fd8, 0x000532cf, 5465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00064735, 0x0006c1f9, 0x0006c62d, 0x000673ba, 0x0005e68f, 0x00053630, 0x000475a3, 0x0003b397, 0x0002fac1, 0x00025257, 0x0001be9e, 0x0001417a, 0x0000dafd, 0x000089eb, 0x00004c28, 0x00001f1d, 5565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xffffec10, 0xffffe0be, 0xffffdbc5, 0xffffdb39, 0xffffdd8b, 0xffffe182, 0xffffe638, 0xffffeb0a, 0xffffef8f, 0xfffff38b, 0xfffff6e3, 0xfffff993, 0xfffffba6, 0xfffffd30, 0xfffffe4a, 5665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0xffffff09, 0xffffff85, 0xffffffd1, 0xfffffffb, 0x0000000f, 0x00000016, 0x00000015, 0x00000012, 0x0000000d, 0x00000009, 0x00000006, 0x00000003, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 5765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000 // this one is needed for lerping the last coefficient 5865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; 5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 6065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 6165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 6265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic inline 6365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianint32_t mulRL(int left, int32_t in, uint32_t vRL) 6465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 6565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if defined(__arm__) && !defined(__thumb__) 6665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t out; 6765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (left) { 6865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smultb %[out], %[in], %[vRL] \n" 6965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 7065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [in]"%r"(in), [vRL]"r"(vRL) 7165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 7265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 7365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smultt %[out], %[in], %[vRL] \n" 7465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 7565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [in]"%r"(in), [vRL]"r"(vRL) 7665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 7765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 7865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return out; 7965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#else 8065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (left) { 8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return int16_t(in>>16) * int16_t(vRL&0xFFFF); 8265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 8365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return int16_t(in>>16) * int16_t(vRL>>16); 8465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 8565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 8665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 8765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 8865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic inline 8965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianint32_t mulAdd(int16_t in, int32_t v, int32_t a) 9065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 9165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if defined(__arm__) && !defined(__thumb__) 9265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t out; 9365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smlawb %[out], %[v], %[in], %[a] \n" 9465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 9565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 9665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 9765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return out; 9865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#else 9965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return a + in * (v>>16); 10065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // improved precision 10165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // return a + in * (v>>16) + ((in * (v & 0xffff)) >> 16); 10265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 10365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 10465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 10565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic inline 10665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianint32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a) 10765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 10865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if defined(__arm__) && !defined(__thumb__) 10965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t out; 11065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (left) { 11165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smlawb %[out], %[v], %[inRL], %[a] \n" 11265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 11365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) 11465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 11565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 11665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smlawt %[out], %[v], %[inRL], %[a] \n" 11765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 11865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) 11965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 12065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 12165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return out; 12265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#else 12365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (left) { 12465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return a + (int16_t(inRL&0xFFFF) * (v>>16)); 12565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian //improved precision 12665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // return a + (int16_t(inRL&0xFFFF) * (v>>16)) + ((int16_t(inRL&0xFFFF) * (v & 0xffff)) >> 16); 12765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 12865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return a + (int16_t(inRL>>16) * (v>>16)); 12965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 13065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 13165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 13265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 13365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 13465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 13565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianAudioResamplerSinc::AudioResamplerSinc(int bitDepth, 13665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int inChannelCount, int32_t sampleRate) 13765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : AudioResampler(bitDepth, inChannelCount, sampleRate), 13865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mState(0) 13965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 14065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian /* 14165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Layout of the state buffer for 32 tap: 14265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 14365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * "present" sample beginning of 2nd buffer 14465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * v v 14565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 0 01 2 23 3 14665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 0 F0 0 F0 F 14765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * [pppppppppppppppInnnnnnnnnnnnnnnnpppppppppppppppInnnnnnnnnnnnnnnn] 14865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * ^ ^ head 14965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 15065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * p = past samples, convoluted with the (p)ositive side of sinc() 15165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * n = future samples, convoluted with the (n)egative side of sinc() 15265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * r = extra space for implementing the ring buffer 15365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 15465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 15565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 15665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const size_t numCoefs = 2*halfNumCoefs; 15765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const size_t stateSize = numCoefs * inChannelCount * 2; 15865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mState = new int16_t[stateSize]; 15965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian memset(mState, 0, sizeof(int16_t)*stateSize); 16065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mImpulse = mState + (halfNumCoefs-1)*inChannelCount; 16165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mRingFull = mImpulse + (numCoefs+1)*inChannelCount; 16265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 16365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 16465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianAudioResamplerSinc::~AudioResamplerSinc() 16565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 16665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian delete [] mState; 16765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 16865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 16965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::init() { 17065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 17165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 17265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, 17365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* provider) 17465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 17565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown; 17665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 17765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // select the appropriate resampler 17865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian switch (mChannelCount) { 17965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case 1: 18065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian resample<1>(out, outFrameCount, provider); 18165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; 18265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case 2: 18365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian resample<2>(out, outFrameCount, provider); 18465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; 18565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 18665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 18765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 18865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 18965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS> 19065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, 19165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* provider) 19265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 19365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t* impulse = mImpulse; 19465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t vRL = mVolumeRL; 19565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inputIndex = mInputIndex; 19665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseFraction = mPhaseFraction; 19765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseIncrement = mPhaseIncrement; 19865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputIndex = 0; 19965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputSampleCount = outFrameCount * 2; 20065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; 20165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 20265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider::Buffer& buffer(mBuffer); 20365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (outputIndex < outputSampleCount) { 20465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // buffer is empty, fetch a new one 20565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (buffer.frameCount == 0) { 20665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian buffer.frameCount = inFrameCount; 20765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian provider->getNextBuffer(&buffer); 20865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (buffer.raw == NULL) { 20965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto resample_exit; 21065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 21165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; 21265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (phaseIndex == 1) { 21365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // read one frame 21465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex); 21565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else if (phaseIndex == 2) { 21665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // read 2 frames 21765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex); 21865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 21965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= mBuffer.frameCount) { 22065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex -= mBuffer.frameCount; 22165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian provider->releaseBuffer(&buffer); 22265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 22365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex); 22465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 22565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 22665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 22765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t *in = buffer.i16; 22865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const size_t frameCount = buffer.frameCount; 22965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 23065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Always read-in the first samples from the input buffer 23165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t* head = impulse + halfNumCoefs*CHANNELS; 23265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian head[0] = in[inputIndex*CHANNELS + 0]; 23365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (CHANNELS == 2) 23465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian head[1] = in[inputIndex*CHANNELS + 1]; 23565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 23665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // handle boundary case 23765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t l, r; 23865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (outputIndex < outputSampleCount) { 23965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian filterCoefficient<CHANNELS>(l, r, phaseFraction, impulse); 24065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += 2 * mulRL(1, l, vRL); 24165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += 2 * mulRL(0, r, vRL); 24265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 24365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction += phaseIncrement; 24465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; 24565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (phaseIndex == 1) { 24665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 24765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= frameCount) 24865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; // need a new buffer 24965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian read<CHANNELS>(impulse, phaseFraction, in, inputIndex); 25065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else if(phaseIndex == 2) { // maximum value 25165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 25265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= frameCount) 25365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; // 0 frame available, 2 frames needed 25465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // read first frame 25565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian read<CHANNELS>(impulse, phaseFraction, in, inputIndex); 25665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 25765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= frameCount) 25865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; // 0 frame available, 1 frame needed 25965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // read second frame 26065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian read<CHANNELS>(impulse, phaseFraction, in, inputIndex); 26165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 26265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 26365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 26465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // if done with buffer, save samples 26565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= frameCount) { 26665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex -= frameCount; 26765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian provider->releaseBuffer(&buffer); 26865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 26965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 27065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 27165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianresample_exit: 27265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mImpulse = impulse; 27365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mInputIndex = inputIndex; 27465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mPhaseFraction = phaseFraction; 27565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 27665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 27765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS> 27865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/*** 27965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* read() 28065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* 28165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* This function reads only one frame from input buffer and writes it in 28265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* state buffer 28365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* 28465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian**/ 28565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::read( 28665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t*& impulse, uint32_t& phaseFraction, 28754c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int16_t* in, size_t inputIndex) 28865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 28965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; 29065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian impulse += CHANNELS; 29165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction -= 1LU<<kNumPhaseBits; 29265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (impulse >= mRingFull) { 29365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const size_t stateSize = (halfNumCoefs*2)*CHANNELS; 29465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize); 29565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian impulse -= stateSize; 29665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 29765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t* head = impulse + halfNumCoefs*CHANNELS; 29865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian head[0] = in[inputIndex*CHANNELS + 0]; 29965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (CHANNELS == 2) 30065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian head[1] = in[inputIndex*CHANNELS + 1]; 30165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 30265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 30365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS> 30465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::filterCoefficient( 30554c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten int32_t& l, int32_t& r, uint32_t phase, const int16_t *samples) 30665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 30765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // compute the index of the coefficient on the positive side and 30865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // negative side 30965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t indexP = (phase & cMask) >> cShift; 31065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint16_t lerpP = (phase & pMask) >> pShift; 31165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t indexN = (-phase & cMask) >> cShift; 31265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint16_t lerpN = (-phase & pMask) >> pShift; 31365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if ((indexP == 0) && (lerpP == 0)) { 31465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian indexN = cMask >> cShift; 31565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian lerpN = pMask >> pShift; 31665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 31765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 31865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian l = 0; 31965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian r = 0; 32054c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int32_t* coefs = mFirCoefs; 32154c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int16_t *sP = samples; 32254c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int16_t *sN = samples+CHANNELS; 32365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) { 32465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); 32565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); 32665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; 32765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); 32865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); 32965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; 33065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); 33165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); 33265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; 33365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); 33465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); 33565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; 33665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 33765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 33865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 33965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS> 34065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::interpolate( 34165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t& l, int32_t& r, 34254c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int32_t* coefs, int16_t lerp, const int16_t* samples) 34365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 34465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t c0 = coefs[0]; 34565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t c1 = coefs[1]; 34665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t sinc = mulAdd(lerp, (c1-c0)<<1, c0); 34765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (CHANNELS == 2) { 34854c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten uint32_t rl = *reinterpret_cast<const uint32_t*>(samples); 34965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian l = mulAddRL(1, rl, sinc, l); 35065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian r = mulAddRL(0, rl, sinc, r); 35165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 35265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian r = l = mulAdd(samples[0], sinc, l); 35365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 35465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 35565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 35665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 35765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; // namespace android 35865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 359