19a19cd78SMatthias Ringwald /****************************************************************************** 29a19cd78SMatthias Ringwald * 3*4930cef6SMatthias Ringwald * Copyright 2022 Google LLC 49a19cd78SMatthias Ringwald * 59a19cd78SMatthias Ringwald * Licensed under the Apache License, Version 2.0 (the "License"); 69a19cd78SMatthias Ringwald * you may not use this file except in compliance with the License. 79a19cd78SMatthias Ringwald * You may obtain a copy of the License at: 89a19cd78SMatthias Ringwald * 99a19cd78SMatthias Ringwald * http://www.apache.org/licenses/LICENSE-2.0 109a19cd78SMatthias Ringwald * 119a19cd78SMatthias Ringwald * Unless required by applicable law or agreed to in writing, software 129a19cd78SMatthias Ringwald * distributed under the License is distributed on an "AS IS" BASIS, 139a19cd78SMatthias Ringwald * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149a19cd78SMatthias Ringwald * See the License for the specific language governing permissions and 159a19cd78SMatthias Ringwald * limitations under the License. 169a19cd78SMatthias Ringwald * 179a19cd78SMatthias Ringwald ******************************************************************************/ 189a19cd78SMatthias Ringwald 199a19cd78SMatthias Ringwald #include "ltpf.h" 209a19cd78SMatthias Ringwald #include "tables.h" 219a19cd78SMatthias Ringwald 22*4930cef6SMatthias Ringwald #include "ltpf_neon.h" 23*4930cef6SMatthias Ringwald #include "ltpf_arm.h" 24*4930cef6SMatthias Ringwald 259a19cd78SMatthias Ringwald 269a19cd78SMatthias Ringwald /* ---------------------------------------------------------------------------- 279a19cd78SMatthias Ringwald * Resampling 289a19cd78SMatthias Ringwald * -------------------------------------------------------------------------- */ 299a19cd78SMatthias Ringwald 309a19cd78SMatthias Ringwald /** 31*4930cef6SMatthias Ringwald * Resampling coefficients 32*4930cef6SMatthias Ringwald * The coefficients, in fixed Q15, are reordered by phase for each source 33*4930cef6SMatthias Ringwald * samplerate (coefficient matrix transposed) 34*4930cef6SMatthias Ringwald */ 35*4930cef6SMatthias Ringwald 36*4930cef6SMatthias Ringwald #ifndef resample_8k_12k8 37*4930cef6SMatthias Ringwald static const int16_t h_8k_12k8_q15[8*10] = { 38*4930cef6SMatthias Ringwald 214, 417, -1052, -4529, 26233, -4529, -1052, 417, 214, 0, 39*4930cef6SMatthias Ringwald 180, 0, -1522, -2427, 24506, -5289, 0, 763, 156, -28, 40*4930cef6SMatthias Ringwald 92, -323, -1361, 0, 19741, -3885, 1317, 861, 0, -61, 41*4930cef6SMatthias Ringwald 0, -457, -752, 1873, 13068, 0, 2389, 598, -213, -79, 42*4930cef6SMatthias Ringwald -61, -398, 0, 2686, 5997, 5997, 2686, 0, -398, -61, 43*4930cef6SMatthias Ringwald -79, -213, 598, 2389, 0, 13068, 1873, -752, -457, 0, 44*4930cef6SMatthias Ringwald -61, 0, 861, 1317, -3885, 19741, 0, -1361, -323, 92, 45*4930cef6SMatthias Ringwald -28, 156, 763, 0, -5289, 24506, -2427, -1522, 0, 180, 46*4930cef6SMatthias Ringwald }; 47*4930cef6SMatthias Ringwald #endif /* resample_8k_12k8 */ 48*4930cef6SMatthias Ringwald 49*4930cef6SMatthias Ringwald #ifndef resample_16k_12k8 50*4930cef6SMatthias Ringwald static const int16_t h_16k_12k8_q15[4*20] = { 51*4930cef6SMatthias Ringwald -61, 214, -398, 417, 0, -1052, 2686, -4529, 5997, 26233, 52*4930cef6SMatthias Ringwald 5997, -4529, 2686, -1052, 0, 417, -398, 214, -61, 0, 53*4930cef6SMatthias Ringwald 54*4930cef6SMatthias Ringwald -79, 180, -213, 0, 598, -1522, 2389, -2427, 0, 24506, 55*4930cef6SMatthias Ringwald 13068, -5289, 1873, 0, -752, 763, -457, 156, 0, -28, 56*4930cef6SMatthias Ringwald 57*4930cef6SMatthias Ringwald -61, 92, 0, -323, 861, -1361, 1317, 0, -3885, 19741, 58*4930cef6SMatthias Ringwald 19741, -3885, 0, 1317, -1361, 861, -323, 0, 92, -61, 59*4930cef6SMatthias Ringwald 60*4930cef6SMatthias Ringwald -28, 0, 156, -457, 763, -752, 0, 1873, -5289, 13068, 61*4930cef6SMatthias Ringwald 24506, 0, -2427, 2389, -1522, 598, 0, -213, 180, -79, 62*4930cef6SMatthias Ringwald }; 63*4930cef6SMatthias Ringwald #endif /* resample_16k_12k8 */ 64*4930cef6SMatthias Ringwald 65*4930cef6SMatthias Ringwald #ifndef resample_32k_12k8 66*4930cef6SMatthias Ringwald static const int16_t h_32k_12k8_q15[2*40] = { 67*4930cef6SMatthias Ringwald -30, -31, 46, 107, 0, -199, -162, 209, 430, 0, 68*4930cef6SMatthias Ringwald -681, -526, 658, 1343, 0, -2264, -1943, 2999, 9871, 13116, 69*4930cef6SMatthias Ringwald 9871, 2999, -1943, -2264, 0, 1343, 658, -526, -681, 0, 70*4930cef6SMatthias Ringwald 430, 209, -162, -199, 0, 107, 46, -31, -30, 0, 71*4930cef6SMatthias Ringwald 72*4930cef6SMatthias Ringwald -14, -39, 0, 90, 78, -106, -229, 0, 382, 299, 73*4930cef6SMatthias Ringwald -376, -761, 0, 1194, 937, -1214, -2644, 0, 6534, 12253, 74*4930cef6SMatthias Ringwald 12253, 6534, 0, -2644, -1214, 937, 1194, 0, -761, -376, 75*4930cef6SMatthias Ringwald 299, 382, 0, -229, -106, 78, 90, 0, -39, -14, 76*4930cef6SMatthias Ringwald }; 77*4930cef6SMatthias Ringwald #endif /* resample_32k_12k8 */ 78*4930cef6SMatthias Ringwald 79*4930cef6SMatthias Ringwald #ifndef resample_24k_12k8 80*4930cef6SMatthias Ringwald static const int16_t h_24k_12k8_q15[8*30] = { 81*4930cef6SMatthias Ringwald -50, 19, 143, -93, -290, 278, 485, -658, -701, 1396, 82*4930cef6SMatthias Ringwald 901, -3019, -1042, 10276, 17488, 10276, -1042, -3019, 901, 1396, 83*4930cef6SMatthias Ringwald -701, -658, 485, 278, -290, -93, 143, 19, -50, 0, 84*4930cef6SMatthias Ringwald 85*4930cef6SMatthias Ringwald -46, 0, 141, -45, -305, 185, 543, -501, -854, 1153, 86*4930cef6SMatthias Ringwald 1249, -2619, -1908, 8712, 17358, 11772, 0, -3319, 480, 1593, 87*4930cef6SMatthias Ringwald -504, -796, 399, 367, -261, -142, 138, 40, -52, -5, 88*4930cef6SMatthias Ringwald 89*4930cef6SMatthias Ringwald -41, -17, 133, 0, -304, 91, 574, -334, -959, 878, 90*4930cef6SMatthias Ringwald 1516, -2143, -2590, 7118, 16971, 13161, 1202, -3495, 0, 1731, 91*4930cef6SMatthias Ringwald -267, -908, 287, 445, -215, -188, 125, 62, -52, -12, 92*4930cef6SMatthias Ringwald 93*4930cef6SMatthias Ringwald -34, -30, 120, 41, -291, 0, 577, -164, -1015, 585, 94*4930cef6SMatthias Ringwald 1697, -1618, -3084, 5534, 16337, 14406, 2544, -3526, -523, 1800, 95*4930cef6SMatthias Ringwald 0, -985, 152, 509, -156, -230, 104, 83, -48, -19, 96*4930cef6SMatthias Ringwald 97*4930cef6SMatthias Ringwald -26, -41, 103, 76, -265, -83, 554, 0, -1023, 288, 98*4930cef6SMatthias Ringwald 1791, -1070, -3393, 3998, 15474, 15474, 3998, -3393, -1070, 1791, 99*4930cef6SMatthias Ringwald 288, -1023, 0, 554, -83, -265, 76, 103, -41, -26, 100*4930cef6SMatthias Ringwald 101*4930cef6SMatthias Ringwald -19, -48, 83, 104, -230, -156, 509, 152, -985, 0, 102*4930cef6SMatthias Ringwald 1800, -523, -3526, 2544, 14406, 16337, 5534, -3084, -1618, 1697, 103*4930cef6SMatthias Ringwald 585, -1015, -164, 577, 0, -291, 41, 120, -30, -34, 104*4930cef6SMatthias Ringwald 105*4930cef6SMatthias Ringwald -12, -52, 62, 125, -188, -215, 445, 287, -908, -267, 106*4930cef6SMatthias Ringwald 1731, 0, -3495, 1202, 13161, 16971, 7118, -2590, -2143, 1516, 107*4930cef6SMatthias Ringwald 878, -959, -334, 574, 91, -304, 0, 133, -17, -41, 108*4930cef6SMatthias Ringwald 109*4930cef6SMatthias Ringwald -5, -52, 40, 138, -142, -261, 367, 399, -796, -504, 110*4930cef6SMatthias Ringwald 1593, 480, -3319, 0, 11772, 17358, 8712, -1908, -2619, 1249, 111*4930cef6SMatthias Ringwald 1153, -854, -501, 543, 185, -305, -45, 141, 0, -46, 112*4930cef6SMatthias Ringwald }; 113*4930cef6SMatthias Ringwald #endif /* resample_24k_12k8 */ 114*4930cef6SMatthias Ringwald 115*4930cef6SMatthias Ringwald #ifndef resample_48k_12k8 116*4930cef6SMatthias Ringwald static const int16_t h_48k_12k8_q15[4*60] = { 117*4930cef6SMatthias Ringwald -13, -25, -20, 10, 51, 71, 38, -47, -133, -145, 118*4930cef6SMatthias Ringwald -42, 139, 277, 242, 0, -329, -511, -351, 144, 698, 119*4930cef6SMatthias Ringwald 895, 450, -535, -1510, -1697, -521, 1999, 5138, 7737, 8744, 120*4930cef6SMatthias Ringwald 7737, 5138, 1999, -521, -1697, -1510, -535, 450, 895, 698, 121*4930cef6SMatthias Ringwald 144, -351, -511, -329, 0, 242, 277, 139, -42, -145, 122*4930cef6SMatthias Ringwald -133, -47, 38, 71, 51, 10, -20, -25, -13, 0, 123*4930cef6SMatthias Ringwald 124*4930cef6SMatthias Ringwald -9, -23, -24, 0, 41, 71, 52, -23, -115, -152, 125*4930cef6SMatthias Ringwald -78, 92, 254, 272, 76, -251, -493, -427, 0, 576, 126*4930cef6SMatthias Ringwald 900, 624, -262, -1309, -1763, -954, 1272, 4356, 7203, 8679, 127*4930cef6SMatthias Ringwald 8169, 5886, 2767, 0, -1542, -1660, -809, 240, 848, 796, 128*4930cef6SMatthias Ringwald 292, -252, -507, -398, -82, 199, 288, 183, 0, -130, 129*4930cef6SMatthias Ringwald -145, -71, 20, 69, 60, 20, -15, -26, -17, -3, 130*4930cef6SMatthias Ringwald 131*4930cef6SMatthias Ringwald -6, -20, -26, -8, 31, 67, 62, 0, -94, -152, 132*4930cef6SMatthias Ringwald -108, 45, 223, 287, 143, -167, -454, -480, -134, 439, 133*4930cef6SMatthias Ringwald 866, 758, 0, -1071, -1748, -1295, 601, 3559, 6580, 8485, 134*4930cef6SMatthias Ringwald 8485, 6580, 3559, 601, -1295, -1748, -1071, 0, 758, 866, 135*4930cef6SMatthias Ringwald 439, -134, -480, -454, -167, 143, 287, 223, 45, -108, 136*4930cef6SMatthias Ringwald -152, -94, 0, 62, 67, 31, -8, -26, -20, -6, 137*4930cef6SMatthias Ringwald 138*4930cef6SMatthias Ringwald -3, -17, -26, -15, 20, 60, 69, 20, -71, -145, 139*4930cef6SMatthias Ringwald -130, 0, 183, 288, 199, -82, -398, -507, -252, 292, 140*4930cef6SMatthias Ringwald 796, 848, 240, -809, -1660, -1542, 0, 2767, 5886, 8169, 141*4930cef6SMatthias Ringwald 8679, 7203, 4356, 1272, -954, -1763, -1309, -262, 624, 900, 142*4930cef6SMatthias Ringwald 576, 0, -427, -493, -251, 76, 272, 254, 92, -78, 143*4930cef6SMatthias Ringwald -152, -115, -23, 52, 71, 41, 0, -24, -23, -9, 144*4930cef6SMatthias Ringwald }; 145*4930cef6SMatthias Ringwald #endif /* resample_48k_12k8 */ 146*4930cef6SMatthias Ringwald 147*4930cef6SMatthias Ringwald 148*4930cef6SMatthias Ringwald /** 149*4930cef6SMatthias Ringwald * High-pass 50Hz filtering, at 12.8 KHz samplerate 150*4930cef6SMatthias Ringwald * hp50 Biquad filter state 151*4930cef6SMatthias Ringwald * xn Input sample, in fixed Q30 152*4930cef6SMatthias Ringwald * return Filtered sample, in fixed Q30 153*4930cef6SMatthias Ringwald */ 154*4930cef6SMatthias Ringwald LC3_HOT static inline int32_t filter_hp50( 155*4930cef6SMatthias Ringwald struct lc3_ltpf_hp50_state *hp50, int32_t xn) 156*4930cef6SMatthias Ringwald { 157*4930cef6SMatthias Ringwald int32_t yn; 158*4930cef6SMatthias Ringwald 159*4930cef6SMatthias Ringwald const int32_t a1 = -2110217691, a2 = 1037111617; 160*4930cef6SMatthias Ringwald const int32_t b1 = -2110535566, b2 = 1055267782; 161*4930cef6SMatthias Ringwald 162*4930cef6SMatthias Ringwald yn = (hp50->s1 + (int64_t)xn * b2) >> 30; 163*4930cef6SMatthias Ringwald hp50->s1 = (hp50->s2 + (int64_t)xn * b1 - (int64_t)yn * a1); 164*4930cef6SMatthias Ringwald hp50->s2 = ( (int64_t)xn * b2 - (int64_t)yn * a2); 165*4930cef6SMatthias Ringwald 166*4930cef6SMatthias Ringwald return yn; 167*4930cef6SMatthias Ringwald } 168*4930cef6SMatthias Ringwald 169*4930cef6SMatthias Ringwald /** 170*4930cef6SMatthias Ringwald * Resample from 8 / 16 / 32 KHz to 12.8 KHz Template 171*4930cef6SMatthias Ringwald * p Resampling factor with compared to 192 KHz (8, 4 or 2) 172*4930cef6SMatthias Ringwald * h Arrange by phase coefficients table 173*4930cef6SMatthias Ringwald * hp50 High-Pass biquad filter state 174*4930cef6SMatthias Ringwald * x [-d..-1] Previous, [0..ns-1] Current samples, Q15 175*4930cef6SMatthias Ringwald * y, n [0..n-1] Output `n` processed samples, Q14 176*4930cef6SMatthias Ringwald * 177*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 178*4930cef6SMatthias Ringwald * The number of previous samples `d` accessed on `x` is : 179*4930cef6SMatthias Ringwald * d: { 10, 20, 40 } - 1 for resampling factors 8, 4 and 2. 180*4930cef6SMatthias Ringwald */ 181*4930cef6SMatthias Ringwald #if !defined(resample_8k_12k8) || !defined(resample_16k_12k8) \ 182*4930cef6SMatthias Ringwald || !defined(resample_32k_12k8) 183*4930cef6SMatthias Ringwald LC3_HOT static inline void resample_x64k_12k8(const int p, const int16_t *h, 184*4930cef6SMatthias Ringwald struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n) 185*4930cef6SMatthias Ringwald { 186*4930cef6SMatthias Ringwald const int w = 2*(40 / p); 187*4930cef6SMatthias Ringwald 188*4930cef6SMatthias Ringwald x -= w - 1; 189*4930cef6SMatthias Ringwald 190*4930cef6SMatthias Ringwald for (int i = 0; i < 5*n; i += 5) { 191*4930cef6SMatthias Ringwald const int16_t *hn = h + (i % p) * w; 192*4930cef6SMatthias Ringwald const int16_t *xn = x + (i / p); 193*4930cef6SMatthias Ringwald int32_t un = 0; 194*4930cef6SMatthias Ringwald 195*4930cef6SMatthias Ringwald for (int k = 0; k < w; k += 10) { 196*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 197*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 198*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 199*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 200*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 201*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 202*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 203*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 204*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 205*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 206*4930cef6SMatthias Ringwald } 207*4930cef6SMatthias Ringwald 208*4930cef6SMatthias Ringwald int32_t yn = filter_hp50(hp50, un); 209*4930cef6SMatthias Ringwald *(y++) = (yn + (1 << 15)) >> 16; 210*4930cef6SMatthias Ringwald } 211*4930cef6SMatthias Ringwald } 212*4930cef6SMatthias Ringwald #endif 213*4930cef6SMatthias Ringwald 214*4930cef6SMatthias Ringwald /** 215*4930cef6SMatthias Ringwald * Resample from 24 / 48 KHz to 12.8 KHz Template 216*4930cef6SMatthias Ringwald * p Resampling factor with compared to 192 KHz (8 or 4) 217*4930cef6SMatthias Ringwald * h Arrange by phase coefficients table 218*4930cef6SMatthias Ringwald * hp50 High-Pass biquad filter state 219*4930cef6SMatthias Ringwald * x [-d..-1] Previous, [0..ns-1] Current samples, Q15 220*4930cef6SMatthias Ringwald * y, n [0..n-1] Output `n` processed samples, Q14 221*4930cef6SMatthias Ringwald * 222*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 223*4930cef6SMatthias Ringwald * The number of previous samples `d` accessed on `x` is : 224*4930cef6SMatthias Ringwald * d: { 30, 60 } - 1 for resampling factors 8 and 4. 225*4930cef6SMatthias Ringwald */ 226*4930cef6SMatthias Ringwald #if !defined(resample_24k_12k8) || !defined(resample_48k_12k8) 227*4930cef6SMatthias Ringwald LC3_HOT static inline void resample_x192k_12k8(const int p, const int16_t *h, 228*4930cef6SMatthias Ringwald struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n) 229*4930cef6SMatthias Ringwald { 230*4930cef6SMatthias Ringwald const int w = 2*(120 / p); 231*4930cef6SMatthias Ringwald 232*4930cef6SMatthias Ringwald x -= w - 1; 233*4930cef6SMatthias Ringwald 234*4930cef6SMatthias Ringwald for (int i = 0; i < 15*n; i += 15) { 235*4930cef6SMatthias Ringwald const int16_t *hn = h + (i % p) * w; 236*4930cef6SMatthias Ringwald const int16_t *xn = x + (i / p); 237*4930cef6SMatthias Ringwald int32_t un = 0; 238*4930cef6SMatthias Ringwald 239*4930cef6SMatthias Ringwald for (int k = 0; k < w; k += 15) { 240*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 241*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 242*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 243*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 244*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 245*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 246*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 247*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 248*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 249*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 250*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 251*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 252*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 253*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 254*4930cef6SMatthias Ringwald un += *(xn++) * *(hn++); 255*4930cef6SMatthias Ringwald } 256*4930cef6SMatthias Ringwald 257*4930cef6SMatthias Ringwald int32_t yn = filter_hp50(hp50, un); 258*4930cef6SMatthias Ringwald *(y++) = (yn + (1 << 15)) >> 16; 259*4930cef6SMatthias Ringwald } 260*4930cef6SMatthias Ringwald } 261*4930cef6SMatthias Ringwald #endif 262*4930cef6SMatthias Ringwald 263*4930cef6SMatthias Ringwald /** 264*4930cef6SMatthias Ringwald * Resample from 8 Khz to 12.8 KHz 265*4930cef6SMatthias Ringwald * hp50 High-Pass biquad filter state 266*4930cef6SMatthias Ringwald * x [-10..-1] Previous, [0..ns-1] Current samples, Q15 267*4930cef6SMatthias Ringwald * y, n [0..n-1] Output `n` processed samples, Q14 268*4930cef6SMatthias Ringwald * 269*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 270*4930cef6SMatthias Ringwald */ 271*4930cef6SMatthias Ringwald #ifndef resample_8k_12k8 272*4930cef6SMatthias Ringwald LC3_HOT static void resample_8k_12k8( 273*4930cef6SMatthias Ringwald struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n) 274*4930cef6SMatthias Ringwald { 275*4930cef6SMatthias Ringwald resample_x64k_12k8(8, h_8k_12k8_q15, hp50, x, y, n); 276*4930cef6SMatthias Ringwald } 277*4930cef6SMatthias Ringwald #endif /* resample_8k_12k8 */ 278*4930cef6SMatthias Ringwald 279*4930cef6SMatthias Ringwald /** 280*4930cef6SMatthias Ringwald * Resample from 16 Khz to 12.8 KHz 281*4930cef6SMatthias Ringwald * hp50 High-Pass biquad filter state 282*4930cef6SMatthias Ringwald * x [-20..-1] Previous, [0..ns-1] Current samples, in fixed Q15 283*4930cef6SMatthias Ringwald * y, n [0..n-1] Output `n` processed samples, in fixed Q14 284*4930cef6SMatthias Ringwald * 285*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 286*4930cef6SMatthias Ringwald */ 287*4930cef6SMatthias Ringwald #ifndef resample_16k_12k8 288*4930cef6SMatthias Ringwald LC3_HOT static void resample_16k_12k8( 289*4930cef6SMatthias Ringwald struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n) 290*4930cef6SMatthias Ringwald { 291*4930cef6SMatthias Ringwald resample_x64k_12k8(4, h_16k_12k8_q15, hp50, x, y, n); 292*4930cef6SMatthias Ringwald } 293*4930cef6SMatthias Ringwald #endif /* resample_16k_12k8 */ 294*4930cef6SMatthias Ringwald 295*4930cef6SMatthias Ringwald /** 296*4930cef6SMatthias Ringwald * Resample from 32 Khz to 12.8 KHz 297*4930cef6SMatthias Ringwald * hp50 High-Pass biquad filter state 298*4930cef6SMatthias Ringwald * x [-30..-1] Previous, [0..ns-1] Current samples, in fixed Q15 299*4930cef6SMatthias Ringwald * y, n [0..n-1] Output `n` processed samples, in fixed Q14 300*4930cef6SMatthias Ringwald * 301*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 302*4930cef6SMatthias Ringwald */ 303*4930cef6SMatthias Ringwald #ifndef resample_32k_12k8 304*4930cef6SMatthias Ringwald LC3_HOT static void resample_32k_12k8( 305*4930cef6SMatthias Ringwald struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n) 306*4930cef6SMatthias Ringwald { 307*4930cef6SMatthias Ringwald resample_x64k_12k8(2, h_32k_12k8_q15, hp50, x, y, n); 308*4930cef6SMatthias Ringwald } 309*4930cef6SMatthias Ringwald #endif /* resample_32k_12k8 */ 310*4930cef6SMatthias Ringwald 311*4930cef6SMatthias Ringwald /** 312*4930cef6SMatthias Ringwald * Resample from 24 Khz to 12.8 KHz 313*4930cef6SMatthias Ringwald * hp50 High-Pass biquad filter state 314*4930cef6SMatthias Ringwald * x [-30..-1] Previous, [0..ns-1] Current samples, in fixed Q15 315*4930cef6SMatthias Ringwald * y, n [0..n-1] Output `n` processed samples, in fixed Q14 316*4930cef6SMatthias Ringwald * 317*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 318*4930cef6SMatthias Ringwald */ 319*4930cef6SMatthias Ringwald #ifndef resample_24k_12k8 320*4930cef6SMatthias Ringwald LC3_HOT static void resample_24k_12k8( 321*4930cef6SMatthias Ringwald struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n) 322*4930cef6SMatthias Ringwald { 323*4930cef6SMatthias Ringwald resample_x192k_12k8(8, h_24k_12k8_q15, hp50, x, y, n); 324*4930cef6SMatthias Ringwald } 325*4930cef6SMatthias Ringwald #endif /* resample_24k_12k8 */ 326*4930cef6SMatthias Ringwald 327*4930cef6SMatthias Ringwald /** 328*4930cef6SMatthias Ringwald * Resample from 48 Khz to 12.8 KHz 329*4930cef6SMatthias Ringwald * hp50 High-Pass biquad filter state 330*4930cef6SMatthias Ringwald * x [-60..-1] Previous, [0..ns-1] Current samples, in fixed Q15 331*4930cef6SMatthias Ringwald * y, n [0..n-1] Output `n` processed samples, in fixed Q14 332*4930cef6SMatthias Ringwald * 333*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 334*4930cef6SMatthias Ringwald */ 335*4930cef6SMatthias Ringwald #ifndef resample_48k_12k8 336*4930cef6SMatthias Ringwald LC3_HOT static void resample_48k_12k8( 337*4930cef6SMatthias Ringwald struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n) 338*4930cef6SMatthias Ringwald { 339*4930cef6SMatthias Ringwald resample_x192k_12k8(4, h_48k_12k8_q15, hp50, x, y, n); 340*4930cef6SMatthias Ringwald } 341*4930cef6SMatthias Ringwald #endif /* resample_48k_12k8 */ 342*4930cef6SMatthias Ringwald 343*4930cef6SMatthias Ringwald /** 344*4930cef6SMatthias Ringwald * Resample to 6.4 KHz 345*4930cef6SMatthias Ringwald * x [-3..-1] Previous, [0..n-1] Current samples 3469a19cd78SMatthias Ringwald * y, n [0..n-1] Output `n` processed samples 3479a19cd78SMatthias Ringwald * 348*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 3499a19cd78SMatthias Ringwald */ 350*4930cef6SMatthias Ringwald #ifndef resample_6k4 351*4930cef6SMatthias Ringwald LC3_HOT static void resample_6k4(const int16_t *x, int16_t *y, int n) 3529a19cd78SMatthias Ringwald { 353*4930cef6SMatthias Ringwald static const int16_t h[] = { 18477, 15424, 8105 }; 354*4930cef6SMatthias Ringwald const int16_t *ye = y + n; 3559a19cd78SMatthias Ringwald 356*4930cef6SMatthias Ringwald for (x--; y < ye; x += 2) 357*4930cef6SMatthias Ringwald *(y++) = (x[0] * h[0] + (x[-1] + x[1]) * h[1] 358*4930cef6SMatthias Ringwald + (x[-2] + x[2]) * h[2]) >> 16; 3599a19cd78SMatthias Ringwald } 360*4930cef6SMatthias Ringwald #endif /* resample_6k4 */ 3619a19cd78SMatthias Ringwald 3629a19cd78SMatthias Ringwald /** 3639a19cd78SMatthias Ringwald * LTPF Resample to 12.8 KHz implementations for each samplerates 3649a19cd78SMatthias Ringwald */ 3659a19cd78SMatthias Ringwald 3669a19cd78SMatthias Ringwald static void (* const resample_12k8[]) 367*4930cef6SMatthias Ringwald (struct lc3_ltpf_hp50_state *, const int16_t *, int16_t *, int ) = 3689a19cd78SMatthias Ringwald { 3699a19cd78SMatthias Ringwald [LC3_SRATE_8K ] = resample_8k_12k8, 3709a19cd78SMatthias Ringwald [LC3_SRATE_16K] = resample_16k_12k8, 3719a19cd78SMatthias Ringwald [LC3_SRATE_24K] = resample_24k_12k8, 3729a19cd78SMatthias Ringwald [LC3_SRATE_32K] = resample_32k_12k8, 3739a19cd78SMatthias Ringwald [LC3_SRATE_48K] = resample_48k_12k8, 3749a19cd78SMatthias Ringwald }; 3759a19cd78SMatthias Ringwald 3769a19cd78SMatthias Ringwald 3779a19cd78SMatthias Ringwald /* ---------------------------------------------------------------------------- 3789a19cd78SMatthias Ringwald * Analysis 3799a19cd78SMatthias Ringwald * -------------------------------------------------------------------------- */ 3809a19cd78SMatthias Ringwald 3819a19cd78SMatthias Ringwald /** 3829a19cd78SMatthias Ringwald * Return dot product of 2 vectors 383*4930cef6SMatthias Ringwald * a, b, n The 2 vectors of size `n` (> 0 and <= 128) 3849a19cd78SMatthias Ringwald * return sum( a[i] * b[i] ), i = [0..n-1] 385*4930cef6SMatthias Ringwald * 386*4930cef6SMatthias Ringwald * The size `n` of vectors must be multiple of 16, and less or equal to 128 3879a19cd78SMatthias Ringwald */ 388*4930cef6SMatthias Ringwald #ifndef dot 389*4930cef6SMatthias Ringwald LC3_HOT static inline float dot(const int16_t *a, const int16_t *b, int n) 3909a19cd78SMatthias Ringwald { 391*4930cef6SMatthias Ringwald int64_t v = 0; 3929a19cd78SMatthias Ringwald 393*4930cef6SMatthias Ringwald for (int i = 0; i < (n >> 4); i++) 394*4930cef6SMatthias Ringwald for (int j = 0; j < 16; j++) 3959a19cd78SMatthias Ringwald v += *(a++) * *(b++); 3969a19cd78SMatthias Ringwald 397*4930cef6SMatthias Ringwald int32_t v32 = (v + (1 << 5)) >> 6; 398*4930cef6SMatthias Ringwald return (float)v32; 3999a19cd78SMatthias Ringwald } 400*4930cef6SMatthias Ringwald #endif /* dot */ 4019a19cd78SMatthias Ringwald 4029a19cd78SMatthias Ringwald /** 4039a19cd78SMatthias Ringwald * Return vector of correlations 404*4930cef6SMatthias Ringwald * a, b, n The 2 vector of size `n` (> 0 and <= 128) 4059a19cd78SMatthias Ringwald * y, nc Output the correlation vector of size `nc` 4069a19cd78SMatthias Ringwald * 407*4930cef6SMatthias Ringwald * The first vector `a` is aligned of 32 bits 408*4930cef6SMatthias Ringwald * The size `n` of vectors is multiple of 16, and less or equal to 128 4099a19cd78SMatthias Ringwald */ 410*4930cef6SMatthias Ringwald #ifndef correlate 411*4930cef6SMatthias Ringwald LC3_HOT static void correlate( 412*4930cef6SMatthias Ringwald const int16_t *a, const int16_t *b, int n, float *y, int nc) 4139a19cd78SMatthias Ringwald { 4149a19cd78SMatthias Ringwald for (const float *ye = y + nc; y < ye; ) 4159a19cd78SMatthias Ringwald *(y++) = dot(a, b--, n); 4169a19cd78SMatthias Ringwald } 417*4930cef6SMatthias Ringwald #endif /* correlate */ 4189a19cd78SMatthias Ringwald 4199a19cd78SMatthias Ringwald /** 4209a19cd78SMatthias Ringwald * Search the maximum value and returns its argument 4219a19cd78SMatthias Ringwald * x, n The input vector of size `n` 4229a19cd78SMatthias Ringwald * x_max Return the maximum value 4239a19cd78SMatthias Ringwald * return Return the argument of the maximum 4249a19cd78SMatthias Ringwald */ 425*4930cef6SMatthias Ringwald LC3_HOT static int argmax(const float *x, int n, float *x_max) 4269a19cd78SMatthias Ringwald { 4279a19cd78SMatthias Ringwald int arg = 0; 4289a19cd78SMatthias Ringwald 4299a19cd78SMatthias Ringwald *x_max = x[arg = 0]; 4309a19cd78SMatthias Ringwald for (int i = 1; i < n; i++) 4319a19cd78SMatthias Ringwald if (*x_max < x[i]) 4329a19cd78SMatthias Ringwald *x_max = x[arg = i]; 4339a19cd78SMatthias Ringwald 4349a19cd78SMatthias Ringwald return arg; 4359a19cd78SMatthias Ringwald } 4369a19cd78SMatthias Ringwald 4379a19cd78SMatthias Ringwald /** 4389a19cd78SMatthias Ringwald * Search the maximum weithed value and returns its argument 4399a19cd78SMatthias Ringwald * x, n The input vector of size `n` 4409a19cd78SMatthias Ringwald * w_incr Increment of the weight 4419a19cd78SMatthias Ringwald * x_max, xw_max Return the maximum not weighted value 4429a19cd78SMatthias Ringwald * return Return the argument of the weigthed maximum 4439a19cd78SMatthias Ringwald */ 444*4930cef6SMatthias Ringwald LC3_HOT static int argmax_weighted( 4459a19cd78SMatthias Ringwald const float *x, int n, float w_incr, float *x_max) 4469a19cd78SMatthias Ringwald { 4479a19cd78SMatthias Ringwald int arg; 4489a19cd78SMatthias Ringwald 4499a19cd78SMatthias Ringwald float xw_max = (*x_max = x[arg = 0]); 4509a19cd78SMatthias Ringwald float w = 1 + w_incr; 4519a19cd78SMatthias Ringwald 4529a19cd78SMatthias Ringwald for (int i = 1; i < n; i++, w += w_incr) 4539a19cd78SMatthias Ringwald if (xw_max < x[i] * w) 4549a19cd78SMatthias Ringwald xw_max = (*x_max = x[arg = i]) * w; 4559a19cd78SMatthias Ringwald 4569a19cd78SMatthias Ringwald return arg; 4579a19cd78SMatthias Ringwald } 4589a19cd78SMatthias Ringwald 4599a19cd78SMatthias Ringwald /** 4609a19cd78SMatthias Ringwald * Interpolate from pitch detected value (3.3.9.8) 4619a19cd78SMatthias Ringwald * x, n [-2..-1] Previous, [0..n] Current input 4629a19cd78SMatthias Ringwald * d The phase of interpolation (0 to 3) 4639a19cd78SMatthias Ringwald * return The interpolated vector 4649a19cd78SMatthias Ringwald * 4659a19cd78SMatthias Ringwald * The size `n` of vectors must be multiple of 4 4669a19cd78SMatthias Ringwald */ 467*4930cef6SMatthias Ringwald LC3_HOT static void interpolate(const int16_t *x, int n, int d, int16_t *y) 4689a19cd78SMatthias Ringwald { 469*4930cef6SMatthias Ringwald static const int16_t h4_q15[][4] = { 470*4930cef6SMatthias Ringwald { 6877, 19121, 6877, 0 }, { 3506, 18025, 11000, 220 }, 471*4930cef6SMatthias Ringwald { 1300, 15048, 15048, 1300 }, { 220, 11000, 18025, 3506 } }; 4729a19cd78SMatthias Ringwald 473*4930cef6SMatthias Ringwald const int16_t *h = h4_q15[d]; 474*4930cef6SMatthias Ringwald int16_t x3 = x[-2], x2 = x[-1], x1, x0; 4759a19cd78SMatthias Ringwald 4769a19cd78SMatthias Ringwald x1 = (*x++); 477*4930cef6SMatthias Ringwald for (const int16_t *ye = y + n; y < ye; ) { 478*4930cef6SMatthias Ringwald int32_t yn; 479*4930cef6SMatthias Ringwald 480*4930cef6SMatthias Ringwald yn = (x0 = *(x++)) * h[0] + x1 * h[1] + x2 * h[2] + x3 * h[3]; 481*4930cef6SMatthias Ringwald *(y++) = yn >> 15; 482*4930cef6SMatthias Ringwald 483*4930cef6SMatthias Ringwald yn = (x3 = *(x++)) * h[0] + x0 * h[1] + x1 * h[2] + x2 * h[3]; 484*4930cef6SMatthias Ringwald *(y++) = yn >> 15; 485*4930cef6SMatthias Ringwald 486*4930cef6SMatthias Ringwald yn = (x2 = *(x++)) * h[0] + x3 * h[1] + x0 * h[2] + x1 * h[3]; 487*4930cef6SMatthias Ringwald *(y++) = yn >> 15; 488*4930cef6SMatthias Ringwald 489*4930cef6SMatthias Ringwald yn = (x1 = *(x++)) * h[0] + x2 * h[1] + x3 * h[2] + x0 * h[3]; 490*4930cef6SMatthias Ringwald *(y++) = yn >> 15; 4919a19cd78SMatthias Ringwald } 4929a19cd78SMatthias Ringwald } 4939a19cd78SMatthias Ringwald 4949a19cd78SMatthias Ringwald /** 4959a19cd78SMatthias Ringwald * Interpolate autocorrelation (3.3.9.7) 4969a19cd78SMatthias Ringwald * x [-4..-1] Previous, [0..4] Current input 4979a19cd78SMatthias Ringwald * d The phase of interpolation (-3 to 3) 4989a19cd78SMatthias Ringwald * return The interpolated value 4999a19cd78SMatthias Ringwald */ 500*4930cef6SMatthias Ringwald LC3_HOT static float interpolate_corr(const float *x, int d) 5019a19cd78SMatthias Ringwald { 5029a19cd78SMatthias Ringwald static const float h4[][8] = { 5039a19cd78SMatthias Ringwald { 1.53572770e-02, -4.72963246e-02, 8.35788573e-02, 8.98638285e-01, 5049a19cd78SMatthias Ringwald 8.35788573e-02, -4.72963246e-02, 1.53572770e-02, }, 5059a19cd78SMatthias Ringwald { 2.74547165e-03, 4.59833449e-03, -7.54404636e-02, 8.17488686e-01, 5069a19cd78SMatthias Ringwald 3.30182571e-01, -1.05835916e-01, 2.86823405e-02, -2.87456116e-03 }, 5079a19cd78SMatthias Ringwald { -3.00125103e-03, 2.95038503e-02, -1.30305021e-01, 6.03297008e-01, 5089a19cd78SMatthias Ringwald 6.03297008e-01, -1.30305021e-01, 2.95038503e-02, -3.00125103e-03 }, 5099a19cd78SMatthias Ringwald { -2.87456116e-03, 2.86823405e-02, -1.05835916e-01, 3.30182571e-01, 5109a19cd78SMatthias Ringwald 8.17488686e-01, -7.54404636e-02, 4.59833449e-03, 2.74547165e-03 }, 5119a19cd78SMatthias Ringwald }; 5129a19cd78SMatthias Ringwald 5139a19cd78SMatthias Ringwald const float *h = h4[(4+d) % 4]; 5149a19cd78SMatthias Ringwald 5159a19cd78SMatthias Ringwald float y = d < 0 ? x[-4] * *(h++) : 5169a19cd78SMatthias Ringwald d > 0 ? x[ 4] * *(h+7) : 0; 5179a19cd78SMatthias Ringwald 5189a19cd78SMatthias Ringwald y += x[-3] * h[0] + x[-2] * h[1] + x[-1] * h[2] + x[0] * h[3] + 5199a19cd78SMatthias Ringwald x[ 1] * h[4] + x[ 2] * h[5] + x[ 3] * h[6]; 5209a19cd78SMatthias Ringwald 5219a19cd78SMatthias Ringwald return y; 5229a19cd78SMatthias Ringwald } 5239a19cd78SMatthias Ringwald 5249a19cd78SMatthias Ringwald /** 5259a19cd78SMatthias Ringwald * Pitch detection algorithm (3.3.9.5-6) 5269a19cd78SMatthias Ringwald * ltpf Context of analysis 5279a19cd78SMatthias Ringwald * x, n [-114..-17] Previous, [0..n-1] Current 6.4KHz samples 5289a19cd78SMatthias Ringwald * tc Return the pitch-lag estimation 5299a19cd78SMatthias Ringwald * return True when pitch present 530*4930cef6SMatthias Ringwald * 531*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 5329a19cd78SMatthias Ringwald */ 5339a19cd78SMatthias Ringwald static bool detect_pitch( 534*4930cef6SMatthias Ringwald struct lc3_ltpf_analysis *ltpf, const int16_t *x, int n, int *tc) 5359a19cd78SMatthias Ringwald { 5369a19cd78SMatthias Ringwald float rm1, rm2; 5379a19cd78SMatthias Ringwald float r[98]; 5389a19cd78SMatthias Ringwald 5399a19cd78SMatthias Ringwald const int r0 = 17, nr = 98; 5409a19cd78SMatthias Ringwald int k0 = LC3_MAX( 0, ltpf->tc-4); 5419a19cd78SMatthias Ringwald int nk = LC3_MIN(nr-1, ltpf->tc+4) - k0 + 1; 5429a19cd78SMatthias Ringwald 5439a19cd78SMatthias Ringwald correlate(x, x - r0, n, r, nr); 5449a19cd78SMatthias Ringwald 545*4930cef6SMatthias Ringwald int t1 = argmax_weighted(r, nr, -.5f/(nr-1), &rm1); 5469a19cd78SMatthias Ringwald int t2 = k0 + argmax(r + k0, nk, &rm2); 5479a19cd78SMatthias Ringwald 548*4930cef6SMatthias Ringwald const int16_t *x1 = x - (r0 + t1); 549*4930cef6SMatthias Ringwald const int16_t *x2 = x - (r0 + t2); 5509a19cd78SMatthias Ringwald 5519a19cd78SMatthias Ringwald float nc1 = rm1 <= 0 ? 0 : 5529a19cd78SMatthias Ringwald rm1 / sqrtf(dot(x, x, n) * dot(x1, x1, n)); 5539a19cd78SMatthias Ringwald 5549a19cd78SMatthias Ringwald float nc2 = rm2 <= 0 ? 0 : 5559a19cd78SMatthias Ringwald rm2 / sqrtf(dot(x, x, n) * dot(x2, x2, n)); 5569a19cd78SMatthias Ringwald 557*4930cef6SMatthias Ringwald int t1sel = nc2 <= 0.85f * nc1; 5589a19cd78SMatthias Ringwald ltpf->tc = (t1sel ? t1 : t2); 5599a19cd78SMatthias Ringwald 5609a19cd78SMatthias Ringwald *tc = r0 + ltpf->tc; 561*4930cef6SMatthias Ringwald return (t1sel ? nc1 : nc2) > 0.6f; 5629a19cd78SMatthias Ringwald } 5639a19cd78SMatthias Ringwald 5649a19cd78SMatthias Ringwald /** 5659a19cd78SMatthias Ringwald * Pitch-lag parameter (3.3.9.7) 566*4930cef6SMatthias Ringwald * x, n [-232..-28] Previous, [0..n-1] Current 12.8KHz samples, Q14 5679a19cd78SMatthias Ringwald * tc Pitch-lag estimation 5689a19cd78SMatthias Ringwald * pitch The pitch value, in fixed .4 5699a19cd78SMatthias Ringwald * return The bitstream pitch index value 570*4930cef6SMatthias Ringwald * 571*4930cef6SMatthias Ringwald * The `x` vector is aligned on 32 bits 5729a19cd78SMatthias Ringwald */ 573*4930cef6SMatthias Ringwald static int refine_pitch(const int16_t *x, int n, int tc, int *pitch) 5749a19cd78SMatthias Ringwald { 5759a19cd78SMatthias Ringwald float r[17], rm; 5769a19cd78SMatthias Ringwald int e, f; 5779a19cd78SMatthias Ringwald 5789a19cd78SMatthias Ringwald int r0 = LC3_MAX( 32, 2*tc - 4); 5799a19cd78SMatthias Ringwald int nr = LC3_MIN(228, 2*tc + 4) - r0 + 1; 5809a19cd78SMatthias Ringwald 5819a19cd78SMatthias Ringwald correlate(x, x - (r0 - 4), n, r, nr + 8); 5829a19cd78SMatthias Ringwald 5839a19cd78SMatthias Ringwald e = r0 + argmax(r + 4, nr, &rm); 5849a19cd78SMatthias Ringwald const float *re = r + (e - (r0 - 4)); 5859a19cd78SMatthias Ringwald 586*4930cef6SMatthias Ringwald float dm = interpolate_corr(re, f = 0); 5879a19cd78SMatthias Ringwald for (int i = 1; i <= 3; i++) { 5889a19cd78SMatthias Ringwald float d; 5899a19cd78SMatthias Ringwald 5909a19cd78SMatthias Ringwald if (e >= 127 && ((i & 1) | (e >= 157))) 5919a19cd78SMatthias Ringwald continue; 5929a19cd78SMatthias Ringwald 593*4930cef6SMatthias Ringwald if ((d = interpolate_corr(re, i)) > dm) 5949a19cd78SMatthias Ringwald dm = d, f = i; 5959a19cd78SMatthias Ringwald 596*4930cef6SMatthias Ringwald if (e > 32 && (d = interpolate_corr(re, -i)) > dm) 5979a19cd78SMatthias Ringwald dm = d, f = -i; 5989a19cd78SMatthias Ringwald } 5999a19cd78SMatthias Ringwald 6009a19cd78SMatthias Ringwald e -= (f < 0); 6019a19cd78SMatthias Ringwald f += 4*(f < 0); 6029a19cd78SMatthias Ringwald 6039a19cd78SMatthias Ringwald *pitch = 4*e + f; 6049a19cd78SMatthias Ringwald return e < 127 ? 4*e + f - 128 : 6059a19cd78SMatthias Ringwald e < 157 ? 2*e + (f >> 1) + 126 : e + 283; 6069a19cd78SMatthias Ringwald } 6079a19cd78SMatthias Ringwald 6089a19cd78SMatthias Ringwald /** 6099a19cd78SMatthias Ringwald * LTPF Analysis 6109a19cd78SMatthias Ringwald */ 611*4930cef6SMatthias Ringwald bool lc3_ltpf_analyse( 612*4930cef6SMatthias Ringwald enum lc3_dt dt, enum lc3_srate sr, struct lc3_ltpf_analysis *ltpf, 613*4930cef6SMatthias Ringwald const int16_t *x, struct lc3_ltpf_data *data) 6149a19cd78SMatthias Ringwald { 6159a19cd78SMatthias Ringwald /* --- Resampling to 12.8 KHz --- */ 6169a19cd78SMatthias Ringwald 617*4930cef6SMatthias Ringwald int z_12k8 = sizeof(ltpf->x_12k8) / sizeof(*ltpf->x_12k8); 6189a19cd78SMatthias Ringwald int n_12k8 = dt == LC3_DT_7M5 ? 96 : 128; 6199a19cd78SMatthias Ringwald 6209a19cd78SMatthias Ringwald memmove(ltpf->x_12k8, ltpf->x_12k8 + n_12k8, 621*4930cef6SMatthias Ringwald (z_12k8 - n_12k8) * sizeof(*ltpf->x_12k8)); 6229a19cd78SMatthias Ringwald 623*4930cef6SMatthias Ringwald int16_t *x_12k8 = ltpf->x_12k8 + (z_12k8 - n_12k8); 624*4930cef6SMatthias Ringwald 6259a19cd78SMatthias Ringwald resample_12k8[sr](<pf->hp50, x, x_12k8, n_12k8); 6269a19cd78SMatthias Ringwald 6279a19cd78SMatthias Ringwald x_12k8 -= (dt == LC3_DT_7M5 ? 44 : 24); 6289a19cd78SMatthias Ringwald 6299a19cd78SMatthias Ringwald /* --- Resampling to 6.4 KHz --- */ 6309a19cd78SMatthias Ringwald 631*4930cef6SMatthias Ringwald int z_6k4 = sizeof(ltpf->x_6k4) / sizeof(*ltpf->x_6k4); 6329a19cd78SMatthias Ringwald int n_6k4 = n_12k8 >> 1; 6339a19cd78SMatthias Ringwald 6349a19cd78SMatthias Ringwald memmove(ltpf->x_6k4, ltpf->x_6k4 + n_6k4, 635*4930cef6SMatthias Ringwald (z_6k4 - n_6k4) * sizeof(*ltpf->x_6k4)); 6369a19cd78SMatthias Ringwald 637*4930cef6SMatthias Ringwald int16_t *x_6k4 = ltpf->x_6k4 + (z_6k4 - n_6k4); 638*4930cef6SMatthias Ringwald 6399a19cd78SMatthias Ringwald resample_6k4(x_12k8, x_6k4, n_6k4); 6409a19cd78SMatthias Ringwald 6419a19cd78SMatthias Ringwald /* --- Pitch detection --- */ 6429a19cd78SMatthias Ringwald 6439a19cd78SMatthias Ringwald int tc, pitch = 0; 6449a19cd78SMatthias Ringwald float nc = 0; 6459a19cd78SMatthias Ringwald 6469a19cd78SMatthias Ringwald bool pitch_present = detect_pitch(ltpf, x_6k4, n_6k4, &tc); 6479a19cd78SMatthias Ringwald 6489a19cd78SMatthias Ringwald if (pitch_present) { 649*4930cef6SMatthias Ringwald int16_t u[n_12k8], v[n_12k8]; 6509a19cd78SMatthias Ringwald 6519a19cd78SMatthias Ringwald data->pitch_index = refine_pitch(x_12k8, n_12k8, tc, &pitch); 6529a19cd78SMatthias Ringwald 6539a19cd78SMatthias Ringwald interpolate(x_12k8, n_12k8, 0, u); 6549a19cd78SMatthias Ringwald interpolate(x_12k8 - (pitch >> 2), n_12k8, pitch & 3, v); 6559a19cd78SMatthias Ringwald 6569a19cd78SMatthias Ringwald nc = dot(u, v, n_12k8) / sqrtf(dot(u, u, n_12k8) * dot(v, v, n_12k8)); 6579a19cd78SMatthias Ringwald } 6589a19cd78SMatthias Ringwald 6599a19cd78SMatthias Ringwald /* --- Activation --- */ 6609a19cd78SMatthias Ringwald 6619a19cd78SMatthias Ringwald if (ltpf->active) { 6629a19cd78SMatthias Ringwald int pitch_diff = 6639a19cd78SMatthias Ringwald LC3_MAX(pitch, ltpf->pitch) - LC3_MIN(pitch, ltpf->pitch); 6649a19cd78SMatthias Ringwald float nc_diff = nc - ltpf->nc[0]; 6659a19cd78SMatthias Ringwald 6669a19cd78SMatthias Ringwald data->active = pitch_present && 667*4930cef6SMatthias Ringwald ((nc > 0.9f) || (nc > 0.84f && pitch_diff < 8 && nc_diff > -0.1f)); 6689a19cd78SMatthias Ringwald 6699a19cd78SMatthias Ringwald } else { 6709a19cd78SMatthias Ringwald data->active = pitch_present && 671*4930cef6SMatthias Ringwald ( (dt == LC3_DT_10M || ltpf->nc[1] > 0.94f) && 672*4930cef6SMatthias Ringwald (ltpf->nc[0] > 0.94f && nc > 0.94f) ); 6739a19cd78SMatthias Ringwald } 6749a19cd78SMatthias Ringwald 6759a19cd78SMatthias Ringwald ltpf->active = data->active; 6769a19cd78SMatthias Ringwald ltpf->pitch = pitch; 6779a19cd78SMatthias Ringwald ltpf->nc[1] = ltpf->nc[0]; 6789a19cd78SMatthias Ringwald ltpf->nc[0] = nc; 6799a19cd78SMatthias Ringwald 6809a19cd78SMatthias Ringwald return pitch_present; 6819a19cd78SMatthias Ringwald } 6829a19cd78SMatthias Ringwald 6839a19cd78SMatthias Ringwald 6849a19cd78SMatthias Ringwald /* ---------------------------------------------------------------------------- 6859a19cd78SMatthias Ringwald * Synthesis 6869a19cd78SMatthias Ringwald * -------------------------------------------------------------------------- */ 6879a19cd78SMatthias Ringwald 6889a19cd78SMatthias Ringwald /** 6899a19cd78SMatthias Ringwald * Synthesis filter template 690*4930cef6SMatthias Ringwald * xh, nh History ring buffer of filtered samples 691*4930cef6SMatthias Ringwald * lag Lag parameter in the ring buffer 692*4930cef6SMatthias Ringwald * x0 w-1 previous input samples 6939a19cd78SMatthias Ringwald * x, n Current samples as input, filtered as output 694*4930cef6SMatthias Ringwald * c, w Coefficients `den` then `num`, and width of filter 6959a19cd78SMatthias Ringwald * fade Fading mode of filter -1: Out 1: In 0: None 6969a19cd78SMatthias Ringwald */ 697*4930cef6SMatthias Ringwald LC3_HOT static inline void synthesize_template( 698*4930cef6SMatthias Ringwald const float *xh, int nh, int lag, 699*4930cef6SMatthias Ringwald const float *x0, float *x, int n, 700*4930cef6SMatthias Ringwald const float *c, const int w, int fade) 7019a19cd78SMatthias Ringwald { 7029a19cd78SMatthias Ringwald float g = (float)(fade <= 0); 7039a19cd78SMatthias Ringwald float g_incr = (float)((fade > 0) - (fade < 0)) / n; 7049a19cd78SMatthias Ringwald float u[w]; 7059a19cd78SMatthias Ringwald 7069a19cd78SMatthias Ringwald /* --- Load previous samples --- */ 7079a19cd78SMatthias Ringwald 708*4930cef6SMatthias Ringwald lag += (w >> 1); 7099a19cd78SMatthias Ringwald 710*4930cef6SMatthias Ringwald const float *y = x - xh < lag ? x + (nh - lag) : x - lag; 711*4930cef6SMatthias Ringwald const float *y_end = xh + nh - 1; 712*4930cef6SMatthias Ringwald 713*4930cef6SMatthias Ringwald for (int j = 0; j < w-1; j++) { 714*4930cef6SMatthias Ringwald 715*4930cef6SMatthias Ringwald u[j] = 0; 716*4930cef6SMatthias Ringwald 717*4930cef6SMatthias Ringwald float yi = *y, xi = *(x0++); 718*4930cef6SMatthias Ringwald y = y < y_end ? y + 1 : xh; 719*4930cef6SMatthias Ringwald 720*4930cef6SMatthias Ringwald for (int k = 0; k <= j; k++) 721*4930cef6SMatthias Ringwald u[j-k] -= yi * c[k]; 722*4930cef6SMatthias Ringwald 723*4930cef6SMatthias Ringwald for (int k = 0; k <= j; k++) 724*4930cef6SMatthias Ringwald u[j-k] += xi * c[w+k]; 7259a19cd78SMatthias Ringwald } 7269a19cd78SMatthias Ringwald 7279a19cd78SMatthias Ringwald u[w-1] = 0; 7289a19cd78SMatthias Ringwald 729*4930cef6SMatthias Ringwald /* --- Process by filter length --- */ 7309a19cd78SMatthias Ringwald 731*4930cef6SMatthias Ringwald for (int i = 0; i < n; i += w) 7329a19cd78SMatthias Ringwald for (int j = 0; j < w; j++, g += g_incr) { 7339a19cd78SMatthias Ringwald 734*4930cef6SMatthias Ringwald float yi = *y, xi = *x; 735*4930cef6SMatthias Ringwald y = y < y_end ? y + 1 : xh; 736*4930cef6SMatthias Ringwald 737*4930cef6SMatthias Ringwald for (int k = 0; k < w; k++) 738*4930cef6SMatthias Ringwald u[(j+(w-1)-k)%w] -= yi * c[k]; 739*4930cef6SMatthias Ringwald 740*4930cef6SMatthias Ringwald for (int k = 0; k < w; k++) 741*4930cef6SMatthias Ringwald u[(j+(w-1)-k)%w] += xi * c[w+k]; 7429a19cd78SMatthias Ringwald 7439a19cd78SMatthias Ringwald *(x++) = xi - g * u[j]; 7449a19cd78SMatthias Ringwald u[j] = 0; 7459a19cd78SMatthias Ringwald } 7469a19cd78SMatthias Ringwald } 7479a19cd78SMatthias Ringwald 7489a19cd78SMatthias Ringwald /** 7499a19cd78SMatthias Ringwald * Synthesis filter for each samplerates (width of filter) 7509a19cd78SMatthias Ringwald */ 7519a19cd78SMatthias Ringwald 752*4930cef6SMatthias Ringwald LC3_HOT static void synthesize_4(const float *xh, int nh, int lag, 753*4930cef6SMatthias Ringwald const float *x0, float *x, int n, const float *c, int fade) 7549a19cd78SMatthias Ringwald { 755*4930cef6SMatthias Ringwald synthesize_template(xh, nh, lag, x0, x, n, c, 4, fade); 7569a19cd78SMatthias Ringwald } 7579a19cd78SMatthias Ringwald 758*4930cef6SMatthias Ringwald LC3_HOT static void synthesize_6(const float *xh, int nh, int lag, 759*4930cef6SMatthias Ringwald const float *x0, float *x, int n, const float *c, int fade) 7609a19cd78SMatthias Ringwald { 761*4930cef6SMatthias Ringwald synthesize_template(xh, nh, lag, x0, x, n, c, 6, fade); 7629a19cd78SMatthias Ringwald } 7639a19cd78SMatthias Ringwald 764*4930cef6SMatthias Ringwald LC3_HOT static void synthesize_8(const float *xh, int nh, int lag, 765*4930cef6SMatthias Ringwald const float *x0, float *x, int n, const float *c, int fade) 7669a19cd78SMatthias Ringwald { 767*4930cef6SMatthias Ringwald synthesize_template(xh, nh, lag, x0, x, n, c, 8, fade); 7689a19cd78SMatthias Ringwald } 7699a19cd78SMatthias Ringwald 770*4930cef6SMatthias Ringwald LC3_HOT static void synthesize_12(const float *xh, int nh, int lag, 771*4930cef6SMatthias Ringwald const float *x0, float *x, int n, const float *c, int fade) 7729a19cd78SMatthias Ringwald { 773*4930cef6SMatthias Ringwald synthesize_template(xh, nh, lag, x0, x, n, c, 12, fade); 7749a19cd78SMatthias Ringwald } 7759a19cd78SMatthias Ringwald 776*4930cef6SMatthias Ringwald static void (* const synthesize[])(const float *, int, int, 777*4930cef6SMatthias Ringwald const float *, float *, int, const float *, int) = 7789a19cd78SMatthias Ringwald { 7799a19cd78SMatthias Ringwald [LC3_SRATE_8K ] = synthesize_4, 7809a19cd78SMatthias Ringwald [LC3_SRATE_16K] = synthesize_4, 7819a19cd78SMatthias Ringwald [LC3_SRATE_24K] = synthesize_6, 7829a19cd78SMatthias Ringwald [LC3_SRATE_32K] = synthesize_8, 7839a19cd78SMatthias Ringwald [LC3_SRATE_48K] = synthesize_12, 7849a19cd78SMatthias Ringwald }; 7859a19cd78SMatthias Ringwald 786*4930cef6SMatthias Ringwald 7879a19cd78SMatthias Ringwald /** 7889a19cd78SMatthias Ringwald * LTPF Synthesis 7899a19cd78SMatthias Ringwald */ 790*4930cef6SMatthias Ringwald void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes, 791*4930cef6SMatthias Ringwald lc3_ltpf_synthesis_t *ltpf, const lc3_ltpf_data_t *data, 792*4930cef6SMatthias Ringwald const float *xh, float *x) 7939a19cd78SMatthias Ringwald { 794*4930cef6SMatthias Ringwald int nh = LC3_NH(dt, sr); 7959a19cd78SMatthias Ringwald int dt_us = LC3_DT_US(dt); 7969a19cd78SMatthias Ringwald 7979a19cd78SMatthias Ringwald /* --- Filter parameters --- */ 7989a19cd78SMatthias Ringwald 7999a19cd78SMatthias Ringwald int p_idx = data ? data->pitch_index : 0; 8009a19cd78SMatthias Ringwald int pitch = 8019a19cd78SMatthias Ringwald p_idx >= 440 ? (((p_idx ) - 283) << 2) : 8029a19cd78SMatthias Ringwald p_idx >= 380 ? (((p_idx >> 1) - 63) << 2) + (((p_idx & 1)) << 1) : 8039a19cd78SMatthias Ringwald (((p_idx >> 2) + 32) << 2) + (((p_idx & 3)) << 0) ; 8049a19cd78SMatthias Ringwald 8059a19cd78SMatthias Ringwald pitch = (pitch * LC3_SRATE_KHZ(sr) * 10 + 64) / 128; 8069a19cd78SMatthias Ringwald 8079a19cd78SMatthias Ringwald int nbits = (nbytes*8 * 10000 + (dt_us/2)) / dt_us; 8089a19cd78SMatthias Ringwald int g_idx = LC3_MAX(nbits / 80, 3 + (int)sr) - (3 + sr); 8099a19cd78SMatthias Ringwald bool active = data && data->active && g_idx < 4; 8109a19cd78SMatthias Ringwald 8119a19cd78SMatthias Ringwald int w = LC3_MAX(4, LC3_SRATE_KHZ(sr) / 4); 812*4930cef6SMatthias Ringwald float c[2*w]; 8139a19cd78SMatthias Ringwald 8149a19cd78SMatthias Ringwald for (int i = 0; i < w; i++) { 8159a19cd78SMatthias Ringwald float g = active ? 0.4f - 0.05f * g_idx : 0; 816*4930cef6SMatthias Ringwald c[ i] = g * lc3_ltpf_cden[sr][pitch & 3][(w-1)-i]; 817*4930cef6SMatthias Ringwald c[w+i] = 0.85f * g * lc3_ltpf_cnum[sr][LC3_MIN(g_idx, 3)][(w-1)-i]; 8189a19cd78SMatthias Ringwald } 8199a19cd78SMatthias Ringwald 8209a19cd78SMatthias Ringwald /* --- Transition handling --- */ 8219a19cd78SMatthias Ringwald 8229a19cd78SMatthias Ringwald int ns = LC3_NS(dt, sr); 823*4930cef6SMatthias Ringwald int nt = ns / (3 + dt); 824*4930cef6SMatthias Ringwald float x0[w]; 8259a19cd78SMatthias Ringwald 8269a19cd78SMatthias Ringwald if (active) 827*4930cef6SMatthias Ringwald memcpy(x0, x + nt-(w-1), (w-1) * sizeof(float)); 8289a19cd78SMatthias Ringwald 8299a19cd78SMatthias Ringwald if (!ltpf->active && active) 830*4930cef6SMatthias Ringwald synthesize[sr](xh, nh, pitch/4, ltpf->x, x, nt, c, 1); 8319a19cd78SMatthias Ringwald else if (ltpf->active && !active) 832*4930cef6SMatthias Ringwald synthesize[sr](xh, nh, ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1); 8339a19cd78SMatthias Ringwald else if (ltpf->active && active && ltpf->pitch == pitch) 834*4930cef6SMatthias Ringwald synthesize[sr](xh, nh, pitch/4, ltpf->x, x, nt, c, 0); 8359a19cd78SMatthias Ringwald else if (ltpf->active && active) { 836*4930cef6SMatthias Ringwald synthesize[sr](xh, nh, ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1); 837*4930cef6SMatthias Ringwald synthesize[sr](xh, nh, pitch/4, 838*4930cef6SMatthias Ringwald (x <= xh ? x + nh : x) - (w-1), x, nt, c, 1); 8399a19cd78SMatthias Ringwald } 8409a19cd78SMatthias Ringwald 8419a19cd78SMatthias Ringwald /* --- Remainder --- */ 8429a19cd78SMatthias Ringwald 8439a19cd78SMatthias Ringwald memcpy(ltpf->x, x + ns - (w-1), (w-1) * sizeof(float)); 8449a19cd78SMatthias Ringwald 8459a19cd78SMatthias Ringwald if (active) 846*4930cef6SMatthias Ringwald synthesize[sr](xh, nh, pitch/4, x0, x + nt, ns-nt, c, 0); 8479a19cd78SMatthias Ringwald 8489a19cd78SMatthias Ringwald /* --- Update state --- */ 8499a19cd78SMatthias Ringwald 8509a19cd78SMatthias Ringwald ltpf->active = active; 8519a19cd78SMatthias Ringwald ltpf->pitch = pitch; 852*4930cef6SMatthias Ringwald memcpy(ltpf->c, c, 2*w * sizeof(*ltpf->c)); 8539a19cd78SMatthias Ringwald } 8549a19cd78SMatthias Ringwald 8559a19cd78SMatthias Ringwald 8569a19cd78SMatthias Ringwald /* ---------------------------------------------------------------------------- 8579a19cd78SMatthias Ringwald * Bitstream data 8589a19cd78SMatthias Ringwald * -------------------------------------------------------------------------- */ 8599a19cd78SMatthias Ringwald 8609a19cd78SMatthias Ringwald /** 8619a19cd78SMatthias Ringwald * LTPF disable 8629a19cd78SMatthias Ringwald */ 8639a19cd78SMatthias Ringwald void lc3_ltpf_disable(struct lc3_ltpf_data *data) 8649a19cd78SMatthias Ringwald { 8659a19cd78SMatthias Ringwald data->active = false; 8669a19cd78SMatthias Ringwald } 8679a19cd78SMatthias Ringwald 8689a19cd78SMatthias Ringwald /** 8699a19cd78SMatthias Ringwald * Return number of bits coding the bitstream data 8709a19cd78SMatthias Ringwald */ 8719a19cd78SMatthias Ringwald int lc3_ltpf_get_nbits(bool pitch) 8729a19cd78SMatthias Ringwald { 8739a19cd78SMatthias Ringwald return 1 + 10 * pitch; 8749a19cd78SMatthias Ringwald } 8759a19cd78SMatthias Ringwald 8769a19cd78SMatthias Ringwald /** 8779a19cd78SMatthias Ringwald * Put bitstream data 8789a19cd78SMatthias Ringwald */ 8799a19cd78SMatthias Ringwald void lc3_ltpf_put_data(lc3_bits_t *bits, 8809a19cd78SMatthias Ringwald const struct lc3_ltpf_data *data) 8819a19cd78SMatthias Ringwald { 8829a19cd78SMatthias Ringwald lc3_put_bit(bits, data->active); 8839a19cd78SMatthias Ringwald lc3_put_bits(bits, data->pitch_index, 9); 8849a19cd78SMatthias Ringwald } 8859a19cd78SMatthias Ringwald 8869a19cd78SMatthias Ringwald /** 8879a19cd78SMatthias Ringwald * Get bitstream data 8889a19cd78SMatthias Ringwald */ 8899a19cd78SMatthias Ringwald void lc3_ltpf_get_data(lc3_bits_t *bits, struct lc3_ltpf_data *data) 8909a19cd78SMatthias Ringwald { 8919a19cd78SMatthias Ringwald data->active = lc3_get_bit(bits); 8929a19cd78SMatthias Ringwald data->pitch_index = lc3_get_bits(bits, 9); 8939a19cd78SMatthias Ringwald } 894