SDL_audiocvt.c (36638B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 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 */ 33static void SDLCALL 34SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) 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 | 43 SDL_AUDIO_MASK_BITSIZE | 44 SDL_AUDIO_MASK_DATATYPE)) { 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 */ 194static void SDLCALL 195SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format) 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: 218 strip_chans_6_to_2(Uint8); 219 break; 220 case 16: 221 strip_chans_6_to_2(Uint16); 222 break; 223 case 32: 224 strip_chans_6_to_2(Uint32); 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 */ 238static void SDLCALL 239SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format) 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: 264 strip_chans_6_to_4(Uint8); 265 break; 266 case 16: 267 strip_chans_6_to_4(Uint16); 268 break; 269 case 32: 270 strip_chans_6_to_4(Uint32); 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 */ 284static void SDLCALL 285SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format) 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: 307 dup_chans_1_to_2(Uint8); 308 break; 309 case 16: 310 dup_chans_1_to_2(Uint16); 311 break; 312 case 32: 313 dup_chans_1_to_2(Uint32); 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 */ 327static void SDLCALL 328SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format) 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 | 337 SDL_AUDIO_MASK_BITSIZE | 338 SDL_AUDIO_MASK_DATATYPE)) { 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 */ 586static void SDLCALL 587SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format) 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 | 596 SDL_AUDIO_MASK_BITSIZE | 597 SDL_AUDIO_MASK_DATATYPE)) { 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 813int 814SDL_ConvertAudio(SDL_AudioCVT * cvt) 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 837static SDL_AudioFilter 838SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt) 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 */ 855static int 856SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt, 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++) { 868 const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[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 898static SDL_AudioFilter 899SDL_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 910static int 911SDL_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 943static int 944SDL_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++) { 959 const SDL_AudioRateFilters *filt = &sdl_audio_rate_filters[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 997int 998SDL_BuildAudioCVT(SDL_AudioCVT * cvt, 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)) { 1066 cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_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: */