Unified · Split
| @@ -31,23 +31,24 @@ · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | #include "mag_spectrum.hh" |
| 33 | 33 | |
| 34 | −#define UPSAMPLE_RATIO 2.0 | |
| 34 | +#define UPSAMPLE_RATIO 2 | |
| 35 | 35 | #define ARRAY_LEN(x) (sizeof (x) / sizeof ((x) [0])) |
| 36 | 36 | |
| 37 | +#define INTERP_LEN 1600 | |
| 37 | 38 | /* |
| 38 | 39 | ** Number of half cycles of impulse response to the left and right |
| 39 | 40 | ** of the center. |
| 40 | −** left_half_offset <= right_half_cycles | |
| 41 | +** left_half_offset <= right_len | |
| 41 | 42 | */ |
| 42 | 43 | |
| 43 | −static int left_half_cycles = 6 ; | |
| 44 | −static int right_half_cycles = 20 ; | |
| 44 | +static int left_len = 150 ; | |
| 45 | +static int right_len = 750 ; | |
| 45 | 46 | |
| 46 | 47 | |
| 47 | 48 | typedef struct |
| 48 | 49 | { |
| 49 | 50 | /* Window coefficients (all in range [0, 1]). */ |
| 50 | − double y_left [3], y_right [3] ; | |
| 51 | + double y_left [10], y_right [10] ; | |
| 51 | 52 | |
| 52 | 53 | double sinc_time_fudge ; |
| 53 | 54 | |
| @@ -57,20 +58,20 @@ typedef struct · 3 unmodified lines | ||
| 57 | 58 | { |
| 58 | 59 | union |
| 59 | 60 | { FIR_PARAMS fir_params ; |
| 60 | − double data [20] ; | |
| 61 | + double data [30] ; | |
| 61 | 62 | } ; |
| 62 | 63 | |
| 63 | 64 | unsigned middle, total_len ; |
| 64 | 65 | |
| 65 | − double left_window_poly [5] ; | |
| 66 | − double right_window_poly [5] ; | |
| 66 | + double left_window_poly [20] ; | |
| 67 | + double right_window_poly [20] ; | |
| 67 | 68 | |
| 68 | − double sinc [2048] ; | |
| 69 | − double window [2048] ; | |
| 70 | − double filter [2048] ; | |
| 71 | − double mag [1024] ; | |
| 72 | − double logmag [1024] ; | |
| 73 | − double phase [1024] ; | |
| 69 | + double sinc [INTERP_LEN] ; | |
| 70 | + double window [INTERP_LEN] ; | |
| 71 | + double filter [INTERP_LEN] ; | |
| 72 | + double mag [INTERP_LEN / 2] ; | |
| 73 | + double logmag [INTERP_LEN / 2] ; | |
| 74 | + double phase [INTERP_LEN / 2] ; | |
| 74 | 75 | } FIR_INTERP ; |
| 75 | 76 | |
| 76 | 77 | static double fir_error (const GMatrix& gm) ; |
| @@ -90,6 +91,7 @@ main (void) · 13 unmodified lines | ||
| 90 | 91 | double error ; |
| 91 | 92 | int param_count ; |
| 92 | 93 | |
| 94 | + puts ("Running ........") ; | |
| 93 | 95 | param_count = sizeof (FIR_PARAMS) / sizeof (double) ; |
| 94 | 96 | |
| 95 | 97 | randomize_data (&interp) ; |
| @@ -128,15 +130,27 @@ poly_evaluate (int order, const double *coeff, double x) · 32 unmodified lines | ||
| 128 | 130 | |
| 129 | 131 | static double |
| 130 | 132 | evaluate_filter (FIR_INTERP *interp) |
| 131 | −{ | |
| 133 | +{ double error = 0.0, temp, stop_max = 0.0, stop_sum = 0.0 ; | |
| 134 | + unsigned k ; | |
| 135 | + | |
| 132 | 136 | mag_spectrum (interp->filter, ARRAY_LEN (interp->filter), interp->mag, interp->logmag, interp->phase) ; |
| 137 | + | |
| 138 | + for (k = ARRAY_LEN (interp->logmag) / UPSAMPLE_RATIO ; k < ARRAY_LEN (interp->logmag) ; k++) | |
| 139 | + { temp = interp->logmag [k] + 150.0 ; | |
| 140 | + if (temp > stop_max) | |
| 141 | + stop_max = temp ; | |
| 142 | + if (temp > 0.0) | |
| 143 | + stop_sum += temp ; | |
| 144 | + } ; | |
| 133 | 145 | |
| 134 | − return 1.0 ; | |
| 146 | + error = stop_max * stop_sum ; | |
| 147 | + return error ; | |
| 135 | 148 | } /* evaluate_filter */ |
| 136 | 149 | |
| 137 | 150 | static double |
| 138 | 151 | fir_error (const GMatrix& gm) |
| 139 | 152 | { static FIR_INTERP interp ; |
| 153 | + static int test_count = 0 ; | |
| 140 | 154 | static double best_error = 1e200 ; |
| 141 | 155 | double error = 0.0 ; |
| 142 | 156 | unsigned param_count ; |
| @@ -146,24 +160,22 @@ fir_error (const GMatrix& gm) · 3 unmodified lines | ||
| 146 | 160 | param_count = sizeof (FIR_PARAMS) / sizeof (double) ; |
| 147 | 161 | |
| 148 | 162 | if (ARRAY_LEN (interp.data) < param_count) |
| 149 | − { printf ("\n\nError : ARRAY_LEN (interp.data) < param_count.\n") ; | |
| 163 | + { printf ("\n\nError : ARRAY_LEN (interp.data) < param_count.\n\n") ; | |
| 150 | 164 | exit (1) ; |
| 151 | 165 | } ; |
| 152 | 166 | |
| 153 | 167 | if (gm.GetData (param_count, interp.data) != param_count) |
| 154 | − { printf ("\n\nError : GetData should return %d.\n", param_count) ; | |
| 168 | + { printf ("\n\nError : GetData should return %d.\n\n", param_count) ; | |
| 155 | 169 | exit (1) ; |
| 156 | 170 | } ; |
| 157 | 171 | |
| 158 | 172 | /* Eval error in sinc_time_fudge. */ |
| 159 | − if (interp.fir_params.sinc_time_fudge < 1.0) | |
| 173 | + if (fabs (interp.fir_params.sinc_time_fudge - 1.0) > 0.5) | |
| 160 | 174 | return 1e30 * (fabs (interp.fir_params.sinc_time_fudge - 1.0)) ; |
| 161 | 175 | |
| 162 | − if (interp.fir_params.sinc_time_fudge > 1.25) | |
| 163 | − return 1e30 * (fabs (interp.fir_params.sinc_time_fudge - 1.25)) ; | |
| 164 | 176 | |
| 165 | − interp.middle = lrint (floor (left_half_cycles * UPSAMPLE_RATIO / interp.fir_params.sinc_time_fudge)) ; | |
| 166 | − interp.total_len = interp.middle + lrint (floor (right_half_cycles * UPSAMPLE_RATIO / interp.fir_params.sinc_time_fudge)) ; | |
| 177 | + interp.middle = left_len ; | |
| 178 | + interp.total_len = left_len + right_len ; | |
| 167 | 179 | |
| 168 | 180 | if (interp.total_len > ARRAY_LEN (interp.sinc)) |
| 169 | 181 | { printf ("\n\nError : interp.total_len > ARRAY_LEN (interp.sinc).\n") ; |
| @@ -178,13 +190,14 @@ fir_error (const GMatrix& gm) · 8 unmodified lines | ||
| 178 | 190 | |
| 179 | 191 | error = evaluate_filter (&interp) ; |
| 180 | 192 | |
| 181 | − oct_save (&interp) ; | |
| 182 | − printf ("%s %d : exit\n", __func__, __LINE__) ; | |
| 183 | − exit (1) ; | |
| 193 | + test_count ++ ; | |
| 194 | +// printf ("%s %d : exit\n", __func__, __LINE__) ; | |
| 195 | +// exit (1) ; | |
| 184 | 196 | |
| 185 | 197 | if (error < best_error) |
| 186 | 198 | { oct_save (&interp) ; |
| 187 | 199 | best_error = error ; |
| 200 | + printf ("%12d best : %f\n", test_count, best_error) ; | |
| 188 | 201 | } ; |
| 189 | 202 | |
| 190 | 203 | return error ; |
| @@ -195,7 +208,8 @@ calc_window (FIR_INTERP *interp, double * returned_error) · 4 unmodified lines | ||
| 195 | 208 | { unsigned k ; |
| 196 | 209 | double error, temp, x ; |
| 197 | 210 | |
| 198 | − error = 0 ; | |
| 211 | + /* Make sure left poly params are in range [0, 1]. */ | |
| 212 | + error = 0.0 ; | |
| 199 | 213 | for (k = 0 ; k < ARRAY_LEN (interp->fir_params.y_left) ; k++) |
| 200 | 214 | { temp = fabs (interp->fir_params.y_left [k] - 0.5) ; |
| 201 | 215 | if (temp > 0.5 && temp > error) |
| @@ -207,7 +221,8 @@ calc_window (FIR_INTERP *interp, double * returned_error) · 5 unmodified lines | ||
| 207 | 221 | return 1 ; |
| 208 | 222 | } ; |
| 209 | 223 | |
| 210 | − error = 0 ; | |
| 224 | + /* Make sure right poly params are in range [0, 1]. */ | |
| 225 | + error = 0.0 ; | |
| 211 | 226 | for (k = 0 ; k < ARRAY_LEN (interp->fir_params.y_right) ; k++) |
| 212 | 227 | { temp = fabs (interp->fir_params.y_right [k] - 0.5) ; |
| 213 | 228 | if (temp > 0.5 && temp > error) |
| @@ -219,11 +234,14 @@ calc_window (FIR_INTERP *interp, double * returned_error) · 5 unmodified lines | ||
| 219 | 234 | return 1 ; |
| 220 | 235 | } ; |
| 221 | 236 | |
| 222 | − interp->left_window_poly [0] = interp->fir_params.y_left [0] ; | |
| 223 | − interp->left_window_poly [1] = 13.0/2 - 13.0/2 * interp->fir_params.y_left [0] + 27.0/2 * interp->fir_params.y_left [1] - 27.0/2 * interp->fir_params.y_left [2] ; | |
| 224 | − interp->left_window_poly [2] = -139.0/4 + 29.0/2 * interp->fir_params.y_left [0] - 189.0/4 * interp->fir_params.y_left [1] + 135.0/2 * interp->fir_params.y_left [2] ; | |
| 225 | − interp->left_window_poly [3] = 54 - 27.0/2 * interp->fir_params.y_left [0] + 54 * interp->fir_params.y_left [1] - 189.0/2 * interp->fir_params.y_left [2] ; | |
| 226 | − interp->left_window_poly [4] = -99.0/4 + 9.0/2 * interp->fir_params.y_left [0] - 81.0/4 * interp->fir_params.y_left [1] + 81.0/2 * interp->fir_params.y_left [2] ; | |
| 237 | + /* Generate polynomial for left side of window. */ | |
| 238 | + interp->left_window_poly [0] = interp->fir_params.y_left [0] ; | |
| 239 | + interp->left_window_poly [1] = 12.4166666667 - 12.4166666667 * interp->fir_params.y_left [0] + 31.25 * interp->fir_params.y_left [1] - 41.6666666667 * interp->fir_params.y_left [2] + 41.6666666667 * interp->fir_params.y_left [3] - 31.25 * interp->fir_params.y_left [4] ; | |
| 240 | + interp->left_window_poly [2] = -140.756944444 + 58.2916666667 * interp->fir_params.y_left [0] - 231.770833333 * interp->fir_params.y_left [1] + 413.194444444 * interp->fir_params.y_left [2] - 447.916666667 * interp->fir_params.y_left [3] + 348.958333333 * interp->fir_params.y_left [4] ; | |
| 241 | + interp->left_window_poly [3] = 571.614583333 - 135.416666667 * interp->fir_params.y_left [0] + 662.760416667 * interp->fir_params.y_left [1] - 1395.83333333 * interp->fir_params.y_left [2] + 1682.29166667 * interp->fir_params.y_left [3] - 1385.41666667 * interp->fir_params.y_left [4] ; | |
| 242 | + interp->left_window_poly [4] = -1062.93402778 + 166.666666667 * interp->fir_params.y_left [0] - 917.96875 * interp->fir_params.y_left [1] + 2152.77777778 * interp->fir_params.y_left [2] - 2838.54166667 * interp->fir_params.y_left [3] + 2500. * interp->fir_params.y_left [4] ; | |
| 243 | + interp->left_window_poly [5] = 917.96875 - 104.166666667 * interp->fir_params.y_left [0] + 618.489583333 * interp->fir_params.y_left [1] - 1562.5 * interp->fir_params.y_left [2] + 2213.54166667 * interp->fir_params.y_left [3] - 2083.33333333 * interp->fir_params.y_left [4] ; | |
| 244 | + interp->left_window_poly [6] = -297.309027778 + 26.0416666667 * interp->fir_params.y_left [0] - 162.760416667 * interp->fir_params.y_left [1] + 434.027777778 * interp->fir_params.y_left [2] - 651.041666667 * interp->fir_params.y_left [3] + 651.041666667 * interp->fir_params.y_left [4] ; | |
| 227 | 245 | |
| 228 | 246 | /* Generate left side of window. */ |
| 229 | 247 | error = 0.0 ; |
| @@ -232,16 +250,20 @@ calc_window (FIR_INTERP *interp, double * returned_error) · 2 unmodified lines | ||
| 232 | 250 | interp->window [k] = poly_evaluate (ARRAY_LEN (interp->left_window_poly) - 1, interp->left_window_poly, x) ; |
| 233 | 251 | } ; |
| 234 | 252 | |
| 235 | − if (fabs (interp->window [0] - 0.2) > 0.2) | |
| 253 | + /* Ensure start value in range [0, 0,2]. */ | |
| 254 | + if (fabs (interp->window [0] - 0.1) > 0.1) | |
| 236 | 255 | { *returned_error = 1e16 * fabs (interp->window [0] - 0.1) ; |
| 237 | 256 | return 1 ; |
| 238 | 257 | } ; |
| 239 | 258 | |
| 240 | − interp->right_window_poly [0] = 1 ; | |
| 241 | − interp->right_window_poly [1] = 0 ; | |
| 242 | − interp->right_window_poly [2] = -85.0/4 + 27 * interp->fir_params.y_right [0] - 27.0/4 * interp->fir_params.y_right [1] + interp->fir_params.y_right [2] ; | |
| 243 | − interp->right_window_poly [3] = 45 - 135.0/2 * interp->fir_params.y_right [0] + 27 * interp->fir_params.y_right [1] - 9.0/2 * interp->fir_params.y_right [2] ; | |
| 244 | − interp->right_window_poly [4] = -99.0/4 + 81.0/2 * interp->fir_params.y_right [0] - 81.0/4 * interp->fir_params.y_right [1] + 9.0/2 * interp->fir_params.y_right [2] ; | |
| 259 | + /* Generate polynomial for right side of window. */ | |
| 260 | + interp->right_window_poly [0] = 1 ; | |
| 261 | + interp->right_window_poly [1] = 0 ; | |
| 262 | + interp->right_window_poly [2] = -83.4652777778 + 125. * interp->fir_params.y_right [0] - 62.5 * interp->fir_params.y_right [1] + 27.7777777778 * interp->fir_params.y_right [2] - 7.8125 * interp->fir_params.y_right [3] + interp->fir_params.y_right [4] ; | |
| 263 | + interp->right_window_poly [3] = 446.614583333 - 802.083333333 * interp->fir_params.y_right [0] + 557.291666667 * interp->fir_params.y_right [1] - 270.833333333 * interp->fir_params.y_right [2] + 79.4270833333 * interp->fir_params.y_right [3] - 10.4166666667 * interp->fir_params.y_right [4] ; | |
| 264 | + interp->right_window_poly [4] = -932.725694444 + 1848.95833333 * interp->fir_params.y_right [0] - 1536.45833333 * interp->fir_params.y_right [1] + 850.694444444 * interp->fir_params.y_right [2] - 266.927083333 * interp->fir_params.y_right [3] + 36.4583333333 * interp->fir_params.y_right [4] ; | |
| 265 | + interp->right_window_poly [5] = 865.885416667 - 1822.91666667 * interp->fir_params.y_right [0] + 1692.70833333 * interp->fir_params.y_right [1] - 1041.66666667 * interp->fir_params.y_right [2] + 358.072916667 * interp->fir_params.y_right [3] - 52.0833333333 * interp->fir_params.y_right [4] ; | |
| 266 | + interp->right_window_poly [6] = -297.309027778 + 651.041666667 * interp->fir_params.y_right [0] - 651.041666667 * interp->fir_params.y_right [1] + 434.027777778 * interp->fir_params.y_right [2] - 162.760416667 * interp->fir_params.y_right [3] + 26.0416666667 * interp->fir_params.y_right [4] ; | |
| 245 | 267 | |
| 246 | 268 | /* Generate right side of window. */ |
| 247 | 269 | error = 0.0 ; |
| @@ -250,12 +272,14 @@ calc_window (FIR_INTERP *interp, double * returned_error) · 2 unmodified lines | ||
| 250 | 272 | interp->window [k] = poly_evaluate (ARRAY_LEN (interp->right_window_poly) - 1, interp->right_window_poly, x) ; |
| 251 | 273 | } ; |
| 252 | 274 | |
| 275 | + /* Ensure end value in range [0, 0,4]. */ | |
| 253 | 276 | k = interp->total_len - 1 ; |
| 254 | − if (fabs (interp->window [k] - 0.2) > 0.2) | |
| 277 | + if (fabs (interp->window [k] - 0.1) > 0.1) | |
| 255 | 278 | { *returned_error = 1e16 * fabs (interp->window [k] - 0.1) ; |
| 256 | 279 | return 1 ; |
| 257 | 280 | } ; |
| 258 | 281 | |
| 282 | + /* Ensure whole window is in [0, 1] range. */ | |
| 259 | 283 | error = 0.0 ; |
| 260 | 284 | for (k = 0 ; k < interp->total_len ; k++) |
| 261 | 285 | { temp = fabs (interp->window [k] - 0.5) ; |
| @@ -268,6 +292,32 @@ calc_window (FIR_INTERP *interp, double * returned_error) · 6 unmodified lines | ||
| 268 | 292 | return 1 ; |
| 269 | 293 | } ; |
| 270 | 294 | |
| 295 | + /* Monotonicity of left side of window. */ | |
| 296 | + error = 0.0 ; | |
| 297 | + for (k = 1 ; k < interp->middle ; k++) | |
| 298 | + { temp = (interp->window [k - 1] - interp->window [k]) ; | |
| 299 | + if (temp > 0.0) | |
| 300 | + error += temp ; | |
| 301 | + } ; | |
| 302 | + | |
| 303 | + if (error > 0.0) | |
| 304 | + { *returned_error = 1e14 * error ; | |
| 305 | + return 1 ; | |
| 306 | + } ; | |
| 307 | + | |
| 308 | + /* Monotonicity of right side of window. */ | |
| 309 | + error = 0.0 ; | |
| 310 | + for (k = interp->middle + 1 ; k < interp->total_len ; k++) | |
| 311 | + { temp = (interp->window [k] - interp->window [k - 1]) ; | |
| 312 | + if (temp > 0.0) | |
| 313 | + error += temp ; | |
| 314 | + } ; | |
| 315 | + | |
| 316 | + if (error > 0.0) | |
| 317 | + { *returned_error = 1e14 * error ; | |
| 318 | + return 1 ; | |
| 319 | + } ; | |
| 320 | + | |
| 271 | 321 | return 0 ; |
| 272 | 322 | } /* calc_window */ |
| 273 | 323 | |