chiark / gitweb /
14e23197358d45721e35008a629849de28da8ef2
[disorder] / libtests / t-resample.c
1 /*
2  * This file is part of DisOrder.
3  * Copyright (C) 2009 Richard Kettlewell
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 #include "test.h"
19 #include "resample.h"
20 #include "vector.h"
21
22 /* Accumulate converted bytes in a dynamic string */
23 static void converted(uint8_t *bytes,
24                       size_t nbytes,
25                       void *cd) {
26   struct dynstr *d = cd;
27   dynstr_append_bytes(d, (void *)bytes, nbytes);
28 }
29
30 /* Converter wrapper */
31 static uint8_t *convert(const struct resampler *rs,
32                         const uint8_t *input, size_t input_bytes,
33                         size_t *output_bytes) {
34   struct dynstr d[1];
35
36   dynstr_init(d);
37   while(input_bytes > 0) {
38     size_t chunk = input_bytes > 1024 ? 1024 : input_bytes;
39     size_t consumed = resample_convert(rs,
40                                        input, input_bytes,
41                                        input_bytes == chunk,
42                                        converted,
43                                        d);
44     input += consumed;
45     input_bytes -= consumed;
46   }
47   *output_bytes = d->nvec;
48   return (uint8_t *)d->vec;
49 }
50
51 static const uint8_t simple_bytes_u[] = {
52   0, 127, 128, 255,
53 };
54
55 static const uint8_t simple_bytes_u2[] = {
56   0, 0, 127, 127, 128, 128, 255, 255,
57 };
58
59 static const uint8_t simple_bytes_s[] = {
60   -128, -1, 0, 127,
61 };
62
63 static const uint8_t simple_words_u_le[] = {
64   0, 1,  0, 255,  1, 0,  1, 255
65 };
66
67 static const uint8_t simple_words_u_be[] = {
68   1, 0,  255, 0,  0, 1,  255, 1
69 };
70
71 static const struct {
72   const char *description;
73   int input_bits;
74   int input_channels;
75   int input_rate;
76   int input_signed;
77   int input_endian;
78   const uint8_t *input;
79   size_t input_bytes;
80   int output_bits;
81   int output_channels;
82   int output_rate;
83   int output_signed;
84   int output_endian;
85   const uint8_t *output;
86   size_t output_bytes;
87 } conversions[] = {
88   /* Conversions that don't change the sample rate */
89   {
90     "empty input",
91     8, 1, 8000, 0, ENDIAN_LITTLE, (const uint8_t *)"", 0,
92     8, 1, 8000, 0, ENDIAN_LITTLE, (const uint8_t *)"", 0
93   },
94   {
95     "sign flip",
96     8, 1, 8000, 0, ENDIAN_LITTLE, simple_bytes_u, 4,
97     8, 1, 8000, 1, ENDIAN_LITTLE, simple_bytes_s, 4
98   },
99   {
100     "mono to stereo",
101     8, 1, 8000, 0, ENDIAN_LITTLE, simple_bytes_u, 4,
102     8, 2, 8000, 0, ENDIAN_LITTLE, simple_bytes_u2, 8
103   },
104   {
105     "endian flip",
106     16, 1, 8000, 0, ENDIAN_LITTLE, simple_words_u_le, 8,
107     16, 1, 8000, 0, ENDIAN_BIG, simple_words_u_be, 8,
108   },
109 #if HAVE_SAMPLERATE_H
110   /* Conversions that do change the sample rate */
111   
112 #endif
113 };
114 #define NCONVERSIONS (sizeof conversions / sizeof *conversions)
115
116 static void test_resample(void) {
117   for(size_t n = 0; n < NCONVERSIONS; ++n) {
118     struct resampler rs[1];
119
120     resample_init(rs, 
121                   conversions[n].input_bits,
122                   conversions[n].input_channels,
123                   conversions[n].input_rate,
124                   conversions[n].input_signed,
125                   conversions[n].input_endian,
126                   conversions[n].output_bits,
127                   conversions[n].output_channels,
128                   conversions[n].output_rate,
129                   conversions[n].output_signed,
130                   conversions[n].output_endian);
131     size_t output_bytes;
132     const uint8_t *output = convert(rs,
133                                     conversions[n].input, 
134                                     conversions[n].input_bytes, 
135                                     &output_bytes);
136     if(output_bytes != conversions[n].output_bytes
137        || memcmp(output, conversions[n].output, output_bytes)) {
138       fprintf(stderr, "index %zu description %s mismatch\n",
139               n, conversions[n].description);
140       size_t k = 0;
141       while(k < conversions[n].output_bytes || k < output_bytes) {
142         size_t j = 0;
143         fprintf(stderr, "%8zu E:", k);
144         for(j = 0; j < 16; ++j) {
145           if(j + k < conversions[n].output_bytes)
146             fprintf(stderr, " %02x", conversions[n].output[j + k]);
147         }
148         fprintf(stderr, "\n         G:");
149         for(j = 0; j < 16; ++j) {
150           if(j + k < output_bytes)
151             fprintf(stderr, " %02x", output[j + k]);
152         }
153         fprintf(stderr, "\n");
154         k += 16;
155       }
156       ++errors;
157     }
158     ++tests;
159   }
160 }
161
162 TEST(resample);
163
164 /*
165 Local Variables:
166 c-basic-offset:2
167 comment-column:40
168 fill-column:79
169 indent-tabs-mode:nil
170 End:
171 */