1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <math.h> 18 #include <stdio.h> 19 #include <unistd.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 static inline double sinc(double x) { 24 if (fabs(x) == 0.0f) return 1.0f; 25 return sin(x) / x; 26 } 27 28 static inline double sqr(double x) { 29 return x*x; 30 } 31 32 static inline int64_t toint(double x, int64_t maxval) { 33 int64_t v; 34 35 v = static_cast<int64_t>(floor(x * maxval + 0.5)); 36 if (v >= maxval) { 37 return maxval - 1; // error! 38 } 39 return v; 40 } 41 42 static double I0(double x) { 43 // from the Numerical Recipes in C p. 237 44 double ax,ans,y; 45 ax=fabs(x); 46 if (ax < 3.75) { 47 y=x/3.75; 48 y*=y; 49 ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492 50 +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2))))); 51 } else { 52 y=3.75/ax; 53 ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1 54 +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2 55 +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1 56 +y*0.392377e-2)))))))); 57 } 58 return ans; 59 } 60 61 static double kaiser(int k, int N, double beta) { 62 if (k < 0 || k > N) 63 return 0; 64 return I0(beta * sqrt(1.0 - sqr((2.0*k)/N - 1.0))) / I0(beta); 65 } 66 67 static void usage(char* name) { 68 fprintf(stderr, 69 "usage: %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]" 70 " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] [-l lerp]\n" 71 " %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]" 72 " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] -p M/N\n" 73 " -h this help message\n" 74 " -d debug, print comma-separated coefficient table\n" 75 " -D generate extra declarations\n" 76 " -p generate poly-phase filter coefficients, with sample increment M/N\n" 77 " -s sample rate (48000)\n" 78 " -c cut-off frequency (20478)\n" 79 " -n number of zero-crossings on one side (8)\n" 80 " -l number of lerping bits (4)\n" 81 " -m number of polyphases (related to -l, default 16)\n" 82 " -f output format, can be fixed, fixed16, or float (fixed)\n" 83 " -b kaiser window parameter beta (7.865 [-80dB])\n" 84 " -v attenuation in dBFS (0)\n", 85 name, name 86 ); 87 exit(0); 88 } 89 90 int main(int argc, char** argv) 91 { 92 // nc is the number of bits to store the coefficients 93 int nc = 32; 94 bool polyphase = false; 95 unsigned int polyM = 160; 96 unsigned int polyN = 147; 97 bool debug = false; 98 double Fs = 48000; 99 double Fc = 20478; 100 double atten = 1; 101 int format = 0; // 0=fixed, 1=float 102 bool declarations = false; 103 104 // in order to keep the errors associated with the linear 105 // interpolation of the coefficients below the quantization error 106 // we must satisfy: 107 // 2^nz >= 2^(nc/2) 108 // 109 // for 16 bit coefficients that would be 256 110 // 111 // note that increasing nz only increases memory requirements, 112 // but doesn't increase the amount of computation to do. 113 // 114 // 115 // see: 116 // Smith, J.O. Digital Audio Resampling Home Page 117 // https://ccrma.stanford.edu/~jos/resample/, 2011-03-29 118 // 119 120 // | 0.1102*(A - 8.7) A > 50 121 // beta = | 0.5842*(A - 21)^0.4 + 0.07886*(A - 21) 21 <= A <= 50 122 // | 0 A < 21 123 // with A is the desired stop-band attenuation in dBFS 124 // 125 // for eg: 126 // 127 // 30 dB 2.210 128 // 40 dB 3.384 129 // 50 dB 4.538 130 // 60 dB 5.658 131 // 70 dB 6.764 132 // 80 dB 7.865 133 // 90 dB 8.960 134 // 100 dB 10.056 135 double beta = 7.865; 136 137 // 2*nzc = (A - 8) / (2.285 * dw) 138 // with dw the transition width = 2*pi*dF/Fs 139 // 140 int nzc = 8; 141 142 /* 143 * Example: 144 * 44.1 KHz to 48 KHz resampling 145 * 100 dB rejection above 28 KHz 146 * (the spectrum will fold around 24 KHz and we want 100 dB rejection 147 * at the point where the folding reaches 20 KHz) 148 * ...___|_____ 149 * | \| 150 * | ____/|\____ 151 * |/alias| \ 152 * ------/------+------\---------> KHz 153 * 20 24 28 154 * 155 * Transition band 8 KHz, or dw = 1.0472 156 * 157 * beta = 10.056 158 * nzc = 20 159 */ 160 161 int M = 1 << 4; // number of phases for interpolation 162 int ch; 163 while ((ch = getopt(argc, argv, ":hds:c:n:f:l:m:b:p:v:z:D")) != -1) { 164 switch (ch) { 165 case 'd': 166 debug = true; 167 break; 168 case 'D': 169 declarations = true; 170 break; 171 case 'p': 172 if (sscanf(optarg, "%u/%u", &polyM, &polyN) != 2) { 173 usage(argv[0]); 174 } 175 polyphase = true; 176 break; 177 case 's': 178 Fs = atof(optarg); 179 break; 180 case 'c': 181 Fc = atof(optarg); 182 break; 183 case 'n': 184 nzc = atoi(optarg); 185 break; 186 case 'm': 187 M = atoi(optarg); 188 break; 189 case 'l': 190 M = 1 << atoi(optarg); 191 break; 192 case 'f': 193 if (!strcmp(optarg, "fixed")) { 194 format = 0; 195 } 196 else if (!strcmp(optarg, "fixed16")) { 197 format = 0; 198 nc = 16; 199 } 200 else if (!strcmp(optarg, "float")) { 201 format = 1; 202 } 203 else { 204 usage(argv[0]); 205 } 206 break; 207 case 'b': 208 beta = atof(optarg); 209 break; 210 case 'v': 211 atten = pow(10, -fabs(atof(optarg))*0.05 ); 212 break; 213 case 'h': 214 default: 215 usage(argv[0]); 216 break; 217 } 218 } 219 220 // cut off frequency ratio Fc/Fs 221 double Fcr = Fc / Fs; 222 223 // total number of coefficients (one side) 224 225 const int N = M * nzc; 226 227 // lerp (which is most useful if M is a power of 2) 228 229 int nz = 0; // recalculate nz as the bits needed to represent M 230 for (int i = M-1 ; i; i>>=1, nz++); 231 // generate the right half of the filter 232 if (!debug) { 233 printf("// cmd-line:"); 234 for (int i=0 ; i<argc ; i++) { 235 printf(" %s", argv[i]); 236 } 237 printf("\n"); 238 if (declarations) { 239 if (!polyphase) { 240 printf("const int32_t RESAMPLE_FIR_SIZE = %d;\n", N); 241 printf("const int32_t RESAMPLE_FIR_INT_PHASES = %d;\n", M); 242 printf("const int32_t RESAMPLE_FIR_NUM_COEF = %d;\n", nzc); 243 } else { 244 printf("const int32_t RESAMPLE_FIR_SIZE = %d;\n", 2*nzc*polyN); 245 printf("const int32_t RESAMPLE_FIR_NUM_COEF = %d;\n", 2*nzc); 246 } 247 if (!format) { 248 printf("const int32_t RESAMPLE_FIR_COEF_BITS = %d;\n", nc); 249 } 250 printf("\n"); 251 printf("static %s resampleFIR[] = {", !format ? "int32_t" : "float"); 252 } 253 } 254 255 if (!polyphase) { 256 for (int i=0 ; i<=M ; i++) { // an extra set of coefs for interpolation 257 for (int j=0 ; j<nzc ; j++) { 258 int ix = j*M + i; 259 double x = (2.0 * M_PI * ix * Fcr) / M; 260 double y = kaiser(ix+N, 2*N, beta) * sinc(x) * 2.0 * Fcr; 261 y *= atten; 262 263 if (!debug) { 264 if (j == 0) 265 printf("\n "); 266 } 267 if (!format) { 268 int64_t yi = toint(y, 1ULL<<(nc-1)); 269 if (nc > 16) { 270 printf("0x%08x,", int32_t(yi)); 271 } else { 272 printf("0x%04x,", int32_t(yi)&0xffff); 273 } 274 } else { 275 printf("%.9g%s", y, debug ? "," : "f,"); 276 } 277 if (j != nzc-1) { 278 printf(" "); 279 } 280 } 281 } 282 } else { 283 for (unsigned int j=0 ; j<polyN ; j++) { 284 // calculate the phase 285 double p = ((polyM*j) % polyN) / double(polyN); 286 if (!debug) printf("\n "); 287 else printf("\n"); 288 // generate a FIR per phase 289 for (int i=-nzc ; i<nzc ; i++) { 290 double x = 2.0 * M_PI * Fcr * (i + p); 291 double y = kaiser(i+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;; 292 y *= atten; 293 if (!format) { 294 int64_t yi = toint(y, 1ULL<<(nc-1)); 295 if (nc > 16) { 296 printf("0x%08x,", int32_t(yi)); 297 } else { 298 printf("0x%04x,", int32_t(yi)&0xffff); 299 } 300 } else { 301 printf("%.9g%s", y, debug ? "," : "f,"); 302 } 303 304 if (i != nzc-1) { 305 printf(" "); 306 } 307 } 308 } 309 } 310 311 if (!debug && declarations) { 312 printf("\n};"); 313 } 314 printf("\n"); 315 return 0; 316 } 317 318 // http://www.csee.umbc.edu/help/sound/AFsp-V2R1/html/audio/ResampAudio.html 319