1 /** @addtogroup dft 2 * @{ 3 */ 4 /* 5 Copyright (C) 2016 D Levin (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 #define KFR_NO_C_COMPLEX_TYPES 1 27 28 #include <kfr/capi.h> 29 #include <kfr/dft.hpp> 30 #include <kfr/dsp.hpp> 31 32 namespace kfr 33 { 34 35 extern "C" 36 { 37 #define KFR_ENABLED_ARCHS "sse2,sse3,ssse3,sse4.1,avx,avx2,avx512" kfr_version_string()38 const char* kfr_version_string() 39 { 40 return "KFR " KFR_VERSION_STRING KFR_DEBUG_STR " " KFR_ENABLED_ARCHS " " CMT_ARCH_BITNESS_NAME 41 " (" CMT_COMPILER_FULL_NAME "/" CMT_OS_NAME ")" KFR_BUILD_DETAILS_1 KFR_BUILD_DETAILS_2; 42 } kfr_version()43 uint32_t kfr_version() { return KFR_VERSION; } kfr_enabled_archs()44 const char* kfr_enabled_archs() { return KFR_ENABLED_ARCHS; } kfr_current_arch()45 int kfr_current_arch() { return static_cast<int>(get_cpu()); } 46 kfr_allocate(size_t size)47 void* kfr_allocate(size_t size) { return details::aligned_malloc(size, KFR_DEFAULT_ALIGNMENT); } kfr_allocate_aligned(size_t size,size_t alignment)48 void* kfr_allocate_aligned(size_t size, size_t alignment) 49 { 50 return details::aligned_malloc(size, alignment); 51 } kfr_deallocate(void * ptr)52 void kfr_deallocate(void* ptr) { return details::aligned_free(ptr); } kfr_allocated_size(void * ptr)53 size_t kfr_allocated_size(void* ptr) { return details::aligned_size(ptr); } 54 kfr_add_ref(void * ptr)55 void* kfr_add_ref(void* ptr) 56 { 57 details::aligned_add_ref(ptr); 58 return ptr; 59 } kfr_release(void * ptr)60 void kfr_release(void* ptr) { details::aligned_release(ptr); } 61 kfr_reallocate(void * ptr,size_t new_size)62 void* kfr_reallocate(void* ptr, size_t new_size) 63 { 64 return details::aligned_reallocate(ptr, new_size, KFR_DEFAULT_ALIGNMENT); 65 } kfr_reallocate_aligned(void * ptr,size_t new_size,size_t alignment)66 void* kfr_reallocate_aligned(void* ptr, size_t new_size, size_t alignment) 67 { 68 return details::aligned_reallocate(ptr, new_size, alignment); 69 } 70 kfr_dft_create_plan_f32(size_t size)71 KFR_DFT_PLAN_F32* kfr_dft_create_plan_f32(size_t size) 72 { 73 if (size < 2) 74 return nullptr; 75 if (size > 16777216) 76 return nullptr; 77 return reinterpret_cast<KFR_DFT_PLAN_F32*>(new kfr::dft_plan<float>(cpu_t::runtime, size)); 78 } kfr_dft_create_plan_f64(size_t size)79 KFR_DFT_PLAN_F64* kfr_dft_create_plan_f64(size_t size) 80 { 81 if (size < 2) 82 return nullptr; 83 if (size > 16777216) 84 return nullptr; 85 return reinterpret_cast<KFR_DFT_PLAN_F64*>(new kfr::dft_plan<double>(cpu_t::runtime, size)); 86 } 87 kfr_dft_dump_f32(KFR_DFT_PLAN_F32 * plan)88 void kfr_dft_dump_f32(KFR_DFT_PLAN_F32* plan) { reinterpret_cast<kfr::dft_plan<float>*>(plan)->dump(); } kfr_dft_dump_f64(KFR_DFT_PLAN_F64 * plan)89 void kfr_dft_dump_f64(KFR_DFT_PLAN_F64* plan) { reinterpret_cast<kfr::dft_plan<double>*>(plan)->dump(); } 90 kfr_dft_get_size_f32(KFR_DFT_PLAN_F32 * plan)91 size_t kfr_dft_get_size_f32(KFR_DFT_PLAN_F32* plan) 92 { 93 return reinterpret_cast<kfr::dft_plan<float>*>(plan)->size; 94 } kfr_dft_get_size_f64(KFR_DFT_PLAN_F64 * plan)95 size_t kfr_dft_get_size_f64(KFR_DFT_PLAN_F64* plan) 96 { 97 return reinterpret_cast<kfr::dft_plan<double>*>(plan)->size; 98 } 99 kfr_dft_get_temp_size_f32(KFR_DFT_PLAN_F32 * plan)100 size_t kfr_dft_get_temp_size_f32(KFR_DFT_PLAN_F32* plan) 101 { 102 return reinterpret_cast<kfr::dft_plan<float>*>(plan)->temp_size; 103 } kfr_dft_get_temp_size_f64(KFR_DFT_PLAN_F64 * plan)104 size_t kfr_dft_get_temp_size_f64(KFR_DFT_PLAN_F64* plan) 105 { 106 return reinterpret_cast<kfr::dft_plan<double>*>(plan)->temp_size; 107 } 108 kfr_dft_execute_f32(KFR_DFT_PLAN_F32 * plan,kfr_c32 * out,const kfr_c32 * in,uint8_t * temp)109 void kfr_dft_execute_f32(KFR_DFT_PLAN_F32* plan, kfr_c32* out, const kfr_c32* in, uint8_t* temp) 110 { 111 reinterpret_cast<kfr::dft_plan<float>*>(plan)->execute( 112 reinterpret_cast<kfr::complex<float>*>(out), reinterpret_cast<const kfr::complex<float>*>(in), 113 temp, kfr::cfalse); 114 } kfr_dft_execute_f64(KFR_DFT_PLAN_F64 * plan,kfr_c64 * out,const kfr_c64 * in,uint8_t * temp)115 void kfr_dft_execute_f64(KFR_DFT_PLAN_F64* plan, kfr_c64* out, const kfr_c64* in, uint8_t* temp) 116 { 117 reinterpret_cast<kfr::dft_plan<double>*>(plan)->execute( 118 reinterpret_cast<kfr::complex<double>*>(out), reinterpret_cast<const kfr::complex<double>*>(in), 119 temp, kfr::cfalse); 120 } kfr_dft_execute_inverse_f32(KFR_DFT_PLAN_F32 * plan,kfr_c32 * out,const kfr_c32 * in,uint8_t * temp)121 void kfr_dft_execute_inverse_f32(KFR_DFT_PLAN_F32* plan, kfr_c32* out, const kfr_c32* in, uint8_t* temp) 122 { 123 reinterpret_cast<kfr::dft_plan<float>*>(plan)->execute( 124 reinterpret_cast<kfr::complex<float>*>(out), reinterpret_cast<const kfr::complex<float>*>(in), 125 temp, kfr::ctrue); 126 } kfr_dft_execute_inverse_f64(KFR_DFT_PLAN_F64 * plan,kfr_c64 * out,const kfr_c64 * in,uint8_t * temp)127 void kfr_dft_execute_inverse_f64(KFR_DFT_PLAN_F64* plan, kfr_c64* out, const kfr_c64* in, uint8_t* temp) 128 { 129 reinterpret_cast<kfr::dft_plan<double>*>(plan)->execute( 130 reinterpret_cast<kfr::complex<double>*>(out), reinterpret_cast<const kfr::complex<double>*>(in), 131 temp, kfr::ctrue); 132 } 133 kfr_dft_delete_plan_f32(KFR_DFT_PLAN_F32 * plan)134 void kfr_dft_delete_plan_f32(KFR_DFT_PLAN_F32* plan) 135 { 136 delete reinterpret_cast<kfr::dft_plan<float>*>(plan); 137 } kfr_dft_delete_plan_f64(KFR_DFT_PLAN_F64 * plan)138 void kfr_dft_delete_plan_f64(KFR_DFT_PLAN_F64* plan) 139 { 140 delete reinterpret_cast<kfr::dft_plan<double>*>(plan); 141 } 142 143 // Real DFT plans 144 kfr_dft_real_create_plan_f32(size_t size,KFR_DFT_PACK_FORMAT pack_format)145 KFR_DFT_REAL_PLAN_F32* kfr_dft_real_create_plan_f32(size_t size, KFR_DFT_PACK_FORMAT pack_format) 146 { 147 if (size < 4) 148 return nullptr; 149 if (size > 16777216) 150 return nullptr; 151 return reinterpret_cast<KFR_DFT_REAL_PLAN_F32*>( 152 new kfr::dft_plan_real<float>(cpu_t::runtime, size, static_cast<dft_pack_format>(pack_format))); 153 } kfr_dft_real_create_plan_f64(size_t size,KFR_DFT_PACK_FORMAT pack_format)154 KFR_DFT_REAL_PLAN_F64* kfr_dft_real_create_plan_f64(size_t size, KFR_DFT_PACK_FORMAT pack_format) 155 { 156 if (size < 4) 157 return nullptr; 158 if (size > 16777216) 159 return nullptr; 160 return reinterpret_cast<KFR_DFT_REAL_PLAN_F64*>( 161 new kfr::dft_plan_real<double>(cpu_t::runtime, size, static_cast<dft_pack_format>(pack_format))); 162 } 163 kfr_dft_real_dump_f32(KFR_DFT_REAL_PLAN_F32 * plan)164 void kfr_dft_real_dump_f32(KFR_DFT_REAL_PLAN_F32* plan) 165 { 166 reinterpret_cast<kfr::dft_plan_real<float>*>(plan)->dump(); 167 } kfr_dft_real_dump_f64(KFR_DFT_REAL_PLAN_F64 * plan)168 void kfr_dft_real_dump_f64(KFR_DFT_REAL_PLAN_F64* plan) 169 { 170 reinterpret_cast<kfr::dft_plan_real<double>*>(plan)->dump(); 171 } 172 kfr_dft_real_get_size_f32(KFR_DFT_REAL_PLAN_F32 * plan)173 size_t kfr_dft_real_get_size_f32(KFR_DFT_REAL_PLAN_F32* plan) 174 { 175 return reinterpret_cast<kfr::dft_plan<float>*>(plan)->size; 176 } kfr_dft_real_get_size_f64(KFR_DFT_REAL_PLAN_F64 * plan)177 size_t kfr_dft_real_get_size_f64(KFR_DFT_REAL_PLAN_F64* plan) 178 { 179 return reinterpret_cast<kfr::dft_plan<double>*>(plan)->size; 180 } 181 kfr_dft_real_get_temp_size_f32(KFR_DFT_REAL_PLAN_F32 * plan)182 size_t kfr_dft_real_get_temp_size_f32(KFR_DFT_REAL_PLAN_F32* plan) 183 { 184 return reinterpret_cast<kfr::dft_plan<float>*>(plan)->temp_size; 185 } kfr_dft_real_get_temp_size_f64(KFR_DFT_REAL_PLAN_F64 * plan)186 size_t kfr_dft_real_get_temp_size_f64(KFR_DFT_REAL_PLAN_F64* plan) 187 { 188 return reinterpret_cast<kfr::dft_plan<double>*>(plan)->temp_size; 189 } 190 kfr_dft_real_execute_f32(KFR_DFT_REAL_PLAN_F32 * plan,kfr_c32 * out,const float * in,uint8_t * temp)191 void kfr_dft_real_execute_f32(KFR_DFT_REAL_PLAN_F32* plan, kfr_c32* out, const float* in, uint8_t* temp) 192 { 193 reinterpret_cast<kfr::dft_plan_real<float>*>(plan)->execute( 194 reinterpret_cast<kfr::complex<float>*>(out), in, temp); 195 } kfr_dft_real_execute_f64(KFR_DFT_REAL_PLAN_F64 * plan,kfr_c64 * out,const double * in,uint8_t * temp)196 void kfr_dft_real_execute_f64(KFR_DFT_REAL_PLAN_F64* plan, kfr_c64* out, const double* in, uint8_t* temp) 197 { 198 reinterpret_cast<kfr::dft_plan_real<double>*>(plan)->execute( 199 reinterpret_cast<kfr::complex<double>*>(out), in, temp); 200 } kfr_dft_real_execute_inverse_f32(KFR_DFT_REAL_PLAN_F32 * plan,float * out,const kfr_c32 * in,uint8_t * temp)201 void kfr_dft_real_execute_inverse_f32(KFR_DFT_REAL_PLAN_F32* plan, float* out, const kfr_c32* in, 202 uint8_t* temp) 203 { 204 reinterpret_cast<kfr::dft_plan_real<float>*>(plan)->execute( 205 out, reinterpret_cast<const kfr::complex<float>*>(in), temp); 206 } kfr_dft_real_execute_inverse_f64(KFR_DFT_REAL_PLAN_F64 * plan,double * out,const kfr_c64 * in,uint8_t * temp)207 void kfr_dft_real_execute_inverse_f64(KFR_DFT_REAL_PLAN_F64* plan, double* out, const kfr_c64* in, 208 uint8_t* temp) 209 { 210 reinterpret_cast<kfr::dft_plan_real<double>*>(plan)->execute( 211 out, reinterpret_cast<const kfr::complex<double>*>(in), temp); 212 } 213 kfr_dft_real_delete_plan_f32(KFR_DFT_REAL_PLAN_F32 * plan)214 void kfr_dft_real_delete_plan_f32(KFR_DFT_REAL_PLAN_F32* plan) 215 { 216 delete reinterpret_cast<kfr::dft_plan_real<float>*>(plan); 217 } kfr_dft_real_delete_plan_f64(KFR_DFT_REAL_PLAN_F64 * plan)218 void kfr_dft_real_delete_plan_f64(KFR_DFT_REAL_PLAN_F64* plan) 219 { 220 delete reinterpret_cast<kfr::dft_plan_real<double>*>(plan); 221 } 222 223 // Discrete Cosine Transform 224 kfr_dct_create_plan_f32(size_t size)225 KFR_DCT_PLAN_F32* kfr_dct_create_plan_f32(size_t size) 226 { 227 if (size < 4) 228 return nullptr; 229 if (size > 16777216) 230 return nullptr; 231 return reinterpret_cast<KFR_DCT_PLAN_F32*>(new kfr::dct_plan<float>(cpu_t::runtime, size)); 232 } kfr_dct_create_plan_f64(size_t size)233 KFR_DCT_PLAN_F64* kfr_dct_create_plan_f64(size_t size) 234 { 235 if (size < 4) 236 return nullptr; 237 if (size > 16777216) 238 return nullptr; 239 return reinterpret_cast<KFR_DCT_PLAN_F64*>(new kfr::dct_plan<double>(cpu_t::runtime, size)); 240 } 241 kfr_dct_dump_f32(KFR_DCT_PLAN_F32 * plan)242 void kfr_dct_dump_f32(KFR_DCT_PLAN_F32* plan) { reinterpret_cast<kfr::dct_plan<float>*>(plan)->dump(); } kfr_dct_dump_f64(KFR_DCT_PLAN_F64 * plan)243 void kfr_dct_dump_f64(KFR_DCT_PLAN_F64* plan) { reinterpret_cast<kfr::dct_plan<double>*>(plan)->dump(); } 244 kfr_dct_get_size_f32(KFR_DCT_PLAN_F32 * plan)245 size_t kfr_dct_get_size_f32(KFR_DCT_PLAN_F32* plan) 246 { 247 return reinterpret_cast<kfr::dft_plan<float>*>(plan)->size; 248 } kfr_dct_get_size_f64(KFR_DCT_PLAN_F64 * plan)249 size_t kfr_dct_get_size_f64(KFR_DCT_PLAN_F64* plan) 250 { 251 return reinterpret_cast<kfr::dft_plan<double>*>(plan)->size; 252 } 253 kfr_dct_get_temp_size_f32(KFR_DCT_PLAN_F32 * plan)254 size_t kfr_dct_get_temp_size_f32(KFR_DCT_PLAN_F32* plan) 255 { 256 return reinterpret_cast<kfr::dft_plan<float>*>(plan)->temp_size; 257 } kfr_dct_get_temp_size_f64(KFR_DCT_PLAN_F64 * plan)258 size_t kfr_dct_get_temp_size_f64(KFR_DCT_PLAN_F64* plan) 259 { 260 return reinterpret_cast<kfr::dft_plan<double>*>(plan)->temp_size; 261 } 262 kfr_dct_execute_f32(KFR_DCT_PLAN_F32 * plan,float * out,const float * in,uint8_t * temp)263 void kfr_dct_execute_f32(KFR_DCT_PLAN_F32* plan, float* out, const float* in, uint8_t* temp) 264 { 265 reinterpret_cast<kfr::dct_plan<float>*>(plan)->execute(out, in, temp); 266 } kfr_dct_execute_f64(KFR_DCT_PLAN_F64 * plan,double * out,const double * in,uint8_t * temp)267 void kfr_dct_execute_f64(KFR_DCT_PLAN_F64* plan, double* out, const double* in, uint8_t* temp) 268 { 269 reinterpret_cast<kfr::dct_plan<double>*>(plan)->execute(out, in, temp); 270 } kfr_dct_execute_inverse_f32(KFR_DCT_PLAN_F32 * plan,float * out,const float * in,uint8_t * temp)271 void kfr_dct_execute_inverse_f32(KFR_DCT_PLAN_F32* plan, float* out, const float* in, uint8_t* temp) 272 { 273 reinterpret_cast<kfr::dct_plan<float>*>(plan)->execute(out, in, temp); 274 } kfr_dct_execute_inverse_f64(KFR_DCT_PLAN_F64 * plan,double * out,const double * in,uint8_t * temp)275 void kfr_dct_execute_inverse_f64(KFR_DCT_PLAN_F64* plan, double* out, const double* in, uint8_t* temp) 276 { 277 reinterpret_cast<kfr::dct_plan<double>*>(plan)->execute(out, in, temp); 278 } 279 kfr_dct_delete_plan_f32(KFR_DCT_PLAN_F32 * plan)280 void kfr_dct_delete_plan_f32(KFR_DCT_PLAN_F32* plan) 281 { 282 delete reinterpret_cast<kfr::dct_plan<float>*>(plan); 283 } kfr_dct_delete_plan_f64(KFR_DCT_PLAN_F64 * plan)284 void kfr_dct_delete_plan_f64(KFR_DCT_PLAN_F64* plan) 285 { 286 delete reinterpret_cast<kfr::dct_plan<double>*>(plan); 287 } 288 289 // Filters 290 kfr_filter_create_fir_plan_f32(const kfr_f32 * taps,size_t size)291 KFR_FILTER_F32* kfr_filter_create_fir_plan_f32(const kfr_f32* taps, size_t size) 292 { 293 return reinterpret_cast<KFR_FILTER_F32*>( 294 make_fir_filter<float>(cpu_t::runtime, make_univector(taps, size))); 295 } kfr_filter_create_fir_plan_f64(const kfr_f64 * taps,size_t size)296 KFR_FILTER_F64* kfr_filter_create_fir_plan_f64(const kfr_f64* taps, size_t size) 297 { 298 return reinterpret_cast<KFR_FILTER_F64*>( 299 make_fir_filter<double>(cpu_t::runtime, make_univector(taps, size))); 300 } 301 kfr_filter_create_convolution_plan_f32(const kfr_f32 * taps,size_t size,size_t block_size)302 KFR_FILTER_F32* kfr_filter_create_convolution_plan_f32(const kfr_f32* taps, size_t size, 303 size_t block_size) 304 { 305 return reinterpret_cast<KFR_FILTER_F32*>(make_convolve_filter<float>( 306 cpu_t::runtime, make_univector(taps, size), block_size ? block_size : 1024)); 307 } kfr_filter_create_convolution_plan_f64(const kfr_f64 * taps,size_t size,size_t block_size)308 KFR_FILTER_F64* kfr_filter_create_convolution_plan_f64(const kfr_f64* taps, size_t size, 309 size_t block_size) 310 { 311 return reinterpret_cast<KFR_FILTER_F64*>(make_convolve_filter<double>( 312 cpu_t::runtime, make_univector(taps, size), block_size ? block_size : 1024)); 313 } 314 kfr_filter_create_iir_plan_f32(const kfr_f32 * sos,size_t sos_count)315 KFR_FILTER_F32* kfr_filter_create_iir_plan_f32(const kfr_f32* sos, size_t sos_count) 316 { 317 if (sos_count < 1 || sos_count > 64) 318 return nullptr; 319 return reinterpret_cast<KFR_FILTER_F32*>(make_biquad_filter<float, 64>( 320 cpu_t::runtime, reinterpret_cast<const biquad_params<float>*>(sos), sos_count)); 321 } kfr_filter_create_iir_plan_f64(const kfr_f64 * sos,size_t sos_count)322 KFR_FILTER_F64* kfr_filter_create_iir_plan_f64(const kfr_f64* sos, size_t sos_count) 323 { 324 if (sos_count < 1 || sos_count > 64) 325 return nullptr; 326 return reinterpret_cast<KFR_FILTER_F64*>(make_biquad_filter<double, 64>( 327 cpu_t::runtime, reinterpret_cast<const biquad_params<double>*>(sos), sos_count)); 328 } 329 kfr_filter_process_f32(KFR_FILTER_F32 * plan,kfr_f32 * output,const kfr_f32 * input,size_t size)330 void kfr_filter_process_f32(KFR_FILTER_F32* plan, kfr_f32* output, const kfr_f32* input, size_t size) 331 { 332 reinterpret_cast<filter<float>*>(plan)->apply(output, input, size); 333 } kfr_filter_process_f64(KFR_FILTER_F64 * plan,kfr_f64 * output,const kfr_f64 * input,size_t size)334 void kfr_filter_process_f64(KFR_FILTER_F64* plan, kfr_f64* output, const kfr_f64* input, size_t size) 335 { 336 reinterpret_cast<filter<double>*>(plan)->apply(output, input, size); 337 } 338 kfr_filter_reset_f32(KFR_FILTER_F32 * plan)339 void kfr_filter_reset_f32(KFR_FILTER_F32* plan) { reinterpret_cast<filter<float>*>(plan)->reset(); } kfr_filter_reset_f64(KFR_FILTER_F64 * plan)340 void kfr_filter_reset_f64(KFR_FILTER_F64* plan) { reinterpret_cast<filter<double>*>(plan)->reset(); } 341 kfr_filter_delete_plan_f32(KFR_FILTER_F32 * plan)342 void kfr_filter_delete_plan_f32(KFR_FILTER_F32* plan) { delete reinterpret_cast<filter<f32>*>(plan); } kfr_filter_delete_plan_f64(KFR_FILTER_F64 * plan)343 void kfr_filter_delete_plan_f64(KFR_FILTER_F64* plan) { delete reinterpret_cast<filter<f64>*>(plan); } 344 } 345 346 } // namespace kfr 347