1 /** \addtogroup utils 2 * @{ 3 * Utility functions 4 * 5 * \note All utility functions working with arrays can work inplace (i.e. in == out) without 6 * allocating additional memory internally. 7 */ 8 9 #ifndef _ltfat_ciutils_h 10 #define _ltfat_ciutils_h 11 12 typedef enum 13 { 14 /** Don't normalize */ 15 LTFAT_NORM_NULL = 0, 16 /** 1 norm (divide by the sum of abs. values) */ 17 /**@{*/ 18 LTFAT_NORM_AREA, 19 LTFAT_NORM_1 = LTFAT_NORM_AREA, 20 /**@}*/ 21 /** 2 norm (divide by the square root of sum of squares of abs. values) */ 22 /**@{*/ 23 LTFAT_NORM_ENERGY, 24 LTFAT_NORM_2 = LTFAT_NORM_ENERGY, 25 /**@}*/ 26 /** inf norm (divide by the max abs. val.)*/ 27 /**@{*/ 28 LTFAT_NORM_INF, 29 LTFAT_NORM_PEAK = LTFAT_NORM_INF, 30 /**@}*/ 31 // LTFAT_NORM_RMS, 32 // LTFAT_NORM_WAV, 33 } ltfat_norm_t; 34 35 36 typedef enum 37 { 38 LTFAT_WHOLEPOINT = 0, 39 LTFAT_HALFPOINT 40 41 } ltfat_symmetry_t; 42 43 #endif 44 45 /** Shift array circularly 46 * 47 * Works exactly like 48 * <a href="http://de.mathworks.com/help/matlab/ref/circshift.html">circshift</a> 49 * from Matlab. 50 * 51 * \param[in] in Input array 52 * \param[in] L Length of arrays 53 * \param[in] shift Shift amount (can be negative) 54 * \param[out] out Output array 55 * 56 * #### Function versions #### 57 * <tt> 58 * ltfat_circshift_d(const double in[], ltfat_int L,ltfat_int shift, double out[]); 59 * 60 * ltfat_circshift_s(const float in[], ltfat_int L,ltfat_int shift, float out[]); 61 * 62 * ltfat_circshift_dc(const ltfat_complex_d in[], ltfat_int L,ltfat_int shift, ltfat_complex_d out[]); 63 * 64 * ltfat_circshift_sc(const ltfat_complex_s in[], ltfat_int L,ltfat_int shift, ltfat_complex_s out[]); 65 * </tt> 66 * 67 * \returns 68 * Status code | Description 69 * ----------------------|-------------------------------------------- 70 * LTFATERR_SUCCESS | Indicates no error 71 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 72 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 73 */ 74 LTFAT_API int 75 LTFAT_NAME(circshift)(const LTFAT_TYPE in[], ltfat_int L, 76 ltfat_int shift, LTFAT_TYPE out[]); 77 78 /** Shift columns of a matrix circularly 79 * 80 * Works like circshift but with entire cols. 81 * 82 * \param[in] in Input array 83 * \param[in] L Length of cols 84 * \param[in] W Number of cols 85 * \param[in] shift Shift amount (can be negative) 86 * \param[out] out Output array 87 * 88 * #### Function versions #### 89 * <tt> 90 * ltfat_circshiftcols_d(const double in[], ltfat_int L, ltfat_int W, ltfat_int shift, double out[]); 91 * 92 * ltfat_circshiftcols_s(const float in[], ltfat_int L, ltfat_int W, ltfat_int shift, float out[]); 93 * 94 * ltfat_circshiftcols_dc(const ltfat_complex_d in[], ltfat_int L, ltfat_int W, ltfat_int shift, ltfat_complex_d out[]); 95 * 96 * ltfat_circshiftcols_sc(const ltfat_complex_s in[], ltfat_int L, ltfat_int W, ltfat_int shift, ltfat_complex_s out[]); 97 * </tt> 98 * 99 * \returns 100 * Status code | Description 101 * ----------------------|-------------------------------------------- 102 * LTFATERR_SUCCESS | Indicates no error 103 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 104 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 105 */ 106 LTFAT_API int 107 LTFAT_NAME(circshiftcols)(const LTFAT_TYPE in[], ltfat_int L, ltfat_int W, 108 ltfat_int shift, LTFAT_TYPE out[]); 109 110 /** 2D circshift 111 * 112 * Works exactly like 113 * <a href="http://de.mathworks.com/help/matlab/ref/circshift.html">circshift</a> 114 * from Matlab for matrices. 115 * 116 * \param[in] in Input array 117 * \param[in] H Number of rows 118 * \param[in] W Number of columns 119 * \param[in] shift_row Shift amount (can be negative) 120 * \param[in] shift_col Shift amount (can be negative) 121 * \param[out] out Output array 122 * 123 * #### Function versions #### 124 * <tt> 125 * ltfat_circshift2_d(const double in[], ltfat_int H, ltfat_int W, ltfat_int shift_row, ltfat_int shift_col, double out[]); 126 * 127 * ltfat_circshift2_s(const float in[], ltfat_int H, ltfat_int W, ltfat_int shift_row, ltfat_int shift_col, float out[]); 128 * 129 * ltfat_circshift2_dc(const ltfat_complex_d in[], ltfat_int H, ltfat_int W, ltfat_int shift_row, ltfat_int shift_col, ltfat_complex_d out[]); 130 * 131 * ltfat_circshift2_sc(const ltfat_complex_s in[], ltfat_int H, ltfat_int W, ltfat_int shift_row, ltfat_int shift_col, ltfat_complex_s out[]); 132 * </tt> 133 * 134 * \returns 135 * Status code | Description 136 * ----------------------|-------------------------------------------- 137 * LTFATERR_SUCCESS | Indicates no error 138 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 139 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 140 */ 141 LTFAT_API int 142 LTFAT_NAME(circshift2)(const LTFAT_TYPE in[], ltfat_int H, ltfat_int W, 143 ltfat_int shift_row, ltfat_int shift_col, LTFAT_TYPE out[]); 144 145 /** fftshift an array 146 * 147 * Works exactly like 148 * <a href="http://de.mathworks.com/help/matlab/ref/fftshift.html">fftshift</a> 149 * form Matlab for vectors. 150 * 151 * \param[in] in Input array 152 * \param[in] L Length of arrays 153 * \param[out] out Output array 154 * 155 * #### Function versions #### 156 * <tt> 157 * ltfat_fftshift_d(const double in[], ltfat_int L, double out[]); 158 * 159 * ltfat_fftshift_s(const float in[], ltfat_int L, float out[]); 160 * 161 * ltfat_fftshift_dc(const ltfat_complex_d in[], ltfat_int L, ltfat_complex_d out[]); 162 * 163 * ltfat_fftshift_sc(const ltfat_complex_s in[], ltfat_int L, ltfat_complex_s out[]); 164 * </tt> 165 * 166 * \returns 167 * Status code | Description 168 * ----------------------|-------------------------------------------- 169 * LTFATERR_SUCCESS | Indicates no error 170 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 171 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 172 */ 173 LTFAT_API int 174 LTFAT_NAME(fftshift)(const LTFAT_TYPE in[], ltfat_int L, LTFAT_TYPE out[]); 175 176 /** ifftshift an array 177 * 178 * Works exactly like 179 * <a href="http://de.mathworks.com/help/matlab/ref/ifftshift.html">ifftshift</a> 180 * form Matlab for vectors. Undoes the action of fftshift 181 * 182 * \param[in] in Input array 183 * \param[in] L Length of arrays 184 * \param[out] out Output array 185 * 186 * #### Function versions #### 187 * <tt> 188 * ltfat_ifftshift_d(const double in[], ltfat_int L, double out[]); 189 * 190 * ltfat_ifftshift_s(const float in[], ltfat_int L, float out[]); 191 * 192 * ltfat_ifftshift_dc(const ltfat_complex_d in[], ltfat_int L, ltfat_complex_d out[]); 193 * 194 * ltfat_ifftshift_sc(const ltfat_complex_s in[], ltfat_int L, ltfat_complex_s out[]); 195 * </tt> 196 * 197 * \returns 198 * Status code | Description 199 * ----------------------|-------------------------------------------- 200 * LTFATERR_SUCCESS | Indicates no error 201 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 202 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 203 */ 204 LTFAT_API int 205 LTFAT_NAME(ifftshift)(const LTFAT_TYPE in[], ltfat_int L, LTFAT_TYPE out[]); 206 207 /** Change signal length by inserting zeros in the middle 208 * 209 * Works exactly like 210 * <a href="http://ltfat.github.io/doc/fourier/middlepad.html">middlepad</a> 211 * form LTFAT i.e. extends \a in by inserting zeros in the middle or 212 * removes the middle part such that the output is \a Lout. 213 * 214 * 215 * \param[in] in Input array 216 * \param[in] Lin Length of input array 217 * \param[in] sym Which symmetry to preserve 218 * \param[in] Lout Length of output array 219 * \param[out] out Output array 220 * 221 * #### Function versions #### 222 * <tt> 223 * ltfat_middlepad_d(const double in[], ltfat_int Lin, ltfat_symmetry_t sym, ltfat_int Lout, double out[]); 224 * 225 * ltfat_middlepad_s(const float in[], ltfat_int Lin, ltfat_symmetry_t sym, ltfat_int Lout, float out[]); 226 * 227 * ltfat_middlepad_dc(const ltfat_complex_d in[], ltfat_int Lin, ltfat_symmetry_t sym, ltfat_int Lout, ltfat_complex_d out[]); 228 * 229 * ltfat_middlepad_sc(const ltfat_complex_s in[], ltfat_int Lin, ltfat_symmetry_t sym, ltfat_int Lout, ltfat_complex_s out[]); 230 * </tt> 231 * 232 * \returns 233 * Status code | Description 234 * ----------------------|-------------------------------------------- 235 * LTFATERR_SUCCESS | Indicates no error 236 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 237 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 238 * LTFATERR_BADREQSIZE | Output array is shorter than the input array: \a Llong < \a Lfir 239 */ 240 LTFAT_API int 241 LTFAT_NAME(middlepad)(const LTFAT_TYPE* in, ltfat_int Lin, ltfat_symmetry_t sym, 242 ltfat_int Lout, LTFAT_TYPE* out); 243 244 245 /** Change signal length by repeating in[0] from both ends 246 * 247 * Intended to be used on windows e.g. from firwin 248 * 249 * \param[in] in Input array 250 * \param[in] Lin Length of input array 251 * \param[in] Lout Length of output array 252 * \param[out] out Output array 253 * 254 * #### Function versions #### 255 * <tt> 256 * ltfat_peakpad_d(const double in[], ltfat_int Lin, ltfat_int Lout, double out[]); 257 * 258 * ltfat_peakpad_s(const float in[], ltfat_int Lin, ltfat_int Lout, float out[]); 259 * 260 * ltfat_peakpad_dc(const ltfat_complex_d in[], ltfat_int Lin, ltfat_int Lout, ltfat_complex_d out[]); 261 * 262 * ltfat_peakpad_sc(const ltfat_complex_s in[], ltfat_int Lin, ltfat_int Lout, ltfat_complex_s out[]); 263 * </tt> 264 * 265 * \returns 266 * Status code | Description 267 * ----------------------|-------------------------------------------- 268 * LTFATERR_SUCCESS | Indicates no error 269 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 270 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 271 * LTFATERR_BADREQSIZE | Output array is shorter than the input array: \a Llong < \a Lfir 272 */ 273 LTFAT_API int 274 LTFAT_NAME(peakpad)(const LTFAT_TYPE* in, ltfat_int Lin, ltfat_int Lout, LTFAT_TYPE* out); 275 276 // LTFAT_API int 277 // LTFAT_NAME(middlepadcols)(const LTFAT_TYPE* in, ltfat_int Hin, ltfat_int Win, ltfat_symmetry_t sym, 278 // ltfat_int Wout, LTFAT_TYPE* out); 279 // 280 // 281 // LTFAT_API int 282 // LTFAT_NAME(middlepad2d)(const LTFAT_TYPE* in, ltfat_int Hin, ltfat_int Win, ltfat_symmetry_t sym, 283 // ltfat_int Hout, ltfat_int Wout, LTFAT_TYPE* out); 284 285 286 /** Extend FIR window to long window 287 * 288 * Works exactly like 289 * <a href="http://ltfat.github.io/doc/sigproc/fir2long.html">fir2long</a> 290 * form LTFAT i.e. extends \a in by inserting zeros in the middle. 291 * \a Llong must be greater or equal to \a Lfir. 292 * 293 * \param[in] in Input array 294 * \param[in] Lfir Length of input array 295 * \param[in] Llong Length of output array 296 * \param[out] out Output array 297 * 298 * #### Function versions #### 299 * <tt> 300 * ltfat_fir2long_d(const double in[], ltfat_int Lfir, ltfat_int Llong, double out[]); 301 * 302 * ltfat_fir2long_s(const float in[], ltfat_int Lfir, ltfat_int Llong, float out[]); 303 * 304 * ltfat_fir2long_dc(const ltfat_complex_d in[], ltfat_int Lfir, ltfat_int Llong, ltfat_complex_d out[]); 305 * 306 * ltfat_fir2long_sc(const ltfat_complex_s in[], ltfat_int Lfir, ltfat_int Llong, ltfat_complex_s out[]); 307 * </tt> 308 * 309 * \returns 310 * Status code | Description 311 * ----------------------|-------------------------------------------- 312 * LTFATERR_SUCCESS | Indicates no error 313 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 314 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 315 * LTFATERR_BADREQSIZE | Output array is shorter than the input array: \a Llong < \a Lfir 316 */ 317 LTFAT_API int 318 LTFAT_NAME(fir2long)(const LTFAT_TYPE in[], ltfat_int Lfir, ltfat_int Llong, 319 LTFAT_TYPE out[]); 320 321 /** Cut long window to a FIR window 322 * 323 * Works exactly like 324 * <a href="http://ltfat.github.io/doc/sigproc/long2fir.html">long2fir</a> 325 * form LTFAT i.e. it removes the middle part. 326 * Llong must be greater or equal to Lfir. 327 * 328 * \param[in] in Input array 329 * \param[in] Llong Length of input array 330 * \param[in] Lfir Length of output array 331 * \param[out] out Output array 332 * 333 * #### Function versions #### 334 * <tt> 335 * ltfat_long2fir_d(const double in[], ltfat_int Llong, ltfat_int Lfir, double out[]); 336 * 337 * ltfat_long2fir_s(const float in[], ltfat_int Llong, ltfat_int Lfir, float out[]); 338 * 339 * ltfat_long2fir_dc(const ltfat_complex_d in[], ltfat_int Llong, ltfat_int Lfir, ltfat_complex_d out[]); 340 * 341 * ltfat_long2fir_sc(const ltfat_complex_s in[], ltfat_int Llong, ltfat_int Lfir, ltfat_complex_s out[]); 342 * </tt> 343 * 344 * \returns 345 * Status code | Description 346 * ----------------------|-------------------------------------------- 347 * LTFATERR_SUCCESS | Indicates no error 348 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 349 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 350 * LTFATERR_BADREQSIZE | Output array is longer than the input array: \a Lfir > \a Llong 351 */ 352 LTFAT_API int 353 LTFAT_NAME(long2fir)(const LTFAT_TYPE in[], ltfat_int Llong, ltfat_int Lfir, 354 LTFAT_TYPE out[]); 355 356 357 /** Compute norm of a vector 358 * 359 * \param[in] in Input array 360 * \param[in] L Length of input array 361 * \param[in] flag Norm 362 * \param[out] out Computed norm 363 * 364 * #### Function versions #### 365 * <tt> 366 * ltfat_norm_d(const double in[], ltfat_int L, ltfat_norm_t flag, double* out); 367 * 368 * ltfat_norm_s(const float in[], ltfat_int L, ltfat_norm_t flag flag, float* out); 369 * 370 * ltfat_norm_dc(const ltfat_complex_d in[], ltfat_int L, ltfat_norm_t flag, double* out); 371 * 372 * ltfat_norm_sc(const ltfat_complex_s in[], ltfat_int L, ltfat_norm_t flag, float* out); 373 * </tt> 374 * 375 * \returns 376 * Status code | Description 377 * ----------------------|-------------------------------------------- 378 * LTFATERR_SUCCESS | Indicates no error 379 * LTFATERR_NULLPOINTER | Either in or norm is NULL 380 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 381 * LTFATERR_CANNOTHAPPEN | Wrong ltfat_norm_t flag 382 */ 383 LTFAT_API int 384 LTFAT_NAME(norm)(const LTFAT_TYPE* in, ltfat_int L, 385 ltfat_norm_t flag, LTFAT_REAL* norm); 386 387 /** Compute normalized signal-to-noise 388 * 389 * Such that snr=20*log10(norm(rec,2)/norm(in,2)) 390 * 391 * \param[in] in Input array 392 * \param[in] rec Reconstructed array 393 * \param[in] L Length of the arrays 394 * \param[out] snr Computed snr 395 * 396 * #### Function versions #### 397 * <tt> 398 * ltfat_snr_d(const double in[], const double rec[], ltfat_int L, double* out); 399 * 400 * ltfat_snr_s(const float in[], const float rec[], ltfat_int L, float* out); 401 * 402 * ltfat_snr_dc(const ltfat_complex_d in[], const ltfat_complex_d rec[], ltfat_int L, double* out); 403 * 404 * ltfat_snr_sc(const ltfat_complex_s in[], const ltfat_complex_s rec[], ltfat_int L, float* out); 405 * </tt> 406 * 407 * \returns 408 * Status code | Description 409 * ----------------------|-------------------------------------------- 410 * LTFATERR_SUCCESS | Indicates no error 411 * LTFATERR_NULLPOINTER | Either in, rec or snr is NULL 412 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 413 */ 414 415 LTFAT_API int 416 LTFAT_NAME(snr)(const LTFAT_TYPE* in, const LTFAT_TYPE* rec, 417 ltfat_int L, LTFAT_REAL* snr); 418 419 /** Normalize a vector 420 * 421 * Normalizes the input array such that the chosen norm is 1. 422 * 423 * \param[in] in Input array 424 * \param[in] L Length of the arrays 425 * \param[in] flag Norm 426 * \param[out] out Output array 427 * 428 * #### Function versions #### 429 * <tt> 430 * ltfat_normalize_d(const double in[], ltfat_int L, ltfat_norm_t flag, double out[]); 431 * 432 * ltfat_normalize_s(const float in[], ltfat_int L, ltfat_norm_t flag, float out[]); 433 * 434 * ltfat_normalize_dc(const ltfat_complex_d in[], ltfat_int L, ltfat_norm_t flag, ltfat_complex_d out[]); 435 * 436 * ltfat_normalize_sc(const ltfat_complex_s in[], ltfat_int L, ltfat_norm_t flag, ltfat_complex_s out[]); 437 * </tt> 438 * 439 * \returns 440 * Status code | Description 441 * ----------------------|-------------------------------------------- 442 * LTFATERR_SUCCESS | Indicates no error 443 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 444 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 445 * LTFATERR_CANNOTHAPPEN | \a flag is not defined in ltfat_norm_t enum. 446 */ 447 LTFAT_API int 448 LTFAT_NAME(normalize)(const LTFAT_TYPE in[], ltfat_int L, 449 ltfat_norm_t flag, LTFAT_TYPE out[]); 450 451 /** Ensure the array has complex interleaved layout 452 * 453 * This is a convenience function. 454 * Obviously the *_dc and *_sc versions of the function do nothing. 455 * 456 * \param[in] in Input array 457 * \param[in] L Length of arrays 458 * \param[out] out Output array 459 * 460 * #### Function versions #### 461 * <tt> 462 * ltfat_ensurecomplex_array_d(const double in[], ltfat_int L, ltfat_complex_d out[]); 463 * 464 * ltfat_ensurecomplex_array_s(const float in[], ltfat_int L, ltfat_complex_s out[]); 465 * 466 * ltfat_ensurecomplex_array_dc(const ltfat_complex_d in[], ltfat_int L, ltfat_complex_d out[]); 467 * 468 * ltfat_ensurecomplex_array_sc(const ltfat_complex_s in[], ltfat_int L, ltfat_complex_s out[]); 469 * </tt> 470 * 471 * \returns 472 * Status code | Description 473 * ----------------------|-------------------------------------------- 474 * LTFATERR_SUCCESS | Indicates no error 475 * LTFATERR_NULLPOINTER | Either of the arrays is NULL 476 * LTFATERR_BADSIZE | Length of the arrays is less or equal to 0. 477 */ 478 LTFAT_API int 479 LTFAT_NAME(ensurecomplex_array)(const LTFAT_TYPE *in, ltfat_int L, LTFAT_COMPLEX *out); 480 481 /** @}*/ 482 483 LTFAT_API void 484 LTFAT_NAME(dgtphaselockhelper)(LTFAT_TYPE *cin, ltfat_int L, 485 ltfat_int W, ltfat_int a, 486 ltfat_int M, ltfat_int M2, 487 LTFAT_TYPE *cout); 488 489 LTFAT_API void 490 LTFAT_NAME(dgtphaseunlockhelper)(LTFAT_TYPE *cin, ltfat_int L, 491 ltfat_int W, ltfat_int a, 492 ltfat_int M, ltfat_int M2, 493 LTFAT_TYPE *cout); 494 495 LTFAT_API int 496 LTFAT_NAME(reverse_array)(const LTFAT_TYPE *in, ltfat_int L, LTFAT_TYPE *out); 497 498 LTFAT_API int 499 LTFAT_NAME(conjugate_array)(const LTFAT_TYPE *in, ltfat_int L, LTFAT_TYPE *out); 500 501 LTFAT_API int 502 LTFAT_NAME(periodize_array)(const LTFAT_TYPE *in, ltfat_int Lin, 503 ltfat_int Lout, LTFAT_TYPE *out ); 504 505 LTFAT_API int 506 LTFAT_NAME(fold_array)(const LTFAT_TYPE *in, ltfat_int Lin, 507 ltfat_int offset, 508 ltfat_int Lfold, LTFAT_TYPE *out); 509 510 LTFAT_API int 511 LTFAT_NAME(reflect)(const LTFAT_TYPE* in, ltfat_int L, LTFAT_TYPE* out); 512 513 LTFAT_API int 514 LTFAT_NAME(involute)(const LTFAT_TYPE* in, ltfat_int L, LTFAT_TYPE* out); 515 516 LTFAT_API void 517 LTFAT_NAME(findmaxinarray)(const LTFAT_TYPE *in, ltfat_int L, LTFAT_TYPE* max, ltfat_int* idx); 518 519 LTFAT_API int 520 LTFAT_NAME(findmaxinarraywrtmask)(const LTFAT_TYPE *in, const int *mask, 521 ltfat_int L, LTFAT_TYPE* max, ltfat_int* idx); 522 523 LTFAT_API void 524 LTFAT_NAME(findmaxincols)(const LTFAT_TYPE* in, ltfat_int M, ltfat_int M2, 525 ltfat_int N, LTFAT_TYPE* max, ltfat_int* idx); 526