Mathias Agopian | 4b8a3d8 | 2007-08-23 03:16:02 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2007 Google Inc. |
| 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 | |
| 20 | static double sinc(double x) { |
| 21 | if (fabs(x) == 0.0f) return 1.0f; |
| 22 | return sin(x) / x; |
| 23 | } |
| 24 | |
| 25 | static double sqr(double x) { |
| 26 | return x*x; |
| 27 | } |
| 28 | |
| 29 | static double I0(double x) { |
| 30 | // from the Numerical Recipes in C p. 237 |
| 31 | double ax,ans,y; |
| 32 | ax=fabs(x); |
| 33 | if (ax < 3.75) { |
| 34 | y=x/3.75; |
| 35 | y*=y; |
| 36 | ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492 |
| 37 | +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2))))); |
| 38 | } else { |
| 39 | y=3.75/ax; |
| 40 | ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1 |
| 41 | +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2 |
| 42 | +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1 |
| 43 | +y*0.392377e-2)))))))); |
| 44 | } |
| 45 | return ans; |
| 46 | } |
| 47 | |
| 48 | static double kaiser(int k, int N, double alpha) { |
| 49 | if (k < 0 || k > N) |
| 50 | return 0; |
| 51 | return I0(M_PI*alpha * sqrt(1.0 - sqr((2.0*k)/N - 1.0))) / I0(M_PI*alpha); |
| 52 | } |
| 53 | |
| 54 | int main(int argc, char** argv) |
| 55 | { |
| 56 | // nc is the number of bits to store the coefficients |
| 57 | int nc = 16; |
| 58 | |
| 59 | // ni is the minimum number of bits needed for interpolation |
| 60 | // (not used for generating the coefficients) |
| 61 | const int ni = nc / 2; |
| 62 | |
| 63 | // nzc is the number of zero-crossing on one half of the filter |
| 64 | int nzc = 12; |
| 65 | |
| 66 | // alpha parameter of the kaiser window |
| 67 | // Larger numbers reduce ripples in the rejection band but increase |
| 68 | // the width of the transition band. In reality there doesn't seem to be |
| 69 | // a good reason to choose a big number because of the limited range |
| 70 | // of our coefficients (16 bits). |
| 71 | double alpha = 3.0; |
| 72 | |
| 73 | // cut off frequency ratio Fc/Fs |
| 74 | double Fcr = 20000.0 / 44100.0; |
| 75 | |
| 76 | // 2^nz is the number coefficients per zero-crossing |
| 77 | // (int theory this should be 1<<(nc/2)) |
| 78 | const int nz = 4; |
| 79 | |
| 80 | // total number of coefficients |
Mathias Agopian | 65682fb | 2007-08-23 21:01:28 -0700 | [diff] [blame^] | 81 | const int N = (1 << nz) * nzc; |
Mathias Agopian | 4b8a3d8 | 2007-08-23 03:16:02 -0700 | [diff] [blame] | 82 | |
| 83 | // generate the right half of the filter |
Mathias Agopian | 4b8a3d8 | 2007-08-23 03:16:02 -0700 | [diff] [blame] | 84 | printf("const int32_t RESAMPLE_FIR_SIZE = %d;\n", N); |
| 85 | printf("const int32_t RESAMPLE_FIR_NUM_COEF = %d;\n", nzc); |
| 86 | printf("const int32_t RESAMPLE_FIR_COEF_BITS = %d;\n", nc); |
| 87 | printf("const int32_t RESAMPLE_FIR_LERP_FRAC_BITS = %d;\n", ni); |
| 88 | printf("const int32_t RESAMPLE_FIR_LERP_INT_BITS = %d;\n", nz); |
| 89 | printf("\n"); |
| 90 | printf("static int16_t resampleFIR[%d] = {", N); |
| 91 | for (int i=0 ; i<N ; i++) |
| 92 | { |
Mathias Agopian | 65682fb | 2007-08-23 21:01:28 -0700 | [diff] [blame^] | 93 | double x = (2.0 * M_PI * i * Fcr) / (1 << nz); |
Mathias Agopian | 4b8a3d8 | 2007-08-23 03:16:02 -0700 | [diff] [blame] | 94 | double y = kaiser(i+N, 2*N, alpha) * sinc(x); |
| 95 | |
| 96 | int yi = floor(y * (1<<(nc-1)) + 0.5); |
| 97 | if (yi >= (1<<(nc-1))) yi = (1<<(nc-1))-1; |
| 98 | |
Mathias Agopian | 4b8a3d8 | 2007-08-23 03:16:02 -0700 | [diff] [blame] | 99 | if ((i % (1 << 4)) == 0) printf("\n "); |
| 100 | printf("0x%04x, ", yi & 0xFFFF); |
| 101 | } |
| 102 | printf("\n};\n"); |
Mathias Agopian | 4b8a3d8 | 2007-08-23 03:16:02 -0700 | [diff] [blame] | 103 | return 0; |
| 104 | } |
| 105 | |