Commit | Line | Data |
---|---|---|
0e8c21de RK |
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 | ||
19 | /** @file lib/resample.c | |
20 | * @brief Audio resampling | |
21 | * | |
22 | * General purpose audio format conversion. Rate conversion only works if the | |
23 | * SRC samplerate library is available, but the bitness/channel/endianness | |
24 | * conversion works regardless. | |
25 | */ | |
26 | ||
27 | #include "common.h" | |
28 | #include "resample.h" | |
29 | #include "log.h" | |
30 | #include "mem.h" | |
31 | ||
32 | /** @brief Number of intermediate-format samples */ | |
33 | #define SAMPLES 1024 | |
34 | ||
35 | /** @brief Multiplier for signed formats to allow easy switching */ | |
36 | #define SIGNED 4 | |
37 | ||
38 | /** @brief Initialize a resampler | |
39 | * @param rs Resampler | |
40 | * @param input_bits Bits/sample in input | |
41 | * @param input_channels Number of input channels | |
42 | * @param input_signed Whether input samples are signed or unsigned | |
43 | * @param input_rate Frames/second in input | |
44 | * @param output_bits Bits/sample in output | |
45 | * @param output_channels Number of output channels | |
46 | * @param output_rate Frames/second in output | |
47 | * @param output_signed Whether output samples are signed or unsigned | |
48 | * | |
49 | * For formats with more than two channels it's assume that the first | |
50 | * two channels are left and right. No particular meaning is attached | |
51 | * to additional channels other than to assume channel N in an input | |
52 | * means the same as channel N in an output, for N>1. | |
53 | */ | |
54 | void resample_init(struct resampler *rs, | |
55 | int input_bits, int input_channels, | |
56 | int input_rate, int input_signed, | |
57 | int input_endian, | |
58 | int output_bits, int output_channels, | |
59 | int output_rate, int output_signed, | |
60 | int output_endian) { | |
0e8c21de RK |
61 | memset(rs, 0, sizeof *rs); |
62 | assert(input_bits == 8 || input_bits == 16); | |
63 | assert(output_bits == 8 || output_bits == 16); | |
64 | assert(input_endian == ENDIAN_BIG || input_endian == ENDIAN_LITTLE); | |
65 | assert(output_endian == ENDIAN_BIG || output_endian == ENDIAN_LITTLE); | |
66 | assert(ENDIAN_BIG >= 0 && ENDIAN_BIG < SIGNED); | |
67 | assert(ENDIAN_LITTLE >= 0 && ENDIAN_LITTLE < SIGNED); | |
68 | rs->input_bits = input_bits; | |
69 | rs->input_channels = input_channels; | |
70 | rs->input_rate = input_rate; | |
71 | rs->input_signed = SIGNED * !!input_signed; | |
72 | rs->input_endian = input_endian; | |
73 | rs->output_bits = output_bits; | |
74 | rs->output_channels = output_channels; | |
75 | rs->output_rate = output_rate; | |
76 | rs->output_signed = SIGNED * !!output_signed; | |
77 | rs->output_endian = output_endian; | |
78 | rs->input_bytes_per_sample = (rs->input_bits + 7) / 8; | |
79 | rs->input_bytes_per_frame = rs->input_channels * rs->input_bytes_per_sample; | |
80 | if(rs->input_rate != rs->output_rate) { | |
81 | #if HAVE_SAMPLERATE_H | |
c69ec1ac | 82 | int error_; |
0e8c21de RK |
83 | rs->state = src_new(SRC_SINC_BEST_QUALITY, rs->output_channels, &error_); |
84 | if(!rs->state) | |
443e4c7c | 85 | disorder_fatal(0, "calling src_new: %s", src_strerror(error_)); |
0e8c21de | 86 | #else |
443e4c7c | 87 | disorder_fatal(0, "need to resample audio data but libsamplerate not available"); |
0e8c21de RK |
88 | #endif |
89 | } | |
90 | } | |
91 | ||
92 | /** @brief Destroy a resampler | |
93 | * @param rs Resampler | |
94 | */ | |
95 | void resample_close(struct resampler *rs) { | |
96 | #if HAVE_SAMPLERATE_H | |
97 | if(rs->state) | |
98 | src_delete(rs->state); | |
c69ec1ac RK |
99 | #else |
100 | rs = 0; /* quieten compiler */ | |
0e8c21de RK |
101 | #endif |
102 | } | |
103 | ||
104 | /** @brief Get one sample value and normalize it to [-1,1] | |
105 | * @param rs Resampler state | |
106 | * @param bytes Pointer to input data | |
107 | * @param where Where to store result | |
108 | * @return Number of bytes consumed | |
109 | */ | |
0024bde0 | 110 | static size_t resample_get_sample(const struct resampler *rs, |
0e8c21de RK |
111 | const uint8_t *bytes, |
112 | float *where) { | |
113 | switch(rs->input_bits + rs->input_signed + rs->input_endian) { | |
114 | case 8+ENDIAN_BIG: | |
115 | case 8+ENDIAN_LITTLE: | |
0024bde0 | 116 | *where = (bytes[0] - 128)/ 128.0; |
0e8c21de RK |
117 | return 1; |
118 | case 8+SIGNED+ENDIAN_BIG: | |
119 | case 8+SIGNED+ENDIAN_LITTLE: | |
0024bde0 | 120 | *where = (int8_t)bytes[0] / 128.0; |
0e8c21de RK |
121 | return 1; |
122 | case 16+ENDIAN_BIG: | |
123 | *where = (bytes[0] * 256 + bytes[1] - 32768)/ 32768.0; | |
124 | return 2; | |
125 | break; | |
126 | case 16+ENDIAN_LITTLE: | |
127 | *where = (bytes[1] * 256 + bytes[0] - 32768)/ 32768.0; | |
128 | return 2; | |
129 | break; | |
130 | case 16+SIGNED+ENDIAN_BIG: | |
131 | *where = (int16_t)(bytes[0] * 256 + bytes[1])/ 32768.0; | |
132 | return 2; | |
133 | break; | |
134 | case 16+SIGNED+ENDIAN_LITTLE: | |
135 | *where = (int16_t)(bytes[1] * 256 + bytes[0])/ 32768.0; | |
136 | return 2; | |
137 | break; | |
138 | default: | |
139 | assert(!"unsupported sample format"); | |
140 | } | |
141 | } | |
142 | ||
143 | static inline int clip(int n, int min, int max) { | |
144 | if(n >= min) { | |
145 | if(n <= max) | |
146 | return n; | |
147 | else | |
148 | return max; | |
149 | } else | |
150 | return min; | |
151 | } | |
152 | ||
153 | /** @brief Store one sample value | |
154 | * @param rs Resampler state | |
155 | * @param sample Sample value | |
156 | * @param bytes Where to store it | |
157 | * @return Number of bytes stored | |
158 | * | |
159 | * The value is clipped naively if it will not fit. | |
160 | */ | |
0024bde0 | 161 | static size_t resample_put_sample(const struct resampler *rs, |
0e8c21de RK |
162 | float sample, |
163 | uint8_t *bytes) { | |
164 | unsigned value; | |
0024bde0 | 165 | switch(rs->output_bits + rs->output_signed + rs->output_endian) { |
0e8c21de RK |
166 | case 8+ENDIAN_BIG: |
167 | case 8+ENDIAN_LITTLE: | |
168 | *bytes = clip(sample * 128.0 + 128, 0, 255); | |
169 | return 1; | |
170 | case 8+SIGNED+ENDIAN_BIG: | |
171 | case 8+SIGNED+ENDIAN_LITTLE: | |
172 | *bytes = clip((int)(sample * 128.0), -128, 127); | |
173 | return 1; | |
174 | case 16+ENDIAN_BIG: /* unsigned */ | |
175 | value = clip(sample * 32768.0 + 32768, 0, 65535); | |
176 | *bytes++ = value >> 8; | |
177 | *bytes++ = value; | |
178 | return 2; | |
179 | case 16+ENDIAN_LITTLE: | |
180 | value = clip(sample * 32768.0 + 32768, 0, 65535); | |
181 | *bytes++ = value; | |
182 | *bytes++ = value >> 8; | |
183 | return 2; | |
184 | case 16+SIGNED+ENDIAN_BIG: | |
185 | value = clip(sample * 32768.0, -32768, 32767); | |
186 | *bytes++ = value >> 8; | |
187 | *bytes++ = value; | |
188 | return 2; | |
189 | case 16+SIGNED+ENDIAN_LITTLE: | |
190 | value = clip(sample * 32768.0, -32768, 32767); | |
191 | *bytes++ = value; | |
192 | *bytes++ = value >> 8; | |
193 | return 2; | |
194 | default: | |
195 | assert(!"unsupported sample format"); | |
196 | } | |
197 | } | |
198 | ||
199 | /** @brief Convert input samples to floats | |
200 | * @param rs Resampler state | |
201 | * @param bytes Input bytes | |
202 | * @param nbytes Number of input bytes | |
203 | * @param floats Where to store converted data | |
204 | * | |
205 | * @p floats must be big enough. As well as converting to floats this | |
206 | * also converts to the output's channel format. | |
207 | * | |
208 | * Excess input channels are just discarded. If there are insufficient input | |
209 | * channels the last one is duplicated as often as necessary to make up the | |
210 | * numbers. This is a rather naff heuristic and may be improved in a future | |
211 | * version, but mostly in DisOrder the output is pretty much always stereo and | |
212 | * the input either mono or stereo, so the result isn't actually going to be | |
213 | * too bad. | |
214 | */ | |
0024bde0 | 215 | static void resample_prepare_input(const struct resampler *rs, |
0e8c21de | 216 | const uint8_t *bytes, |
bfdadcc9 | 217 | size_t nframes, |
0e8c21de | 218 | float *floats) { |
0e8c21de RK |
219 | while(nframes > 0) { |
220 | int n; | |
221 | ||
222 | for(n = 0; n < rs->input_channels && n < rs->output_channels; ++n) { | |
223 | bytes += resample_get_sample(rs, bytes, floats); | |
224 | ++floats; | |
225 | } | |
226 | if(n < rs->input_channels) { | |
227 | /* More input channels; discard them */ | |
228 | bytes += (rs->input_channels - n) * rs->input_bytes_per_sample; | |
229 | } else if(n < rs->output_channels) { | |
230 | /* More output channels; duplicate the last input channel */ | |
231 | for(; n < rs->output_channels; ++n) { | |
232 | *floats = floats[-1]; | |
233 | ++floats; | |
234 | } | |
235 | } | |
0024bde0 | 236 | --nframes; |
0e8c21de RK |
237 | } |
238 | } | |
239 | ||
240 | /** @brief Convert between sample formats | |
241 | * @param rs Resampler state | |
242 | * @param bytes Bytes to convert | |
243 | * @param nbytes Number of bytes to convert | |
244 | * @param eof Set an end of input stream | |
245 | * @param converted Called with converted data (possibly more than once) | |
0024bde0 | 246 | * @param cd Passed to @p cd |
0e8c21de RK |
247 | * @return Number of bytes consumed |
248 | */ | |
0024bde0 | 249 | size_t resample_convert(const struct resampler *rs, |
0e8c21de RK |
250 | const uint8_t *bytes, |
251 | size_t nbytes, | |
252 | int eof, | |
253 | void (*converted)(uint8_t *bytes, | |
0024bde0 RK |
254 | size_t nbytes, |
255 | void *cd), | |
256 | void *cd) { | |
0e8c21de RK |
257 | size_t nframesin = nbytes / (rs->input_bytes_per_frame); |
258 | size_t nsamplesout; | |
259 | float *input = xcalloc(nframesin * rs->output_channels, sizeof (float)); | |
260 | float *output = 0; | |
261 | ||
bfdadcc9 | 262 | resample_prepare_input(rs, bytes, nframesin, input); |
0e8c21de RK |
263 | #if HAVE_SAMPLERATE_H |
264 | if(rs->state) { | |
265 | /* A sample-rate conversion must be performed */ | |
266 | SRC_DATA data; | |
c57b3a9e | 267 | memset(&data, 0, sizeof data); |
0e8c21de RK |
268 | /* Compute how many frames are expected to come out. */ |
269 | size_t maxframesout = nframesin * rs->output_rate / rs->input_rate + 1; | |
270 | output = xcalloc(maxframesout * rs->output_channels, sizeof(float)); | |
271 | data.data_in = input; | |
272 | data.data_out = output; | |
273 | data.input_frames = nframesin; | |
274 | data.output_frames = maxframesout; | |
275 | data.end_of_input = eof; | |
929f577e | 276 | data.src_ratio = (double)rs->output_rate / rs->input_rate; |
c57b3a9e RK |
277 | D(("nframesin=%zu maxframesout=%zu eof=%d ratio=%d.%06d", |
278 | nframesin, maxframesout, eof, | |
279 | (int)data.src_ratio, | |
280 | ((int)(data.src_ratio * 1000000) % 1000000))); | |
0e8c21de RK |
281 | int error_ = src_process(rs->state, &data); |
282 | if(error_) | |
443e4c7c | 283 | disorder_fatal(0, "calling src_process: %s", src_strerror(error_)); |
0e8c21de RK |
284 | nframesin = data.input_frames_used; |
285 | nsamplesout = data.output_frames_gen * rs->output_channels; | |
c57b3a9e | 286 | D(("new nframesin=%zu nsamplesout=%zu", nframesin, nsamplesout)); |
0e8c21de RK |
287 | } |
288 | #endif | |
289 | if(!output) { | |
290 | /* No sample-rate conversion required */ | |
291 | output = input; | |
292 | nsamplesout = nframesin * rs->output_channels; | |
293 | } | |
294 | const float *op = output; | |
295 | while(nsamplesout > 0) { | |
296 | uint8_t buffer[4096]; | |
297 | size_t bufused = 0; | |
298 | ||
299 | while(bufused < sizeof buffer && nsamplesout > 0) { | |
300 | bufused += resample_put_sample(rs, *op++, buffer + bufused); | |
301 | --nsamplesout; | |
302 | } | |
0024bde0 | 303 | converted(buffer, bufused, cd); |
0e8c21de RK |
304 | } |
305 | if(output != input) | |
306 | xfree(output); | |
307 | xfree(input); | |
c69ec1ac | 308 | eof = 0; /* quieten compiler */ |
0e8c21de | 309 | /* Report how many input bytes were actually consumed */ |
929f577e | 310 | //fprintf(stderr, "converted %zu frames\n", nframesin); |
0e8c21de RK |
311 | return nframesin * rs->input_bytes_per_frame; |
312 | } | |
313 | ||
314 | /* | |
315 | Local Variables: | |
316 | c-basic-offset:2 | |
317 | comment-column:40 | |
318 | fill-column:79 | |
319 | indent-tabs-mode:nil | |
320 | End: | |
321 | */ |