capi_test.cpp (9982B)
1 #define KFR_NO_C_COMPLEX_TYPES 1 2 3 #include <kfr/capi.h> 4 #include <math.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 8 static int failures = 0; 9 10 #ifdef _MSC_VER 11 #define CHECK(condition, message, ...) \ 12 if (!(condition)) \ 13 { \ 14 ++failures; \ 15 fprintf(stderr, "[FAILED] " message "\n", __VA_ARGS__); \ 16 } 17 #else 18 #define CHECK(condition, message, ...) \ 19 if (!(condition)) \ 20 { \ 21 ++failures; \ 22 fprintf(stderr, "[FAILED] " message "\n", ##__VA_ARGS__); \ 23 } 24 #endif 25 26 void test_memory() 27 { 28 printf("[TEST] Memory allocation\n"); 29 uint8_t* d = (uint8_t*)(kfr_allocate(256)); 30 for (size_t i = 0; i < 256; i++) 31 d[i] = i; 32 CHECK(kfr_allocated_size(d) == 256, "kfr_allocated_size: wrong size: %zu", kfr_allocated_size(d)); 33 d = (uint8_t*)(kfr_reallocate(d, 512)); 34 CHECK(kfr_allocated_size(d) == 512, "kfr_allocated_size: wrong size: %zu", kfr_allocated_size(d)); 35 for (size_t i = 0; i < 256; i++) 36 { 37 CHECK(d[i] == i, "kfr_reallocate: data lost after reallocation\n"); 38 } 39 kfr_deallocate(d); 40 41 void* page = kfr_allocate_aligned(4096, 4096); 42 CHECK(((uintptr_t)page & 0xFFF) == 0, "kfr_allocate_aligned: wrong alignment: 0x%zx", 43 ((uintptr_t)page & 0xFFF)); 44 45 kfr_deallocate(page); 46 } 47 48 #define DFT_SIZE 32 49 50 static void init_data_f32(kfr_f32* buf) 51 { 52 for (int i = 0; i < DFT_SIZE; i++) 53 { 54 buf[i * 2 + 0] = (float)(i) / DFT_SIZE; 55 buf[i * 2 + 1] = (float)(-i) / DFT_SIZE; 56 } 57 } 58 static void init_data_f64(kfr_f64* buf) 59 { 60 for (int i = 0; i < DFT_SIZE; i++) 61 { 62 buf[i * 2 + 0] = (double)(i) / DFT_SIZE; 63 buf[i * 2 + 1] = (double)(-i) / DFT_SIZE; 64 } 65 } 66 67 static void test_data_f32(kfr_f32* buf) 68 { 69 const float eps = 0.00001f; 70 for (int i = 0; i < DFT_SIZE; i++) 71 { 72 CHECK(fabsf(buf[i * 2 + 0] - (float)(i)) < eps, "DFT: wrong result at %d: re = %f", i, 73 buf[i * 2 + 0]); 74 CHECK(fabsf(buf[i * 2 + 1] - (float)(-i)) < eps, "DFT: wrong result at %d: im = %f", i, 75 buf[i * 2 + 1]); 76 } 77 } 78 static void test_data_f64(kfr_f64* buf) 79 { 80 const double eps = 0.00001; 81 for (int i = 0; i < DFT_SIZE; i++) 82 { 83 CHECK(fabs(buf[i * 2 + 0] - (double)(i)) < eps, "DFT: wrong result at %d: re = %f", i, 84 buf[i * 2 + 0]); 85 CHECK(fabs(buf[i * 2 + 1] - (double)(-i)) < eps, "DFT: wrong result at %d: im = %f", i, 86 buf[i * 2 + 1]); 87 } 88 } 89 90 void test_dft_f32() 91 { 92 printf("[TEST] DFT f32\n"); 93 // kfr_dft_dump_f32(plan); 94 kfr_f32 buf[DFT_SIZE * 2]; 95 KFR_DFT_PLAN_F32* plan; 96 uint8_t* tmp; 97 98 init_data_f32(buf); 99 plan = kfr_dft_create_plan_f32(DFT_SIZE); 100 tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f32(plan)); 101 kfr_dft_execute_f32(plan, buf, buf, tmp); 102 kfr_dft_execute_inverse_f32(plan, buf, buf, tmp); 103 kfr_deallocate(tmp); 104 kfr_dft_delete_plan_f32(plan); 105 test_data_f32(buf); 106 107 init_data_f32(buf); 108 plan = kfr_dft_create_2d_plan_f32(8, 4); 109 tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f32(plan)); 110 kfr_dft_execute_f32(plan, buf, buf, tmp); 111 kfr_dft_execute_inverse_f32(plan, buf, buf, tmp); 112 kfr_deallocate(tmp); 113 kfr_dft_delete_plan_f32(plan); 114 test_data_f32(buf); 115 116 init_data_f32(buf); 117 plan = kfr_dft_create_3d_plan_f32(4, 4, 2); 118 tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f32(plan)); 119 kfr_dft_execute_f32(plan, buf, buf, tmp); 120 kfr_dft_execute_inverse_f32(plan, buf, buf, tmp); 121 kfr_deallocate(tmp); 122 kfr_dft_delete_plan_f32(plan); 123 test_data_f32(buf); 124 125 unsigned sizes[4] = { 2, 2, 2, 4 }; 126 init_data_f32(buf); 127 plan = kfr_dft_create_md_plan_f32(4, sizes); 128 tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f32(plan)); 129 kfr_dft_execute_f32(plan, buf, buf, tmp); 130 kfr_dft_execute_inverse_f32(plan, buf, buf, tmp); 131 kfr_deallocate(tmp); 132 kfr_dft_delete_plan_f32(plan); 133 test_data_f32(buf); 134 } 135 136 void test_dft_f64() 137 { 138 printf("[TEST] DFT f64\n"); 139 // kfr_dft_dump_f64(plan); 140 kfr_f64 buf[DFT_SIZE * 2]; 141 KFR_DFT_PLAN_F64* plan; 142 uint8_t* tmp; 143 144 init_data_f64(buf); 145 plan = kfr_dft_create_plan_f64(DFT_SIZE); 146 tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f64(plan)); 147 kfr_dft_execute_f64(plan, buf, buf, tmp); 148 kfr_dft_execute_inverse_f64(plan, buf, buf, tmp); 149 kfr_deallocate(tmp); 150 kfr_dft_delete_plan_f64(plan); 151 test_data_f64(buf); 152 153 init_data_f64(buf); 154 plan = kfr_dft_create_2d_plan_f64(8, 4); 155 tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f64(plan)); 156 kfr_dft_execute_f64(plan, buf, buf, tmp); 157 kfr_dft_execute_inverse_f64(plan, buf, buf, tmp); 158 kfr_deallocate(tmp); 159 kfr_dft_delete_plan_f64(plan); 160 test_data_f64(buf); 161 162 init_data_f64(buf); 163 plan = kfr_dft_create_3d_plan_f64(4, 4, 2); 164 tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f64(plan)); 165 kfr_dft_execute_f64(plan, buf, buf, tmp); 166 kfr_dft_execute_inverse_f64(plan, buf, buf, tmp); 167 kfr_deallocate(tmp); 168 kfr_dft_delete_plan_f64(plan); 169 test_data_f64(buf); 170 171 unsigned sizes[4] = { 2, 2, 2, 4 }; 172 init_data_f64(buf); 173 plan = kfr_dft_create_md_plan_f64(4, sizes); 174 tmp = (uint8_t*)kfr_allocate(kfr_dft_get_temp_size_f64(plan)); 175 kfr_dft_execute_f64(plan, buf, buf, tmp); 176 kfr_dft_execute_inverse_f64(plan, buf, buf, tmp); 177 kfr_deallocate(tmp); 178 kfr_dft_delete_plan_f64(plan); 179 test_data_f64(buf); 180 } 181 182 #define FILTER_SIZE 256 183 184 void test_fir_f32() 185 { 186 printf("[TEST] FIR f32\n"); 187 kfr_f32 taps[] = { 1.f, 2.f, -2.f, -1.f }; 188 KFR_FILTER_F32* filter = kfr_filter_create_fir_plan_f32(taps, sizeof(taps) / sizeof(kfr_f32)); 189 190 kfr_f32 buf[FILTER_SIZE]; 191 for (int i = 0; i < FILTER_SIZE; i++) 192 buf[i] = i; 193 194 kfr_filter_process_f32(filter, buf, buf, FILTER_SIZE); 195 CHECK(buf[0] == 0, "FIR: wrong result at %d: %g", 0, buf[0]); 196 CHECK(buf[1] == 1, "FIR: wrong result at %d: %g", 1, buf[1]); 197 CHECK(buf[2] == 4, "FIR: wrong result at %d: %g", 2, buf[2]); 198 CHECK(buf[3] == 5, "FIR: wrong result at %d: %g", 3, buf[3]); 199 CHECK(buf[FILTER_SIZE - 1] == 5, "FIR: wrong result at %d: %g", FILTER_SIZE - 1, buf[FILTER_SIZE - 1]); 200 201 kfr_filter_delete_plan_f32(filter); 202 } 203 204 void test_fir_f64() 205 { 206 printf("[TEST] FIR f64\n"); 207 kfr_f64 taps[] = { 1.f, 2.f, -2.f, -1.f }; 208 KFR_FILTER_F64* filter = kfr_filter_create_fir_plan_f64(taps, sizeof(taps) / sizeof(kfr_f64)); 209 210 kfr_f64 buf[FILTER_SIZE]; 211 for (int i = 0; i < FILTER_SIZE; i++) 212 buf[i] = i; 213 214 kfr_filter_process_f64(filter, buf, buf, FILTER_SIZE); 215 CHECK(buf[0] == 0, "FIR: wrong result at %d: %g", 0, buf[0]); 216 CHECK(buf[1] == 1, "FIR: wrong result at %d: %g", 1, buf[1]); 217 CHECK(buf[2] == 4, "FIR: wrong result at %d: %g", 2, buf[2]); 218 CHECK(buf[3] == 5, "FIR: wrong result at %d: %g", 3, buf[3]); 219 CHECK(buf[FILTER_SIZE - 1] == 5, "FIR: wrong result at %d: %g", FILTER_SIZE - 1, buf[FILTER_SIZE - 1]); 220 221 kfr_filter_delete_plan_f64(filter); 222 } 223 224 void test_iir_f32() 225 { 226 const float eps = 0.00001f; 227 printf("[TEST] IIR f32\n"); 228 float sos[6] = { 229 1., 230 -1.872871474946867, 231 0.8809814578599688, 232 0.002027495728275458, 233 0.004054991456550916, 234 0.002027495728275458, 235 }; 236 KFR_FILTER_F32* filter = kfr_filter_create_iir_plan_f32(sos, 1); 237 238 kfr_f32 buf[FILTER_SIZE]; 239 kfr_f32 src[4] = { 0, 1, 0, -1 }; 240 for (int i = 0; i < FILTER_SIZE; i++) 241 buf[i] = src[i % 4]; 242 243 kfr_filter_process_f32(filter, buf, buf, FILTER_SIZE); 244 245 CHECK(fabsf(buf[0] - 0.f) < eps, "IIR: wrong result at %d: %f", 0, buf[0]); 246 CHECK(fabsf(buf[1] - 0.002027496f) < eps, "IIR: wrong result at %d: %f", 1, buf[1]); 247 CHECK(fabsf(buf[60] - -0.001285130f) < eps, "IIR: wrong result at %d: %f", 60, buf[60]); 248 249 kfr_filter_delete_plan_f32(filter); 250 } 251 252 void test_iir_f64() 253 { 254 const double eps = 0.0000001; 255 printf("[TEST] IIR f64\n"); 256 double sos[6] = { 257 1., 258 -1.872871474946867, 259 0.8809814578599688, 260 0.002027495728275458, 261 0.004054991456550916, 262 0.002027495728275458, 263 }; 264 KFR_FILTER_F64* filter = kfr_filter_create_iir_plan_f64(sos, 1); 265 266 kfr_f64 buf[FILTER_SIZE]; 267 kfr_f64 src[4] = { 0, 1, 0, -1 }; 268 for (int i = 0; i < FILTER_SIZE; i++) 269 buf[i] = src[i % 4]; 270 271 kfr_filter_process_f64(filter, buf, buf, FILTER_SIZE); 272 273 CHECK(fabs(buf[0] - 0.) < eps, "IIR: wrong result at %d: %f", 0, buf[0]); 274 CHECK(fabs(buf[1] - 0.002027496) < eps, "IIR: wrong result at %d: %f", 1, buf[1]); 275 CHECK(fabs(buf[60] - -0.001285130) < eps, "IIR: wrong result at %d: %f", 60, buf[60]); 276 277 kfr_filter_delete_plan_f64(filter); 278 } 279 280 int main() 281 { 282 CHECK(KFR_HEADERS_VERSION <= kfr_version(), "Dynamic library is too old. At least %d required", 283 KFR_HEADERS_VERSION); 284 285 printf("[INFO] %s\n", kfr_version_string()); 286 287 test_memory(); 288 test_dft_f32(); 289 test_dft_f64(); 290 test_fir_f32(); 291 test_fir_f64(); 292 test_iir_f32(); 293 test_iir_f64(); 294 295 if (failures == 0) 296 printf("[PASSED]\n"); 297 else 298 printf("[FAILED] %d check(s)\n", failures); 299 return failures; 300 }