capi.cpp (21807B)
1 /** @addtogroup dft 2 * @{ 3 */ 4 /* 5 Copyright (C) 2016-2023 Dan Cazarin (https://www.kfrlib.com) 6 This file is part of KFR 7 8 KFR is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 2 of the License, or 11 (at your option) any later version. 12 13 KFR is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with KFR. 20 21 If GPL is not suitable for your project, you must purchase a commercial license to use KFR. 22 Buying a commercial license is mandatory as soon as you develop commercial activities without 23 disclosing the source code of your own applications. 24 See https://www.kfrlib.com for details. 25 */ 26 #include <variant> 27 #define KFR_NO_C_COMPLEX_TYPES 1 28 29 #include <kfr/capi.h> 30 #include <kfr/dft.hpp> 31 #include <kfr/dsp.hpp> 32 #include <kfr/multiarch.h> 33 34 namespace kfr 35 { 36 static thread_local std::array<char, 256> error; 37 38 void reset_error() { std::fill(error.begin(), error.end(), 0); } 39 void set_error(std::string_view s) 40 { 41 size_t n = std::min(s.size(), error.size() - 1); 42 auto end = std::copy_n(s.begin(), n, error.begin()); 43 std::fill(end, error.end(), 0); 44 } 45 46 template <typename Fn, typename R = std::invoke_result_t<Fn>, typename T> 47 static R try_fn(Fn&& fn, T fallback) 48 { 49 try 50 { 51 auto result = fn(); 52 reset_error(); 53 return result; 54 } 55 catch (std::exception& e) 56 { 57 set_error(e.what()); 58 return fallback; 59 } 60 catch (...) 61 { 62 set_error("(unknown exception)"); 63 return fallback; 64 } 65 } 66 67 template <typename Fn> 68 static void try_fn(Fn&& fn) 69 { 70 try 71 { 72 fn(); 73 reset_error(); 74 } 75 catch (std::exception& e) 76 { 77 set_error(e.what()); 78 } 79 catch (...) 80 { 81 set_error("(unknown exception)"); 82 } 83 } 84 85 template <typename T> 86 class var_dft_plan 87 { 88 public: 89 virtual ~var_dft_plan() {} 90 virtual void dump() = 0; 91 virtual size_t size() = 0; 92 virtual size_t temp_size() = 0; 93 virtual void execute(T*, const T*, u8*) = 0; 94 virtual void execute_inverse(T*, const T*, u8*) = 0; 95 }; 96 97 static shape<dynamic_shape> init_shape(size_t dims, const unsigned* shape_) 98 { 99 shape<dynamic_shape> sh(dims); 100 for (size_t i = 0; i < dims; ++i) 101 { 102 sh[i] = shape_[i]; 103 } 104 return sh; 105 } 106 107 template <typename T, size_t Dims> 108 struct var_dft_plan_select 109 { 110 using complex = dft_plan_md<T, dynamic_shape>; 111 using real = dft_plan_md_real<T, dynamic_shape>; 112 113 static size_t size(const complex& plan) { return plan.size.product(); } 114 static size_t size(const real& plan) { return plan.size.product(); } 115 }; 116 template <typename T> 117 struct var_dft_plan_select<T, 1> 118 { 119 using complex = dft_plan<T>; 120 using real = dft_plan_real<T>; 121 122 static size_t size(const complex& plan) { return plan.size; } 123 static size_t size(const real& plan) { return plan.size; } 124 }; 125 126 template <typename T, size_t Dims> 127 class var_dft_plan_impl final : public var_dft_plan<T> 128 { 129 public: 130 template <typename... Args> 131 CMT_ALWAYS_INLINE var_dft_plan_impl(Args&&... args) : plan(std::forward<Args>(args)...) 132 { 133 } 134 typename var_dft_plan_select<T, Dims>::complex plan; 135 void dump() { plan.dump(); } 136 size_t size() { return var_dft_plan_select<T, Dims>::size(plan); } 137 size_t temp_size() { return plan.temp_size; } 138 void execute(T* out, const T* in, u8* temp) 139 { 140 plan.execute(reinterpret_cast<complex<T>*>(out), reinterpret_cast<const complex<T>*>(in), temp, 141 cfalse); 142 } 143 void execute_inverse(T* out, const T* in, u8* temp) 144 { 145 plan.execute(reinterpret_cast<complex<T>*>(out), reinterpret_cast<const complex<T>*>(in), temp, 146 ctrue); 147 } 148 }; 149 150 template <typename T, size_t Dims> 151 class var_dft_plan_real_impl final : public var_dft_plan<T> 152 { 153 public: 154 template <typename... Args> 155 CMT_ALWAYS_INLINE var_dft_plan_real_impl(Args&&... args) : plan(std::forward<Args>(args)...) 156 { 157 } 158 typename var_dft_plan_select<T, Dims>::real plan; 159 void dump() { plan.dump(); } 160 size_t size() { return var_dft_plan_select<T, Dims>::size(plan); } 161 size_t temp_size() { return plan.temp_size; } 162 void execute(T* out, const T* in, u8* temp) 163 { 164 plan.execute(reinterpret_cast<complex<T>*>(out), reinterpret_cast<const T*>(in), temp, cfalse); 165 } 166 void execute_inverse(T* out, const T* in, u8* temp) 167 { 168 plan.execute(reinterpret_cast<T*>(out), reinterpret_cast<const complex<T>*>(in), temp, ctrue); 169 } 170 }; 171 172 extern "C" 173 { 174 KFR_API_SPEC const char* kfr_version_string() 175 { 176 return "KFR " KFR_VERSION_STRING KFR_DEBUG_STR " " KFR_ENABLED_ARCHS_LIST " " CMT_ARCH_BITNESS_NAME 177 " (" CMT_COMPILER_FULL_NAME "/" CMT_OS_NAME ")" KFR_BUILD_DETAILS_1 KFR_BUILD_DETAILS_2; 178 } 179 KFR_API_SPEC uint32_t kfr_version() { return KFR_VERSION; } 180 KFR_API_SPEC const char* kfr_enabled_archs() { return KFR_ENABLED_ARCHS_LIST; } 181 KFR_API_SPEC int kfr_current_arch() { return static_cast<int>(get_cpu()); } 182 183 KFR_API_SPEC const char* kfr_last_error() { return error.data(); } 184 185 KFR_API_SPEC void* kfr_allocate(size_t size) { return details::aligned_malloc(size, KFR_DEFAULT_ALIGNMENT); } 186 KFR_API_SPEC void* kfr_allocate_aligned(size_t size, size_t alignment) 187 { 188 return details::aligned_malloc(size, alignment); 189 } 190 KFR_API_SPEC void kfr_deallocate(void* ptr) { return details::aligned_free(ptr); } 191 KFR_API_SPEC size_t kfr_allocated_size(void* ptr) { return details::aligned_size(ptr); } 192 193 KFR_API_SPEC void* kfr_add_ref(void* ptr) 194 { 195 details::aligned_add_ref(ptr); 196 return ptr; 197 } 198 KFR_API_SPEC void kfr_release(void* ptr) { details::aligned_release(ptr); } 199 200 KFR_API_SPEC void* kfr_reallocate(void* ptr, size_t new_size) 201 { 202 return details::aligned_reallocate(ptr, new_size, KFR_DEFAULT_ALIGNMENT); 203 } 204 KFR_API_SPEC void* kfr_reallocate_aligned(void* ptr, size_t new_size, size_t alignment) 205 { 206 return details::aligned_reallocate(ptr, new_size, alignment); 207 } 208 209 KFR_API_SPEC KFR_DFT_PLAN_F32* kfr_dft_create_plan_f32(size_t size) 210 { 211 return try_fn([&]() 212 { return reinterpret_cast<KFR_DFT_PLAN_F32*>(new var_dft_plan_impl<float, 1>(size)); }, 213 nullptr); 214 } 215 216 KFR_API_SPEC KFR_DFT_PLAN_F32* kfr_dft_create_2d_plan_f32(size_t size1, size_t size2) 217 { 218 return try_fn( 219 [&]() { 220 return reinterpret_cast<KFR_DFT_PLAN_F32*>( 221 new var_dft_plan_impl<float, 2>(shape{ size1, size2 })); 222 }, 223 nullptr); 224 } 225 KFR_API_SPEC KFR_DFT_PLAN_F32* kfr_dft_create_3d_plan_f32(size_t size1, size_t size2, size_t size3) 226 { 227 return try_fn( 228 [&]() 229 { 230 return reinterpret_cast<KFR_DFT_PLAN_F32*>( 231 new var_dft_plan_impl<float, 3>(shape{ size1, size2, size3 })); 232 }, 233 nullptr); 234 } 235 KFR_API_SPEC KFR_DFT_PLAN_F32* kfr_dft_create_md_plan_f32(size_t dims, const unsigned* shape) 236 { 237 return try_fn( 238 [&]() 239 { 240 return reinterpret_cast<KFR_DFT_PLAN_F32*>( 241 new var_dft_plan_impl<float, dynamic_shape>(init_shape(dims, shape))); 242 }, 243 nullptr); 244 } 245 KFR_API_SPEC KFR_DFT_PLAN_F64* kfr_dft_create_plan_f64(size_t size) 246 { 247 return try_fn([&]() 248 { return reinterpret_cast<KFR_DFT_PLAN_F64*>(new var_dft_plan_impl<double, 1>(size)); }, 249 nullptr); 250 } 251 KFR_API_SPEC KFR_DFT_PLAN_F64* kfr_dft_create_2d_plan_f64(size_t size1, size_t size2) 252 { 253 return try_fn( 254 [&]() { 255 return reinterpret_cast<KFR_DFT_PLAN_F64*>( 256 new var_dft_plan_impl<double, 2>(shape{ size1, size2 })); 257 }, 258 nullptr); 259 } 260 KFR_API_SPEC KFR_DFT_PLAN_F64* kfr_dft_create_3d_plan_f64(size_t size1, size_t size2, size_t size3) 261 { 262 return try_fn( 263 [&]() 264 { 265 return reinterpret_cast<KFR_DFT_PLAN_F64*>( 266 new var_dft_plan_impl<double, 3>(shape{ size1, size2, size3 })); 267 }, 268 nullptr); 269 } 270 KFR_API_SPEC KFR_DFT_PLAN_F64* kfr_dft_create_md_plan_f64(size_t dims, const unsigned* shape) 271 { 272 return try_fn( 273 [&]() 274 { 275 return reinterpret_cast<KFR_DFT_PLAN_F64*>( 276 new var_dft_plan_impl<double, dynamic_shape>(init_shape(dims, shape))); 277 }, 278 nullptr); 279 } 280 281 KFR_API_SPEC void kfr_dft_dump_f32(KFR_DFT_PLAN_F32* plan) 282 { 283 try_fn([&] { reinterpret_cast<var_dft_plan<float>*>(plan)->dump(); }); 284 } 285 KFR_API_SPEC void kfr_dft_dump_f64(KFR_DFT_PLAN_F64* plan) 286 { 287 try_fn([&] { reinterpret_cast<var_dft_plan<double>*>(plan)->dump(); }); 288 } 289 290 KFR_API_SPEC size_t kfr_dft_get_size_f32(KFR_DFT_PLAN_F32* plan) 291 { 292 return try_fn([&]() { return reinterpret_cast<var_dft_plan<float>*>(plan)->size(); }, 0); 293 } 294 KFR_API_SPEC size_t kfr_dft_get_size_f64(KFR_DFT_PLAN_F64* plan) 295 { 296 return try_fn([&]() { return reinterpret_cast<var_dft_plan<double>*>(plan)->size(); }, 0); 297 } 298 299 KFR_API_SPEC size_t kfr_dft_get_temp_size_f32(KFR_DFT_PLAN_F32* plan) 300 { 301 return try_fn([&]() { return reinterpret_cast<var_dft_plan<float>*>(plan)->temp_size(); }, 0); 302 } 303 KFR_API_SPEC size_t kfr_dft_get_temp_size_f64(KFR_DFT_PLAN_F64* plan) 304 { 305 return try_fn([&]() { return reinterpret_cast<var_dft_plan<double>*>(plan)->temp_size(); }, 0); 306 } 307 308 KFR_API_SPEC void kfr_dft_execute_f32(KFR_DFT_PLAN_F32* plan, kfr_c32* out, const kfr_c32* in, uint8_t* temp) 309 { 310 try_fn( 311 [&]() 312 { 313 reinterpret_cast<var_dft_plan<float>*>(plan)->execute(reinterpret_cast<float*>(out), 314 reinterpret_cast<const float*>(in), temp); 315 }); 316 } 317 KFR_API_SPEC void kfr_dft_execute_f64(KFR_DFT_PLAN_F64* plan, kfr_c64* out, const kfr_c64* in, uint8_t* temp) 318 { 319 try_fn( 320 [&]() 321 { 322 reinterpret_cast<var_dft_plan<double>*>(plan)->execute(reinterpret_cast<double*>(out), 323 reinterpret_cast<const double*>(in), temp); 324 }); 325 } 326 KFR_API_SPEC void kfr_dft_execute_inverse_f32(KFR_DFT_PLAN_F32* plan, kfr_c32* out, const kfr_c32* in, 327 uint8_t* temp) 328 { 329 try_fn( 330 [&]() 331 { 332 reinterpret_cast<var_dft_plan<float>*>(plan)->execute_inverse( 333 reinterpret_cast<float*>(out), reinterpret_cast<const float*>(in), temp); 334 }); 335 } 336 KFR_API_SPEC void kfr_dft_execute_inverse_f64(KFR_DFT_PLAN_F64* plan, kfr_c64* out, const kfr_c64* in, 337 uint8_t* temp) 338 { 339 try_fn( 340 [&]() 341 { 342 reinterpret_cast<var_dft_plan<double>*>(plan)->execute_inverse( 343 reinterpret_cast<double*>(out), reinterpret_cast<const double*>(in), temp); 344 }); 345 } 346 347 KFR_API_SPEC void kfr_dft_delete_plan_f32(KFR_DFT_PLAN_F32* plan) 348 { 349 try_fn([&]() { delete reinterpret_cast<var_dft_plan<float>*>(plan); }); 350 } 351 KFR_API_SPEC void kfr_dft_delete_plan_f64(KFR_DFT_PLAN_F64* plan) 352 { 353 try_fn([&]() { delete reinterpret_cast<var_dft_plan<double>*>(plan); }); 354 } 355 356 // Real DFT plans 357 358 KFR_API_SPEC KFR_DFT_REAL_PLAN_F32* kfr_dft_real_create_plan_f32(size_t size, KFR_DFT_PACK_FORMAT pack_format) 359 { 360 return try_fn( 361 [&]() 362 { 363 return reinterpret_cast<KFR_DFT_REAL_PLAN_F32*>( 364 new var_dft_plan_real_impl<float, 1>(size, static_cast<dft_pack_format>(pack_format))); 365 }, 366 nullptr); 367 } 368 369 KFR_API_SPEC KFR_DFT_REAL_PLAN_F32* kfr_dft_real_create_2d_plan_f32(size_t size1, size_t size2, 370 bool real_out_is_enough) 371 { 372 return try_fn( 373 [&]() 374 { 375 return reinterpret_cast<KFR_DFT_REAL_PLAN_F32*>( 376 new var_dft_plan_real_impl<float, 2>(shape{ size1, size2 }, real_out_is_enough)); 377 }, 378 nullptr); 379 } 380 KFR_API_SPEC KFR_DFT_REAL_PLAN_F32* kfr_dft_real_create_3d_plan_f32(size_t size1, size_t size2, size_t size3, 381 bool real_out_is_enough) 382 { 383 return try_fn( 384 [&]() 385 { 386 return reinterpret_cast<KFR_DFT_REAL_PLAN_F32*>( 387 new var_dft_plan_real_impl<float, 3>(shape{ size1, size2, size3 }, real_out_is_enough)); 388 }, 389 nullptr); 390 } 391 KFR_API_SPEC KFR_DFT_REAL_PLAN_F32* kfr_dft_real_create_md_plan_f32(size_t dims, const unsigned* shape, 392 bool real_out_is_enough) 393 { 394 return try_fn( 395 [&]() 396 { 397 return reinterpret_cast<KFR_DFT_REAL_PLAN_F32*>( 398 new var_dft_plan_real_impl<float, dynamic_shape>(init_shape(dims, shape), real_out_is_enough)); 399 }, 400 nullptr); 401 } 402 403 KFR_API_SPEC KFR_DFT_REAL_PLAN_F64* kfr_dft_real_create_plan_f64(size_t size, KFR_DFT_PACK_FORMAT pack_format) 404 { 405 return try_fn( 406 [&]() 407 { 408 return reinterpret_cast<KFR_DFT_REAL_PLAN_F64*>( 409 new var_dft_plan_real_impl<double, 1>(size, static_cast<dft_pack_format>(pack_format))); 410 }, 411 nullptr); 412 } 413 414 KFR_API_SPEC void kfr_dft_real_dump_f32(KFR_DFT_REAL_PLAN_F32* plan) 415 { 416 try_fn([&]() { reinterpret_cast<var_dft_plan<float>*>(plan)->dump(); }); 417 } 418 KFR_API_SPEC void kfr_dft_real_dump_f64(KFR_DFT_REAL_PLAN_F64* plan) 419 { 420 try_fn([&]() { reinterpret_cast<var_dft_plan<double>*>(plan)->dump(); }); 421 } 422 423 KFR_API_SPEC size_t kfr_dft_real_get_size_f32(KFR_DFT_REAL_PLAN_F32* plan) 424 { 425 return try_fn([&]() { return reinterpret_cast<var_dft_plan<float>*>(plan)->size(); }, 0); 426 } 427 KFR_API_SPEC size_t kfr_dft_real_get_size_f64(KFR_DFT_REAL_PLAN_F64* plan) 428 { 429 return try_fn([&]() { return reinterpret_cast<var_dft_plan<double>*>(plan)->size(); }, 0); 430 } 431 432 KFR_API_SPEC size_t kfr_dft_real_get_temp_size_f32(KFR_DFT_REAL_PLAN_F32* plan) 433 { 434 return try_fn([&]() { return reinterpret_cast<var_dft_plan<float>*>(plan)->temp_size(); }, 0); 435 } 436 KFR_API_SPEC size_t kfr_dft_real_get_temp_size_f64(KFR_DFT_REAL_PLAN_F64* plan) 437 { 438 return try_fn([&]() { return reinterpret_cast<var_dft_plan<double>*>(plan)->temp_size(); }, 0); 439 } 440 441 KFR_API_SPEC void kfr_dft_real_execute_f32(KFR_DFT_REAL_PLAN_F32* plan, kfr_c32* out, const float* in, 442 uint8_t* temp) 443 { 444 try_fn( 445 [&]() 446 { reinterpret_cast<var_dft_plan<float>*>(plan)->execute(reinterpret_cast<float*>(out), in, temp); }); 447 } 448 KFR_API_SPEC void kfr_dft_real_execute_f64(KFR_DFT_REAL_PLAN_F64* plan, kfr_c64* out, const double* in, 449 uint8_t* temp) 450 { 451 try_fn( 452 [&]() { 453 reinterpret_cast<var_dft_plan<double>*>(plan)->execute(reinterpret_cast<double*>(out), in, temp); 454 }); 455 } 456 KFR_API_SPEC void kfr_dft_real_execute_inverse_f32(KFR_DFT_REAL_PLAN_F32* plan, float* out, const kfr_c32* in, 457 uint8_t* temp) 458 { 459 try_fn( 460 [&]() 461 { 462 reinterpret_cast<var_dft_plan<float>*>(plan)->execute_inverse( 463 out, reinterpret_cast<const float*>(in), temp); 464 }); 465 } 466 KFR_API_SPEC void kfr_dft_real_execute_inverse_f64(KFR_DFT_REAL_PLAN_F64* plan, double* out, 467 const kfr_c64* in, uint8_t* temp) 468 { 469 try_fn( 470 [&]() 471 { 472 reinterpret_cast<var_dft_plan<double>*>(plan)->execute_inverse( 473 out, reinterpret_cast<const double*>(in), temp); 474 }); 475 } 476 477 KFR_API_SPEC void kfr_dft_real_delete_plan_f32(KFR_DFT_REAL_PLAN_F32* plan) 478 { 479 try_fn([&]() { delete reinterpret_cast<var_dft_plan<float>*>(plan); }); 480 } 481 KFR_API_SPEC void kfr_dft_real_delete_plan_f64(KFR_DFT_REAL_PLAN_F64* plan) 482 { 483 try_fn([&]() { delete reinterpret_cast<var_dft_plan<double>*>(plan); }); 484 } 485 486 // Discrete Cosine Transform 487 488 KFR_API_SPEC KFR_DCT_PLAN_F32* kfr_dct_create_plan_f32(size_t size) 489 { 490 return try_fn([&]() { return reinterpret_cast<KFR_DCT_PLAN_F32*>(new dct_plan<float>(size)); }, nullptr); 491 } 492 KFR_API_SPEC KFR_DCT_PLAN_F64* kfr_dct_create_plan_f64(size_t size) 493 { 494 return try_fn([&]() { return reinterpret_cast<KFR_DCT_PLAN_F64*>(new dct_plan<double>(size)); }, nullptr); 495 } 496 497 KFR_API_SPEC void kfr_dct_dump_f32(KFR_DCT_PLAN_F32* plan) 498 { 499 try_fn([&]() { reinterpret_cast<dct_plan<float>*>(plan)->dump(); }); 500 } 501 KFR_API_SPEC void kfr_dct_dump_f64(KFR_DCT_PLAN_F64* plan) 502 { 503 try_fn([&]() { reinterpret_cast<dct_plan<double>*>(plan)->dump(); }); 504 } 505 506 KFR_API_SPEC size_t kfr_dct_get_size_f32(KFR_DCT_PLAN_F32* plan) 507 { 508 return try_fn([&]() { return reinterpret_cast<dft_plan<float>*>(plan)->size; }, 0); 509 } 510 KFR_API_SPEC size_t kfr_dct_get_size_f64(KFR_DCT_PLAN_F64* plan) 511 { 512 return try_fn([&]() { return reinterpret_cast<dft_plan<double>*>(plan)->size; }, 0); 513 } 514 515 KFR_API_SPEC size_t kfr_dct_get_temp_size_f32(KFR_DCT_PLAN_F32* plan) 516 { 517 return try_fn([&]() { return reinterpret_cast<dft_plan<float>*>(plan)->temp_size; }, 0); 518 } 519 KFR_API_SPEC size_t kfr_dct_get_temp_size_f64(KFR_DCT_PLAN_F64* plan) 520 { 521 return try_fn([&]() { return reinterpret_cast<dft_plan<double>*>(plan)->temp_size; }, 0); 522 } 523 524 KFR_API_SPEC void kfr_dct_execute_f32(KFR_DCT_PLAN_F32* plan, float* out, const float* in, uint8_t* temp) 525 { 526 try_fn([&]() { reinterpret_cast<dct_plan<float>*>(plan)->execute(out, in, temp, cfalse); }); 527 } 528 KFR_API_SPEC void kfr_dct_execute_f64(KFR_DCT_PLAN_F64* plan, double* out, const double* in, uint8_t* temp) 529 { 530 try_fn([&]() { reinterpret_cast<dct_plan<double>*>(plan)->execute(out, in, temp, cfalse); }); 531 } 532 KFR_API_SPEC void kfr_dct_execute_inverse_f32(KFR_DCT_PLAN_F32* plan, float* out, const float* in, 533 uint8_t* temp) 534 { 535 try_fn([&]() { reinterpret_cast<dct_plan<float>*>(plan)->execute(out, in, temp, ctrue); }); 536 } 537 KFR_API_SPEC void kfr_dct_execute_inverse_f64(KFR_DCT_PLAN_F64* plan, double* out, const double* in, 538 uint8_t* temp) 539 { 540 try_fn([&]() { reinterpret_cast<dct_plan<double>*>(plan)->execute(out, in, temp, ctrue); }); 541 } 542 543 KFR_API_SPEC void kfr_dct_delete_plan_f32(KFR_DCT_PLAN_F32* plan) 544 { 545 try_fn([&]() { delete reinterpret_cast<dct_plan<float>*>(plan); }); 546 } 547 KFR_API_SPEC void kfr_dct_delete_plan_f64(KFR_DCT_PLAN_F64* plan) 548 { 549 try_fn([&]() { delete reinterpret_cast<dct_plan<double>*>(plan); }); 550 } 551 552 // Filters 553 554 KFR_API_SPEC KFR_FILTER_F32* kfr_filter_create_fir_plan_f32(const kfr_f32* taps, size_t size) 555 { 556 return try_fn( 557 [&]() 558 { return reinterpret_cast<KFR_FILTER_F32*>(new fir_filter<float>(make_univector(taps, size))); }, 559 nullptr); 560 } 561 KFR_API_SPEC KFR_FILTER_F64* kfr_filter_create_fir_plan_f64(const kfr_f64* taps, size_t size) 562 { 563 return try_fn( 564 [&]() 565 { return reinterpret_cast<KFR_FILTER_F64*>(new fir_filter<double>(make_univector(taps, size))); }, 566 nullptr); 567 } 568 569 KFR_API_SPEC KFR_FILTER_F32* kfr_filter_create_convolution_plan_f32(const kfr_f32* taps, size_t size, 570 size_t block_size) 571 { 572 return try_fn( 573 [&]() 574 { 575 return reinterpret_cast<KFR_FILTER_F32*>( 576 new convolve_filter<float>(make_univector(taps, size), block_size ? block_size : 1024)); 577 }, 578 nullptr); 579 } 580 KFR_API_SPEC KFR_FILTER_F64* kfr_filter_create_convolution_plan_f64(const kfr_f64* taps, size_t size, 581 size_t block_size) 582 { 583 return try_fn( 584 [&]() 585 { 586 return reinterpret_cast<KFR_FILTER_F64*>( 587 new convolve_filter<double>(make_univector(taps, size), block_size ? block_size : 1024)); 588 }, 589 nullptr); 590 } 591 592 KFR_API_SPEC KFR_FILTER_F32* kfr_filter_create_iir_plan_f32(const kfr_f32* sos, size_t sos_count) 593 { 594 return try_fn( 595 [&]() 596 { 597 return reinterpret_cast<KFR_FILTER_F32*>(new iir_filter<float>( 598 iir_params{ reinterpret_cast<const biquad_section<float>*>(sos), sos_count })); 599 }, 600 nullptr); 601 } 602 KFR_API_SPEC KFR_FILTER_F64* kfr_filter_create_iir_plan_f64(const kfr_f64* sos, size_t sos_count) 603 { 604 return try_fn( 605 [&]() 606 { 607 return reinterpret_cast<KFR_FILTER_F64*>(new iir_filter<double>( 608 iir_params{ reinterpret_cast<const biquad_section<double>*>(sos), sos_count })); 609 }, 610 nullptr); 611 } 612 613 KFR_API_SPEC void kfr_filter_process_f32(KFR_FILTER_F32* plan, kfr_f32* output, const kfr_f32* input, 614 size_t size) 615 { 616 try_fn([&]() { reinterpret_cast<filter<float>*>(plan)->apply(output, input, size); }); 617 } 618 KFR_API_SPEC void kfr_filter_process_f64(KFR_FILTER_F64* plan, kfr_f64* output, const kfr_f64* input, 619 size_t size) 620 { 621 try_fn([&]() { reinterpret_cast<filter<double>*>(plan)->apply(output, input, size); }); 622 } 623 624 KFR_API_SPEC void kfr_filter_reset_f32(KFR_FILTER_F32* plan) 625 { 626 try_fn([&]() { reinterpret_cast<filter<float>*>(plan)->reset(); }); 627 } 628 KFR_API_SPEC void kfr_filter_reset_f64(KFR_FILTER_F64* plan) 629 { 630 try_fn([&]() { reinterpret_cast<filter<double>*>(plan)->reset(); }); 631 } 632 633 KFR_API_SPEC void kfr_filter_delete_plan_f32(KFR_FILTER_F32* plan) 634 { 635 try_fn([&]() { delete reinterpret_cast<filter<f32>*>(plan); }); 636 } 637 KFR_API_SPEC void kfr_filter_delete_plan_f64(KFR_FILTER_F64* plan) 638 { 639 try_fn([&]() { delete reinterpret_cast<filter<f64>*>(plan); }); 640 } 641 } 642 643 } // namespace kfr