AudioResamplerSinc.cpp revision d198b61603d5fa9298edea4ddb5852ea45159906
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    while (outputIndex < outputSampleCount) {
20365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // buffer is empty, fetch a new one
204d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten        while (mBuffer.frameCount == 0) {
205d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten            mBuffer.frameCount = inFrameCount;
206d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten            provider->getNextBuffer(&mBuffer);
207d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten            if (mBuffer.raw == NULL) {
20865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                goto resample_exit;
20965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            }
21065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
21165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            if (phaseIndex == 1) {
21265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                // read one frame
213d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten                read<CHANNELS>(impulse, phaseFraction, mBuffer.i16, inputIndex);
21465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            } else if (phaseIndex == 2) {
21565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                // read 2 frames
216d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten                read<CHANNELS>(impulse, phaseFraction, mBuffer.i16, inputIndex);
21765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                inputIndex++;
21865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                if (inputIndex >= mBuffer.frameCount) {
21965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    inputIndex -= mBuffer.frameCount;
220d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten                    provider->releaseBuffer(&mBuffer);
22165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                } else {
222d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten                    read<CHANNELS>(impulse, phaseFraction, mBuffer.i16, inputIndex);
22365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                }
22465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian           }
22565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
226d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten        int16_t *in = mBuffer.i16;
227d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten        const size_t frameCount = mBuffer.frameCount;
22865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
22965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // Always read-in the first samples from the input buffer
23065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        int16_t* head = impulse + halfNumCoefs*CHANNELS;
23165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        head[0] = in[inputIndex*CHANNELS + 0];
23265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (CHANNELS == 2)
23365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            head[1] = in[inputIndex*CHANNELS + 1];
23465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
23565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // handle boundary case
23665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        int32_t l, r;
23765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        while (outputIndex < outputSampleCount) {
23865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            filterCoefficient<CHANNELS>(l, r, phaseFraction, impulse);
23965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            out[outputIndex++] += 2 * mulRL(1, l, vRL);
24065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            out[outputIndex++] += 2 * mulRL(0, r, vRL);
24165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
24265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            phaseFraction += phaseIncrement;
24365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
24465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            if (phaseIndex == 1) {
24565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                inputIndex++;
24665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                if (inputIndex >= frameCount)
24765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    break;  // need a new buffer
24865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
24965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            } else if(phaseIndex == 2) {    // maximum value
25065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                inputIndex++;
25165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                if (inputIndex >= frameCount)
25265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    break;  // 0 frame available, 2 frames needed
25365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                // read first frame
25465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
25565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                inputIndex++;
25665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                if (inputIndex >= frameCount)
25765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    break;  // 0 frame available, 1 frame needed
25865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                // read second frame
25965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
26065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            }
26165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
26265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
26365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        // if done with buffer, save samples
26465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (inputIndex >= frameCount) {
26565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            inputIndex -= frameCount;
266d198b61603d5fa9298edea4ddb5852ea45159906Glenn Kasten            provider->releaseBuffer(&mBuffer);
26765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
26865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
26965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
27065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianresample_exit:
27165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mImpulse = impulse;
27265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mInputIndex = inputIndex;
27365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mPhaseFraction = phaseFraction;
27465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
27565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
27665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS>
27765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/***
27865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* read()
27965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian*
28065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* This function reads only one frame from input buffer and writes it in
28165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian* state buffer
28265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian*
28365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian**/
28465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::read(
28565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        int16_t*& impulse, uint32_t& phaseFraction,
28654c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten        const int16_t* in, size_t inputIndex)
28765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
28865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
28965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    impulse += CHANNELS;
29065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    phaseFraction -= 1LU<<kNumPhaseBits;
29165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (impulse >= mRingFull) {
29265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        const size_t stateSize = (halfNumCoefs*2)*CHANNELS;
29365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize);
29465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        impulse -= stateSize;
29565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
29665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int16_t* head = impulse + halfNumCoefs*CHANNELS;
29765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    head[0] = in[inputIndex*CHANNELS + 0];
29865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (CHANNELS == 2)
29965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        head[1] = in[inputIndex*CHANNELS + 1];
30065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
30165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
30265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS>
30365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::filterCoefficient(
30454c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten        int32_t& l, int32_t& r, uint32_t phase, const int16_t *samples)
30565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
30665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // compute the index of the coefficient on the positive side and
30765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // negative side
30865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    uint32_t indexP = (phase & cMask) >> cShift;
30965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    uint16_t lerpP  = (phase & pMask) >> pShift;
31065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    uint32_t indexN = (-phase & cMask) >> cShift;
31165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    uint16_t lerpN  = (-phase & pMask) >> pShift;
31265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if ((indexP == 0) && (lerpP == 0)) {
31365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        indexN = cMask >> cShift;
31465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        lerpN = pMask >> pShift;
31565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
31665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
31765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    l = 0;
31865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    r = 0;
31954c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten    const int32_t* coefs = mFirCoefs;
32054c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten    const int16_t *sP = samples;
32154c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten    const int16_t *sN = samples+CHANNELS;
32265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) {
32365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
32465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
32565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
32665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
32765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
32865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
32965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
33065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
33165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
33265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
33365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
33465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
33565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
33665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
33765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
33865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiantemplate<int CHANNELS>
33965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerSinc::interpolate(
34065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        int32_t& l, int32_t& r,
34154c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten        const int32_t* coefs, int16_t lerp, const int16_t* samples)
34265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
34365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int32_t c0 = coefs[0];
34465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int32_t c1 = coefs[1];
34565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int32_t sinc = mulAdd(lerp, (c1-c0)<<1, c0);
34665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (CHANNELS == 2) {
34754c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten        uint32_t rl = *reinterpret_cast<const uint32_t*>(samples);
34865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        l = mulAddRL(1, rl, sinc, l);
34965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        r = mulAddRL(0, rl, sinc, r);
35065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    } else {
35165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        r = l = mulAdd(samples[0], sinc, l);
35265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
35365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
35465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
35565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
35665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; // namespace android
35765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
358