Cinnamon audio library
Revision | 85891696b14c620679b762b85e4edf76e4ba9dbe (tree) |
---|---|
Zeit | 2019-09-22 12:02:09 |
Autor | AlaskanEmily <emily@alas...> |
Commiter | AlaskanEmily |
Add new sample conversion code, in C this time so that the OSS/BSD backend doesn't need a C++ compiler at all
@@ -0,0 +1,159 @@ | ||
1 | + | |
2 | +/*****************************************************************************/ | |
3 | +/* This file generates the converter core when included. | |
4 | + * It expects IN_TYPE and OUT_TYPE to be defined as types. If COMMON_TYPE is | |
5 | + * defined, then it is used as the intermediate type. Otherwise, we use the | |
6 | + * output type as the intermediate type. | |
7 | + * If CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON is defined, then it is used as a | |
8 | + * macro to convert from the input to the common type. | |
9 | + * If CIN_DSP_CONVERT_SAMPLE_TO_OUT is defined, then it is used as a macro to | |
10 | + * convert from the common to the output type. | |
11 | + * This will undefine IN_TYPE, OUT_TYPE, COMMON_TYPE, | |
12 | + * CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON and | |
13 | + * CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT. | |
14 | + * This is meant just to make it more concise to use. */ | |
15 | +/*****************************************************************************/ | |
16 | + | |
17 | +#ifndef COMMON_TYPE | |
18 | +#define COMMON_TYPE OUT_TYPE | |
19 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) (X) | |
20 | +#endif | |
21 | + | |
22 | +#ifndef CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON | |
23 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) \ | |
24 | + CIN_DSP_CONVERT_SAMPLE_INT_TO_INT(IN_TYPE, COMMON_TYPE, X) | |
25 | +#endif | |
26 | + | |
27 | +#ifndef CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT | |
28 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X)\ | |
29 | + CIN_DSP_CONVERT_SAMPLE_INT_TO_INT(COMMON_TYPE, OUT_TYPE, X) | |
30 | +#endif | |
31 | + | |
32 | +static void CIN_DSP_CONVERT_NAME ( | |
33 | + const unsigned num_in_frames, | |
34 | + const IN_TYPE *in, | |
35 | + OUT_TYPE *out, | |
36 | + const unsigned in_sample_rate, | |
37 | + const unsigned in_num_channels, | |
38 | + const unsigned out_sample_rate, | |
39 | + const unsigned out_num_channels){ | |
40 | + | |
41 | + const unsigned num_common_channels = | |
42 | + (out_num_channels > in_num_channels) ? | |
43 | + in_num_channels : out_num_channels; | |
44 | + | |
45 | + const ldiv_t rate = ldiv(out_sample_rate, in_sample_rate); | |
46 | + int at = 0; | |
47 | + unsigned i, channel; | |
48 | + | |
49 | + for(i = 0; i < num_in_frames; i++){ | |
50 | + unsigned out_frames = 0; | |
51 | + | |
52 | + at -= rate.rem; | |
53 | + if(at < 0){ | |
54 | + at += in_sample_rate; | |
55 | + out_frames++; | |
56 | + } | |
57 | + | |
58 | + /* Check if there are any samples to output. | |
59 | + * This can be false when down-sampling. | |
60 | + */ | |
61 | + out_frames += rate.quot; | |
62 | + if(out_frames != 0){ | |
63 | + | |
64 | + { | |
65 | + /* Hold on to the final channel we processed, so that we can | |
66 | + * paste it over all the remaining channels. | |
67 | + */ | |
68 | + OUT_TYPE last_out; | |
69 | + /* Output the first frame verbatim. This is an optimization for | |
70 | + * downsampling, and also uses a slightly cheaper calculation for | |
71 | + * the first output frame in other cases. | |
72 | + */ | |
73 | + for(channel = 0; channel < num_common_channels; channel++){ | |
74 | + const IN_TYPE in_sample = in[channel]; | |
75 | + const COMMON_TYPE common_sample = | |
76 | + CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(in_sample); | |
77 | + out[channel] = | |
78 | + last_out = | |
79 | + CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(common_sample); | |
80 | + } | |
81 | + | |
82 | + /* Put the last channel we processed over any remaining | |
83 | + * channels. | |
84 | + */ | |
85 | + for(;channel < out_num_channels; channel++){ | |
86 | + out[channel] = last_out; | |
87 | + } | |
88 | + } | |
89 | + | |
90 | + out += out_num_channels; | |
91 | + in += in_num_channels; | |
92 | + | |
93 | + out_frames--; | |
94 | + if(out_frames != 0){ | |
95 | + COMMON_TYPE common_step, common_sample_begin; | |
96 | + /* Process per-channel, since we need to do lerps. */ | |
97 | + for(channel = 0; channel < num_common_channels; channel++){ | |
98 | + /* Get the input samples we will lerp between. */ | |
99 | + const IN_TYPE in_sample_start = in[channel]; | |
100 | + const IN_TYPE in_sample_end = | |
101 | + in[channel + in_num_channels]; | |
102 | + | |
103 | + /* Do a simple lerp between the start and the end in the | |
104 | + * common type. Ideally we would be using the derivative of | |
105 | + * the waveform to lerp smartly, but linear approximation | |
106 | + * works OK and is very simple to implement */ | |
107 | + COMMON_TYPE common_sample = | |
108 | + common_sample_begin = | |
109 | + CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(in_sample_start); | |
110 | + const COMMON_TYPE common_sample_end = | |
111 | + CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(in_sample_end); | |
112 | + | |
113 | + OUT_TYPE *dest = out + channel; /* Will be advanced on each frame */ | |
114 | + unsigned frame = 0; | |
115 | + | |
116 | + /* This is slightly lossy with integer common types and | |
117 | + * small steps. */ | |
118 | + common_step = | |
119 | + (common_sample_end - common_sample) / | |
120 | + ((COMMON_TYPE)out_frames); | |
121 | + | |
122 | + while(1){ | |
123 | + *dest = common_sample; | |
124 | + if(++frame == out_frames) | |
125 | + break; | |
126 | + common_sample += common_step; | |
127 | + dest += out_num_channels; | |
128 | + } | |
129 | + } | |
130 | + | |
131 | + /* Repeat just the stepping for any remaining channels. */ | |
132 | + for(; channel < out_num_channels; channel++){ | |
133 | + OUT_TYPE *dest = out + channel; /* Will be advanced on each frame */ | |
134 | + COMMON_TYPE common_sample = common_sample_begin; | |
135 | + unsigned frame = 0; | |
136 | + while(1){ | |
137 | + *dest = common_sample; | |
138 | + if(++frame == out_frames) | |
139 | + break; | |
140 | + common_sample += common_step; | |
141 | + dest += out_num_channels; | |
142 | + } | |
143 | + } | |
144 | + | |
145 | + in += in_num_channels; | |
146 | + out += out_num_channels * (out_frames + 1); | |
147 | + } | |
148 | + } | |
149 | + } | |
150 | +} | |
151 | + | |
152 | +#undef COMMON_TYPE | |
153 | +#undef OUT_TYPE | |
154 | +#undef IN_TYPE | |
155 | +#undef CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON | |
156 | +#undef CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT | |
157 | +#undef CIN_DSP_CONVERT_NAME | |
158 | + | |
159 | +/*****************************************************************************/ |
@@ -25,19 +25,38 @@ | ||
25 | 25 | #include <assert.h> |
26 | 26 | #include <stdlib.h> |
27 | 27 | #include <stdint.h> |
28 | +#include <string.h> | |
28 | 29 | #include <limits.h> |
29 | 30 | |
30 | 31 | /*****************************************************************************/ |
31 | 32 | |
32 | -static const double one_by_in8 = 0.007874015748031496, | |
33 | - one_by_in16 = 3.051850948e-05, | |
34 | - one_by_in32 = 4.656612875e-10; | |
33 | +#ifdef __GNUC__ | |
34 | +#pragma GCC diagnostic push | |
35 | +#pragma GCC diagnostic ignored "-Wunused-variable" | |
36 | +#pragma GCC diagnostic ignored "-Wunused-const-variable" | |
37 | +#pragma GCC diagnostic ignored "-Wunused-function" | |
38 | +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" | |
39 | +#endif | |
35 | 40 | |
36 | 41 | /*****************************************************************************/ |
37 | 42 | |
38 | -static const float one_by_in8f = 0.007874015748f, | |
39 | - one_by_in16f = 3.051851e-05f, | |
40 | - one_by_in32f = 4.656613e-10f; | |
43 | +static const double | |
44 | + cin_dsp_reciprocal_S8Float64 = 0.007874015748031496, | |
45 | + cin_dsp_reciprocal_S16Float64 = 3.051850948e-05, | |
46 | + cin_dsp_reciprocal_S32Float64 = 4.656612875e-10, | |
47 | + cin_dsp_coefficient_S8Float64 = 127.0, | |
48 | + cin_dsp_coefficient_S16Float64 = 32767.0, | |
49 | + cin_dsp_coefficient_S32Float64 = 2147483647.0; | |
50 | + | |
51 | +/*****************************************************************************/ | |
52 | + | |
53 | +static const float | |
54 | + cin_dsp_reciprocal_S8Float32 = 0.007874015748f, | |
55 | + cin_dsp_reciprocal_S16Float32 = 3.051851e-05f, | |
56 | + cin_dsp_reciprocal_S32Float32 = 4.656613e-10f, | |
57 | + cin_dsp_coefficient_S8Float32 = 127.0f, | |
58 | + cin_dsp_coefficient_S16Float32 = 32767.0f, | |
59 | + cin_dsp_coefficient_S32Float32 = 2147483647.0f; | |
41 | 60 | |
42 | 61 | /*****************************************************************************/ |
43 | 62 |
@@ -68,7 +87,7 @@ static const float one_by_in8f = 0.007874015748f, | ||
68 | 87 | /*****************************************************************************/ |
69 | 88 | |
70 | 89 | #define CIN_DSP_MIX(TYPE) \ |
71 | -void Cin_DSP_Mix ## TYPE(unsigned num_bytes, \ | |
90 | +static void Cin_DSP_Mix ## TYPE(unsigned num_bytes, \ | |
72 | 91 | unsigned num_streams, \ |
73 | 92 | const TYPE **in, \ |
74 | 93 | TYPE *out){ \ |
@@ -212,9 +231,6 @@ unsigned Cin_DSP_ConversionSize(unsigned num_bytes, | ||
212 | 231 | const struct Cin_DSP_MixerFormat *in_format, |
213 | 232 | const struct Cin_DSP_MixerFormat *out_format){ |
214 | 233 | |
215 | - assert(in_format->sample_format < CIN_DSP_FORMAT_NUM_FORMATS); | |
216 | - assert(out_format->sample_format < CIN_DSP_FORMAT_NUM_FORMATS); | |
217 | - | |
218 | 234 | const unsigned in_bytes_per_sample = |
219 | 235 | cin_dsp_bytes_per_sample[in_format->sample_format]; |
220 | 236 | const unsigned out_bytes_per_sample = |
@@ -229,6 +245,9 @@ unsigned Cin_DSP_ConversionSize(unsigned num_bytes, | ||
229 | 245 | unsigned in_rate = in_format->sample_rate; |
230 | 246 | unsigned out_rate = out_format->sample_rate; |
231 | 247 | |
248 | + assert(in_format->sample_format < CIN_DSP_FORMAT_NUM_FORMATS); | |
249 | + assert(out_format->sample_format < CIN_DSP_FORMAT_NUM_FORMATS); | |
250 | + | |
232 | 251 | assert(num_bytes % in_bytes_per_sample == 0); |
233 | 252 | assert(num_samples % in_format->num_channels == 0); |
234 | 253 |
@@ -248,12 +267,204 @@ unsigned Cin_DSP_ConversionSize(unsigned num_bytes, | ||
248 | 267 | |
249 | 268 | /*****************************************************************************/ |
250 | 269 | |
251 | -#define CIN_DSP_CONVERT_SAMPLE(INTYPE, OUTTYPE, IN) \ | |
252 | - (( sizeof(INTYPE) == sizeof(OUTTYPE) ) ? \ | |
253 | - (IN) : \ | |
254 | - ( sizeof(INTYPE) < sizeof(OUTTYPE) ) ? \ | |
255 | - (IN << (sizeof(OUTTYPE) - sizeof(INTYPE))) : \ | |
256 | - (IN >> (sizeof(INTYPE) - sizeof(OUTTYPE))))\ | |
270 | +#define CIN_DSP_CONVERT_SAMPLE_INT_TO_INT(IN_TYPE, OUT_TYPE, IN) \ | |
271 | + (( sizeof(IN_TYPE) == sizeof(OUT_TYPE) ) ? \ | |
272 | + ((OUT_TYPE)(IN)) : \ | |
273 | + ( sizeof(IN_TYPE) < sizeof(OUT_TYPE) ) ? \ | |
274 | + (((OUT_TYPE)(IN)) << (sizeof(OUT_TYPE) - sizeof(IN_TYPE))) : \ | |
275 | + (OUT_TYPE)(IN >> (sizeof(IN_TYPE) - sizeof(OUT_TYPE)))) | |
276 | + | |
277 | +#define CIN_DSP_CONVERT_SAMPLE_INT_TO_FLOAT(IN_TYPE, OUT_TYPE, IN) \ | |
278 | + (((OUT_TYPE)(IN))*cin_dsp_reciprocal_ ## IN_TYPE ## OUT_TYPE) | |
279 | + | |
280 | +#define CIN_DSP_CONVERT_SAMPLE_FLOAT_TO_INT(IN_TYPE, OUT_TYPE, IN) \ | |
281 | + (((OUT_TYPE)(IN))*cin_dsp_coefficient_ ## OUT_TYPE ## IN_TYPE) | |
282 | + | |
283 | +/* Generate the converters */ | |
284 | +#define CIN_DSP_GEN_NAME(A, B) Cin_DSP_Convert ## A ## B | |
285 | + | |
286 | +/*****************************************************************************/ | |
287 | +/* Signed 8-bit converters */ | |
288 | +#define IN_TYPE S8 | |
289 | +#define OUT_TYPE S8 | |
290 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S8, S8) | |
291 | +#include "cin_convert_core.inc" | |
292 | + | |
293 | +#define IN_TYPE S8 | |
294 | +#define OUT_TYPE S16 | |
295 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S8, S16) | |
296 | +#include "cin_convert_core.inc" | |
297 | + | |
298 | +#define IN_TYPE S8 | |
299 | +#define COMMON_TYPE S16 | |
300 | +#define OUT_TYPE S32 | |
301 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S8, S32) | |
302 | +#include "cin_convert_core.inc" | |
303 | + | |
304 | +#define IN_TYPE S8 | |
305 | +#define COMMON_TYPE S16 | |
306 | +#define OUT_TYPE Float32 | |
307 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) \ | |
308 | + CIN_DSP_CONVERT_SAMPLE_INT_TO_FLOAT(S16, Float32, (X)) | |
309 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S8, Float32) | |
310 | +#include "cin_convert_core.inc" | |
311 | + | |
312 | +#define IN_TYPE S8 | |
313 | +#define COMMON_TYPE S16 | |
314 | +#define OUT_TYPE Float64 | |
315 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) \ | |
316 | + CIN_DSP_CONVERT_SAMPLE_INT_TO_FLOAT(S16, Float64, (X)) | |
317 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S8, Float64) | |
318 | +#include "cin_convert_core.inc" | |
319 | + | |
320 | +/*****************************************************************************/ | |
321 | +/* Signed 16-bit converters */ | |
322 | +#define IN_TYPE S16 | |
323 | +#define COMMON_TYPE S16 | |
324 | +#define OUT_TYPE S8 | |
325 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S16, S8) | |
326 | +#include "cin_convert_core.inc" | |
327 | + | |
328 | +#define IN_TYPE S16 | |
329 | +#define OUT_TYPE S16 | |
330 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S16, S16) | |
331 | +#include "cin_convert_core.inc" | |
332 | + | |
333 | +#define IN_TYPE S16 | |
334 | +#define OUT_TYPE S32 | |
335 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S16, S32) | |
336 | +#include "cin_convert_core.inc" | |
337 | + | |
338 | +#define IN_TYPE S16 | |
339 | +#define COMMON_TYPE S16 | |
340 | +#define OUT_TYPE Float32 | |
341 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) \ | |
342 | + CIN_DSP_CONVERT_SAMPLE_INT_TO_FLOAT(S16, Float32, (X)) | |
343 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S16, Float32) | |
344 | +#include "cin_convert_core.inc" | |
345 | + | |
346 | +#define IN_TYPE S16 | |
347 | +#define COMMON_TYPE S16 | |
348 | +#define OUT_TYPE Float64 | |
349 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) \ | |
350 | + CIN_DSP_CONVERT_SAMPLE_INT_TO_FLOAT(S16, Float64, (X)) | |
351 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S16, Float64) | |
352 | +#include "cin_convert_core.inc" | |
353 | + | |
354 | +/*****************************************************************************/ | |
355 | +/* Signed 32-bit converters */ | |
356 | +#define IN_TYPE S32 | |
357 | +#define COMMON_TYPE S32 | |
358 | +#define OUT_TYPE S8 | |
359 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S32, S8) | |
360 | +#include "cin_convert_core.inc" | |
361 | + | |
362 | +#define IN_TYPE S32 | |
363 | +#define COMMON_TYPE S32 | |
364 | +#define OUT_TYPE S16 | |
365 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S32, S16) | |
366 | +#include "cin_convert_core.inc" | |
367 | + | |
368 | +#define IN_TYPE S32 | |
369 | +#define OUT_TYPE S32 | |
370 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S32, S32) | |
371 | +#include "cin_convert_core.inc" | |
372 | + | |
373 | +#define IN_TYPE S32 | |
374 | +#define COMMON_TYPE S32 | |
375 | +#define OUT_TYPE Float32 | |
376 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) \ | |
377 | + CIN_DSP_CONVERT_SAMPLE_INT_TO_FLOAT(S32, Float32, (X)) | |
378 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S32, Float32) | |
379 | +#include "cin_convert_core.inc" | |
380 | + | |
381 | +#define IN_TYPE S32 | |
382 | +#define COMMON_TYPE S32 | |
383 | +#define OUT_TYPE Float64 | |
384 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) \ | |
385 | + CIN_DSP_CONVERT_SAMPLE_INT_TO_FLOAT(S32, Float64, (X)) | |
386 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(S32, Float64) | |
387 | +#include "cin_convert_core.inc" | |
388 | + | |
389 | +/*****************************************************************************/ | |
390 | +/* float converters */ | |
391 | +#define IN_TYPE Float32 | |
392 | +#define COMMON_TYPE Float32 | |
393 | +#define OUT_TYPE S8 | |
394 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) (X) | |
395 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) \ | |
396 | + CIN_DSP_CONVERT_SAMPLE_FLOAT_TO_INT(Float32, S8, (X)) | |
397 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float32, S8) | |
398 | +#include "cin_convert_core.inc" | |
399 | + | |
400 | +#define IN_TYPE Float32 | |
401 | +#define COMMON_TYPE S16 | |
402 | +#define OUT_TYPE S16 | |
403 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) \ | |
404 | + CIN_DSP_CONVERT_SAMPLE_FLOAT_TO_INT(Float32, S16, (X)) | |
405 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float32, S16) | |
406 | +#include "cin_convert_core.inc" | |
407 | + | |
408 | +#define IN_TYPE Float32 | |
409 | +#define COMMON_TYPE Float32 | |
410 | +#define OUT_TYPE S32 | |
411 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) (X) | |
412 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) \ | |
413 | + CIN_DSP_CONVERT_SAMPLE_FLOAT_TO_INT(Float32, S32, (X)) | |
414 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float32, S32) | |
415 | +#include "cin_convert_core.inc" | |
416 | + | |
417 | +#define IN_TYPE Float32 | |
418 | +#define OUT_TYPE Float32 | |
419 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) (X) | |
420 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float32, Float32) | |
421 | +#include "cin_convert_core.inc" | |
422 | + | |
423 | +#define IN_TYPE Float32 | |
424 | +#define OUT_TYPE Float64 | |
425 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) ((Float64)(X)) | |
426 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float32, Float64) | |
427 | +#include "cin_convert_core.inc" | |
428 | + | |
429 | +/*****************************************************************************/ | |
430 | +/* double converters */ | |
431 | +#define IN_TYPE Float64 | |
432 | +#define COMMON_TYPE Float64 | |
433 | +#define OUT_TYPE S8 | |
434 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) (X) | |
435 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) \ | |
436 | + CIN_DSP_CONVERT_SAMPLE_FLOAT_TO_INT(Float64, S8, (X)) | |
437 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float64, S8) | |
438 | +#include "cin_convert_core.inc" | |
439 | + | |
440 | +#define IN_TYPE Float64 | |
441 | +#define COMMON_TYPE S16 | |
442 | +#define OUT_TYPE S16 | |
443 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) \ | |
444 | + CIN_DSP_CONVERT_SAMPLE_FLOAT_TO_INT(Float64, S16, (X)) | |
445 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float64, S16) | |
446 | +#include "cin_convert_core.inc" | |
447 | + | |
448 | +#define IN_TYPE Float64 | |
449 | +#define COMMON_TYPE S32 | |
450 | +#define OUT_TYPE S32 | |
451 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) \ | |
452 | + CIN_DSP_CONVERT_SAMPLE_FLOAT_TO_INT(Float64, S32, (X)) | |
453 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float64, S32) | |
454 | +#include "cin_convert_core.inc" | |
455 | + | |
456 | +#define IN_TYPE Float64 | |
457 | +#define OUT_TYPE Float32 | |
458 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) (X) | |
459 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float64, Float32) | |
460 | +#include "cin_convert_core.inc" | |
461 | + | |
462 | +#define IN_TYPE Float64 | |
463 | +#define OUT_TYPE Float64 | |
464 | +#define CIN_DSP_CONVERT_SAMPLE_IN_TO_COMMON(X) (X) | |
465 | +#define CIN_DSP_CONVERT_SAMPLE_COMMON_TO_OUT(X) (X) | |
466 | +#define CIN_DSP_CONVERT_NAME CIN_DSP_GEN_NAME(Float64, Float64) | |
467 | +#include "cin_convert_core.inc" | |
257 | 468 | |
258 | 469 | /*****************************************************************************/ |
259 | 470 |
@@ -262,20 +473,57 @@ unsigned Cin_DSP_Convert(unsigned num_bytes, | ||
262 | 473 | const void *in_data, |
263 | 474 | const struct Cin_DSP_MixerFormat *out_format, |
264 | 475 | void *out_data){ |
265 | - | |
266 | - const ldiv_t rate = ldiv(out_format->sample_rate, in_format->sample_rate); | |
267 | - | |
268 | - /* HUGE HUGE HACK! */ | |
269 | - const unsigned n = Cin_DSP_ConversionSize(num_bytes, in_format, out_format); | |
270 | - | |
271 | - if(n < num_bytes){ | |
272 | - memcpy(out_data, in_data, n); | |
476 | + | |
477 | +#define CIN_DSP_CONVERT_CALL(IN_TYPE, OUT_TYPE) \ | |
478 | + (num_bytes / sizeof(IN_TYPE))/in_format->num_channels, \ | |
479 | + (const IN_TYPE *)in_data, \ | |
480 | + (OUT_TYPE *)out_data, \ | |
481 | + in_format->sample_rate, \ | |
482 | + in_format->num_channels, \ | |
483 | + out_format->sample_rate, \ | |
484 | + out_format->num_channels | |
485 | + | |
486 | +#define CIN_DSP_CONVERT_1(IN_TYPE) \ | |
487 | + switch(out_format->sample_format){ \ | |
488 | + case CIN_DSP_FORMAT_S8: \ | |
489 | + Cin_DSP_Convert ## IN_TYPE ## S8( \ | |
490 | + CIN_DSP_CONVERT_CALL(IN_TYPE, S8) ); break; \ | |
491 | + case CIN_DSP_FORMAT_S16: \ | |
492 | + Cin_DSP_Convert ## IN_TYPE ## S16( \ | |
493 | + CIN_DSP_CONVERT_CALL(IN_TYPE, S16) ); break; \ | |
494 | + case CIN_DSP_FORMAT_S32: \ | |
495 | + Cin_DSP_Convert ## IN_TYPE ## S32( \ | |
496 | + CIN_DSP_CONVERT_CALL(IN_TYPE, S32) ); break; \ | |
497 | + case CIN_DSP_FORMAT_FLOAT32: \ | |
498 | + Cin_DSP_Convert ## IN_TYPE ## Float32( \ | |
499 | + CIN_DSP_CONVERT_CALL(IN_TYPE, Float32) ); break; \ | |
500 | + case CIN_DSP_FORMAT_FLOAT64: \ | |
501 | + Cin_DSP_Convert ## IN_TYPE ## Float64( \ | |
502 | + CIN_DSP_CONVERT_CALL(IN_TYPE, Float64) ); break; \ | |
503 | + default: \ | |
504 | + return 0; \ | |
273 | 505 | } |
274 | - else{ | |
275 | - memcpy(out_data, in_data, num_bytes); | |
276 | - memset(((unsigned char)out_data) + num_bytes, 0, n - num_bytes); | |
506 | + | |
507 | + switch(in_format->sample_format){ | |
508 | + case CIN_DSP_FORMAT_S8: | |
509 | + CIN_DSP_CONVERT_1(S8); break; | |
510 | + | |
511 | + case CIN_DSP_FORMAT_S16: | |
512 | + CIN_DSP_CONVERT_1(S16); break; | |
513 | + | |
514 | + case CIN_DSP_FORMAT_S32: | |
515 | + CIN_DSP_CONVERT_1(S32); break; | |
516 | + | |
517 | + case CIN_DSP_FORMAT_FLOAT32: | |
518 | + CIN_DSP_CONVERT_1(Float32); break; | |
519 | + | |
520 | + case CIN_DSP_FORMAT_FLOAT64: | |
521 | + CIN_DSP_CONVERT_1(Float64); break; | |
522 | + | |
523 | + default: | |
524 | + return 0; | |
277 | 525 | } |
278 | - return n; | |
526 | + return num_bytes; | |
279 | 527 | } |
280 | 528 | |
281 | 529 | /*****************************************************************************/ |
@@ -286,6 +534,11 @@ unsigned Cin_DSP_Mix(unsigned num_bytes, | ||
286 | 534 | const void **in_data, |
287 | 535 | void *out_data){ |
288 | 536 | |
537 | +#ifdef __GNUC__ | |
538 | +/* For some bizarre reason, GCC says that void ** can't be case to float **? */ | |
539 | +#pragma GCC diagnostic ignored "-Wincompatible-pointer-types" | |
540 | +#endif | |
541 | + | |
289 | 542 | switch(format->sample_format){ |
290 | 543 | case CIN_DSP_FORMAT_S8: |
291 | 544 | Cin_DSP_MixS8(num_bytes, num_streams, in_data, out_data); break; |
@@ -307,3 +560,7 @@ unsigned Cin_DSP_Mix(unsigned num_bytes, | ||
307 | 560 | } |
308 | 561 | return num_bytes; |
309 | 562 | } |
563 | + | |
564 | +#ifdef __GNUC__ | |
565 | +#pragma GCC diagnostic pop | |
566 | +#endif |