1 /*
2 This file is part of Deadbeef Player source code
3 http://deadbeef.sourceforge.net
4
5 routines for converting between wave formats and channel configurations
6
7 Copyright (C) 2009-2013 Alexey Yakovenko
8
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any damages
11 arising from the use of this software.
12
13 Permission is granted to anyone to use this software for any purpose,
14 including commercial applications, and to alter it and redistribute it
15 freely, subject to the following restrictions:
16
17 1. The origin of this software must not be misrepresented; you must not
18 claim that you wrote the original software. If you use this software
19 in a product, an acknowledgment in the product documentation would be
20 appreciated but is not required.
21 2. Altered source versions must be plainly marked as such, and must not be
22 misrepresented as being the original software.
23 3. This notice may not be removed or altered from any source distribution.
24
25 Alexey Yakovenko waker@users.sourceforge.net
26 */
27
28 #include <assert.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include "deadbeef.h"
32 #include "premix.h"
33 #include "fastftoi.h"
34
35 #define trace(...) { fprintf(stderr, __VA_ARGS__); }
36 //#define trace(fmt,...)
37
38
39 static inline void
pcm_write_samples_8_to_8(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)40 pcm_write_samples_8_to_8 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
41 for (int s = 0; s < nsamples; s++) {
42 for (int c = 0; c < outputfmt->channels; c++) {
43 *(output + c) = *(input + channelmap[c]);
44 }
45 input += inputfmt->channels;
46 output += outputsamplesize;
47 }
48 }
49
50 static inline void
pcm_write_samples_8_to_16(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)51 pcm_write_samples_8_to_16 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
52 for (int s = 0; s < nsamples; s++) {
53 for (int c = 0; c < outputfmt->channels; c++) {
54 *((int16_t*)(output + 2 * c)) = (int16_t)(*(input + channelmap[c])) << 8;
55 }
56 input += inputfmt->channels;
57 output += outputsamplesize;
58 }
59 }
60
61 static inline void
pcm_write_samples_8_to_24(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)62 pcm_write_samples_8_to_24 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
63 for (int s = 0; s < nsamples; s++) {
64 for (int c = 0; c < outputfmt->channels; c++) {
65 char *out = output + 3 * c;
66 out[0] = 0;
67 out[1] = 0;
68 out[2] = *(input + channelmap[c]);
69 }
70 input += inputfmt->channels;
71 output += outputsamplesize;
72 }
73 }
74
75 static inline void
pcm_write_samples_8_to_32(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)76 pcm_write_samples_8_to_32 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
77 for (int s = 0; s < nsamples; s++) {
78 for (int c = 0; c < outputfmt->channels; c++) {
79 char *out = output + 4 * c;
80 out[0] = 0;
81 out[1] = 0;
82 out[2] = 0;
83 out[3] = *(input + channelmap[c]);
84 }
85 input += inputfmt->channels;
86 output += outputsamplesize;
87 }
88 }
89
90 static inline void
pcm_write_samples_8_to_float(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)91 pcm_write_samples_8_to_float (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
92 for (int s = 0; s < nsamples; s++) {
93 for (int c = 0; c < outputfmt->channels; c++) {
94 float sample = (*(input+channelmap[c])) / (float)0x80;
95 *((float *)(output + 4 * c)) = sample;
96 }
97 input += inputfmt->channels;
98 output += outputsamplesize;
99 }
100 }
101
102 static inline void
pcm_write_samples_16_to_16(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)103 pcm_write_samples_16_to_16 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
104 for (int s = 0; s < nsamples; s++) {
105 for (int c = 0; c < outputfmt->channels; c++) {
106 *((int16_t*)(output + 2 * c)) = *((int16_t*)(input + channelmap[c]*2));
107 }
108 input += 2 * inputfmt->channels;
109 output += outputsamplesize;
110 }
111 }
112
113 static inline void
pcm_write_samples_16_to_8(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)114 pcm_write_samples_16_to_8 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
115 for (int s = 0; s < nsamples; s++) {
116 for (int c = 0; c < outputfmt->channels; c++) {
117 *((int8_t*)(output + c)) = *((int16_t*)(input + channelmap[c]*2)) >> 8;
118 }
119 input += 2 * inputfmt->channels;
120 output += outputsamplesize;
121 }
122 }
123
124 static inline void
pcm_write_samples_16_to_24(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)125 pcm_write_samples_16_to_24 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
126 for (int s = 0; s < nsamples; s++) {
127 for (int c = 0; c < outputfmt->channels; c++) {
128 char *out = output + 3 * c;
129 const char *in = input + channelmap[c]*2;
130 out[0] = 0;
131 out[1] = in[0];
132 out[2] = in[1];
133 }
134 input += 2 * inputfmt->channels;
135 output += outputsamplesize;
136 }
137 }
138
139 static inline void
pcm_write_samples_16_to_32(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)140 pcm_write_samples_16_to_32 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
141 for (int s = 0; s < nsamples; s++) {
142 for (int c = 0; c < outputfmt->channels; c++) {
143 char *out = output + 4 * c;
144 const char *in = input + channelmap[c]*2;
145 out[0] = 0;
146 out[1] = 0;
147 out[2] = in[0];
148 out[3] = in[1];
149 }
150 input += 2 * inputfmt->channels;
151 output += outputsamplesize;
152 }
153 }
154
155 static inline void
pcm_write_samples_16_to_float(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)156 pcm_write_samples_16_to_float (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
157 for (int s = 0; s < nsamples; s++) {
158 for (int c = 0; c < outputfmt->channels; c++) {
159 float sample = (*((int16_t*)(input + channelmap[c]*2))) / (float)0x8000;
160 *((float *)(output + 4 * c)) = sample;
161 }
162 input += 2 * inputfmt->channels;
163 output += outputsamplesize;
164 }
165 }
166
167 static inline void
pcm_write_samples_24_to_8(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)168 pcm_write_samples_24_to_8 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
169 for (int s = 0; s < nsamples; s++) {
170 for (int c = 0; c < outputfmt->channels; c++) {
171 char *out = output + c;
172 *out = (input + channelmap[c] * 3)[2];
173 }
174 input += 3 * inputfmt->channels;
175 output += outputsamplesize;
176 }
177 }
178
179 static inline void
pcm_write_samples_24_to_24(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)180 pcm_write_samples_24_to_24 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
181 for (int s = 0; s < nsamples; s++) {
182 for (int c = 0; c < outputfmt->channels; c++) {
183 char *out = output + 3 * c;
184 const char *in = input + channelmap[c] * 3;
185 out[0] = in[0];
186 out[1] = in[1];
187 out[2] = in[2];
188 }
189 input += 3 * inputfmt->channels;
190 output += outputsamplesize;
191 }
192 }
193
194 static inline void
pcm_write_samples_24_to_32(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)195 pcm_write_samples_24_to_32 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
196 for (int s = 0; s < nsamples; s++) {
197 for (int c = 0; c < outputfmt->channels; c++) {
198 char *out = output + 4 * c;
199 const char *in = input + 3 * channelmap[c];
200 out[0] = 0;
201 out[1] = in[0];
202 out[2] = in[1];
203 out[3] = in[2];
204 }
205 input += inputfmt->channels * 3;
206 output += outputsamplesize;
207 }
208 }
209
210 static inline void
pcm_write_samples_24_to_16(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)211 pcm_write_samples_24_to_16 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
212 for (int s = 0; s < nsamples; s++) {
213 for (int c = 0; c < outputfmt->channels; c++) {
214 char *out = output + 2 * c;
215 const char *in = input + 3 * channelmap[c];
216 out[0] = in[1];
217 out[1] = in[2];
218 }
219 input += inputfmt->channels * 3;
220 output += outputsamplesize;
221 }
222 }
223
224 static inline void
pcm_write_samples_24_to_float(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)225 pcm_write_samples_24_to_float (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
226 for (int s = 0; s < nsamples; s++) {
227 for (int c = 0; c < outputfmt->channels; c++) {
228 float *out = (float *)(output + 4 * c);
229 const char *in = input + 3 * channelmap[c];
230 int32_t sample = ((unsigned char)in[0]) | ((unsigned char)in[1]<<8) | (in[2]<<16);
231 *out = sample / (float)0x800000;
232 }
233 input += inputfmt->channels * 3;
234 output += outputsamplesize;
235 }
236 }
237
238 static inline void
pcm_write_samples_32_to_8(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)239 pcm_write_samples_32_to_8 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
240 for (int s = 0; s < nsamples; s++) {
241 for (int c = 0; c < outputfmt->channels; c++) {
242 int8_t *out = (int8_t*)(output + c);
243 int32_t sample = *((int32_t*)(input + 4 * channelmap[c]));
244 *out = (int8_t)(sample>>24);
245 }
246 input += 4 * inputfmt->channels;
247 output += outputsamplesize;
248 }
249 }
250
251 static inline void
pcm_write_samples_32_to_16(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)252 pcm_write_samples_32_to_16 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
253 for (int s = 0; s < nsamples; s++) {
254 for (int c = 0; c < outputfmt->channels; c++) {
255 int16_t *out = (int16_t*)(output + 2 * c);
256 int32_t sample = *((int32_t*)(input + 4 * channelmap[c]));
257 *out = (int16_t)(sample>>16);
258 }
259 input += 4 * inputfmt->channels;
260 output += outputsamplesize;
261 }
262 }
263
264 static inline void
pcm_write_samples_32_to_24(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)265 pcm_write_samples_32_to_24 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
266 for (int s = 0; s < nsamples; s++) {
267 for (int c = 0; c < outputfmt->channels; c++) {
268 char *out = output + 3 * c;
269 const char *in = input + 4 * channelmap[c];
270 out[0] = in[1];
271 out[1] = in[2];
272 out[2] = in[3];
273 }
274 input += 4 * inputfmt->channels;
275 output += outputsamplesize;
276 }
277 }
278
279 static inline void
pcm_write_samples_32_to_32(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)280 pcm_write_samples_32_to_32 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
281 for (int s = 0; s < nsamples; s++) {
282 for (int c = 0; c < outputfmt->channels; c++) {
283 *((int32_t*)(output + 4 * c)) = *((int32_t*)(input + channelmap[c] * 4));
284 }
285 input += 4 * inputfmt->channels;
286 output += outputsamplesize;
287 }
288 }
289
290
291 static inline void
pcm_write_samples_32_to_float(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)292 pcm_write_samples_32_to_float (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
293 for (int s = 0; s < nsamples; s++) {
294 for (int c = 0; c < outputfmt->channels; c++) {
295 float *out = (float *)(output + 4 * c);
296 int32_t sample = *((int32_t*)(input + channelmap[c] * 4));
297 *out = sample / (float)0x80000000;
298 }
299 input += 4 * inputfmt->channels;
300 output += outputsamplesize;
301 }
302 }
303 static inline void
pcm_write_samples_float_to_8(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)304 pcm_write_samples_float_to_8 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
305 fpu_control ctl;
306 fpu_setround (&ctl);
307 for (int s = 0; s < nsamples; s++) {
308 for (int c = 0; c < outputfmt->channels; c++) {
309 int8_t *out = (int8_t*)(output + c);
310 float sample = *((float*)(input + channelmap[c] * 4));
311 int isample = sample * 0x80;
312 if (isample > 0x7f) {
313 isample = 0x7f;
314 }
315 else if (isample < -0x80) {
316 isample = -0x80;
317 }
318 *out = (int8_t)ftoi (isample);
319 }
320 input += 4 * inputfmt->channels;
321 output += outputsamplesize;
322 }
323 fpu_restore (ctl);
324 }
325
326 static inline void
pcm_write_samples_float_to_16(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)327 pcm_write_samples_float_to_16 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
328 fpu_control ctl;
329 fpu_setround (&ctl);
330 for (int s = 0; s < nsamples; s++) {
331 for (int c = 0; c < outputfmt->channels; c++) {
332 int16_t *out = (int16_t*)(output + 2 * c);
333 float sample = *((float*)(input + 4 * channelmap[c]));
334 int isample = ftoi (sample*0x8000);
335 if (isample > 0x7fff) {
336 isample = 0x7fff;
337 }
338 else if (isample < -0x8000) {
339 isample = -0x8000;
340 }
341 *out = (int16_t)isample;
342 }
343 input += 4 * inputfmt->channels;
344 output += outputsamplesize;
345 }
346 fpu_restore (ctl);
347 }
348
349 static inline void
pcm_write_samples_float_to_24(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)350 pcm_write_samples_float_to_24 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
351 fpu_control ctl;
352 fpu_setround (&ctl);
353 for (int s = 0; s < nsamples; s++) {
354 for (int c = 0; c < outputfmt->channels; c++) {
355 char *out = output + 3 * c;
356 float sample = *((float*)(input + channelmap[c] * 4));
357 int32_t outsample = (int32_t)ftoi (sample * 0x800000);
358 if (outsample >= 0x7fffff) {
359 outsample = 0x7fffff;
360 }
361 else if (outsample < -0x800000) {
362 outsample = -0x800000;
363 }
364 out[0] = (outsample&0x0000ff);
365 out[1] = (outsample&0x00ff00)>>8;
366 out[2] = (outsample&0xff0000)>>16;
367 }
368 input += 4 * inputfmt->channels;
369 output += outputsamplesize;
370 }
371 fpu_restore (ctl);
372 }
373
374
375 static inline void
pcm_write_samples_float_to_32(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int nsamples,int * restrict channelmap,int outputsamplesize)376 pcm_write_samples_float_to_32 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) {
377 for (int s = 0; s < nsamples; s++) {
378 for (int c = 0; c < outputfmt->channels; c++) {
379 float fsample = (*((float*)(input + channelmap[c] * 4)));
380 if (fsample > (float)0x7fffffff/0x80000000) {
381 fsample = (float)0x7fffffff/0x80000000;
382 }
383 else if (fsample < -1.f) {
384 fsample = -1.f;
385 }
386 int32_t sample = fsample * (float)0x80000000;
387 *((int32_t *)(output + 4 * c)) = sample;
388 }
389 input += 4 * inputfmt->channels;
390 output += outputsamplesize;
391 }
392 }
393
394 typedef void (*remap_fn_t) (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize);
395
396
397 remap_fn_t remappers[8][8] = {
398 {
399 pcm_write_samples_8_to_8,
400 pcm_write_samples_8_to_16,
401 pcm_write_samples_8_to_24,
402 pcm_write_samples_8_to_32,
403 NULL,
404 NULL,
405 NULL,
406 pcm_write_samples_8_to_float,
407 },
408 {
409 pcm_write_samples_16_to_8,
410 pcm_write_samples_16_to_16,
411 pcm_write_samples_16_to_24,
412 pcm_write_samples_16_to_32,
413 NULL,
414 NULL,
415 NULL,
416 pcm_write_samples_16_to_float,
417 },
418 {
419 pcm_write_samples_24_to_8,
420 pcm_write_samples_24_to_16,
421 pcm_write_samples_24_to_24,
422 pcm_write_samples_24_to_32,
423 NULL,
424 NULL,
425 NULL,
426 pcm_write_samples_24_to_float,
427 },
428 {
429 pcm_write_samples_32_to_8,
430 pcm_write_samples_32_to_16,
431 pcm_write_samples_32_to_24,
432 pcm_write_samples_32_to_32,
433 NULL,
434 NULL,
435 NULL,
436 pcm_write_samples_32_to_float,
437 },
438 {
439 },
440 {
441 },
442 {
443 },
444 {
445 pcm_write_samples_float_to_8,
446 pcm_write_samples_float_to_16,
447 pcm_write_samples_float_to_24,
448 pcm_write_samples_float_to_32,
449 NULL,
450 NULL,
451 NULL,
452 pcm_write_samples_32_to_32,
453 }
454 };
455
456 int
pcm_convert(const ddb_waveformat_t * restrict inputfmt,const char * restrict input,const ddb_waveformat_t * restrict outputfmt,char * restrict output,int inputsize)457 pcm_convert (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int inputsize) {
458 // calculate output size
459 int inputsamplesize = (inputfmt->bps >> 3) * inputfmt->channels;
460 int outputsamplesize = (outputfmt->bps >> 3) * outputfmt->channels;
461 int nsamples = inputsize / inputsamplesize;
462
463 uint32_t outchannels = 0;
464
465 if (output) {
466 // build channelmap
467 int channelmap[32] = {0};
468 uint32_t inputbitmask = 1;
469 for (int i = 0; i < inputfmt->channels; i++) {
470 // find next input channel
471 while (inputbitmask < 0x80000000 && !(inputfmt->channelmask & inputbitmask)) {
472 inputbitmask <<= 1;
473 }
474 if (!(inputfmt->channelmask & inputbitmask)) {
475 trace ("pcm_convert: channelmask doesn't correspond inputfmt (channels=%d, channelmask=%X)!\n", inputfmt->channels, inputfmt->channelmask);
476 break;
477 }
478 if (outputfmt->channelmask & inputbitmask) {
479 int o = 0;
480 uint32_t outputbitmask = 1;
481 while (outputbitmask < 0x80000000 && (outputfmt->channelmask & outputbitmask) != inputbitmask) {
482 outputbitmask <<= 1;
483 o++;
484 }
485 if (!(inputfmt->channelmask & outputbitmask)) {
486 // no corresponding output channel -- ignore
487 continue;
488 }
489 outchannels |= outputbitmask;
490 channelmap[i] = o; // input channel i going to output channel o
491 //trace ("channelmap[%d]=%d\n", i, o);
492 }
493 inputbitmask <<= 1;
494 }
495
496 if (outchannels != outputfmt->channelmask) {
497 // some of the channels are not used
498 memset (output, 0, nsamples * outputsamplesize);
499 }
500
501 int outidx = ((outputfmt->bps >> 3) - 1) | (outputfmt->is_float << 2);
502 int inidx = ((inputfmt->bps >> 3) - 1) | (inputfmt->is_float << 2);
503 if (remappers[inidx][outidx]) {
504 remappers[inidx][outidx] (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize);
505 }
506 else {
507 trace ("no converter from %d %s to %d %s ([%d][%d])\n", inputfmt->bps, inputfmt->is_float ? "float" : "", outputfmt->bps, outputfmt->is_float ? "float" : "", inidx, outidx);
508 }
509 }
510 return nsamples * outputsamplesize;
511 }
512
513