AudioResamplerSinc.cpp revision 76b111685010e1fea7c0a865c038aee35507fde4
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 1776b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani#define LOG_TAG "AudioResamplerSinc" 1876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani//#define LOG_NDEBUG 0 1976b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani 2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <string.h> 2165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "AudioResamplerSinc.h" 2276b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani#include <dlfcn.h> 2376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani#include <cutils/properties.h> 2476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani#include <stdlib.h> 2576b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani#include <utils/Log.h> 2665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace android { 2865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 2965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/* 3265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * These coeficients are computed with the "fir" utility found in 3365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * tools/resampler_tools 3465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * TODO: A good optimization would be to transpose this matrix, to take 3565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * better advantage of the data-cache. 3665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 3765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianconst int32_t AudioResamplerSinc::mFirCoefsUp[] = { 3865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x7fffffff, 0x7f15d078, 0x7c5e0da6, 0x77ecd867, 0x71e2e251, 0x6a6c304a, 0x61be7269, 0x58170412, 0x4db8ab05, 0x42e92ea6, 0x37eee214, 0x2d0e3bb1, 0x22879366, 0x18951e95, 0x0f693d0d, 0x072d2621, 3965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xf9f66655, 0xf51a5fd7, 0xf16bbd84, 0xeee0d9ac, 0xed67a922, 0xece70de6, 0xed405897, 0xee50e505, 0xeff3be30, 0xf203370f, 0xf45a6741, 0xf6d67d53, 0xf957db66, 0xfbc2f647, 0xfe00f2b9, 4065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0x01b37218, 0x0313a0c6, 0x041d930d, 0x04d28057, 0x053731b0, 0x05534dff, 0x05309bfd, 0x04da440d, 0x045c1aee, 0x03c1fcdd, 0x03173ef5, 0x02663ae8, 0x01b7f736, 0x0113ec79, 0x007fe6a9, 4165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xff96b229, 0xff44f99f, 0xff0a86be, 0xfee5f803, 0xfed518fd, 0xfed521fd, 0xfee2f4fd, 0xfefb54f8, 0xff1b159b, 0xff3f4203, 0xff6539e0, 0xff8ac502, 0xffae1ddd, 0xffcdf3f9, 0xffe96798, 4265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0x00119de6, 0x001e6b7e, 0x0026cb7a, 0x002b4830, 0x002c83d6, 0x002b2a82, 0x0027e67a, 0x002356f9, 0x001e098e, 0x001875e4, 0x0012fbbe, 0x000de2d1, 0x00095c10, 0x00058414, 0x00026636, 4365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xfffe44a9, 0xfffd206d, 0xfffc7b7f, 0xfffc3c8f, 0xfffc4ac2, 0xfffc8f2b, 0xfffcf5c4, 0xfffd6df3, 0xfffdeab2, 0xfffe6275, 0xfffececf, 0xffff2c07, 0xffff788c, 0xffffb471, 0xffffe0f2, 4465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0x000013e6, 0x00001f03, 0x00002396, 0x00002399, 0x000020b6, 0x00001c3c, 0x00001722, 0x00001216, 0x00000d81, 0x0000099c, 0x0000067c, 0x00000419, 0x0000025f, 0x00000131, 0x00000070, 4565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xffffffc7, 0xffffffb3, 0xffffffb3, 0xffffffbe, 0xffffffcd, 0xffffffdb, 0xffffffe7, 0xfffffff0, 0xfffffff7, 0xfffffffb, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 4665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000 // this one is needed for lerping the last coefficient 4765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; 4865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 4965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/* 5065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * These coefficients are optimized for 48KHz -> 44.1KHz (stop-band at 22.050KHz) 5165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * It's possible to use the above coefficient for any down-sampling 5265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * at the expense of a slower processing loop (we can interpolate 5365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * these coefficient from the above by "Stretching" them in time). 5465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 5565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianconst int32_t AudioResamplerSinc::mFirCoefsDown[] = { 5665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x7fffffff, 0x7f55e46d, 0x7d5b4c60, 0x7a1b4b98, 0x75a7fb14, 0x7019f0bd, 0x698f875a, 0x622bfd59, 0x5a167256, 0x5178cc54, 0x487e8e6c, 0x3f53aae8, 0x36235ad4, 0x2d17047b, 0x245539ab, 0x1c00d540, 5765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x14383e57, 0x0d14d5ca, 0x06aa910b, 0x0107c38b, 0xfc351654, 0xf835abae, 0xf5076b45, 0xf2a37202, 0xf0fe9faa, 0xf00a3bbd, 0xefb4aa81, 0xefea2b05, 0xf0959716, 0xf1a11e83, 0xf2f6f7a0, 0xf481fff4, 5865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0xf62e48ce, 0xf7e98ca5, 0xf9a38b4c, 0xfb4e4bfa, 0xfcde456f, 0xfe4a6d30, 0xff8c2fdf, 0x009f5555, 0x0181d393, 0x0233940f, 0x02b62f06, 0x030ca07d, 0x033afa62, 0x03461725, 0x03334f83, 0x030835fa, 5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x02ca59cc, 0x027f12d1, 0x022b570d, 0x01d39a49, 0x017bb78f, 0x0126e414, 0x00d7aaaf, 0x008feec7, 0x0050f584, 0x001b73e3, 0xffefa063, 0xffcd46ed, 0xffb3ddcd, 0xffa29aaa, 0xff988691, 0xff949066, 6065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0xff959d24, 0xff9a959e, 0xffa27195, 0xffac4011, 0xffb72d2b, 0xffc28569, 0xffcdb706, 0xffd85171, 0xffe20364, 0xffea97e9, 0xfff1f2b2, 0xfff80c06, 0xfffcec92, 0x0000a955, 0x00035fd8, 0x000532cf, 6165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00064735, 0x0006c1f9, 0x0006c62d, 0x000673ba, 0x0005e68f, 0x00053630, 0x000475a3, 0x0003b397, 0x0002fac1, 0x00025257, 0x0001be9e, 0x0001417a, 0x0000dafd, 0x000089eb, 0x00004c28, 0x00001f1d, 6265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000, 0xffffec10, 0xffffe0be, 0xffffdbc5, 0xffffdb39, 0xffffdd8b, 0xffffe182, 0xffffe638, 0xffffeb0a, 0xffffef8f, 0xfffff38b, 0xfffff6e3, 0xfffff993, 0xfffffba6, 0xfffffd30, 0xfffffe4a, 6365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0xffffff09, 0xffffff85, 0xffffffd1, 0xfffffffb, 0x0000000f, 0x00000016, 0x00000015, 0x00000012, 0x0000000d, 0x00000009, 0x00000006, 0x00000003, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 6465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 0x00000000 // this one is needed for lerping the last coefficient 6565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; 6665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 6776b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani//Define the static variables 6876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Maniint AudioResamplerSinc::coefsBits; 6976b111685010e1fea7c0a865c038aee35507fde4SathishKumar Maniint AudioResamplerSinc::cShift; 7076b111685010e1fea7c0a865c038aee35507fde4SathishKumar Maniuint32_t AudioResamplerSinc::cMask; 7176b111685010e1fea7c0a865c038aee35507fde4SathishKumar Maniint AudioResamplerSinc::pShift; 7276b111685010e1fea7c0a865c038aee35507fde4SathishKumar Maniuint32_t AudioResamplerSinc::pMask; 7376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Maniunsigned int AudioResamplerSinc::halfNumCoefs; 7476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani 7565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 7665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 7765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic inline 7865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianint32_t mulRL(int left, int32_t in, uint32_t vRL) 7965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 8065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if defined(__arm__) && !defined(__thumb__) 8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t out; 8265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (left) { 8365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smultb %[out], %[in], %[vRL] \n" 8465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 8565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [in]"%r"(in), [vRL]"r"(vRL) 8665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 8765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 8865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smultt %[out], %[in], %[vRL] \n" 8965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 9065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [in]"%r"(in), [vRL]"r"(vRL) 9165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 9265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 9365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return out; 9465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#else 9565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (left) { 9665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return int16_t(in>>16) * int16_t(vRL&0xFFFF); 9765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 9865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return int16_t(in>>16) * int16_t(vRL>>16); 9965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 10065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 10165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 10265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 10365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic inline 10465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianint32_t mulAdd(int16_t in, int32_t v, int32_t a) 10565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 10665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if defined(__arm__) && !defined(__thumb__) 10765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t out; 10865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smlawb %[out], %[v], %[in], %[a] \n" 10965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 11065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [in]"%r"(in), [v]"r"(v), [a]"r"(a) 11165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 11265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return out; 11365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#else 11465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return a + in * (v>>16); 11565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // improved precision 11665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // return a + in * (v>>16) + ((in * (v & 0xffff)) >> 16); 11765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 11865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 11965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 12065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic inline 12165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianint32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a) 12265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 12365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#if defined(__arm__) && !defined(__thumb__) 12465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t out; 12565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (left) { 12665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smlawb %[out], %[v], %[inRL], %[a] \n" 12765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 12865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) 12965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 13065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 13165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian asm( "smlawt %[out], %[v], %[inRL], %[a] \n" 13265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [out]"=r"(out) 13365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a) 13465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : ); 13565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 13665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return out; 13765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#else 13865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (left) { 13965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return a + (int16_t(inRL&0xFFFF) * (v>>16)); 14065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian //improved precision 14165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // return a + (int16_t(inRL&0xFFFF) * (v>>16)) + ((int16_t(inRL&0xFFFF) * (v & 0xffff)) >> 16); 14265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 14365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return a + (int16_t(inRL>>16) * (v>>16)); 14465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 14565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif 14665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 14765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 14865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 14965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 15065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianAudioResamplerSinc::AudioResamplerSinc(int bitDepth, 15176b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani int inChannelCount, int32_t sampleRate, int32_t quality) 15265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian : AudioResampler(bitDepth, inChannelCount, sampleRate), 15365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mState(0) 15465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 15565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian /* 15665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Layout of the state buffer for 32 tap: 15765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 15865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * "present" sample beginning of 2nd buffer 15965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * v v 16065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 0 01 2 23 3 16165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 0 F0 0 F0 F 16265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * [pppppppppppppppInnnnnnnnnnnnnnnnpppppppppppppppInnnnnnnnnnnnnnnn] 16365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * ^ ^ head 16465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 16565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * p = past samples, convoluted with the (p)ositive side of sinc() 16665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * n = future samples, convoluted with the (n)egative side of sinc() 16765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * r = extra space for implementing the ring buffer 16865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 16965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 17065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 17176b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mResampleCoeffLib = NULL; 17276b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani //Intialize the parameters for resampler coefficients 17376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani //for high quality 17476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani coefsBits = RESAMPLE_FIR_LERP_INT_BITS; 17576b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani cShift = kNumPhaseBits - coefsBits; 17676b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani cMask = ((1<< coefsBits)-1) << cShift; 17776b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani 17876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani pShift = kNumPhaseBits - coefsBits - pLerpBits; 17976b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani pMask = ((1<< pLerpBits)-1) << pShift; 18076b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani 18176b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani halfNumCoefs = RESAMPLE_FIR_NUM_COEF; 18276b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani 18376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani //Check if qcom highest quality can be used 18476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani char value[PROPERTY_VALUE_MAX]; 18576b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani //Open the dll to get the coefficients for VERY_HIGH_QUALITY 18676b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani if (quality == VERY_HIGH_QUALITY ) { 18776b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mResampleCoeffLib = dlopen("libaudio-resampler.so", RTLD_NOW); 18876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani ALOGV("Open libaudio-resampler library = %p",mResampleCoeffLib); 18976b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani if (mResampleCoeffLib == NULL) { 19076b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani ALOGE("Could not open audio-resampler library: %s", dlerror()); 19176b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani return; 19276b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani } 19376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mReadResampleCoefficients = (readCoefficientsFn)dlsym(mResampleCoeffLib, "readResamplerCoefficients"); 19476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mReadResampleFirNumCoeff = (readResampleFirNumCoeffFn)dlsym(mResampleCoeffLib, "readResampleFirNumCoeff"); 19576b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mReadResampleFirLerpIntBits = (readResampleFirLerpIntBitsFn)dlsym(mResampleCoeffLib,"readResampleFirLerpIntBits"); 19676b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani if (!mReadResampleCoefficients || !mReadResampleFirNumCoeff || !mReadResampleFirLerpIntBits) { 19776b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mReadResampleCoefficients = NULL; 19876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mReadResampleFirNumCoeff = NULL; 19976b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mReadResampleFirLerpIntBits = NULL; 20076b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani dlclose(mResampleCoeffLib); 20176b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mResampleCoeffLib = NULL; 20276b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani ALOGE("Could not find convert symbol: %s", dlerror()); 20376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani return; 20476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani } 20576b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani // we have 16 coefs samples per zero-crossing 20676b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani coefsBits = mReadResampleFirLerpIntBits(); 20776b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani ALOGV("coefsBits = %d",coefsBits); 20876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani cShift = kNumPhaseBits - coefsBits; 20976b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani cMask = ((1<<coefsBits)-1) << cShift; 21076b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani pShift = kNumPhaseBits - coefsBits - pLerpBits; 21176b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani pMask = ((1<<pLerpBits)-1) << pShift; 21276b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani // number of zero-crossing on each side 21376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani halfNumCoefs = mReadResampleFirNumCoeff(); 21476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani ALOGV("halfNumCoefs = %d",halfNumCoefs); 21576b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani } 21665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 21765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 21876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani 21965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianAudioResamplerSinc::~AudioResamplerSinc() 22065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 22176b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani if(mResampleCoeffLib) { 22276b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani ALOGV("close the libaudio-resampler library"); 22376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani dlclose(mResampleCoeffLib); 22476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mResampleCoeffLib = NULL; 22576b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mReadResampleCoefficients = NULL; 22676b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mReadResampleFirNumCoeff = NULL; 22776b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mReadResampleFirLerpIntBits = NULL; 22876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani } 22965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian delete [] mState; 23065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 23165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 23265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::init() { 23376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani 23476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani const size_t numCoefs = 2*halfNumCoefs; 23576b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani const size_t stateSize = numCoefs * mChannelCount * 2; 23676b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mState = new int16_t[stateSize]; 23776b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani memset(mState, 0, sizeof(int16_t)*stateSize); 23876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mImpulse = mState + (halfNumCoefs-1)*mChannelCount; 23976b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mRingFull = mImpulse + (numCoefs+1)*mChannelCount; 24065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 24165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 24265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, 24365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* provider) 24465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 24576b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani 24676b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani if(mResampleCoeffLib){ 24776b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani ALOGV("get coefficient from libmm-audio resampler library"); 24876b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mFirCoefs = (mInSampleRate <= mSampleRate) ? mReadResampleCoefficients(true) : mReadResampleCoefficients(false); 24976b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani } 25076b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani else { 25176b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani ALOGV("Use default coefficients"); 25276b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown; 25376b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani } 25465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 25565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // select the appropriate resampler 25665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian switch (mChannelCount) { 25765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case 1: 25865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian resample<1>(out, outFrameCount, provider); 25965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; 26065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case 2: 26165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian resample<2>(out, outFrameCount, provider); 26265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; 26365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 26476b111685010e1fea7c0a865c038aee35507fde4SathishKumar Mani 26565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 26665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 26765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 26865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS> 26965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount, 27065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* provider) 27165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 27265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t* impulse = mImpulse; 27365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t vRL = mVolumeRL; 27465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inputIndex = mInputIndex; 27565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseFraction = mPhaseFraction; 27665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseIncrement = mPhaseIncrement; 27765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputIndex = 0; 27865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputSampleCount = outFrameCount * 2; 27965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; 28065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 28165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (outputIndex < outputSampleCount) { 28265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // buffer is empty, fetch a new one 283d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten while (mBuffer.frameCount == 0) { 284d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten mBuffer.frameCount = inFrameCount; 2854ff14bae91075eb274eb1c2975982358946e7e63John Grossman provider->getNextBuffer(&mBuffer, 2864ff14bae91075eb274eb1c2975982358946e7e63John Grossman calculateOutputPTS(outputIndex / 2)); 287d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten if (mBuffer.raw == NULL) { 28865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto resample_exit; 28965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 29065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; 29165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (phaseIndex == 1) { 29265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // read one frame 293d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten read<CHANNELS>(impulse, phaseFraction, mBuffer.i16, inputIndex); 29465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else if (phaseIndex == 2) { 29565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // read 2 frames 296d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten read<CHANNELS>(impulse, phaseFraction, mBuffer.i16, inputIndex); 29765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 29865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= mBuffer.frameCount) { 29965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex -= mBuffer.frameCount; 300d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten provider->releaseBuffer(&mBuffer); 30165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 302d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten read<CHANNELS>(impulse, phaseFraction, mBuffer.i16, inputIndex); 30365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 304e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten } 30565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 306d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten int16_t *in = mBuffer.i16; 307d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten const size_t frameCount = mBuffer.frameCount; 30865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 30965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Always read-in the first samples from the input buffer 31065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t* head = impulse + halfNumCoefs*CHANNELS; 31165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian head[0] = in[inputIndex*CHANNELS + 0]; 31265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (CHANNELS == 2) 31365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian head[1] = in[inputIndex*CHANNELS + 1]; 31465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 31565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // handle boundary case 31665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t l, r; 31765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (outputIndex < outputSampleCount) { 31865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian filterCoefficient<CHANNELS>(l, r, phaseFraction, impulse); 31965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += 2 * mulRL(1, l, vRL); 32065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += 2 * mulRL(0, r, vRL); 32165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 32265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction += phaseIncrement; 32365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; 32465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (phaseIndex == 1) { 32565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 32665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= frameCount) 32765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; // need a new buffer 32865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian read<CHANNELS>(impulse, phaseFraction, in, inputIndex); 329e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten } else if (phaseIndex == 2) { // maximum value 33065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 33165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= frameCount) 33265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; // 0 frame available, 2 frames needed 33365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // read first frame 33465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian read<CHANNELS>(impulse, phaseFraction, in, inputIndex); 33565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 33665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= frameCount) 33765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; // 0 frame available, 1 frame needed 33865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // read second frame 33965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian read<CHANNELS>(impulse, phaseFraction, in, inputIndex); 34065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 34165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 34265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 34365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // if done with buffer, save samples 34465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex >= frameCount) { 34565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex -= frameCount; 346d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten provider->releaseBuffer(&mBuffer); 34765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 34865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 34965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 35065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianresample_exit: 35165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mImpulse = impulse; 35265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mInputIndex = inputIndex; 35365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mPhaseFraction = phaseFraction; 35465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 35565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 35665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS> 35765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/*** 35865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* read() 35965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* 36065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* This function reads only one frame from input buffer and writes it in 36165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* state buffer 36265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* 36365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian**/ 36465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::read( 36565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t*& impulse, uint32_t& phaseFraction, 36654c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int16_t* in, size_t inputIndex) 36765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 36865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits; 36965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian impulse += CHANNELS; 37065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction -= 1LU<<kNumPhaseBits; 37165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (impulse >= mRingFull) { 37265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const size_t stateSize = (halfNumCoefs*2)*CHANNELS; 37365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize); 37465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian impulse -= stateSize; 37565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 37665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t* head = impulse + halfNumCoefs*CHANNELS; 37765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian head[0] = in[inputIndex*CHANNELS + 0]; 37865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (CHANNELS == 2) 37965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian head[1] = in[inputIndex*CHANNELS + 1]; 38065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 38165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 38265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS> 38365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::filterCoefficient( 38454c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten int32_t& l, int32_t& r, uint32_t phase, const int16_t *samples) 38565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 38665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // compute the index of the coefficient on the positive side and 38765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // negative side 38865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t indexP = (phase & cMask) >> cShift; 38965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint16_t lerpP = (phase & pMask) >> pShift; 39065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t indexN = (-phase & cMask) >> cShift; 39165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint16_t lerpN = (-phase & pMask) >> pShift; 39265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if ((indexP == 0) && (lerpP == 0)) { 39365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian indexN = cMask >> cShift; 39465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian lerpN = pMask >> pShift; 39565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 39665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 39765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian l = 0; 39865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian r = 0; 39954c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int32_t* coefs = mFirCoefs; 40054c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int16_t *sP = samples; 40154c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int16_t *sN = samples+CHANNELS; 40265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) { 40365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); 40465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); 40565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; 40665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); 40765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); 40865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; 40965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); 41065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); 41165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; 41265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP); 41365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN); 41465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits; 41565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 41665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 41765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 41865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS> 41965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::interpolate( 42065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t& l, int32_t& r, 42154c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const int32_t* coefs, int16_t lerp, const int16_t* samples) 42265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 42365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t c0 = coefs[0]; 42465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t c1 = coefs[1]; 42565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t sinc = mulAdd(lerp, (c1-c0)<<1, c0); 42665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (CHANNELS == 2) { 42754c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten uint32_t rl = *reinterpret_cast<const uint32_t*>(samples); 42865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian l = mulAddRL(1, rl, sinc, l); 42965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian r = mulAddRL(0, rl, sinc, r); 43065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } else { 43165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian r = l = mulAdd(samples[0], sinc, l); 43265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 43365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 43465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 43565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; // namespace android 436