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