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