1 //
2 // Copyright 2011-2012 Ettus Research LLC
3 // Copyright 2018 Ettus Research, a National Instruments Company
4 //
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7
8 #include <uhd/convert.hpp>
9 #include <stdint.h>
10 #include <boost/test/unit_test.hpp>
11 #include <complex>
12 #include <cstdlib>
13 #include <iostream>
14 #include <vector>
15
16 using namespace uhd;
17
18 // typedefs for complex types
19 typedef std::complex<int16_t> sc16_t;
20 typedef std::complex<float> fc32_t;
21 typedef std::complex<double> fc64_t;
22
23 #define MY_CHECK_CLOSE(a, b, f) \
24 { \
25 BOOST_CHECK_MESSAGE(std::abs((a) - (b)) < f, \
26 "\n\t" << #a << " (" << (a) << ") error " << #b << " (" << (b) << ")"); \
27 }
28
29 /***********************************************************************
30 * Loopback runner:
31 * convert input buffer into intermediate buffer
32 * convert intermediate buffer into output buffer
33 **********************************************************************/
34 template <typename Range>
loopback(size_t nsamps,convert::id_type & in_id,convert::id_type & out_id,const Range & input,Range & output,const int prio_in=-1,const int prio_out=-1)35 static void loopback(size_t nsamps,
36 convert::id_type& in_id,
37 convert::id_type& out_id,
38 const Range& input,
39 Range& output,
40 const int prio_in = -1,
41 const int prio_out = -1)
42 {
43 // make this buffer large enough for all test types
44 std::vector<uint64_t> interm(nsamps);
45
46 std::vector<const void*> input0(1, &input[0]), input1(1, &interm[0]);
47 std::vector<void*> output0(1, &interm[0]), output1(1, &output[0]);
48
49 // convert to intermediate type
50 convert::converter::sptr c0 = convert::get_converter(in_id, prio_in)();
51 c0->set_scalar(32767.);
52 c0->conv(input0, output0, nsamps);
53
54 // convert back to host type
55 convert::converter::sptr c1 = convert::get_converter(out_id, prio_out)();
56 c1->set_scalar(1 / 32767.);
57 c1->conv(input1, output1, nsamps);
58 }
59
60 /***********************************************************************
61 * Test short conversion
62 **********************************************************************/
test_convert_types_sc16(size_t nsamps,convert::id_type & id,const int extra_div=1,int mask=0xffff)63 static void test_convert_types_sc16(
64 size_t nsamps, convert::id_type& id, const int extra_div = 1, int mask = 0xffff)
65 {
66 // fill the input samples
67 std::vector<sc16_t> input(nsamps), output(nsamps);
68 for (sc16_t& in : input)
69 in = sc16_t(
70 short((float((std::rand()) / (double(RAND_MAX) / 2)) - 1) * 32767 / extra_div)
71 & mask,
72 short((float((std::rand()) / (double(RAND_MAX) / 2)) - 1) * 32767 / extra_div)
73 & mask);
74
75 // run the loopback and test
76 convert::id_type in_id = id;
77 convert::id_type out_id = id;
78 std::swap(out_id.input_format, out_id.output_format);
79 std::swap(out_id.num_inputs, out_id.num_outputs);
80 loopback(nsamps, in_id, out_id, input, output);
81 BOOST_CHECK_EQUAL_COLLECTIONS(
82 input.begin(), input.end(), output.begin(), output.end());
83 }
84
BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16)85 BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16)
86 {
87 convert::id_type id;
88 id.input_format = "sc16";
89 id.num_inputs = 1;
90 id.output_format = "sc16_item32_be";
91 id.num_outputs = 1;
92
93 // try various lengths to test edge cases
94 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
95 test_convert_types_sc16(nsamps, id);
96 }
97 }
98
BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16)99 BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16)
100 {
101 convert::id_type id;
102 id.input_format = "sc16";
103 id.num_inputs = 1;
104 id.output_format = "sc16_item32_le";
105 id.num_outputs = 1;
106
107 // try various lengths to test edge cases
108 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
109 test_convert_types_sc16(nsamps, id);
110 }
111 }
112
BOOST_AUTO_TEST_CASE(test_convert_types_chdr_sc16)113 BOOST_AUTO_TEST_CASE(test_convert_types_chdr_sc16)
114 {
115 convert::id_type id;
116 id.input_format = "sc16";
117 id.num_inputs = 1;
118 id.output_format = "sc16_chdr";
119 id.num_outputs = 1;
120
121 // try various lengths to test edge cases
122 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
123 test_convert_types_sc16(nsamps, id);
124 }
125 }
126
127 /***********************************************************************
128 * Test float conversion
129 **********************************************************************/
130 template <typename data_type>
test_convert_types_for_floats(size_t nsamps,convert::id_type & id,const double extra_scale=1.0)131 static void test_convert_types_for_floats(
132 size_t nsamps, convert::id_type& id, const double extra_scale = 1.0)
133 {
134 typedef typename data_type::value_type value_type;
135
136 // fill the input samples
137 std::vector<data_type> input(nsamps), output(nsamps);
138 for (data_type& in : input)
139 in = data_type(
140 ((std::rand() / (value_type(RAND_MAX) / 2)) - 1) * float(extra_scale),
141 ((std::rand() / (value_type(RAND_MAX) / 2)) - 1) * float(extra_scale));
142
143 // run the loopback and test
144 convert::id_type in_id = id;
145 convert::id_type out_id = id;
146 std::swap(out_id.input_format, out_id.output_format);
147 std::swap(out_id.num_inputs, out_id.num_outputs);
148
149 // make a list of all prio: best/generic combos
150 typedef std::pair<int, int> int_pair_t;
151 const std::vector<int_pair_t> prios{
152 int_pair_t(0, 0), int_pair_t(-1, 0), int_pair_t(0, -1), int_pair_t(-1, -1)};
153
154 // loopback foreach prio combo (generic vs best)
155 for (const auto& prio : prios) {
156 loopback(nsamps, in_id, out_id, input, output, prio.first, prio.second);
157 for (size_t i = 0; i < nsamps; i++) {
158 MY_CHECK_CLOSE(input[i].real(), output[i].real(), value_type(1. / (1 << 14)));
159 MY_CHECK_CLOSE(input[i].imag(), output[i].imag(), value_type(1. / (1 << 14)));
160 }
161 }
162 }
163
BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32)164 BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32)
165 {
166 convert::id_type id;
167 id.input_format = "fc32";
168 id.num_inputs = 1;
169 id.output_format = "sc16_item32_be";
170 id.num_outputs = 1;
171
172 // try various lengths to test edge cases
173 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
174 test_convert_types_for_floats<fc32_t>(nsamps, id);
175 }
176 }
177
BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32)178 BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32)
179 {
180 convert::id_type id;
181 id.input_format = "fc32";
182 id.num_inputs = 1;
183 id.output_format = "sc16_item32_le";
184 id.num_outputs = 1;
185
186 // try various lengths to test edge cases
187 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
188 test_convert_types_for_floats<fc32_t>(nsamps, id);
189 }
190 }
191
BOOST_AUTO_TEST_CASE(test_convert_types_chdr_fc32)192 BOOST_AUTO_TEST_CASE(test_convert_types_chdr_fc32)
193 {
194 convert::id_type id;
195 id.input_format = "fc32";
196 id.num_inputs = 1;
197 id.output_format = "sc16_chdr";
198 id.num_outputs = 1;
199
200 // try various lengths to test edge cases
201 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
202 test_convert_types_for_floats<fc32_t>(nsamps, id);
203 }
204 }
205
BOOST_AUTO_TEST_CASE(test_convert_types_be_fc64)206 BOOST_AUTO_TEST_CASE(test_convert_types_be_fc64)
207 {
208 convert::id_type id;
209 id.input_format = "fc64";
210 id.num_inputs = 1;
211 id.output_format = "sc16_item32_be";
212 id.num_outputs = 1;
213
214 // try various lengths to test edge cases
215 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
216 test_convert_types_for_floats<fc64_t>(nsamps, id);
217 }
218 }
219
BOOST_AUTO_TEST_CASE(test_convert_types_le_fc64)220 BOOST_AUTO_TEST_CASE(test_convert_types_le_fc64)
221 {
222 convert::id_type id;
223 id.input_format = "fc64";
224 id.num_inputs = 1;
225 id.output_format = "sc16_item32_le";
226 id.num_outputs = 1;
227
228 // try various lengths to test edge cases
229 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
230 test_convert_types_for_floats<fc64_t>(nsamps, id);
231 }
232 }
233
BOOST_AUTO_TEST_CASE(test_convert_types_chdr_fc64)234 BOOST_AUTO_TEST_CASE(test_convert_types_chdr_fc64)
235 {
236 convert::id_type id;
237 id.input_format = "fc64";
238 id.num_inputs = 1;
239 id.output_format = "sc16_chdr";
240 id.num_outputs = 1;
241
242 // try various lengths to test edge cases
243 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
244 test_convert_types_for_floats<fc64_t>(nsamps, id);
245 }
246 }
247
248 /***********************************************************************
249 * Test float to/from sc12 conversion loopback
250 **********************************************************************/
251
BOOST_AUTO_TEST_CASE(test_convert_types_le_sc12_with_fc32)252 BOOST_AUTO_TEST_CASE(test_convert_types_le_sc12_with_fc32)
253 {
254 convert::id_type id;
255 id.input_format = "fc32";
256 id.num_inputs = 1;
257 id.output_format = "sc12_item32_le";
258 id.num_outputs = 1;
259
260 // try various lengths to test edge cases
261 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
262 test_convert_types_for_floats<fc32_t>(nsamps, id, 1. / 16);
263 }
264 }
265
BOOST_AUTO_TEST_CASE(test_convert_types_be_sc12_with_fc32)266 BOOST_AUTO_TEST_CASE(test_convert_types_be_sc12_with_fc32)
267 {
268 convert::id_type id;
269 id.input_format = "fc32";
270 id.num_inputs = 1;
271 id.output_format = "sc12_item32_be";
272 id.num_outputs = 1;
273
274 // try various lengths to test edge cases
275 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
276 test_convert_types_for_floats<fc32_t>(nsamps, id, 1. / 16);
277 }
278 }
279
BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16_and_sc12)280 BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16_and_sc12)
281 {
282 convert::id_type id;
283 id.input_format = "sc16";
284 id.num_inputs = 1;
285 id.num_outputs = 1;
286
287 // try various lengths to test edge cases
288 id.output_format = "sc12_item32_le";
289 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
290 test_convert_types_sc16(nsamps, id, 1, 0xfff0);
291 }
292 }
293
BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16_and_sc12)294 BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16_and_sc12)
295 {
296 convert::id_type id;
297 id.input_format = "sc16";
298 id.num_inputs = 1;
299 id.num_outputs = 1;
300
301 id.output_format = "sc12_item32_be";
302 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
303 test_convert_types_sc16(nsamps, id, 1, 0xfff0);
304 }
305 }
306
307 /***********************************************************************
308 * Test float to/from fc32 conversion loopback
309 **********************************************************************/
310
BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32_with_fc32)311 BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32_with_fc32)
312 {
313 convert::id_type id;
314 id.input_format = "fc32";
315 id.num_inputs = 1;
316 id.output_format = "fc32_item32_le";
317 id.num_outputs = 1;
318
319 // try various lengths to test edge cases
320 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
321 test_convert_types_for_floats<fc32_t>(nsamps, id);
322 }
323 }
324
BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32_with_fc32)325 BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32_with_fc32)
326 {
327 convert::id_type id;
328 id.input_format = "fc32";
329 id.num_inputs = 1;
330 id.output_format = "fc32_item32_be";
331 id.num_outputs = 1;
332
333 // try various lengths to test edge cases
334 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
335 test_convert_types_for_floats<fc32_t>(nsamps, id);
336 }
337 }
338
BOOST_AUTO_TEST_CASE(test_convert_types_fc32_with_fc32_chdr)339 BOOST_AUTO_TEST_CASE(test_convert_types_fc32_with_fc32_chdr)
340 {
341 convert::id_type id;
342 id.input_format = "fc32";
343 id.num_inputs = 1;
344 id.output_format = "fc32_chdr";
345 id.num_outputs = 1;
346
347 // try various lengths to test edge cases
348 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
349 test_convert_types_for_floats<fc32_t>(nsamps, id);
350 }
351 }
352
353 /***********************************************************************
354 * Test float to short conversion loopback
355 **********************************************************************/
BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16)356 BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16)
357 {
358 convert::id_type in_id;
359 in_id.input_format = "fc32";
360 in_id.num_inputs = 1;
361 in_id.output_format = "sc16_item32_le";
362 in_id.num_outputs = 1;
363
364 convert::id_type out_id;
365 out_id.input_format = "sc16_item32_le";
366 out_id.num_inputs = 1;
367 out_id.output_format = "sc16";
368 out_id.num_outputs = 1;
369
370 const size_t nsamps = 13;
371 std::vector<fc32_t> input(nsamps);
372 for (fc32_t& in : input)
373 in = fc32_t(
374 (std::rand() / (RAND_MAX / 2.0)) - 1, (std::rand() / (RAND_MAX / 2.0)) - 1);
375 std::vector<uint32_t> interm(nsamps);
376 std::vector<sc16_t> output(nsamps);
377
378 std::vector<const void*> input0(1, &input[0]), input1(1, &interm[0]);
379 std::vector<void*> output0(1, &interm[0]), output1(1, &output[0]);
380
381 // convert float to intermediate
382 convert::converter::sptr c0 = convert::get_converter(in_id)();
383 c0->set_scalar(32767.);
384 c0->conv(input0, output0, nsamps);
385
386 // convert intermediate to short
387 convert::converter::sptr c1 = convert::get_converter(out_id)();
388 c1->set_scalar(1 / 32767.);
389 c1->conv(input1, output1, nsamps);
390
391 // test that the inputs and outputs match
392 for (size_t i = 0; i < nsamps; i++) {
393 MY_CHECK_CLOSE(input[i].real(), output[i].real() / float(32767), float(0.01));
394 MY_CHECK_CLOSE(input[i].imag(), output[i].imag() / float(32767), float(0.01));
395 }
396 }
397
398 /***********************************************************************
399 * Test short to float conversion loopback
400 **********************************************************************/
BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32)401 BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32)
402 {
403 convert::id_type in_id;
404 in_id.input_format = "sc16";
405 in_id.num_inputs = 1;
406 in_id.output_format = "sc16_item32_le";
407 in_id.num_outputs = 1;
408
409 convert::id_type out_id;
410 out_id.input_format = "sc16_item32_le";
411 out_id.num_inputs = 1;
412 out_id.output_format = "fc32";
413 out_id.num_outputs = 1;
414
415 const size_t nsamps = 13;
416 std::vector<sc16_t> input(nsamps);
417 for (sc16_t& in : input)
418 in = sc16_t(std::rand() - (RAND_MAX / 2), std::rand() - (RAND_MAX / 2));
419 std::vector<uint32_t> interm(nsamps);
420 std::vector<fc32_t> output(nsamps);
421
422 std::vector<const void*> input0(1, &input[0]), input1(1, &interm[0]);
423 std::vector<void*> output0(1, &interm[0]), output1(1, &output[0]);
424
425 // convert short to intermediate
426 convert::converter::sptr c0 = convert::get_converter(in_id)();
427 c0->set_scalar(32767.);
428 c0->conv(input0, output0, nsamps);
429
430 // convert intermediate to float
431 convert::converter::sptr c1 = convert::get_converter(out_id)();
432 c1->set_scalar(1 / 32767.);
433 c1->conv(input1, output1, nsamps);
434
435 // test that the inputs and outputs match
436 for (size_t i = 0; i < nsamps; i++) {
437 MY_CHECK_CLOSE(input[i].real() / float(32767), output[i].real(), float(0.01));
438 MY_CHECK_CLOSE(input[i].imag() / float(32767), output[i].imag(), float(0.01));
439 }
440 }
441
442 /***********************************************************************
443 * Test sc8 conversions
444 **********************************************************************/
BOOST_AUTO_TEST_CASE(test_convert_types_fc64_and_sc8)445 BOOST_AUTO_TEST_CASE(test_convert_types_fc64_and_sc8)
446 {
447 convert::id_type id;
448 id.input_format = "fc64";
449 id.num_inputs = 1;
450 id.num_outputs = 1;
451
452 // try various lengths to test edge cases
453 id.output_format = "sc8_item32_le";
454 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
455 test_convert_types_for_floats<fc64_t>(nsamps, id, 1. / 256);
456 }
457
458 // try various lengths to test edge cases
459 id.output_format = "sc8_item32_be";
460 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
461 test_convert_types_for_floats<fc64_t>(nsamps, id, 1. / 256);
462 }
463 }
464
BOOST_AUTO_TEST_CASE(test_convert_types_fc32_and_sc8)465 BOOST_AUTO_TEST_CASE(test_convert_types_fc32_and_sc8)
466 {
467 convert::id_type id;
468 id.input_format = "fc32";
469 id.num_inputs = 1;
470 id.num_outputs = 1;
471
472 // try various lengths to test edge cases
473 id.output_format = "sc8_item32_le";
474 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
475 test_convert_types_for_floats<fc32_t>(nsamps, id, 1. / 256);
476 }
477
478 // try various lengths to test edge cases
479 id.output_format = "sc8_item32_be";
480 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
481 test_convert_types_for_floats<fc32_t>(nsamps, id, 1. / 256);
482 }
483 }
484
BOOST_AUTO_TEST_CASE(test_convert_types_sc16_and_sc8)485 BOOST_AUTO_TEST_CASE(test_convert_types_sc16_and_sc8)
486 {
487 convert::id_type id;
488 id.input_format = "sc16";
489 id.num_inputs = 1;
490 id.num_outputs = 1;
491
492 // try various lengths to test edge cases
493 id.output_format = "sc8_item32_le";
494 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
495 test_convert_types_sc16(nsamps, id, 256);
496 }
497
498 // try various lengths to test edge cases
499 id.output_format = "sc8_item32_be";
500 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
501 test_convert_types_sc16(nsamps, id, 256);
502 }
503 }
504
505 /***********************************************************************
506 * Test u8 conversion
507 **********************************************************************/
test_convert_types_u8(size_t nsamps,convert::id_type & id)508 static void test_convert_types_u8(size_t nsamps, convert::id_type& id)
509 {
510 // fill the input samples
511 std::vector<uint8_t> input(nsamps), output(nsamps);
512 for (uint8_t& in : input)
513 in = uint8_t(std::rand() & 0xFF);
514 // uint32_t d = 48;
515 // for(uint8_t &in: input) in = d++;
516
517 // run the loopback and test
518 convert::id_type in_id = id;
519 convert::id_type out_id = id;
520 std::swap(out_id.input_format, out_id.output_format);
521 std::swap(out_id.num_inputs, out_id.num_outputs);
522 loopback(nsamps, in_id, out_id, input, output);
523 BOOST_CHECK_EQUAL_COLLECTIONS(
524 input.begin(), input.end(), output.begin(), output.end());
525 }
526
BOOST_AUTO_TEST_CASE(test_convert_types_u8_and_u8)527 BOOST_AUTO_TEST_CASE(test_convert_types_u8_and_u8)
528 {
529 convert::id_type id;
530 id.input_format = "u8";
531 id.num_inputs = 1;
532 id.num_outputs = 1;
533
534 // try various lengths to test edge cases
535 id.output_format = "u8_item32_le";
536 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
537 test_convert_types_u8(nsamps, id);
538 }
539
540 // try various lengths to test edge cases
541 id.output_format = "u8_item32_be";
542 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
543 test_convert_types_u8(nsamps, id);
544 }
545 }
546
BOOST_AUTO_TEST_CASE(test_convert_types_u8_and_u8_chdr)547 BOOST_AUTO_TEST_CASE(test_convert_types_u8_and_u8_chdr)
548 {
549 convert::id_type id;
550 id.input_format = "u8";
551 id.output_format = "u8_chdr";
552 id.num_inputs = 1;
553 id.num_outputs = 1;
554
555 // try various lengths to test edge cases
556 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
557 test_convert_types_u8(nsamps, id);
558 }
559 }
560
561 /***********************************************************************
562 * Test s8 conversion
563 **********************************************************************/
test_convert_types_s8(size_t nsamps,convert::id_type & id)564 static void test_convert_types_s8(size_t nsamps, convert::id_type& id)
565 {
566 // fill the input samples
567 std::vector<int8_t> input(nsamps), output(nsamps);
568 for (int8_t& in : input)
569 in = int8_t(std::rand() & 0xFF);
570
571 // run the loopback and test
572 convert::id_type in_id = id;
573 convert::id_type out_id = id;
574 std::swap(out_id.input_format, out_id.output_format);
575 std::swap(out_id.num_inputs, out_id.num_outputs);
576 loopback(nsamps, in_id, out_id, input, output);
577 BOOST_CHECK_EQUAL_COLLECTIONS(
578 input.begin(), input.end(), output.begin(), output.end());
579 }
580
BOOST_AUTO_TEST_CASE(test_convert_types_s8_and_s8)581 BOOST_AUTO_TEST_CASE(test_convert_types_s8_and_s8)
582 {
583 convert::id_type id;
584 id.input_format = "s8";
585 id.num_inputs = 1;
586 id.num_outputs = 1;
587
588 // try various lengths to test edge cases
589 id.output_format = "s8_item32_le";
590 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
591 test_convert_types_s8(nsamps, id);
592 }
593
594 // try various lengths to test edge cases
595 id.output_format = "s8_item32_be";
596 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
597 test_convert_types_s8(nsamps, id);
598 }
599 }
600
BOOST_AUTO_TEST_CASE(test_convert_types_s8_and_s8_chdr)601 BOOST_AUTO_TEST_CASE(test_convert_types_s8_and_s8_chdr)
602 {
603 convert::id_type id;
604 id.input_format = "s8";
605 id.output_format = "s8_chdr";
606 id.num_inputs = 1;
607 id.num_outputs = 1;
608
609 // try various lengths to test edge cases
610 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
611 test_convert_types_s8(nsamps, id);
612 }
613 }
614
615 /***********************************************************************
616 * Test s16 conversion
617 **********************************************************************/
test_convert_types_s16(size_t nsamps,convert::id_type & id)618 static void test_convert_types_s16(size_t nsamps, convert::id_type& id)
619 {
620 // fill the input samples
621 std::vector<int16_t> input(nsamps), output(nsamps);
622 for (int16_t& in : input)
623 in = int16_t(std::rand() & 0xFFFF);
624
625 // run the loopback and test
626 convert::id_type in_id = id;
627 convert::id_type out_id = id;
628 std::swap(out_id.input_format, out_id.output_format);
629 std::swap(out_id.num_inputs, out_id.num_outputs);
630 loopback(nsamps, in_id, out_id, input, output);
631 BOOST_CHECK_EQUAL_COLLECTIONS(
632 input.begin(), input.end(), output.begin(), output.end());
633 }
634
BOOST_AUTO_TEST_CASE(test_convert_types_s16_and_s16)635 BOOST_AUTO_TEST_CASE(test_convert_types_s16_and_s16)
636 {
637 convert::id_type id;
638 id.input_format = "s16";
639 id.num_inputs = 1;
640 id.num_outputs = 1;
641
642 // try various lengths to test edge cases
643 id.output_format = "s16_item32_le";
644 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
645 test_convert_types_s16(nsamps, id);
646 }
647
648 // try various lengths to test edge cases
649 id.output_format = "s16_item32_be";
650 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
651 test_convert_types_s16(nsamps, id);
652 }
653 }
654
BOOST_AUTO_TEST_CASE(test_convert_types_s16_and_s16_chdr)655 BOOST_AUTO_TEST_CASE(test_convert_types_s16_and_s16_chdr)
656 {
657 convert::id_type id;
658 id.input_format = "s16";
659 id.output_format = "s16_chdr";
660 id.num_inputs = 1;
661 id.num_outputs = 1;
662
663 // try various lengths to test edge cases
664 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
665 test_convert_types_s16(nsamps, id);
666 }
667 }
668
669 /***********************************************************************
670 * Test fc32 -> fc32 conversion
671 **********************************************************************/
test_convert_types_fc32(size_t nsamps,convert::id_type & id)672 static void test_convert_types_fc32(size_t nsamps, convert::id_type& id)
673 {
674 // fill the input samples
675 std::vector<std::complex<float>> input(nsamps), output(nsamps);
676 for (fc32_t& in : input)
677 in = fc32_t((std::rand() / float(RAND_MAX / 2)) - 1,
678 (std::rand() / float(RAND_MAX / 2)) - 1);
679
680 // run the loopback and test
681 convert::id_type in_id = id;
682 convert::id_type out_id = id;
683 std::swap(out_id.input_format, out_id.output_format);
684 std::swap(out_id.num_inputs, out_id.num_outputs);
685 loopback(nsamps, in_id, out_id, input, output);
686 for (size_t i = 0; i < nsamps; i++) {
687 MY_CHECK_CLOSE(input[i].real(), output[i].real(), float(1. / (1 << 16)));
688 MY_CHECK_CLOSE(input[i].imag(), output[i].imag(), float(1. / (1 << 16)));
689 }
690 }
691
BOOST_AUTO_TEST_CASE(test_convert_types_fc32_and_fc32)692 BOOST_AUTO_TEST_CASE(test_convert_types_fc32_and_fc32)
693 {
694 convert::id_type id;
695 id.input_format = "fc32";
696 id.num_inputs = 1;
697 id.num_outputs = 1;
698
699 // try various lengths to test edge cases
700 id.output_format = "fc32_item32_le";
701 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
702 test_convert_types_fc32(nsamps, id);
703 }
704
705 // try various lengths to test edge cases
706 id.output_format = "fc32_item32_be";
707 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
708 test_convert_types_fc32(nsamps, id);
709 }
710 }
711
BOOST_AUTO_TEST_CASE(test_convert_types_fc32_and_fc32_chdr)712 BOOST_AUTO_TEST_CASE(test_convert_types_fc32_and_fc32_chdr)
713 {
714 convert::id_type id;
715 id.input_format = "fc32";
716 id.output_format = "fc32_chdr";
717 id.num_inputs = 1;
718 id.num_outputs = 1;
719
720 // try various lengths to test edge cases
721 for (size_t nsamps = 1; nsamps < 16; nsamps++) {
722 test_convert_types_fc32(nsamps, id);
723 }
724 }
725