chiark / gitweb /
Automatically rescan when a filesystem is mounted or unmounted.
[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 struct {
52   const char *description;
53   int input_bits;
54   int input_channels;
55   int input_rate;
56   int input_signed;
57   int input_endian;
58   const char *input;
59   size_t input_bytes;
60   int output_bits;
61   int output_channels;
62   int output_rate;
63   int output_signed;
64   int output_endian;
65   const char *output;
66   size_t output_bytes;
67 } conversions[] = {
68   /* Conversions that don't change the sample rate */
69   {
70     "empty input",
71     8, 1, 8000, 0, ENDIAN_LITTLE, "", 0,
72     8, 1, 8000, 0, ENDIAN_LITTLE, "", 0
73   },
74   {
75     "sign flip 8-bit unsigned->signed",
76     8, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x7F\x80\xFF", 4,
77     8, 1, 8000, 1, ENDIAN_LITTLE, "\x80\xFF\x00\x7F", 4
78   },
79   {
80     "sign flip 8-bit signed->unsigned",
81     8, 1, 8000, 1, ENDIAN_BIG, "\x80\xFF\x00\x7F", 4,
82     8, 1, 8000, 0, ENDIAN_BIG, "\x00\x7F\x80\xFF", 4
83   },
84   {
85     "mono to stereo",
86     8, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x7F\x80\xFF", 4,
87     8, 2, 8000, 0, ENDIAN_LITTLE, "\x00\x00\x7F\x7F\x80\x80\xFF\xFF", 8
88   },
89   {
90     "stereo to mono",
91     8, 2, 8000, 0, ENDIAN_LITTLE, "\x00\x01\x7F\x02\x80\x03\xFF\x04", 8,
92     8, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x7F\x80\xFF", 4
93   },
94   {
95     "endian flip little->big",
96     16, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x01\x00\xFF\x01\x00\x01\xFF", 8,
97     16, 1, 8000, 0, ENDIAN_BIG, "\x01\x00\xFF\x00\x00\x01\xFF\x01", 8,
98   },
99   {
100     "endian flip big->little",
101     16, 1, 8000, 0, ENDIAN_BIG, "\x01\x00\xFF\x00\x00\x01\xFF\x01", 8,
102     16, 1, 8000, 0, ENDIAN_LITTLE, "\x00\x01\x00\xFF\x01\x00\x01\xFF", 8,
103   },
104   {
105     "8-bit to 16-bit",
106     8, 1, 8000, 0, ENDIAN_BIG, "\x00\x7F\x80\xFF", 4,
107     16, 1, 8000, 0, ENDIAN_BIG, "\x00\x00\x7F\x00\x80\x00\xFF\x00", 8
108   },
109   {
110     "16-bit to 8-bit",
111     16, 1, 8000, 0, ENDIAN_BIG, "\x00\x00\x7F\xFF\x80\x00\xFF\xFF", 8,
112     8, 1, 8000, 0, ENDIAN_BIG, "\x00\x7F\x80\xFF", 4
113   },
114 #if HAVE_SAMPLERATE_H
115   /* Conversions that do change the sample rate */
116   
117 #endif
118 };
119 #define NCONVERSIONS (sizeof conversions / sizeof *conversions)
120
121 static void test_resample(void) {
122   for(size_t n = 0; n < NCONVERSIONS; ++n) {
123     struct resampler rs[1];
124
125     resample_init(rs, 
126                   conversions[n].input_bits,
127                   conversions[n].input_channels,
128                   conversions[n].input_rate,
129                   conversions[n].input_signed,
130                   conversions[n].input_endian,
131                   conversions[n].output_bits,
132                   conversions[n].output_channels,
133                   conversions[n].output_rate,
134                   conversions[n].output_signed,
135                   conversions[n].output_endian);
136     size_t output_bytes;
137     const uint8_t *output = convert(rs,
138                                     (const uint8_t *)conversions[n].input, 
139                                     conversions[n].input_bytes, 
140                                     &output_bytes);
141     if(output_bytes != conversions[n].output_bytes
142        || memcmp(output, conversions[n].output, output_bytes)) {
143       fprintf(stderr, "index %zu description %s mismatch\n",
144               n, conversions[n].description);
145       size_t k = 0;
146       while(k < conversions[n].output_bytes || k < output_bytes) {
147         size_t j = 0;
148         fprintf(stderr, "%8zu E:", k);
149         for(j = 0; j < 16; ++j) {
150           if(j + k < conversions[n].output_bytes)
151             fprintf(stderr, " %02x", conversions[n].output[j + k]);
152         }
153         fprintf(stderr, "\n         G:");
154         for(j = 0; j < 16; ++j) {
155           if(j + k < output_bytes)
156             fprintf(stderr, " %02x", output[j + k]);
157         }
158         fprintf(stderr, "\n");
159         k += 16;
160       }
161       ++errors;
162     }
163     ++tests;
164   }
165 }
166
167 TEST(resample);
168
169 /*
170 Local Variables:
171 c-basic-offset:2
172 comment-column:40
173 fill-column:79
174 indent-tabs-mode:nil
175 End:
176 */