SDL  2.0
SDL_audiocvt.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22 
23 /* Functions for audio drivers to perform runtime conversion of audio format */
24 
25 #include "SDL_audio.h"
26 #include "SDL_audio_c.h"
27 
28 #include "SDL_assert.h"
29 
30 /* #define DEBUG_CONVERT */
31 
32 /* Effectively mix right and left channels into a single channel */
33 static void SDLCALL
35 {
36  int i;
37  Sint32 sample;
38 
39 #ifdef DEBUG_CONVERT
40  fprintf(stderr, "Converting to mono\n");
41 #endif
42  switch (format & (SDL_AUDIO_MASK_SIGNED |
45  case AUDIO_U8:
46  {
47  Uint8 *src, *dst;
48 
49  src = cvt->buf;
50  dst = cvt->buf;
51  for (i = cvt->len_cvt / 2; i; --i) {
52  sample = src[0] + src[1];
53  *dst = (Uint8) (sample / 2);
54  src += 2;
55  dst += 1;
56  }
57  }
58  break;
59 
60  case AUDIO_S8:
61  {
62  Sint8 *src, *dst;
63 
64  src = (Sint8 *) cvt->buf;
65  dst = (Sint8 *) cvt->buf;
66  for (i = cvt->len_cvt / 2; i; --i) {
67  sample = src[0] + src[1];
68  *dst = (Sint8) (sample / 2);
69  src += 2;
70  dst += 1;
71  }
72  }
73  break;
74 
75  case AUDIO_U16:
76  {
77  Uint8 *src, *dst;
78 
79  src = cvt->buf;
80  dst = cvt->buf;
81  if (SDL_AUDIO_ISBIGENDIAN(format)) {
82  for (i = cvt->len_cvt / 4; i; --i) {
83  sample = (Uint16) ((src[0] << 8) | src[1]) +
84  (Uint16) ((src[2] << 8) | src[3]);
85  sample /= 2;
86  dst[1] = (sample & 0xFF);
87  sample >>= 8;
88  dst[0] = (sample & 0xFF);
89  src += 4;
90  dst += 2;
91  }
92  } else {
93  for (i = cvt->len_cvt / 4; i; --i) {
94  sample = (Uint16) ((src[1] << 8) | src[0]) +
95  (Uint16) ((src[3] << 8) | src[2]);
96  sample /= 2;
97  dst[0] = (sample & 0xFF);
98  sample >>= 8;
99  dst[1] = (sample & 0xFF);
100  src += 4;
101  dst += 2;
102  }
103  }
104  }
105  break;
106 
107  case AUDIO_S16:
108  {
109  Uint8 *src, *dst;
110 
111  src = cvt->buf;
112  dst = cvt->buf;
113  if (SDL_AUDIO_ISBIGENDIAN(format)) {
114  for (i = cvt->len_cvt / 4; i; --i) {
115  sample = (Sint16) ((src[0] << 8) | src[1]) +
116  (Sint16) ((src[2] << 8) | src[3]);
117  sample /= 2;
118  dst[1] = (sample & 0xFF);
119  sample >>= 8;
120  dst[0] = (sample & 0xFF);
121  src += 4;
122  dst += 2;
123  }
124  } else {
125  for (i = cvt->len_cvt / 4; i; --i) {
126  sample = (Sint16) ((src[1] << 8) | src[0]) +
127  (Sint16) ((src[3] << 8) | src[2]);
128  sample /= 2;
129  dst[0] = (sample & 0xFF);
130  sample >>= 8;
131  dst[1] = (sample & 0xFF);
132  src += 4;
133  dst += 2;
134  }
135  }
136  }
137  break;
138 
139  case AUDIO_S32:
140  {
141  const Uint32 *src = (const Uint32 *) cvt->buf;
142  Uint32 *dst = (Uint32 *) cvt->buf;
143  if (SDL_AUDIO_ISBIGENDIAN(format)) {
144  for (i = cvt->len_cvt / 8; i; --i, src += 2) {
145  const Sint64 added =
146  (((Sint64) (Sint32) SDL_SwapBE32(src[0])) +
147  ((Sint64) (Sint32) SDL_SwapBE32(src[1])));
148  *(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added / 2)));
149  }
150  } else {
151  for (i = cvt->len_cvt / 8; i; --i, src += 2) {
152  const Sint64 added =
153  (((Sint64) (Sint32) SDL_SwapLE32(src[0])) +
154  ((Sint64) (Sint32) SDL_SwapLE32(src[1])));
155  *(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added / 2)));
156  }
157  }
158  }
159  break;
160 
161  case AUDIO_F32:
162  {
163  const float *src = (const float *) cvt->buf;
164  float *dst = (float *) cvt->buf;
165  if (SDL_AUDIO_ISBIGENDIAN(format)) {
166  for (i = cvt->len_cvt / 8; i; --i, src += 2) {
167  const float src1 = SDL_SwapFloatBE(src[0]);
168  const float src2 = SDL_SwapFloatBE(src[1]);
169  const double added = ((double) src1) + ((double) src2);
170  const float halved = (float) (added * 0.5);
171  *(dst++) = SDL_SwapFloatBE(halved);
172  }
173  } else {
174  for (i = cvt->len_cvt / 8; i; --i, src += 2) {
175  const float src1 = SDL_SwapFloatLE(src[0]);
176  const float src2 = SDL_SwapFloatLE(src[1]);
177  const double added = ((double) src1) + ((double) src2);
178  const float halved = (float) (added * 0.5);
179  *(dst++) = SDL_SwapFloatLE(halved);
180  }
181  }
182  }
183  break;
184  }
185 
186  cvt->len_cvt /= 2;
187  if (cvt->filters[++cvt->filter_index]) {
188  cvt->filters[cvt->filter_index] (cvt, format);
189  }
190 }
191 
192 
193 /* Discard top 4 channels */
194 static void SDLCALL
196 {
197  int i;
198 
199 #ifdef DEBUG_CONVERT
200  fprintf(stderr, "Converting down from 6 channels to stereo\n");
201 #endif
202 
203 #define strip_chans_6_to_2(type) \
204  { \
205  const type *src = (const type *) cvt->buf; \
206  type *dst = (type *) cvt->buf; \
207  for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
208  dst[0] = src[0]; \
209  dst[1] = src[1]; \
210  src += 6; \
211  dst += 2; \
212  } \
213  }
214 
215  /* this function only cares about typesize, and data as a block of bits. */
216  switch (SDL_AUDIO_BITSIZE(format)) {
217  case 8:
219  break;
220  case 16:
222  break;
223  case 32:
225  break;
226  }
227 
228 #undef strip_chans_6_to_2
229 
230  cvt->len_cvt /= 3;
231  if (cvt->filters[++cvt->filter_index]) {
232  cvt->filters[cvt->filter_index] (cvt, format);
233  }
234 }
235 
236 
237 /* Discard top 2 channels of 6 */
238 static void SDLCALL
240 {
241  int i;
242 
243 #ifdef DEBUG_CONVERT
244  fprintf(stderr, "Converting 6 down to quad\n");
245 #endif
246 
247 #define strip_chans_6_to_4(type) \
248  { \
249  const type *src = (const type *) cvt->buf; \
250  type *dst = (type *) cvt->buf; \
251  for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
252  dst[0] = src[0]; \
253  dst[1] = src[1]; \
254  dst[2] = src[2]; \
255  dst[3] = src[3]; \
256  src += 6; \
257  dst += 4; \
258  } \
259  }
260 
261  /* this function only cares about typesize, and data as a block of bits. */
262  switch (SDL_AUDIO_BITSIZE(format)) {
263  case 8:
265  break;
266  case 16:
268  break;
269  case 32:
271  break;
272  }
273 
274 #undef strip_chans_6_to_4
275 
276  cvt->len_cvt /= 6;
277  cvt->len_cvt *= 4;
278  if (cvt->filters[++cvt->filter_index]) {
279  cvt->filters[cvt->filter_index] (cvt, format);
280  }
281 }
282 
283 /* Duplicate a mono channel to both stereo channels */
284 static void SDLCALL
286 {
287  int i;
288 
289 #ifdef DEBUG_CONVERT
290  fprintf(stderr, "Converting to stereo\n");
291 #endif
292 
293 #define dup_chans_1_to_2(type) \
294  { \
295  const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
296  type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \
297  for (i = cvt->len_cvt / sizeof(type); i; --i) { \
298  src -= 1; \
299  dst -= 2; \
300  dst[0] = dst[1] = *src; \
301  } \
302  }
303 
304  /* this function only cares about typesize, and data as a block of bits. */
305  switch (SDL_AUDIO_BITSIZE(format)) {
306  case 8:
308  break;
309  case 16:
311  break;
312  case 32:
314  break;
315  }
316 
317 #undef dup_chans_1_to_2
318 
319  cvt->len_cvt *= 2;
320  if (cvt->filters[++cvt->filter_index]) {
321  cvt->filters[cvt->filter_index] (cvt, format);
322  }
323 }
324 
325 
326 /* Duplicate a stereo channel to a pseudo-5.1 stream */
327 static void SDLCALL
329 {
330  int i;
331 
332 #ifdef DEBUG_CONVERT
333  fprintf(stderr, "Converting stereo to surround\n");
334 #endif
335 
336  switch (format & (SDL_AUDIO_MASK_SIGNED |
339  case AUDIO_U8:
340  {
341  Uint8 *src, *dst, lf, rf, ce;
342 
343  src = (Uint8 *) (cvt->buf + cvt->len_cvt);
344  dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
345  for (i = cvt->len_cvt; i; --i) {
346  dst -= 6;
347  src -= 2;
348  lf = src[0];
349  rf = src[1];
350  ce = (lf / 2) + (rf / 2);
351  dst[0] = lf;
352  dst[1] = rf;
353  dst[2] = lf - ce;
354  dst[3] = rf - ce;
355  dst[4] = ce;
356  dst[5] = ce;
357  }
358  }
359  break;
360 
361  case AUDIO_S8:
362  {
363  Sint8 *src, *dst, lf, rf, ce;
364 
365  src = (Sint8 *) cvt->buf + cvt->len_cvt;
366  dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
367  for (i = cvt->len_cvt; i; --i) {
368  dst -= 6;
369  src -= 2;
370  lf = src[0];
371  rf = src[1];
372  ce = (lf / 2) + (rf / 2);
373  dst[0] = lf;
374  dst[1] = rf;
375  dst[2] = lf - ce;
376  dst[3] = rf - ce;
377  dst[4] = ce;
378  dst[5] = ce;
379  }
380  }
381  break;
382 
383  case AUDIO_U16:
384  {
385  Uint8 *src, *dst;
386  Uint16 lf, rf, ce, lr, rr;
387 
388  src = cvt->buf + cvt->len_cvt;
389  dst = cvt->buf + cvt->len_cvt * 3;
390 
391  if (SDL_AUDIO_ISBIGENDIAN(format)) {
392  for (i = cvt->len_cvt / 4; i; --i) {
393  dst -= 12;
394  src -= 4;
395  lf = (Uint16) ((src[0] << 8) | src[1]);
396  rf = (Uint16) ((src[2] << 8) | src[3]);
397  ce = (lf / 2) + (rf / 2);
398  rr = lf - ce;
399  lr = rf - ce;
400  dst[1] = (lf & 0xFF);
401  dst[0] = ((lf >> 8) & 0xFF);
402  dst[3] = (rf & 0xFF);
403  dst[2] = ((rf >> 8) & 0xFF);
404 
405  dst[1 + 4] = (lr & 0xFF);
406  dst[0 + 4] = ((lr >> 8) & 0xFF);
407  dst[3 + 4] = (rr & 0xFF);
408  dst[2 + 4] = ((rr >> 8) & 0xFF);
409 
410  dst[1 + 8] = (ce & 0xFF);
411  dst[0 + 8] = ((ce >> 8) & 0xFF);
412  dst[3 + 8] = (ce & 0xFF);
413  dst[2 + 8] = ((ce >> 8) & 0xFF);
414  }
415  } else {
416  for (i = cvt->len_cvt / 4; i; --i) {
417  dst -= 12;
418  src -= 4;
419  lf = (Uint16) ((src[1] << 8) | src[0]);
420  rf = (Uint16) ((src[3] << 8) | src[2]);
421  ce = (lf / 2) + (rf / 2);
422  rr = lf - ce;
423  lr = rf - ce;
424  dst[0] = (lf & 0xFF);
425  dst[1] = ((lf >> 8) & 0xFF);
426  dst[2] = (rf & 0xFF);
427  dst[3] = ((rf >> 8) & 0xFF);
428 
429  dst[0 + 4] = (lr & 0xFF);
430  dst[1 + 4] = ((lr >> 8) & 0xFF);
431  dst[2 + 4] = (rr & 0xFF);
432  dst[3 + 4] = ((rr >> 8) & 0xFF);
433 
434  dst[0 + 8] = (ce & 0xFF);
435  dst[1 + 8] = ((ce >> 8) & 0xFF);
436  dst[2 + 8] = (ce & 0xFF);
437  dst[3 + 8] = ((ce >> 8) & 0xFF);
438  }
439  }
440  }
441  break;
442 
443  case AUDIO_S16:
444  {
445  Uint8 *src, *dst;
446  Sint16 lf, rf, ce, lr, rr;
447 
448  src = cvt->buf + cvt->len_cvt;
449  dst = cvt->buf + cvt->len_cvt * 3;
450 
451  if (SDL_AUDIO_ISBIGENDIAN(format)) {
452  for (i = cvt->len_cvt / 4; i; --i) {
453  dst -= 12;
454  src -= 4;
455  lf = (Sint16) ((src[0] << 8) | src[1]);
456  rf = (Sint16) ((src[2] << 8) | src[3]);
457  ce = (lf / 2) + (rf / 2);
458  rr = lf - ce;
459  lr = rf - ce;
460  dst[1] = (lf & 0xFF);
461  dst[0] = ((lf >> 8) & 0xFF);
462  dst[3] = (rf & 0xFF);
463  dst[2] = ((rf >> 8) & 0xFF);
464 
465  dst[1 + 4] = (lr & 0xFF);
466  dst[0 + 4] = ((lr >> 8) & 0xFF);
467  dst[3 + 4] = (rr & 0xFF);
468  dst[2 + 4] = ((rr >> 8) & 0xFF);
469 
470  dst[1 + 8] = (ce & 0xFF);
471  dst[0 + 8] = ((ce >> 8) & 0xFF);
472  dst[3 + 8] = (ce & 0xFF);
473  dst[2 + 8] = ((ce >> 8) & 0xFF);
474  }
475  } else {
476  for (i = cvt->len_cvt / 4; i; --i) {
477  dst -= 12;
478  src -= 4;
479  lf = (Sint16) ((src[1] << 8) | src[0]);
480  rf = (Sint16) ((src[3] << 8) | src[2]);
481  ce = (lf / 2) + (rf / 2);
482  rr = lf - ce;
483  lr = rf - ce;
484  dst[0] = (lf & 0xFF);
485  dst[1] = ((lf >> 8) & 0xFF);
486  dst[2] = (rf & 0xFF);
487  dst[3] = ((rf >> 8) & 0xFF);
488 
489  dst[0 + 4] = (lr & 0xFF);
490  dst[1 + 4] = ((lr >> 8) & 0xFF);
491  dst[2 + 4] = (rr & 0xFF);
492  dst[3 + 4] = ((rr >> 8) & 0xFF);
493 
494  dst[0 + 8] = (ce & 0xFF);
495  dst[1 + 8] = ((ce >> 8) & 0xFF);
496  dst[2 + 8] = (ce & 0xFF);
497  dst[3 + 8] = ((ce >> 8) & 0xFF);
498  }
499  }
500  }
501  break;
502 
503  case AUDIO_S32:
504  {
505  Sint32 lf, rf, ce;
506  const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
507  Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 3);
508 
509  if (SDL_AUDIO_ISBIGENDIAN(format)) {
510  for (i = cvt->len_cvt / 8; i; --i) {
511  dst -= 6;
512  src -= 2;
513  lf = (Sint32) SDL_SwapBE32(src[0]);
514  rf = (Sint32) SDL_SwapBE32(src[1]);
515  ce = (lf / 2) + (rf / 2);
516  dst[0] = SDL_SwapBE32((Uint32) lf);
517  dst[1] = SDL_SwapBE32((Uint32) rf);
518  dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
519  dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
520  dst[4] = SDL_SwapBE32((Uint32) ce);
521  dst[5] = SDL_SwapBE32((Uint32) ce);
522  }
523  } else {
524  for (i = cvt->len_cvt / 8; i; --i) {
525  dst -= 6;
526  src -= 2;
527  lf = (Sint32) SDL_SwapLE32(src[0]);
528  rf = (Sint32) SDL_SwapLE32(src[1]);
529  ce = (lf / 2) + (rf / 2);
530  dst[0] = src[0];
531  dst[1] = src[1];
532  dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
533  dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
534  dst[4] = SDL_SwapLE32((Uint32) ce);
535  dst[5] = SDL_SwapLE32((Uint32) ce);
536  }
537  }
538  }
539  break;
540 
541  case AUDIO_F32:
542  {
543  float lf, rf, ce;
544  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
545  float *dst = (float *) (cvt->buf + cvt->len_cvt * 3);
546 
547  if (SDL_AUDIO_ISBIGENDIAN(format)) {
548  for (i = cvt->len_cvt / 8; i; --i) {
549  dst -= 6;
550  src -= 2;
551  lf = SDL_SwapFloatBE(src[0]);
552  rf = SDL_SwapFloatBE(src[1]);
553  ce = (lf * 0.5f) + (rf * 0.5f);
554  dst[0] = src[0];
555  dst[1] = src[1];
556  dst[2] = SDL_SwapFloatBE(lf - ce);
557  dst[3] = SDL_SwapFloatBE(rf - ce);
558  dst[4] = dst[5] = SDL_SwapFloatBE(ce);
559  }
560  } else {
561  for (i = cvt->len_cvt / 8; i; --i) {
562  dst -= 6;
563  src -= 2;
564  lf = SDL_SwapFloatLE(src[0]);
565  rf = SDL_SwapFloatLE(src[1]);
566  ce = (lf * 0.5f) + (rf * 0.5f);
567  dst[0] = src[0];
568  dst[1] = src[1];
569  dst[2] = SDL_SwapFloatLE(lf - ce);
570  dst[3] = SDL_SwapFloatLE(rf - ce);
571  dst[4] = dst[5] = SDL_SwapFloatLE(ce);
572  }
573  }
574  }
575  break;
576 
577  }
578  cvt->len_cvt *= 3;
579  if (cvt->filters[++cvt->filter_index]) {
580  cvt->filters[cvt->filter_index] (cvt, format);
581  }
582 }
583 
584 
585 /* Duplicate a stereo channel to a pseudo-4.0 stream */
586 static void SDLCALL
588 {
589  int i;
590 
591 #ifdef DEBUG_CONVERT
592  fprintf(stderr, "Converting stereo to quad\n");
593 #endif
594 
595  switch (format & (SDL_AUDIO_MASK_SIGNED |
598  case AUDIO_U8:
599  {
600  Uint8 *src, *dst, lf, rf, ce;
601 
602  src = (Uint8 *) (cvt->buf + cvt->len_cvt);
603  dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
604  for (i = cvt->len_cvt; i; --i) {
605  dst -= 4;
606  src -= 2;
607  lf = src[0];
608  rf = src[1];
609  ce = (lf / 2) + (rf / 2);
610  dst[0] = lf;
611  dst[1] = rf;
612  dst[2] = lf - ce;
613  dst[3] = rf - ce;
614  }
615  }
616  break;
617 
618  case AUDIO_S8:
619  {
620  Sint8 *src, *dst, lf, rf, ce;
621 
622  src = (Sint8 *) cvt->buf + cvt->len_cvt;
623  dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
624  for (i = cvt->len_cvt; i; --i) {
625  dst -= 4;
626  src -= 2;
627  lf = src[0];
628  rf = src[1];
629  ce = (lf / 2) + (rf / 2);
630  dst[0] = lf;
631  dst[1] = rf;
632  dst[2] = lf - ce;
633  dst[3] = rf - ce;
634  }
635  }
636  break;
637 
638  case AUDIO_U16:
639  {
640  Uint8 *src, *dst;
641  Uint16 lf, rf, ce, lr, rr;
642 
643  src = cvt->buf + cvt->len_cvt;
644  dst = cvt->buf + cvt->len_cvt * 2;
645 
646  if (SDL_AUDIO_ISBIGENDIAN(format)) {
647  for (i = cvt->len_cvt / 4; i; --i) {
648  dst -= 8;
649  src -= 4;
650  lf = (Uint16) ((src[0] << 8) | src[1]);
651  rf = (Uint16) ((src[2] << 8) | src[3]);
652  ce = (lf / 2) + (rf / 2);
653  rr = lf - ce;
654  lr = rf - ce;
655  dst[1] = (lf & 0xFF);
656  dst[0] = ((lf >> 8) & 0xFF);
657  dst[3] = (rf & 0xFF);
658  dst[2] = ((rf >> 8) & 0xFF);
659 
660  dst[1 + 4] = (lr & 0xFF);
661  dst[0 + 4] = ((lr >> 8) & 0xFF);
662  dst[3 + 4] = (rr & 0xFF);
663  dst[2 + 4] = ((rr >> 8) & 0xFF);
664  }
665  } else {
666  for (i = cvt->len_cvt / 4; i; --i) {
667  dst -= 8;
668  src -= 4;
669  lf = (Uint16) ((src[1] << 8) | src[0]);
670  rf = (Uint16) ((src[3] << 8) | src[2]);
671  ce = (lf / 2) + (rf / 2);
672  rr = lf - ce;
673  lr = rf - ce;
674  dst[0] = (lf & 0xFF);
675  dst[1] = ((lf >> 8) & 0xFF);
676  dst[2] = (rf & 0xFF);
677  dst[3] = ((rf >> 8) & 0xFF);
678 
679  dst[0 + 4] = (lr & 0xFF);
680  dst[1 + 4] = ((lr >> 8) & 0xFF);
681  dst[2 + 4] = (rr & 0xFF);
682  dst[3 + 4] = ((rr >> 8) & 0xFF);
683  }
684  }
685  }
686  break;
687 
688  case AUDIO_S16:
689  {
690  Uint8 *src, *dst;
691  Sint16 lf, rf, ce, lr, rr;
692 
693  src = cvt->buf + cvt->len_cvt;
694  dst = cvt->buf + cvt->len_cvt * 2;
695 
696  if (SDL_AUDIO_ISBIGENDIAN(format)) {
697  for (i = cvt->len_cvt / 4; i; --i) {
698  dst -= 8;
699  src -= 4;
700  lf = (Sint16) ((src[0] << 8) | src[1]);
701  rf = (Sint16) ((src[2] << 8) | src[3]);
702  ce = (lf / 2) + (rf / 2);
703  rr = lf - ce;
704  lr = rf - ce;
705  dst[1] = (lf & 0xFF);
706  dst[0] = ((lf >> 8) & 0xFF);
707  dst[3] = (rf & 0xFF);
708  dst[2] = ((rf >> 8) & 0xFF);
709 
710  dst[1 + 4] = (lr & 0xFF);
711  dst[0 + 4] = ((lr >> 8) & 0xFF);
712  dst[3 + 4] = (rr & 0xFF);
713  dst[2 + 4] = ((rr >> 8) & 0xFF);
714  }
715  } else {
716  for (i = cvt->len_cvt / 4; i; --i) {
717  dst -= 8;
718  src -= 4;
719  lf = (Sint16) ((src[1] << 8) | src[0]);
720  rf = (Sint16) ((src[3] << 8) | src[2]);
721  ce = (lf / 2) + (rf / 2);
722  rr = lf - ce;
723  lr = rf - ce;
724  dst[0] = (lf & 0xFF);
725  dst[1] = ((lf >> 8) & 0xFF);
726  dst[2] = (rf & 0xFF);
727  dst[3] = ((rf >> 8) & 0xFF);
728 
729  dst[0 + 4] = (lr & 0xFF);
730  dst[1 + 4] = ((lr >> 8) & 0xFF);
731  dst[2 + 4] = (rr & 0xFF);
732  dst[3 + 4] = ((rr >> 8) & 0xFF);
733  }
734  }
735  }
736  break;
737 
738  case AUDIO_S32:
739  {
740  const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
741  Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2);
742  Sint32 lf, rf, ce;
743 
744  if (SDL_AUDIO_ISBIGENDIAN(format)) {
745  for (i = cvt->len_cvt / 8; i; --i) {
746  dst -= 4;
747  src -= 2;
748  lf = (Sint32) SDL_SwapBE32(src[0]);
749  rf = (Sint32) SDL_SwapBE32(src[1]);
750  ce = (lf / 2) + (rf / 2);
751  dst[0] = src[0];
752  dst[1] = src[1];
753  dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
754  dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
755  }
756  } else {
757  for (i = cvt->len_cvt / 8; i; --i) {
758  dst -= 4;
759  src -= 2;
760  lf = (Sint32) SDL_SwapLE32(src[0]);
761  rf = (Sint32) SDL_SwapLE32(src[1]);
762  ce = (lf / 2) + (rf / 2);
763  dst[0] = src[0];
764  dst[1] = src[1];
765  dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
766  dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
767  }
768  }
769  }
770  break;
771 
772  case AUDIO_F32:
773  {
774  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
775  float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
776  float lf, rf, ce;
777 
778  if (SDL_AUDIO_ISBIGENDIAN(format)) {
779  for (i = cvt->len_cvt / 8; i; --i) {
780  dst -= 4;
781  src -= 2;
782  lf = SDL_SwapFloatBE(src[0]);
783  rf = SDL_SwapFloatBE(src[1]);
784  ce = (lf / 2) + (rf / 2);
785  dst[0] = src[0];
786  dst[1] = src[1];
787  dst[2] = SDL_SwapFloatBE(lf - ce);
788  dst[3] = SDL_SwapFloatBE(rf - ce);
789  }
790  } else {
791  for (i = cvt->len_cvt / 8; i; --i) {
792  dst -= 4;
793  src -= 2;
794  lf = SDL_SwapFloatLE(src[0]);
795  rf = SDL_SwapFloatLE(src[1]);
796  ce = (lf / 2) + (rf / 2);
797  dst[0] = src[0];
798  dst[1] = src[1];
799  dst[2] = SDL_SwapFloatLE(lf - ce);
800  dst[3] = SDL_SwapFloatLE(rf - ce);
801  }
802  }
803  }
804  break;
805  }
806  cvt->len_cvt *= 2;
807  if (cvt->filters[++cvt->filter_index]) {
808  cvt->filters[cvt->filter_index] (cvt, format);
809  }
810 }
811 
812 
813 int
815 {
816  /* !!! FIXME: (cvt) should be const; stack-copy it here. */
817  /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
818 
819  /* Make sure there's data to convert */
820  if (cvt->buf == NULL) {
821  SDL_SetError("No buffer allocated for conversion");
822  return (-1);
823  }
824  /* Return okay if no conversion is necessary */
825  cvt->len_cvt = cvt->len;
826  if (cvt->filters[0] == NULL) {
827  return (0);
828  }
829 
830  /* Set up the conversion and go! */
831  cvt->filter_index = 0;
832  cvt->filters[0] (cvt, cvt->src_format);
833  return (0);
834 }
835 
836 
837 static SDL_AudioFilter
839 {
840  /*
841  * Fill in any future conversions that are specialized to a
842  * processor, platform, compiler, or library here.
843  */
844 
845  return NULL; /* no specialized converter code available. */
846 }
847 
848 
849 /*
850  * Find a converter between two data types. We try to select a hand-tuned
851  * asm/vectorized/optimized function first, and then fallback to an
852  * autogenerated function that is customized to convert between two
853  * specific data types.
854  */
855 static int
857  SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
858 {
859  if (src_fmt != dst_fmt) {
860  const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
861  const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
862  SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
863 
864  /* No hand-tuned converter? Try the autogenerated ones. */
865  if (filter == NULL) {
866  int i;
867  for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
869  if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
870  filter = filt->filter;
871  break;
872  }
873  }
874 
875  if (filter == NULL) {
876  SDL_SetError("No conversion available for these formats");
877  return -1;
878  }
879  }
880 
881  /* Update (cvt) with filter details... */
882  cvt->filters[cvt->filter_index++] = filter;
883  if (src_bitsize < dst_bitsize) {
884  const int mult = (dst_bitsize / src_bitsize);
885  cvt->len_mult *= mult;
886  cvt->len_ratio *= mult;
887  } else if (src_bitsize > dst_bitsize) {
888  cvt->len_ratio /= (src_bitsize / dst_bitsize);
889  }
890 
891  return 1; /* added a converter. */
892  }
893 
894  return 0; /* no conversion necessary. */
895 }
896 
897 
898 static SDL_AudioFilter
899 SDL_HandTunedResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
900  int src_rate, int dst_rate)
901 {
902  /*
903  * Fill in any future conversions that are specialized to a
904  * processor, platform, compiler, or library here.
905  */
906 
907  return NULL; /* no specialized converter code available. */
908 }
909 
910 static int
911 SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
912 {
913  int retval = 0;
914 
915  /* If we only built with the arbitrary resamplers, ignore multiples. */
916 #if !LESS_RESAMPLERS
917  int lo, hi;
918  int div;
919 
920  SDL_assert(src_rate != 0);
921  SDL_assert(dst_rate != 0);
922  SDL_assert(src_rate != dst_rate);
923 
924  if (src_rate < dst_rate) {
925  lo = src_rate;
926  hi = dst_rate;
927  } else {
928  lo = dst_rate;
929  hi = src_rate;
930  }
931 
932  /* zero means "not a supported multiple" ... we only do 2x and 4x. */
933  if ((hi % lo) != 0)
934  return 0; /* not a multiple. */
935 
936  div = hi / lo;
937  retval = ((div == 2) || (div == 4)) ? div : 0;
938 #endif
939 
940  return retval;
941 }
942 
943 static int
944 SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
945  int src_rate, int dst_rate)
946 {
947  if (src_rate != dst_rate) {
948  SDL_AudioFilter filter = SDL_HandTunedResampleCVT(cvt, dst_channels,
949  src_rate, dst_rate);
950 
951  /* No hand-tuned converter? Try the autogenerated ones. */
952  if (filter == NULL) {
953  int i;
954  const int upsample = (src_rate < dst_rate) ? 1 : 0;
955  const int multiple =
956  SDL_FindFrequencyMultiple(src_rate, dst_rate);
957 
958  for (i = 0; sdl_audio_rate_filters[i].filter != NULL; i++) {
960  if ((filt->fmt == cvt->dst_format) &&
961  (filt->channels == dst_channels) &&
962  (filt->upsample == upsample) &&
963  (filt->multiple == multiple)) {
964  filter = filt->filter;
965  break;
966  }
967  }
968 
969  if (filter == NULL) {
970  SDL_SetError("No conversion available for these rates");
971  return -1;
972  }
973  }
974 
975  /* Update (cvt) with filter details... */
976  cvt->filters[cvt->filter_index++] = filter;
977  if (src_rate < dst_rate) {
978  const double mult = ((double) dst_rate) / ((double) src_rate);
979  cvt->len_mult *= (int) SDL_ceil(mult);
980  cvt->len_ratio *= mult;
981  } else {
982  cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
983  }
984 
985  return 1; /* added a converter. */
986  }
987 
988  return 0; /* no conversion necessary. */
989 }
990 
991 
992 /* Creates a set of audio filters to convert from one format to another.
993  Returns -1 if the format conversion is not supported, 0 if there's
994  no conversion needed, or 1 if the audio filter is set up.
995 */
996 
997 int
999  SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
1000  SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
1001 {
1002  /*
1003  * !!! FIXME: reorder filters based on which grow/shrink the buffer.
1004  * !!! FIXME: ideally, we should do everything that shrinks the buffer
1005  * !!! FIXME: first, so we don't have to process as many bytes in a given
1006  * !!! FIXME: filter and abuse the CPU cache less. This might not be as
1007  * !!! FIXME: good in practice as it sounds in theory, though.
1008  */
1009 
1010  /* Sanity check target pointer */
1011  if (cvt == NULL) {
1012  return SDL_InvalidParamError("cvt");
1013  }
1014 
1015  /* there are no unsigned types over 16 bits, so catch this up front. */
1016  if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
1017  return SDL_SetError("Invalid source format");
1018  }
1019  if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
1020  return SDL_SetError("Invalid destination format");
1021  }
1022 
1023  /* prevent possible divisions by zero, etc. */
1024  if ((src_channels == 0) || (dst_channels == 0)) {
1025  return SDL_SetError("Source or destination channels is zero");
1026  }
1027  if ((src_rate == 0) || (dst_rate == 0)) {
1028  return SDL_SetError("Source or destination rate is zero");
1029  }
1030 #ifdef DEBUG_CONVERT
1031  printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
1032  src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
1033 #endif
1034 
1035  /* Start off with no conversion necessary */
1036  SDL_zerop(cvt);
1037  cvt->src_format = src_fmt;
1038  cvt->dst_format = dst_fmt;
1039  cvt->needed = 0;
1040  cvt->filter_index = 0;
1041  cvt->filters[0] = NULL;
1042  cvt->len_mult = 1;
1043  cvt->len_ratio = 1.0;
1044  cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
1045 
1046  /* Convert data types, if necessary. Updates (cvt). */
1047  if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1) {
1048  return -1; /* shouldn't happen, but just in case... */
1049  }
1050 
1051  /* Channel conversion */
1052  if (src_channels != dst_channels) {
1053  if ((src_channels == 1) && (dst_channels > 1)) {
1054  cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
1055  cvt->len_mult *= 2;
1056  src_channels = 2;
1057  cvt->len_ratio *= 2;
1058  }
1059  if ((src_channels == 2) && (dst_channels == 6)) {
1060  cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
1061  src_channels = 6;
1062  cvt->len_mult *= 3;
1063  cvt->len_ratio *= 3;
1064  }
1065  if ((src_channels == 2) && (dst_channels == 4)) {
1067  src_channels = 4;
1068  cvt->len_mult *= 2;
1069  cvt->len_ratio *= 2;
1070  }
1071  while ((src_channels * 2) <= dst_channels) {
1072  cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
1073  cvt->len_mult *= 2;
1074  src_channels *= 2;
1075  cvt->len_ratio *= 2;
1076  }
1077  if ((src_channels == 6) && (dst_channels <= 2)) {
1078  cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
1079  src_channels = 2;
1080  cvt->len_ratio /= 3;
1081  }
1082  if ((src_channels == 6) && (dst_channels == 4)) {
1083  cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
1084  src_channels = 4;
1085  cvt->len_ratio /= 2;
1086  }
1087  /* This assumes that 4 channel audio is in the format:
1088  Left {front/back} + Right {front/back}
1089  so converting to L/R stereo works properly.
1090  */
1091  while (((src_channels % 2) == 0) &&
1092  ((src_channels / 2) >= dst_channels)) {
1093  cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
1094  src_channels /= 2;
1095  cvt->len_ratio /= 2;
1096  }
1097  if (src_channels != dst_channels) {
1098  /* Uh oh.. */ ;
1099  }
1100  }
1101 
1102  /* Do rate conversion, if necessary. Updates (cvt). */
1103  if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) ==
1104  -1) {
1105  return -1; /* shouldn't happen, but just in case... */
1106  }
1107 
1108  /* Set up the filter information */
1109  if (cvt->filter_index != 0) {
1110  cvt->needed = 1;
1111  cvt->src_format = src_fmt;
1112  cvt->dst_format = dst_fmt;
1113  cvt->len = 0;
1114  cvt->buf = NULL;
1115  cvt->filters[cvt->filter_index] = NULL;
1116  }
1117  return (cvt->needed);
1118 }
1119 
1120 
1121 /* vi: set ts=4 sw=4 expandtab: */
GLenum GLenum dst
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1565
#define SDL_SwapFloatBE(X)
Definition: SDL_endian.h:218
#define SDL_ceil
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:155
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
Uint8 * buf
Definition: SDL_audio.h:206
#define strip_chans_6_to_4(type)
#define dup_chans_1_to_2(type)
int filter_index
Definition: SDL_audio.h:212
double len_ratio
Definition: SDL_audio.h:210
#define SDL_AUDIO_ISSIGNED(x)
Definition: SDL_audio.h:78
GLfloat f
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
const SDL_AudioTypeFilters sdl_audio_type_filters[]
#define SDL_SwapFloatLE(X)
Definition: SDL_endian.h:214
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
static SDL_AudioFilter SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
Definition: SDL_audiocvt.c:838
#define SDL_zerop(x)
Definition: SDL_stdinc.h:356
#define SDL_SwapBE32(X)
Definition: SDL_endian.h:216
SDL_AudioFilter filter
Definition: SDL_audio_c.h:51
SDL_bool retval
#define AUDIO_U8
Definition: SDL_audio.h:89
static int SDL_BuildAudioResampleCVT(SDL_AudioCVT *cvt, int dst_channels, int src_rate, int dst_rate)
Definition: SDL_audiocvt.c:944
static void SDL_ConvertStrip_2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:239
SDL_AudioFilter filters[10]
Definition: SDL_audio.h:211
int8_t Sint8
A signed 8-bit integer type.
Definition: SDL_stdinc.h:135
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:139
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:212
#define SDL_AUDIO_MASK_DATATYPE
Definition: SDL_audio.h:72
#define AUDIO_S32
Definition: SDL_audio.h:105
int SDL_ConvertAudio(SDL_AudioCVT *cvt)
Definition: SDL_audiocvt.c:814
SDL_AudioFormat fmt
Definition: SDL_audio_c.h:47
int32_t Sint32
A signed 32-bit integer type.
Definition: SDL_stdinc.h:151
SDL_AudioFormat src_format
Definition: SDL_audio.h:203
#define SDL_AUDIO_MASK_SIGNED
Definition: SDL_audio.h:74
void(* SDL_AudioFilter)(struct SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audio.h:183
int SDL_BuildAudioCVT(SDL_AudioCVT *cvt, SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate, SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
Definition: SDL_audiocvt.c:998
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:42
#define SDL_assert(condition)
Definition: SDL_assert.h:167
static int SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
Definition: SDL_audiocvt.c:911
static void SDL_ConvertSurround(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:328
#define NULL
Definition: begin_code.h:143
static void SDL_ConvertStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:285
#define SDL_SetError
SDL_AudioFormat dst_format
Definition: SDL_audio.h:204
static void SDL_ConvertSurround_4(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:587
double rate_incr
Definition: SDL_audio.h:205
#define AUDIO_S16
Definition: SDL_audio.h:96
const SDL_AudioRateFilters sdl_audio_rate_filters[]
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:147
SDL_AudioFilter filter
Definition: SDL_audio_c.h:40
static void SDL_ConvertMono(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:34
SDL_AudioFormat dst_fmt
Definition: SDL_audio_c.h:39
static void SDL_ConvertStrip(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:195
#define AUDIO_F32
Definition: SDL_audio.h:114
int64_t Sint64
A signed 64-bit integer type.
Definition: SDL_stdinc.h:160
SDL_AudioFormat src_fmt
Definition: SDL_audio_c.h:38
#define AUDIO_U16
Definition: SDL_audio.h:95
#define AUDIO_S8
Definition: SDL_audio.h:90
#define SDL_AUDIO_MASK_BITSIZE
Definition: SDL_audio.h:71
GLenum src
#define SDLCALL
Definition: SDL_internal.h:31
static int SDL_BuildAudioTypeCVT(SDL_AudioCVT *cvt, SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
Definition: SDL_audiocvt.c:856
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
int16_t Sint16
A signed 16-bit integer type.
Definition: SDL_stdinc.h:143
#define strip_chans_6_to_2(type)
static SDL_AudioFilter SDL_HandTunedResampleCVT(SDL_AudioCVT *cvt, int dst_channels, int src_rate, int dst_rate)
Definition: SDL_audiocvt.c:899