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