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