SDL_audiocvt.c (58724B)
1 /* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2020 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 /* FIXME: Channel weights when converting from more channels to fewer may need to be adjusted, see https://msdn.microsoft.com/en-us/library/windows/desktop/ff819070(v=vs.85).aspx 26 */ 27 28 #include "SDL.h" 29 #include "SDL_audio.h" 30 #include "SDL_audio_c.h" 31 32 #include "SDL_loadso.h" 33 #include "../SDL_dataqueue.h" 34 #include "SDL_cpuinfo.h" 35 36 #define DEBUG_AUDIOSTREAM 0 37 38 #ifdef __SSE3__ 39 #define HAVE_SSE3_INTRINSICS 1 40 #endif 41 42 #if HAVE_SSE3_INTRINSICS 43 /* Convert from stereo to mono. Average left and right. */ 44 static void SDLCALL 45 SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format) 46 { 47 float *dst = (float *) cvt->buf; 48 const float *src = dst; 49 int i = cvt->len_cvt / 8; 50 51 LOG_DEBUG_CONVERT("stereo", "mono (using SSE3)"); 52 SDL_assert(format == AUDIO_F32SYS); 53 54 /* We can only do this if dst is aligned to 16 bytes; since src is the 55 same pointer and it moves by 2, it can't be forcibly aligned. */ 56 if ((((size_t) dst) & 15) == 0) { 57 /* Aligned! Do SSE blocks as long as we have 16 bytes available. */ 58 const __m128 divby2 = _mm_set1_ps(0.5f); 59 while (i >= 4) { /* 4 * float32 */ 60 _mm_store_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_load_ps(src), _mm_load_ps(src+4)), divby2)); 61 i -= 4; src += 8; dst += 4; 62 } 63 } 64 65 /* Finish off any leftovers with scalar operations. */ 66 while (i) { 67 *dst = (src[0] + src[1]) * 0.5f; 68 dst++; i--; src += 2; 69 } 70 71 cvt->len_cvt /= 2; 72 if (cvt->filters[++cvt->filter_index]) { 73 cvt->filters[cvt->filter_index] (cvt, format); 74 } 75 } 76 #endif 77 78 /* Convert from stereo to mono. Average left and right. */ 79 static void SDLCALL 80 SDL_ConvertStereoToMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) 81 { 82 float *dst = (float *) cvt->buf; 83 const float *src = dst; 84 int i; 85 86 LOG_DEBUG_CONVERT("stereo", "mono"); 87 SDL_assert(format == AUDIO_F32SYS); 88 89 for (i = cvt->len_cvt / 8; i; --i, src += 2) { 90 *(dst++) = (src[0] + src[1]) * 0.5f; 91 } 92 93 cvt->len_cvt /= 2; 94 if (cvt->filters[++cvt->filter_index]) { 95 cvt->filters[cvt->filter_index] (cvt, format); 96 } 97 } 98 99 100 /* Convert from 5.1 to stereo. Average left and right, distribute center, discard LFE. */ 101 static void SDLCALL 102 SDL_Convert51ToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format) 103 { 104 float *dst = (float *) cvt->buf; 105 const float *src = dst; 106 int i; 107 108 LOG_DEBUG_CONVERT("5.1", "stereo"); 109 SDL_assert(format == AUDIO_F32SYS); 110 111 /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */ 112 for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 2) { 113 const float front_center_distributed = src[2] * 0.5f; 114 dst[0] = (src[0] + front_center_distributed + src[4]) / 2.5f; /* left */ 115 dst[1] = (src[1] + front_center_distributed + src[5]) / 2.5f; /* right */ 116 } 117 118 cvt->len_cvt /= 3; 119 if (cvt->filters[++cvt->filter_index]) { 120 cvt->filters[cvt->filter_index] (cvt, format); 121 } 122 } 123 124 125 /* Convert from quad to stereo. Average left and right. */ 126 static void SDLCALL 127 SDL_ConvertQuadToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format) 128 { 129 float *dst = (float *) cvt->buf; 130 const float *src = dst; 131 int i; 132 133 LOG_DEBUG_CONVERT("quad", "stereo"); 134 SDL_assert(format == AUDIO_F32SYS); 135 136 for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src += 4, dst += 2) { 137 dst[0] = (src[0] + src[2]) * 0.5f; /* left */ 138 dst[1] = (src[1] + src[3]) * 0.5f; /* right */ 139 } 140 141 cvt->len_cvt /= 2; 142 if (cvt->filters[++cvt->filter_index]) { 143 cvt->filters[cvt->filter_index] (cvt, format); 144 } 145 } 146 147 148 /* Convert from 7.1 to 5.1. Distribute sides across front and back. */ 149 static void SDLCALL 150 SDL_Convert71To51(SDL_AudioCVT * cvt, SDL_AudioFormat format) 151 { 152 float *dst = (float *) cvt->buf; 153 const float *src = dst; 154 int i; 155 156 LOG_DEBUG_CONVERT("7.1", "5.1"); 157 SDL_assert(format == AUDIO_F32SYS); 158 159 for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8, dst += 6) { 160 const float surround_left_distributed = src[6] * 0.5f; 161 const float surround_right_distributed = src[7] * 0.5f; 162 dst[0] = (src[0] + surround_left_distributed) / 1.5f; /* FL */ 163 dst[1] = (src[1] + surround_right_distributed) / 1.5f; /* FR */ 164 dst[2] = src[2] / 1.5f; /* CC */ 165 dst[3] = src[3] / 1.5f; /* LFE */ 166 dst[4] = (src[4] + surround_left_distributed) / 1.5f; /* BL */ 167 dst[5] = (src[5] + surround_right_distributed) / 1.5f; /* BR */ 168 } 169 170 cvt->len_cvt /= 8; 171 cvt->len_cvt *= 6; 172 if (cvt->filters[++cvt->filter_index]) { 173 cvt->filters[cvt->filter_index] (cvt, format); 174 } 175 } 176 177 178 /* Convert from 5.1 to quad. Distribute center across front, discard LFE. */ 179 static void SDLCALL 180 SDL_Convert51ToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format) 181 { 182 float *dst = (float *) cvt->buf; 183 const float *src = dst; 184 int i; 185 186 LOG_DEBUG_CONVERT("5.1", "quad"); 187 SDL_assert(format == AUDIO_F32SYS); 188 189 /* SDL's 4.0 layout: FL+FR+BL+BR */ 190 /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */ 191 for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 4) { 192 const float front_center_distributed = src[2] * 0.5f; 193 dst[0] = (src[0] + front_center_distributed) / 1.5f; /* FL */ 194 dst[1] = (src[1] + front_center_distributed) / 1.5f; /* FR */ 195 dst[2] = src[4] / 1.5f; /* BL */ 196 dst[3] = src[5] / 1.5f; /* BR */ 197 } 198 199 cvt->len_cvt /= 6; 200 cvt->len_cvt *= 4; 201 if (cvt->filters[++cvt->filter_index]) { 202 cvt->filters[cvt->filter_index] (cvt, format); 203 } 204 } 205 206 207 /* Upmix mono to stereo (by duplication) */ 208 static void SDLCALL 209 SDL_ConvertMonoToStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format) 210 { 211 const float *src = (const float *) (cvt->buf + cvt->len_cvt); 212 float *dst = (float *) (cvt->buf + cvt->len_cvt * 2); 213 int i; 214 215 LOG_DEBUG_CONVERT("mono", "stereo"); 216 SDL_assert(format == AUDIO_F32SYS); 217 218 for (i = cvt->len_cvt / sizeof (float); i; --i) { 219 src--; 220 dst -= 2; 221 dst[0] = dst[1] = *src; 222 } 223 224 cvt->len_cvt *= 2; 225 if (cvt->filters[++cvt->filter_index]) { 226 cvt->filters[cvt->filter_index] (cvt, format); 227 } 228 } 229 230 231 /* Upmix stereo to a pseudo-5.1 stream */ 232 static void SDLCALL 233 SDL_ConvertStereoTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format) 234 { 235 int i; 236 float lf, rf, ce; 237 const float *src = (const float *) (cvt->buf + cvt->len_cvt); 238 float *dst = (float *) (cvt->buf + cvt->len_cvt * 3); 239 240 LOG_DEBUG_CONVERT("stereo", "5.1"); 241 SDL_assert(format == AUDIO_F32SYS); 242 243 for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) { 244 dst -= 6; 245 src -= 2; 246 lf = src[0]; 247 rf = src[1]; 248 ce = (lf + rf) * 0.5f; 249 /* !!! FIXME: FL and FR may clip */ 250 dst[0] = lf + (lf - ce); /* FL */ 251 dst[1] = rf + (rf - ce); /* FR */ 252 dst[2] = ce; /* FC */ 253 dst[3] = 0; /* LFE (only meant for special LFE effects) */ 254 dst[4] = lf; /* BL */ 255 dst[5] = rf; /* BR */ 256 } 257 258 cvt->len_cvt *= 3; 259 if (cvt->filters[++cvt->filter_index]) { 260 cvt->filters[cvt->filter_index] (cvt, format); 261 } 262 } 263 264 265 /* Upmix quad to a pseudo-5.1 stream */ 266 static void SDLCALL 267 SDL_ConvertQuadTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format) 268 { 269 int i; 270 float lf, rf, lb, rb, ce; 271 const float *src = (const float *) (cvt->buf + cvt->len_cvt); 272 float *dst = (float *) (cvt->buf + cvt->len_cvt * 3 / 2); 273 274 LOG_DEBUG_CONVERT("quad", "5.1"); 275 SDL_assert(format == AUDIO_F32SYS); 276 SDL_assert(cvt->len_cvt % (sizeof(float) * 4) == 0); 277 278 for (i = cvt->len_cvt / (sizeof(float) * 4); i; --i) { 279 dst -= 6; 280 src -= 4; 281 lf = src[0]; 282 rf = src[1]; 283 lb = src[2]; 284 rb = src[3]; 285 ce = (lf + rf) * 0.5f; 286 /* !!! FIXME: FL and FR may clip */ 287 dst[0] = lf + (lf - ce); /* FL */ 288 dst[1] = rf + (rf - ce); /* FR */ 289 dst[2] = ce; /* FC */ 290 dst[3] = 0; /* LFE (only meant for special LFE effects) */ 291 dst[4] = lb; /* BL */ 292 dst[5] = rb; /* BR */ 293 } 294 295 cvt->len_cvt = cvt->len_cvt * 3 / 2; 296 if (cvt->filters[++cvt->filter_index]) { 297 cvt->filters[cvt->filter_index] (cvt, format); 298 } 299 } 300 301 302 /* Upmix stereo to a pseudo-4.0 stream (by duplication) */ 303 static void SDLCALL 304 SDL_ConvertStereoToQuad(SDL_AudioCVT * cvt, SDL_AudioFormat format) 305 { 306 const float *src = (const float *) (cvt->buf + cvt->len_cvt); 307 float *dst = (float *) (cvt->buf + cvt->len_cvt * 2); 308 float lf, rf; 309 int i; 310 311 LOG_DEBUG_CONVERT("stereo", "quad"); 312 SDL_assert(format == AUDIO_F32SYS); 313 314 for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) { 315 dst -= 4; 316 src -= 2; 317 lf = src[0]; 318 rf = src[1]; 319 dst[0] = lf; /* FL */ 320 dst[1] = rf; /* FR */ 321 dst[2] = lf; /* BL */ 322 dst[3] = rf; /* BR */ 323 } 324 325 cvt->len_cvt *= 2; 326 if (cvt->filters[++cvt->filter_index]) { 327 cvt->filters[cvt->filter_index] (cvt, format); 328 } 329 } 330 331 332 /* Upmix 5.1 to 7.1 */ 333 static void SDLCALL 334 SDL_Convert51To71(SDL_AudioCVT * cvt, SDL_AudioFormat format) 335 { 336 float lf, rf, lb, rb, ls, rs; 337 int i; 338 const float *src = (const float *) (cvt->buf + cvt->len_cvt); 339 float *dst = (float *) (cvt->buf + cvt->len_cvt * 4 / 3); 340 341 LOG_DEBUG_CONVERT("5.1", "7.1"); 342 SDL_assert(format == AUDIO_F32SYS); 343 SDL_assert(cvt->len_cvt % (sizeof(float) * 6) == 0); 344 345 for (i = cvt->len_cvt / (sizeof(float) * 6); i; --i) { 346 dst -= 8; 347 src -= 6; 348 lf = src[0]; 349 rf = src[1]; 350 lb = src[4]; 351 rb = src[5]; 352 ls = (lf + lb) * 0.5f; 353 rs = (rf + rb) * 0.5f; 354 /* !!! FIXME: these four may clip */ 355 lf += lf - ls; 356 rf += rf - ls; 357 lb += lb - ls; 358 rb += rb - ls; 359 dst[3] = src[3]; /* LFE */ 360 dst[2] = src[2]; /* FC */ 361 dst[7] = rs; /* SR */ 362 dst[6] = ls; /* SL */ 363 dst[5] = rb; /* BR */ 364 dst[4] = lb; /* BL */ 365 dst[1] = rf; /* FR */ 366 dst[0] = lf; /* FL */ 367 } 368 369 cvt->len_cvt = cvt->len_cvt * 4 / 3; 370 371 if (cvt->filters[++cvt->filter_index]) { 372 cvt->filters[cvt->filter_index] (cvt, format); 373 } 374 } 375 376 /* SDL's resampler uses a "bandlimited interpolation" algorithm: 377 https://ccrma.stanford.edu/~jos/resample/ */ 378 379 #define RESAMPLER_ZERO_CROSSINGS 5 380 #define RESAMPLER_BITS_PER_SAMPLE 16 381 #define RESAMPLER_SAMPLES_PER_ZERO_CROSSING (1 << ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1)) 382 #define RESAMPLER_FILTER_SIZE ((RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS) + 1) 383 384 /* This is a "modified" bessel function, so you can't use POSIX j0() */ 385 static double 386 bessel(const double x) 387 { 388 const double xdiv2 = x / 2.0; 389 double i0 = 1.0f; 390 double f = 1.0f; 391 int i = 1; 392 393 while (SDL_TRUE) { 394 const double diff = SDL_pow(xdiv2, i * 2) / SDL_pow(f, 2); 395 if (diff < 1.0e-21f) { 396 break; 397 } 398 i0 += diff; 399 i++; 400 f *= (double) i; 401 } 402 403 return i0; 404 } 405 406 /* build kaiser table with cardinal sine applied to it, and array of differences between elements. */ 407 static void 408 kaiser_and_sinc(float *table, float *diffs, const int tablelen, const double beta) 409 { 410 const int lenm1 = tablelen - 1; 411 const int lenm1div2 = lenm1 / 2; 412 int i; 413 414 table[0] = 1.0f; 415 for (i = 1; i < tablelen; i++) { 416 const double kaiser = bessel(beta * SDL_sqrt(1.0 - SDL_pow(((i - lenm1) / 2.0) / lenm1div2, 2.0))) / bessel(beta); 417 table[tablelen - i] = (float) kaiser; 418 } 419 420 for (i = 1; i < tablelen; i++) { 421 const float x = (((float) i) / ((float) RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) * ((float) M_PI); 422 table[i] *= SDL_sinf(x) / x; 423 diffs[i - 1] = table[i] - table[i - 1]; 424 } 425 diffs[lenm1] = 0.0f; 426 } 427 428 429 static SDL_SpinLock ResampleFilterSpinlock = 0; 430 static float *ResamplerFilter = NULL; 431 static float *ResamplerFilterDifference = NULL; 432 433 int 434 SDL_PrepareResampleFilter(void) 435 { 436 SDL_AtomicLock(&ResampleFilterSpinlock); 437 if (!ResamplerFilter) { 438 /* if dB > 50, beta=(0.1102 * (dB - 8.7)), according to Matlab. */ 439 const double dB = 80.0; 440 const double beta = 0.1102 * (dB - 8.7); 441 const size_t alloclen = RESAMPLER_FILTER_SIZE * sizeof (float); 442 443 ResamplerFilter = (float *) SDL_malloc(alloclen); 444 if (!ResamplerFilter) { 445 SDL_AtomicUnlock(&ResampleFilterSpinlock); 446 return SDL_OutOfMemory(); 447 } 448 449 ResamplerFilterDifference = (float *) SDL_malloc(alloclen); 450 if (!ResamplerFilterDifference) { 451 SDL_free(ResamplerFilter); 452 ResamplerFilter = NULL; 453 SDL_AtomicUnlock(&ResampleFilterSpinlock); 454 return SDL_OutOfMemory(); 455 } 456 kaiser_and_sinc(ResamplerFilter, ResamplerFilterDifference, RESAMPLER_FILTER_SIZE, beta); 457 } 458 SDL_AtomicUnlock(&ResampleFilterSpinlock); 459 return 0; 460 } 461 462 void 463 SDL_FreeResampleFilter(void) 464 { 465 SDL_free(ResamplerFilter); 466 SDL_free(ResamplerFilterDifference); 467 ResamplerFilter = NULL; 468 ResamplerFilterDifference = NULL; 469 } 470 471 static int 472 ResamplerPadding(const int inrate, const int outrate) 473 { 474 if (inrate == outrate) { 475 return 0; 476 } else if (inrate > outrate) { 477 return (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate))); 478 } 479 return RESAMPLER_SAMPLES_PER_ZERO_CROSSING; 480 } 481 482 /* lpadding and rpadding are expected to be buffers of (ResamplePadding(inrate, outrate) * chans * sizeof (float)) bytes. */ 483 static int 484 SDL_ResampleAudio(const int chans, const int inrate, const int outrate, 485 const float *lpadding, const float *rpadding, 486 const float *inbuf, const int inbuflen, 487 float *outbuf, const int outbuflen) 488 { 489 const double finrate = (double) inrate; 490 const double outtimeincr = 1.0 / ((float) outrate); 491 const double ratio = ((float) outrate) / ((float) inrate); 492 const int paddinglen = ResamplerPadding(inrate, outrate); 493 const int framelen = chans * (int)sizeof (float); 494 const int inframes = inbuflen / framelen; 495 const int wantedoutframes = (int) ((inbuflen / framelen) * ratio); /* outbuflen isn't total to write, it's total available. */ 496 const int maxoutframes = outbuflen / framelen; 497 const int outframes = SDL_min(wantedoutframes, maxoutframes); 498 float *dst = outbuf; 499 double outtime = 0.0; 500 int i, j, chan; 501 502 for (i = 0; i < outframes; i++) { 503 const int srcindex = (int) (outtime * inrate); 504 const double intime = ((double) srcindex) / finrate; 505 const double innexttime = ((double) (srcindex + 1)) / finrate; 506 const double interpolation1 = 1.0 - ((innexttime - outtime) / (innexttime - intime)); 507 const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING); 508 const double interpolation2 = 1.0 - interpolation1; 509 const int filterindex2 = (int) (interpolation2 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING); 510 511 for (chan = 0; chan < chans; chan++) { 512 float outsample = 0.0f; 513 514 /* do this twice to calculate the sample, once for the "left wing" and then same for the right. */ 515 /* !!! FIXME: do both wings in one loop */ 516 for (j = 0; (filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) { 517 const int srcframe = srcindex - j; 518 /* !!! FIXME: we can bubble this conditional out of here by doing a pre loop. */ 519 const float insample = (srcframe < 0) ? lpadding[((paddinglen + srcframe) * chans) + chan] : inbuf[(srcframe * chans) + chan]; 520 outsample += (float)(insample * (ResamplerFilter[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation1 * ResamplerFilterDifference[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)]))); 521 } 522 523 for (j = 0; (filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) { 524 const int srcframe = srcindex + 1 + j; 525 /* !!! FIXME: we can bubble this conditional out of here by doing a post loop. */ 526 const float insample = (srcframe >= inframes) ? rpadding[((srcframe - inframes) * chans) + chan] : inbuf[(srcframe * chans) + chan]; 527 outsample += (float)(insample * (ResamplerFilter[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation2 * ResamplerFilterDifference[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)]))); 528 } 529 *(dst++) = outsample; 530 } 531 532 outtime += outtimeincr; 533 } 534 535 return outframes * chans * sizeof (float); 536 } 537 538 int 539 SDL_ConvertAudio(SDL_AudioCVT * cvt) 540 { 541 /* !!! FIXME: (cvt) should be const; stack-copy it here. */ 542 /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */ 543 544 /* Make sure there's data to convert */ 545 if (cvt->buf == NULL) { 546 return SDL_SetError("No buffer allocated for conversion"); 547 } 548 549 /* Return okay if no conversion is necessary */ 550 cvt->len_cvt = cvt->len; 551 if (cvt->filters[0] == NULL) { 552 return 0; 553 } 554 555 /* Set up the conversion and go! */ 556 cvt->filter_index = 0; 557 cvt->filters[0] (cvt, cvt->src_format); 558 return 0; 559 } 560 561 static void SDLCALL 562 SDL_Convert_Byteswap(SDL_AudioCVT *cvt, SDL_AudioFormat format) 563 { 564 #if DEBUG_CONVERT 565 printf("Converting byte order\n"); 566 #endif 567 568 switch (SDL_AUDIO_BITSIZE(format)) { 569 #define CASESWAP(b) \ 570 case b: { \ 571 Uint##b *ptr = (Uint##b *) cvt->buf; \ 572 int i; \ 573 for (i = cvt->len_cvt / sizeof (*ptr); i; --i, ++ptr) { \ 574 *ptr = SDL_Swap##b(*ptr); \ 575 } \ 576 break; \ 577 } 578 579 CASESWAP(16); 580 CASESWAP(32); 581 CASESWAP(64); 582 583 #undef CASESWAP 584 585 default: SDL_assert(!"unhandled byteswap datatype!"); break; 586 } 587 588 if (cvt->filters[++cvt->filter_index]) { 589 /* flip endian flag for data. */ 590 if (format & SDL_AUDIO_MASK_ENDIAN) { 591 format &= ~SDL_AUDIO_MASK_ENDIAN; 592 } else { 593 format |= SDL_AUDIO_MASK_ENDIAN; 594 } 595 cvt->filters[cvt->filter_index](cvt, format); 596 } 597 } 598 599 static int 600 SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter) 601 { 602 if (cvt->filter_index >= SDL_AUDIOCVT_MAX_FILTERS) { 603 return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS); 604 } 605 if (filter == NULL) { 606 return SDL_SetError("Audio filter pointer is NULL"); 607 } 608 cvt->filters[cvt->filter_index++] = filter; 609 cvt->filters[cvt->filter_index] = NULL; /* Moving terminator */ 610 return 0; 611 } 612 613 static int 614 SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt) 615 { 616 int retval = 0; /* 0 == no conversion necessary. */ 617 618 if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) { 619 if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) { 620 return -1; 621 } 622 retval = 1; /* added a converter. */ 623 } 624 625 if (!SDL_AUDIO_ISFLOAT(src_fmt)) { 626 const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt); 627 const Uint16 dst_bitsize = 32; 628 SDL_AudioFilter filter = NULL; 629 630 switch (src_fmt & ~SDL_AUDIO_MASK_ENDIAN) { 631 case AUDIO_S8: filter = SDL_Convert_S8_to_F32; break; 632 case AUDIO_U8: filter = SDL_Convert_U8_to_F32; break; 633 case AUDIO_S16: filter = SDL_Convert_S16_to_F32; break; 634 case AUDIO_U16: filter = SDL_Convert_U16_to_F32; break; 635 case AUDIO_S32: filter = SDL_Convert_S32_to_F32; break; 636 default: SDL_assert(!"Unexpected audio format!"); break; 637 } 638 639 if (!filter) { 640 return SDL_SetError("No conversion from source format to float available"); 641 } 642 643 if (SDL_AddAudioCVTFilter(cvt, filter) < 0) { 644 return -1; 645 } 646 if (src_bitsize < dst_bitsize) { 647 const int mult = (dst_bitsize / src_bitsize); 648 cvt->len_mult *= mult; 649 cvt->len_ratio *= mult; 650 } else if (src_bitsize > dst_bitsize) { 651 cvt->len_ratio /= (src_bitsize / dst_bitsize); 652 } 653 654 retval = 1; /* added a converter. */ 655 } 656 657 return retval; 658 } 659 660 static int 661 SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt) 662 { 663 int retval = 0; /* 0 == no conversion necessary. */ 664 665 if (!SDL_AUDIO_ISFLOAT(dst_fmt)) { 666 const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt); 667 const Uint16 src_bitsize = 32; 668 SDL_AudioFilter filter = NULL; 669 switch (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN) { 670 case AUDIO_S8: filter = SDL_Convert_F32_to_S8; break; 671 case AUDIO_U8: filter = SDL_Convert_F32_to_U8; break; 672 case AUDIO_S16: filter = SDL_Convert_F32_to_S16; break; 673 case AUDIO_U16: filter = SDL_Convert_F32_to_U16; break; 674 case AUDIO_S32: filter = SDL_Convert_F32_to_S32; break; 675 default: SDL_assert(!"Unexpected audio format!"); break; 676 } 677 678 if (!filter) { 679 return SDL_SetError("No conversion from float to format 0x%.4x available", dst_fmt); 680 } 681 682 if (SDL_AddAudioCVTFilter(cvt, filter) < 0) { 683 return -1; 684 } 685 if (src_bitsize < dst_bitsize) { 686 const int mult = (dst_bitsize / src_bitsize); 687 cvt->len_mult *= mult; 688 cvt->len_ratio *= mult; 689 } else if (src_bitsize > dst_bitsize) { 690 cvt->len_ratio /= (src_bitsize / dst_bitsize); 691 } 692 retval = 1; /* added a converter. */ 693 } 694 695 if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) { 696 if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) { 697 return -1; 698 } 699 retval = 1; /* added a converter. */ 700 } 701 702 return retval; 703 } 704 705 static void 706 SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format) 707 { 708 /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator). 709 !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates, 710 !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */ 711 const int inrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1]; 712 const int outrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS]; 713 const float *src = (const float *) cvt->buf; 714 const int srclen = cvt->len_cvt; 715 /*float *dst = (float *) cvt->buf; 716 const int dstlen = (cvt->len * cvt->len_mult);*/ 717 /* !!! FIXME: remove this if we can get the resampler to work in-place again. */ 718 float *dst = (float *) (cvt->buf + srclen); 719 const int dstlen = (cvt->len * cvt->len_mult) - srclen; 720 const int requestedpadding = ResamplerPadding(inrate, outrate); 721 int paddingsamples; 722 float *padding; 723 724 if (requestedpadding < SDL_MAX_SINT32 / chans) { 725 paddingsamples = requestedpadding * chans; 726 } else { 727 paddingsamples = 0; 728 } 729 SDL_assert(format == AUDIO_F32SYS); 730 731 /* we keep no streaming state here, so pad with silence on both ends. */ 732 padding = (float *) SDL_calloc(paddingsamples ? paddingsamples : 1, sizeof (float)); 733 if (!padding) { 734 SDL_OutOfMemory(); 735 return; 736 } 737 738 cvt->len_cvt = SDL_ResampleAudio(chans, inrate, outrate, padding, padding, src, srclen, dst, dstlen); 739 740 SDL_free(padding); 741 742 SDL_memmove(cvt->buf, dst, cvt->len_cvt); /* !!! FIXME: remove this if we can get the resampler to work in-place again. */ 743 744 if (cvt->filters[++cvt->filter_index]) { 745 cvt->filters[cvt->filter_index](cvt, format); 746 } 747 } 748 749 /* !!! FIXME: We only have this macro salsa because SDL_AudioCVT doesn't 750 !!! FIXME: store channel info, so we have to have function entry 751 !!! FIXME: points for each supported channel count and multiple 752 !!! FIXME: vs arbitrary. When we rev the ABI, clean this up. */ 753 #define RESAMPLER_FUNCS(chans) \ 754 static void SDLCALL \ 755 SDL_ResampleCVT_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \ 756 SDL_ResampleCVT(cvt, chans, format); \ 757 } 758 RESAMPLER_FUNCS(1) 759 RESAMPLER_FUNCS(2) 760 RESAMPLER_FUNCS(4) 761 RESAMPLER_FUNCS(6) 762 RESAMPLER_FUNCS(8) 763 #undef RESAMPLER_FUNCS 764 765 static SDL_AudioFilter 766 ChooseCVTResampler(const int dst_channels) 767 { 768 switch (dst_channels) { 769 case 1: return SDL_ResampleCVT_c1; 770 case 2: return SDL_ResampleCVT_c2; 771 case 4: return SDL_ResampleCVT_c4; 772 case 6: return SDL_ResampleCVT_c6; 773 case 8: return SDL_ResampleCVT_c8; 774 default: break; 775 } 776 777 return NULL; 778 } 779 780 static int 781 SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, const int dst_channels, 782 const int src_rate, const int dst_rate) 783 { 784 SDL_AudioFilter filter; 785 786 if (src_rate == dst_rate) { 787 return 0; /* no conversion necessary. */ 788 } 789 790 filter = ChooseCVTResampler(dst_channels); 791 if (filter == NULL) { 792 return SDL_SetError("No conversion available for these rates"); 793 } 794 795 if (SDL_PrepareResampleFilter() < 0) { 796 return -1; 797 } 798 799 /* Update (cvt) with filter details... */ 800 if (SDL_AddAudioCVTFilter(cvt, filter) < 0) { 801 return -1; 802 } 803 804 /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator). 805 !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates, 806 !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */ 807 if (cvt->filter_index >= (SDL_AUDIOCVT_MAX_FILTERS-2)) { 808 return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS-2); 809 } 810 cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1] = (SDL_AudioFilter) (size_t) src_rate; 811 cvt->filters[SDL_AUDIOCVT_MAX_FILTERS] = (SDL_AudioFilter) (size_t) dst_rate; 812 813 if (src_rate < dst_rate) { 814 const double mult = ((double) dst_rate) / ((double) src_rate); 815 cvt->len_mult *= (int) SDL_ceil(mult); 816 cvt->len_ratio *= mult; 817 } else { 818 cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate); 819 } 820 821 /* !!! FIXME: remove this if we can get the resampler to work in-place again. */ 822 /* the buffer is big enough to hold the destination now, but 823 we need it large enough to hold a separate scratch buffer. */ 824 cvt->len_mult *= 2; 825 826 return 1; /* added a converter. */ 827 } 828 829 static SDL_bool 830 SDL_SupportedAudioFormat(const SDL_AudioFormat fmt) 831 { 832 switch (fmt) { 833 case AUDIO_U8: 834 case AUDIO_S8: 835 case AUDIO_U16LSB: 836 case AUDIO_S16LSB: 837 case AUDIO_U16MSB: 838 case AUDIO_S16MSB: 839 case AUDIO_S32LSB: 840 case AUDIO_S32MSB: 841 case AUDIO_F32LSB: 842 case AUDIO_F32MSB: 843 return SDL_TRUE; /* supported. */ 844 845 default: 846 break; 847 } 848 849 return SDL_FALSE; /* unsupported. */ 850 } 851 852 static SDL_bool 853 SDL_SupportedChannelCount(const int channels) 854 { 855 switch (channels) { 856 case 1: /* mono */ 857 case 2: /* stereo */ 858 case 4: /* quad */ 859 case 6: /* 5.1 */ 860 case 8: /* 7.1 */ 861 return SDL_TRUE; /* supported. */ 862 863 default: 864 break; 865 } 866 867 return SDL_FALSE; /* unsupported. */ 868 } 869 870 871 /* Creates a set of audio filters to convert from one format to another. 872 Returns 0 if no conversion is needed, 1 if the audio filter is set up, 873 or -1 if an error like invalid parameter, unsupported format, etc. occurred. 874 */ 875 876 int 877 SDL_BuildAudioCVT(SDL_AudioCVT * cvt, 878 SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate, 879 SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate) 880 { 881 /* Sanity check target pointer */ 882 if (cvt == NULL) { 883 return SDL_InvalidParamError("cvt"); 884 } 885 886 /* Make sure we zero out the audio conversion before error checking */ 887 SDL_zerop(cvt); 888 889 if (!SDL_SupportedAudioFormat(src_fmt)) { 890 return SDL_SetError("Invalid source format"); 891 } else if (!SDL_SupportedAudioFormat(dst_fmt)) { 892 return SDL_SetError("Invalid destination format"); 893 } else if (!SDL_SupportedChannelCount(src_channels)) { 894 return SDL_SetError("Invalid source channels"); 895 } else if (!SDL_SupportedChannelCount(dst_channels)) { 896 return SDL_SetError("Invalid destination channels"); 897 } else if (src_rate <= 0) { 898 return SDL_SetError("Source rate is equal to or less than zero"); 899 } else if (dst_rate <= 0) { 900 return SDL_SetError("Destination rate is equal to or less than zero"); 901 } else if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) { 902 return SDL_SetError("Source rate is too high"); 903 } else if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) { 904 return SDL_SetError("Destination rate is too high"); 905 } 906 907 #if DEBUG_CONVERT 908 printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n", 909 src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate); 910 #endif 911 912 /* Start off with no conversion necessary */ 913 cvt->src_format = src_fmt; 914 cvt->dst_format = dst_fmt; 915 cvt->needed = 0; 916 cvt->filter_index = 0; 917 SDL_zeroa(cvt->filters); 918 cvt->len_mult = 1; 919 cvt->len_ratio = 1.0; 920 cvt->rate_incr = ((double) dst_rate) / ((double) src_rate); 921 922 /* Make sure we've chosen audio conversion functions (MMX, scalar, etc.) */ 923 SDL_ChooseAudioConverters(); 924 925 /* Type conversion goes like this now: 926 - byteswap to CPU native format first if necessary. 927 - convert to native Float32 if necessary. 928 - resample and change channel count if necessary. 929 - convert back to native format. 930 - byteswap back to foreign format if necessary. 931 932 The expectation is we can process data faster in float32 933 (possibly with SIMD), and making several passes over the same 934 buffer is likely to be CPU cache-friendly, avoiding the 935 biggest performance hit in modern times. Previously we had 936 (script-generated) custom converters for every data type and 937 it was a bloat on SDL compile times and final library size. */ 938 939 /* see if we can skip float conversion entirely. */ 940 if (src_rate == dst_rate && src_channels == dst_channels) { 941 if (src_fmt == dst_fmt) { 942 return 0; 943 } 944 945 /* just a byteswap needed? */ 946 if ((src_fmt & ~SDL_AUDIO_MASK_ENDIAN) == (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN)) { 947 if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) { 948 return -1; 949 } 950 cvt->needed = 1; 951 return 1; 952 } 953 } 954 955 /* Convert data types, if necessary. Updates (cvt). */ 956 if (SDL_BuildAudioTypeCVTToFloat(cvt, src_fmt) < 0) { 957 return -1; /* shouldn't happen, but just in case... */ 958 } 959 960 /* Channel conversion */ 961 if (src_channels < dst_channels) { 962 /* Upmixing */ 963 /* Mono -> Stereo [-> ...] */ 964 if ((src_channels == 1) && (dst_channels > 1)) { 965 if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertMonoToStereo) < 0) { 966 return -1; 967 } 968 cvt->len_mult *= 2; 969 src_channels = 2; 970 cvt->len_ratio *= 2; 971 } 972 /* [Mono ->] Stereo -> 5.1 [-> 7.1] */ 973 if ((src_channels == 2) && (dst_channels >= 6)) { 974 if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertStereoTo51) < 0) { 975 return -1; 976 } 977 src_channels = 6; 978 cvt->len_mult *= 3; 979 cvt->len_ratio *= 3; 980 } 981 /* Quad -> 5.1 [-> 7.1] */ 982 if ((src_channels == 4) && (dst_channels >= 6)) { 983 if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertQuadTo51) < 0) { 984 return -1; 985 } 986 src_channels = 6; 987 cvt->len_mult = (cvt->len_mult * 3 + 1) / 2; 988 cvt->len_ratio *= 1.5; 989 } 990 /* [[Mono ->] Stereo ->] 5.1 -> 7.1 */ 991 if ((src_channels == 6) && (dst_channels == 8)) { 992 if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51To71) < 0) { 993 return -1; 994 } 995 src_channels = 8; 996 cvt->len_mult = (cvt->len_mult * 4 + 2) / 3; 997 /* Should be numerically exact with every valid input to this 998 function */ 999 cvt->len_ratio = cvt->len_ratio * 4 / 3; 1000 } 1001 /* [Mono ->] Stereo -> Quad */ 1002 if ((src_channels == 2) && (dst_channels == 4)) { 1003 if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertStereoToQuad) < 0) { 1004 return -1; 1005 } 1006 src_channels = 4; 1007 cvt->len_mult *= 2; 1008 cvt->len_ratio *= 2; 1009 } 1010 } else if (src_channels > dst_channels) { 1011 /* Downmixing */ 1012 /* 7.1 -> 5.1 [-> Stereo [-> Mono]] */ 1013 /* 7.1 -> 5.1 [-> Quad] */ 1014 if ((src_channels == 8) && (dst_channels <= 6)) { 1015 if (SDL_AddAudioCVTFilter(cvt, SDL_Convert71To51) < 0) { 1016 return -1; 1017 } 1018 src_channels = 6; 1019 cvt->len_ratio *= 0.75; 1020 } 1021 /* [7.1 ->] 5.1 -> Stereo [-> Mono] */ 1022 if ((src_channels == 6) && (dst_channels <= 2)) { 1023 if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51ToStereo) < 0) { 1024 return -1; 1025 } 1026 src_channels = 2; 1027 cvt->len_ratio /= 3; 1028 } 1029 /* 5.1 -> Quad */ 1030 if ((src_channels == 6) && (dst_channels == 4)) { 1031 if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51ToQuad) < 0) { 1032 return -1; 1033 } 1034 src_channels = 4; 1035 cvt->len_ratio = cvt->len_ratio * 2 / 3; 1036 } 1037 /* Quad -> Stereo [-> Mono] */ 1038 if ((src_channels == 4) && (dst_channels <= 2)) { 1039 if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertQuadToStereo) < 0) { 1040 return -1; 1041 } 1042 src_channels = 2; 1043 cvt->len_ratio /= 2; 1044 } 1045 /* [... ->] Stereo -> Mono */ 1046 if ((src_channels == 2) && (dst_channels == 1)) { 1047 SDL_AudioFilter filter = NULL; 1048 1049 #if HAVE_SSE3_INTRINSICS 1050 if (SDL_HasSSE3()) { 1051 filter = SDL_ConvertStereoToMono_SSE3; 1052 } 1053 #endif 1054 1055 if (!filter) { 1056 filter = SDL_ConvertStereoToMono; 1057 } 1058 1059 if (SDL_AddAudioCVTFilter(cvt, filter) < 0) { 1060 return -1; 1061 } 1062 1063 src_channels = 1; 1064 cvt->len_ratio /= 2; 1065 } 1066 } 1067 1068 if (src_channels != dst_channels) { 1069 /* All combinations of supported channel counts should have been 1070 handled by now, but let's be defensive */ 1071 return SDL_SetError("Invalid channel combination"); 1072 } 1073 1074 /* Do rate conversion, if necessary. Updates (cvt). */ 1075 if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) < 0) { 1076 return -1; /* shouldn't happen, but just in case... */ 1077 } 1078 1079 /* Move to final data type. */ 1080 if (SDL_BuildAudioTypeCVTFromFloat(cvt, dst_fmt) < 0) { 1081 return -1; /* shouldn't happen, but just in case... */ 1082 } 1083 1084 cvt->needed = (cvt->filter_index != 0); 1085 return (cvt->needed); 1086 } 1087 1088 typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen); 1089 typedef void (*SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream); 1090 typedef void (*SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream); 1091 1092 struct _SDL_AudioStream 1093 { 1094 SDL_AudioCVT cvt_before_resampling; 1095 SDL_AudioCVT cvt_after_resampling; 1096 SDL_DataQueue *queue; 1097 SDL_bool first_run; 1098 Uint8 *staging_buffer; 1099 int staging_buffer_size; 1100 int staging_buffer_filled; 1101 Uint8 *work_buffer_base; /* maybe unaligned pointer from SDL_realloc(). */ 1102 int work_buffer_len; 1103 int src_sample_frame_size; 1104 SDL_AudioFormat src_format; 1105 Uint8 src_channels; 1106 int src_rate; 1107 int dst_sample_frame_size; 1108 SDL_AudioFormat dst_format; 1109 Uint8 dst_channels; 1110 int dst_rate; 1111 double rate_incr; 1112 Uint8 pre_resample_channels; 1113 int packetlen; 1114 int resampler_padding_samples; 1115 float *resampler_padding; 1116 void *resampler_state; 1117 SDL_ResampleAudioStreamFunc resampler_func; 1118 SDL_ResetAudioStreamResamplerFunc reset_resampler_func; 1119 SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func; 1120 }; 1121 1122 static Uint8 * 1123 EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen) 1124 { 1125 Uint8 *ptr; 1126 size_t offset; 1127 1128 if (stream->work_buffer_len >= newlen) { 1129 ptr = stream->work_buffer_base; 1130 } else { 1131 ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32); 1132 if (!ptr) { 1133 SDL_OutOfMemory(); 1134 return NULL; 1135 } 1136 /* Make sure we're aligned to 16 bytes for SIMD code. */ 1137 stream->work_buffer_base = ptr; 1138 stream->work_buffer_len = newlen; 1139 } 1140 1141 offset = ((size_t) ptr) & 15; 1142 return offset ? ptr + (16 - offset) : ptr; 1143 } 1144 1145 #ifdef HAVE_LIBSAMPLERATE_H 1146 static int 1147 SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen) 1148 { 1149 const float *inbuf = (const float *) _inbuf; 1150 float *outbuf = (float *) _outbuf; 1151 const int framelen = sizeof(float) * stream->pre_resample_channels; 1152 SRC_STATE *state = (SRC_STATE *)stream->resampler_state; 1153 SRC_DATA data; 1154 int result; 1155 1156 SDL_assert(inbuf != ((const float *) outbuf)); /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */ 1157 1158 data.data_in = (float *)inbuf; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */ 1159 data.input_frames = inbuflen / framelen; 1160 data.input_frames_used = 0; 1161 1162 data.data_out = outbuf; 1163 data.output_frames = outbuflen / framelen; 1164 1165 data.end_of_input = 0; 1166 data.src_ratio = stream->rate_incr; 1167 1168 result = SRC_src_process(state, &data); 1169 if (result != 0) { 1170 SDL_SetError("src_process() failed: %s", SRC_src_strerror(result)); 1171 return 0; 1172 } 1173 1174 /* If this fails, we need to store them off somewhere */ 1175 SDL_assert(data.input_frames_used == data.input_frames); 1176 1177 return data.output_frames_gen * (sizeof(float) * stream->pre_resample_channels); 1178 } 1179 1180 static void 1181 SDL_ResetAudioStreamResampler_SRC(SDL_AudioStream *stream) 1182 { 1183 SRC_src_reset((SRC_STATE *)stream->resampler_state); 1184 } 1185 1186 static void 1187 SDL_CleanupAudioStreamResampler_SRC(SDL_AudioStream *stream) 1188 { 1189 SRC_STATE *state = (SRC_STATE *)stream->resampler_state; 1190 if (state) { 1191 SRC_src_delete(state); 1192 } 1193 1194 stream->resampler_state = NULL; 1195 stream->resampler_func = NULL; 1196 stream->reset_resampler_func = NULL; 1197 stream->cleanup_resampler_func = NULL; 1198 } 1199 1200 static SDL_bool 1201 SetupLibSampleRateResampling(SDL_AudioStream *stream) 1202 { 1203 int result = 0; 1204 SRC_STATE *state = NULL; 1205 1206 if (SRC_available) { 1207 state = SRC_src_new(SRC_converter, stream->pre_resample_channels, &result); 1208 if (!state) { 1209 SDL_SetError("src_new() failed: %s", SRC_src_strerror(result)); 1210 } 1211 } 1212 1213 if (!state) { 1214 SDL_CleanupAudioStreamResampler_SRC(stream); 1215 return SDL_FALSE; 1216 } 1217 1218 stream->resampler_state = state; 1219 stream->resampler_func = SDL_ResampleAudioStream_SRC; 1220 stream->reset_resampler_func = SDL_ResetAudioStreamResampler_SRC; 1221 stream->cleanup_resampler_func = SDL_CleanupAudioStreamResampler_SRC; 1222 1223 return SDL_TRUE; 1224 } 1225 #endif /* HAVE_LIBSAMPLERATE_H */ 1226 1227 1228 static int 1229 SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen) 1230 { 1231 const Uint8 *inbufend = ((const Uint8 *) _inbuf) + inbuflen; 1232 const float *inbuf = (const float *) _inbuf; 1233 float *outbuf = (float *) _outbuf; 1234 const int chans = (int) stream->pre_resample_channels; 1235 const int inrate = stream->src_rate; 1236 const int outrate = stream->dst_rate; 1237 const int paddingsamples = stream->resampler_padding_samples; 1238 const int paddingbytes = paddingsamples * sizeof (float); 1239 float *lpadding = (float *) stream->resampler_state; 1240 const float *rpadding = (const float *) inbufend; /* we set this up so there are valid padding samples at the end of the input buffer. */ 1241 const int cpy = SDL_min(inbuflen, paddingbytes); 1242 int retval; 1243 1244 SDL_assert(inbuf != ((const float *) outbuf)); /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */ 1245 1246 retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, inbuf, inbuflen, outbuf, outbuflen); 1247 1248 /* update our left padding with end of current input, for next run. */ 1249 SDL_memcpy((lpadding + paddingsamples) - (cpy / sizeof (float)), inbufend - cpy, cpy); 1250 return retval; 1251 } 1252 1253 static void 1254 SDL_ResetAudioStreamResampler(SDL_AudioStream *stream) 1255 { 1256 /* set all the padding to silence. */ 1257 const int len = stream->resampler_padding_samples; 1258 SDL_memset(stream->resampler_state, '\0', len * sizeof (float)); 1259 } 1260 1261 static void 1262 SDL_CleanupAudioStreamResampler(SDL_AudioStream *stream) 1263 { 1264 SDL_free(stream->resampler_state); 1265 } 1266 1267 SDL_AudioStream * 1268 SDL_NewAudioStream(const SDL_AudioFormat src_format, 1269 const Uint8 src_channels, 1270 const int src_rate, 1271 const SDL_AudioFormat dst_format, 1272 const Uint8 dst_channels, 1273 const int dst_rate) 1274 { 1275 const int packetlen = 4096; /* !!! FIXME: good enough for now. */ 1276 Uint8 pre_resample_channels; 1277 SDL_AudioStream *retval; 1278 1279 retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream)); 1280 if (!retval) { 1281 return NULL; 1282 } 1283 1284 /* If increasing channels, do it after resampling, since we'd just 1285 do more work to resample duplicate channels. If we're decreasing, do 1286 it first so we resample the interpolated data instead of interpolating 1287 the resampled data (!!! FIXME: decide if that works in practice, though!). */ 1288 pre_resample_channels = SDL_min(src_channels, dst_channels); 1289 1290 retval->first_run = SDL_TRUE; 1291 retval->src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels; 1292 retval->src_format = src_format; 1293 retval->src_channels = src_channels; 1294 retval->src_rate = src_rate; 1295 retval->dst_sample_frame_size = (SDL_AUDIO_BITSIZE(dst_format) / 8) * dst_channels; 1296 retval->dst_format = dst_format; 1297 retval->dst_channels = dst_channels; 1298 retval->dst_rate = dst_rate; 1299 retval->pre_resample_channels = pre_resample_channels; 1300 retval->packetlen = packetlen; 1301 retval->rate_incr = ((double) dst_rate) / ((double) src_rate); 1302 retval->resampler_padding_samples = ResamplerPadding(retval->src_rate, retval->dst_rate) * pre_resample_channels; 1303 retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples ? retval->resampler_padding_samples : 1, sizeof (float)); 1304 1305 if (retval->resampler_padding == NULL) { 1306 SDL_FreeAudioStream(retval); 1307 SDL_OutOfMemory(); 1308 return NULL; 1309 } 1310 1311 retval->staging_buffer_size = ((retval->resampler_padding_samples / retval->pre_resample_channels) * retval->src_sample_frame_size); 1312 if (retval->staging_buffer_size > 0) { 1313 retval->staging_buffer = (Uint8 *) SDL_malloc(retval->staging_buffer_size); 1314 if (retval->staging_buffer == NULL) { 1315 SDL_FreeAudioStream(retval); 1316 SDL_OutOfMemory(); 1317 return NULL; 1318 } 1319 } 1320 1321 /* Not resampling? It's an easy conversion (and maybe not even that!) */ 1322 if (src_rate == dst_rate) { 1323 retval->cvt_before_resampling.needed = SDL_FALSE; 1324 if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, src_format, src_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) { 1325 SDL_FreeAudioStream(retval); 1326 return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */ 1327 } 1328 } else { 1329 /* Don't resample at first. Just get us to Float32 format. */ 1330 /* !!! FIXME: convert to int32 on devices without hardware float. */ 1331 if (SDL_BuildAudioCVT(&retval->cvt_before_resampling, src_format, src_channels, src_rate, AUDIO_F32SYS, pre_resample_channels, src_rate) < 0) { 1332 SDL_FreeAudioStream(retval); 1333 return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */ 1334 } 1335 1336 #ifdef HAVE_LIBSAMPLERATE_H 1337 SetupLibSampleRateResampling(retval); 1338 #endif 1339 1340 if (!retval->resampler_func) { 1341 retval->resampler_state = SDL_calloc(retval->resampler_padding_samples, sizeof (float)); 1342 if (!retval->resampler_state) { 1343 SDL_FreeAudioStream(retval); 1344 SDL_OutOfMemory(); 1345 return NULL; 1346 } 1347 1348 if (SDL_PrepareResampleFilter() < 0) { 1349 SDL_free(retval->resampler_state); 1350 retval->resampler_state = NULL; 1351 SDL_FreeAudioStream(retval); 1352 return NULL; 1353 } 1354 1355 retval->resampler_func = SDL_ResampleAudioStream; 1356 retval->reset_resampler_func = SDL_ResetAudioStreamResampler; 1357 retval->cleanup_resampler_func = SDL_CleanupAudioStreamResampler; 1358 } 1359 1360 /* Convert us to the final format after resampling. */ 1361 if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, AUDIO_F32SYS, pre_resample_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) { 1362 SDL_FreeAudioStream(retval); 1363 return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */ 1364 } 1365 } 1366 1367 retval->queue = SDL_NewDataQueue(packetlen, packetlen * 2); 1368 if (!retval->queue) { 1369 SDL_FreeAudioStream(retval); 1370 return NULL; /* SDL_NewDataQueue should have called SDL_SetError. */ 1371 } 1372 1373 return retval; 1374 } 1375 1376 static int 1377 SDL_AudioStreamPutInternal(SDL_AudioStream *stream, const void *buf, int len, int *maxputbytes) 1378 { 1379 int buflen = len; 1380 int workbuflen; 1381 Uint8 *workbuf; 1382 Uint8 *resamplebuf = NULL; 1383 int resamplebuflen = 0; 1384 int neededpaddingbytes; 1385 int paddingbytes; 1386 1387 /* !!! FIXME: several converters can take advantage of SIMD, but only 1388 !!! FIXME: if the data is aligned to 16 bytes. EnsureStreamBufferSize() 1389 !!! FIXME: guarantees the buffer will align, but the 1390 !!! FIXME: converters will iterate over the data backwards if 1391 !!! FIXME: the output grows, and this means we won't align if buflen 1392 !!! FIXME: isn't a multiple of 16. In these cases, we should chop off 1393 !!! FIXME: a few samples at the end and convert them separately. */ 1394 1395 /* no padding prepended on first run. */ 1396 neededpaddingbytes = stream->resampler_padding_samples * sizeof (float); 1397 paddingbytes = stream->first_run ? 0 : neededpaddingbytes; 1398 stream->first_run = SDL_FALSE; 1399 1400 /* Make sure the work buffer can hold all the data we need at once... */ 1401 workbuflen = buflen; 1402 if (stream->cvt_before_resampling.needed) { 1403 workbuflen *= stream->cvt_before_resampling.len_mult; 1404 } 1405 1406 if (stream->dst_rate != stream->src_rate) { 1407 /* resamples can't happen in place, so make space for second buf. */ 1408 const int framesize = stream->pre_resample_channels * sizeof (float); 1409 const int frames = workbuflen / framesize; 1410 resamplebuflen = ((int) SDL_ceil(frames * stream->rate_incr)) * framesize; 1411 #if DEBUG_AUDIOSTREAM 1412 printf("AUDIOSTREAM: will resample %d bytes to %d (ratio=%.6f)\n", workbuflen, resamplebuflen, stream->rate_incr); 1413 #endif 1414 workbuflen += resamplebuflen; 1415 } 1416 1417 if (stream->cvt_after_resampling.needed) { 1418 /* !!! FIXME: buffer might be big enough already? */ 1419 workbuflen *= stream->cvt_after_resampling.len_mult; 1420 } 1421 1422 workbuflen += neededpaddingbytes; 1423 1424 #if DEBUG_AUDIOSTREAM 1425 printf("AUDIOSTREAM: Putting %d bytes of preconverted audio, need %d byte work buffer\n", buflen, workbuflen); 1426 #endif 1427 1428 workbuf = EnsureStreamBufferSize(stream, workbuflen); 1429 if (!workbuf) { 1430 return -1; /* probably out of memory. */ 1431 } 1432 1433 resamplebuf = workbuf; /* default if not resampling. */ 1434 1435 SDL_memcpy(workbuf + paddingbytes, buf, buflen); 1436 1437 if (stream->cvt_before_resampling.needed) { 1438 stream->cvt_before_resampling.buf = workbuf + paddingbytes; 1439 stream->cvt_before_resampling.len = buflen; 1440 if (SDL_ConvertAudio(&stream->cvt_before_resampling) == -1) { 1441 return -1; /* uhoh! */ 1442 } 1443 buflen = stream->cvt_before_resampling.len_cvt; 1444 1445 #if DEBUG_AUDIOSTREAM 1446 printf("AUDIOSTREAM: After initial conversion we have %d bytes\n", buflen); 1447 #endif 1448 } 1449 1450 if (stream->dst_rate != stream->src_rate) { 1451 /* save off some samples at the end; they are used for padding now so 1452 the resampler is coherent and then used at the start of the next 1453 put operation. Prepend last put operation's padding, too. */ 1454 1455 /* prepend prior put's padding. :P */ 1456 if (paddingbytes) { 1457 SDL_memcpy(workbuf, stream->resampler_padding, paddingbytes); 1458 buflen += paddingbytes; 1459 } 1460 1461 /* save off the data at the end for the next run. */ 1462 SDL_memcpy(stream->resampler_padding, workbuf + (buflen - neededpaddingbytes), neededpaddingbytes); 1463 1464 resamplebuf = workbuf + buflen; /* skip to second piece of workbuf. */ 1465 SDL_assert(buflen >= neededpaddingbytes); 1466 if (buflen > neededpaddingbytes) { 1467 buflen = stream->resampler_func(stream, workbuf, buflen - neededpaddingbytes, resamplebuf, resamplebuflen); 1468 } else { 1469 buflen = 0; 1470 } 1471 1472 #if DEBUG_AUDIOSTREAM 1473 printf("AUDIOSTREAM: After resampling we have %d bytes\n", buflen); 1474 #endif 1475 } 1476 1477 if (stream->cvt_after_resampling.needed && (buflen > 0)) { 1478 stream->cvt_after_resampling.buf = resamplebuf; 1479 stream->cvt_after_resampling.len = buflen; 1480 if (SDL_ConvertAudio(&stream->cvt_after_resampling) == -1) { 1481 return -1; /* uhoh! */ 1482 } 1483 buflen = stream->cvt_after_resampling.len_cvt; 1484 1485 #if DEBUG_AUDIOSTREAM 1486 printf("AUDIOSTREAM: After final conversion we have %d bytes\n", buflen); 1487 #endif 1488 } 1489 1490 #if DEBUG_AUDIOSTREAM 1491 printf("AUDIOSTREAM: Final output is %d bytes\n", buflen); 1492 #endif 1493 1494 if (maxputbytes) { 1495 const int maxbytes = *maxputbytes; 1496 if (buflen > maxbytes) 1497 buflen = maxbytes; 1498 *maxputbytes -= buflen; 1499 } 1500 1501 /* resamplebuf holds the final output, even if we didn't resample. */ 1502 return buflen ? SDL_WriteToDataQueue(stream->queue, resamplebuf, buflen) : 0; 1503 } 1504 1505 int 1506 SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len) 1507 { 1508 /* !!! FIXME: several converters can take advantage of SIMD, but only 1509 !!! FIXME: if the data is aligned to 16 bytes. EnsureStreamBufferSize() 1510 !!! FIXME: guarantees the buffer will align, but the 1511 !!! FIXME: converters will iterate over the data backwards if 1512 !!! FIXME: the output grows, and this means we won't align if buflen 1513 !!! FIXME: isn't a multiple of 16. In these cases, we should chop off 1514 !!! FIXME: a few samples at the end and convert them separately. */ 1515 1516 #if DEBUG_AUDIOSTREAM 1517 printf("AUDIOSTREAM: wants to put %d preconverted bytes\n", buflen); 1518 #endif 1519 1520 if (!stream) { 1521 return SDL_InvalidParamError("stream"); 1522 } else if (!buf) { 1523 return SDL_InvalidParamError("buf"); 1524 } else if (len == 0) { 1525 return 0; /* nothing to do. */ 1526 } else if ((len % stream->src_sample_frame_size) != 0) { 1527 return SDL_SetError("Can't add partial sample frames"); 1528 } 1529 1530 if (!stream->cvt_before_resampling.needed && 1531 (stream->dst_rate == stream->src_rate) && 1532 !stream->cvt_after_resampling.needed) { 1533 #if DEBUG_AUDIOSTREAM 1534 printf("AUDIOSTREAM: no conversion needed at all, queueing %d bytes.\n", len); 1535 #endif 1536 return SDL_WriteToDataQueue(stream->queue, buf, len); 1537 } 1538 1539 while (len > 0) { 1540 int amount; 1541 1542 /* If we don't have a staging buffer or we're given enough data that 1543 we don't need to store it for later, skip the staging process. 1544 */ 1545 if (!stream->staging_buffer_filled && len >= stream->staging_buffer_size) { 1546 return SDL_AudioStreamPutInternal(stream, buf, len, NULL); 1547 } 1548 1549 /* If there's not enough data to fill the staging buffer, just save it */ 1550 if ((stream->staging_buffer_filled + len) < stream->staging_buffer_size) { 1551 SDL_memcpy(stream->staging_buffer + stream->staging_buffer_filled, buf, len); 1552 stream->staging_buffer_filled += len; 1553 return 0; 1554 } 1555 1556 /* Fill the staging buffer, process it, and continue */ 1557 amount = (stream->staging_buffer_size - stream->staging_buffer_filled); 1558 SDL_assert(amount > 0); 1559 SDL_memcpy(stream->staging_buffer + stream->staging_buffer_filled, buf, amount); 1560 stream->staging_buffer_filled = 0; 1561 if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, NULL) < 0) { 1562 return -1; 1563 } 1564 buf = (void *)((Uint8 *)buf + amount); 1565 len -= amount; 1566 } 1567 return 0; 1568 } 1569 1570 int SDL_AudioStreamFlush(SDL_AudioStream *stream) 1571 { 1572 if (!stream) { 1573 return SDL_InvalidParamError("stream"); 1574 } 1575 1576 #if DEBUG_AUDIOSTREAM 1577 printf("AUDIOSTREAM: flushing! staging_buffer_filled=%d bytes\n", stream->staging_buffer_filled); 1578 #endif 1579 1580 /* shouldn't use a staging buffer if we're not resampling. */ 1581 SDL_assert((stream->dst_rate != stream->src_rate) || (stream->staging_buffer_filled == 0)); 1582 1583 if (stream->staging_buffer_filled > 0) { 1584 /* push the staging buffer + silence. We need to flush out not just 1585 the staging buffer, but the piece that the stream was saving off 1586 for right-side resampler padding. */ 1587 const SDL_bool first_run = stream->first_run; 1588 const int filled = stream->staging_buffer_filled; 1589 int actual_input_frames = filled / stream->src_sample_frame_size; 1590 if (!first_run) 1591 actual_input_frames += stream->resampler_padding_samples / stream->pre_resample_channels; 1592 1593 if (actual_input_frames > 0) { /* don't bother if nothing to flush. */ 1594 /* This is how many bytes we're expecting without silence appended. */ 1595 int flush_remaining = ((int) SDL_ceil(actual_input_frames * stream->rate_incr)) * stream->dst_sample_frame_size; 1596 1597 #if DEBUG_AUDIOSTREAM 1598 printf("AUDIOSTREAM: flushing with padding to get max %d bytes!\n", flush_remaining); 1599 #endif 1600 1601 SDL_memset(stream->staging_buffer + filled, '\0', stream->staging_buffer_size - filled); 1602 if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, &flush_remaining) < 0) { 1603 return -1; 1604 } 1605 1606 /* we have flushed out (or initially filled) the pending right-side 1607 resampler padding, but we need to push more silence to guarantee 1608 the staging buffer is fully flushed out, too. */ 1609 SDL_memset(stream->staging_buffer, '\0', filled); 1610 if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, &flush_remaining) < 0) { 1611 return -1; 1612 } 1613 } 1614 } 1615 1616 stream->staging_buffer_filled = 0; 1617 stream->first_run = SDL_TRUE; 1618 1619 return 0; 1620 } 1621 1622 /* get converted/resampled data from the stream */ 1623 int 1624 SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len) 1625 { 1626 #if DEBUG_AUDIOSTREAM 1627 printf("AUDIOSTREAM: want to get %d converted bytes\n", len); 1628 #endif 1629 1630 if (!stream) { 1631 return SDL_InvalidParamError("stream"); 1632 } else if (!buf) { 1633 return SDL_InvalidParamError("buf"); 1634 } else if (len <= 0) { 1635 return 0; /* nothing to do. */ 1636 } else if ((len % stream->dst_sample_frame_size) != 0) { 1637 return SDL_SetError("Can't request partial sample frames"); 1638 } 1639 1640 return (int) SDL_ReadFromDataQueue(stream->queue, buf, len); 1641 } 1642 1643 /* number of converted/resampled bytes available */ 1644 int 1645 SDL_AudioStreamAvailable(SDL_AudioStream *stream) 1646 { 1647 return stream ? (int) SDL_CountDataQueue(stream->queue) : 0; 1648 } 1649 1650 void 1651 SDL_AudioStreamClear(SDL_AudioStream *stream) 1652 { 1653 if (!stream) { 1654 SDL_InvalidParamError("stream"); 1655 } else { 1656 SDL_ClearDataQueue(stream->queue, stream->packetlen * 2); 1657 if (stream->reset_resampler_func) { 1658 stream->reset_resampler_func(stream); 1659 } 1660 stream->first_run = SDL_TRUE; 1661 stream->staging_buffer_filled = 0; 1662 } 1663 } 1664 1665 /* dispose of a stream */ 1666 void 1667 SDL_FreeAudioStream(SDL_AudioStream *stream) 1668 { 1669 if (stream) { 1670 if (stream->cleanup_resampler_func) { 1671 stream->cleanup_resampler_func(stream); 1672 } 1673 SDL_FreeDataQueue(stream->queue); 1674 SDL_free(stream->staging_buffer); 1675 SDL_free(stream->work_buffer_base); 1676 SDL_free(stream->resampler_padding); 1677 SDL_free(stream); 1678 } 1679 } 1680 1681 /* vi: set ts=4 sw=4 expandtab: */ 1682