diff options
Diffstat (limited to '3rdparty/SDL2/src/audio/SDL_audiocvt.c')
-rw-r--r-- | 3rdparty/SDL2/src/audio/SDL_audiocvt.c | 1121 |
1 files changed, 0 insertions, 1121 deletions
diff --git a/3rdparty/SDL2/src/audio/SDL_audiocvt.c b/3rdparty/SDL2/src/audio/SDL_audiocvt.c deleted file mode 100644 index 3b47c4cbcc0..00000000000 --- a/3rdparty/SDL2/src/audio/SDL_audiocvt.c +++ /dev/null @@ -1,1121 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org> - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "../SDL_internal.h" - -/* Functions for audio drivers to perform runtime conversion of audio format */ - -#include "SDL_audio.h" -#include "SDL_audio_c.h" - -#include "SDL_assert.h" - -/* #define DEBUG_CONVERT */ - -/* Effectively mix right and left channels into a single channel */ -static void SDLCALL -SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) -{ - int i; - Sint32 sample; - -#ifdef DEBUG_CONVERT - fprintf(stderr, "Converting to mono\n"); -#endif - switch (format & (SDL_AUDIO_MASK_SIGNED | - SDL_AUDIO_MASK_BITSIZE | - SDL_AUDIO_MASK_DATATYPE)) { - case AUDIO_U8: - { - Uint8 *src, *dst; - - src = cvt->buf; - dst = cvt->buf; - for (i = cvt->len_cvt / 2; i; --i) { - sample = src[0] + src[1]; - *dst = (Uint8) (sample / 2); - src += 2; - dst += 1; - } - } - break; - - case AUDIO_S8: - { - Sint8 *src, *dst; - - src = (Sint8 *) cvt->buf; - dst = (Sint8 *) cvt->buf; - for (i = cvt->len_cvt / 2; i; --i) { - sample = src[0] + src[1]; - *dst = (Sint8) (sample / 2); - src += 2; - dst += 1; - } - } - break; - - case AUDIO_U16: - { - Uint8 *src, *dst; - - src = cvt->buf; - dst = cvt->buf; - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 4; i; --i) { - sample = (Uint16) ((src[0] << 8) | src[1]) + - (Uint16) ((src[2] << 8) | src[3]); - sample /= 2; - dst[1] = (sample & 0xFF); - sample >>= 8; - dst[0] = (sample & 0xFF); - src += 4; - dst += 2; - } - } else { - for (i = cvt->len_cvt / 4; i; --i) { - sample = (Uint16) ((src[1] << 8) | src[0]) + - (Uint16) ((src[3] << 8) | src[2]); - sample /= 2; - dst[0] = (sample & 0xFF); - sample >>= 8; - dst[1] = (sample & 0xFF); - src += 4; - dst += 2; - } - } - } - break; - - case AUDIO_S16: - { - Uint8 *src, *dst; - - src = cvt->buf; - dst = cvt->buf; - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 4; i; --i) { - sample = (Sint16) ((src[0] << 8) | src[1]) + - (Sint16) ((src[2] << 8) | src[3]); - sample /= 2; - dst[1] = (sample & 0xFF); - sample >>= 8; - dst[0] = (sample & 0xFF); - src += 4; - dst += 2; - } - } else { - for (i = cvt->len_cvt / 4; i; --i) { - sample = (Sint16) ((src[1] << 8) | src[0]) + - (Sint16) ((src[3] << 8) | src[2]); - sample /= 2; - dst[0] = (sample & 0xFF); - sample >>= 8; - dst[1] = (sample & 0xFF); - src += 4; - dst += 2; - } - } - } - break; - - case AUDIO_S32: - { - const Uint32 *src = (const Uint32 *) cvt->buf; - Uint32 *dst = (Uint32 *) cvt->buf; - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 8; i; --i, src += 2) { - const Sint64 added = - (((Sint64) (Sint32) SDL_SwapBE32(src[0])) + - ((Sint64) (Sint32) SDL_SwapBE32(src[1]))); - *(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added / 2))); - } - } else { - for (i = cvt->len_cvt / 8; i; --i, src += 2) { - const Sint64 added = - (((Sint64) (Sint32) SDL_SwapLE32(src[0])) + - ((Sint64) (Sint32) SDL_SwapLE32(src[1]))); - *(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added / 2))); - } - } - } - break; - - case AUDIO_F32: - { - const float *src = (const float *) cvt->buf; - float *dst = (float *) cvt->buf; - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 8; i; --i, src += 2) { - const float src1 = SDL_SwapFloatBE(src[0]); - const float src2 = SDL_SwapFloatBE(src[1]); - const double added = ((double) src1) + ((double) src2); - const float halved = (float) (added * 0.5); - *(dst++) = SDL_SwapFloatBE(halved); - } - } else { - for (i = cvt->len_cvt / 8; i; --i, src += 2) { - const float src1 = SDL_SwapFloatLE(src[0]); - const float src2 = SDL_SwapFloatLE(src[1]); - const double added = ((double) src1) + ((double) src2); - const float halved = (float) (added * 0.5); - *(dst++) = SDL_SwapFloatLE(halved); - } - } - } - break; - } - - cvt->len_cvt /= 2; - if (cvt->filters[++cvt->filter_index]) { - cvt->filters[cvt->filter_index] (cvt, format); - } -} - - -/* Discard top 4 channels */ -static void SDLCALL -SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format) -{ - int i; - -#ifdef DEBUG_CONVERT - fprintf(stderr, "Converting down from 6 channels to stereo\n"); -#endif - -#define strip_chans_6_to_2(type) \ - { \ - const type *src = (const type *) cvt->buf; \ - type *dst = (type *) cvt->buf; \ - for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \ - dst[0] = src[0]; \ - dst[1] = src[1]; \ - src += 6; \ - dst += 2; \ - } \ - } - - /* this function only cares about typesize, and data as a block of bits. */ - switch (SDL_AUDIO_BITSIZE(format)) { - case 8: - strip_chans_6_to_2(Uint8); - break; - case 16: - strip_chans_6_to_2(Uint16); - break; - case 32: - strip_chans_6_to_2(Uint32); - break; - } - -#undef strip_chans_6_to_2 - - cvt->len_cvt /= 3; - if (cvt->filters[++cvt->filter_index]) { - cvt->filters[cvt->filter_index] (cvt, format); - } -} - - -/* Discard top 2 channels of 6 */ -static void SDLCALL -SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format) -{ - int i; - -#ifdef DEBUG_CONVERT - fprintf(stderr, "Converting 6 down to quad\n"); -#endif - -#define strip_chans_6_to_4(type) \ - { \ - const type *src = (const type *) cvt->buf; \ - type *dst = (type *) cvt->buf; \ - for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \ - dst[0] = src[0]; \ - dst[1] = src[1]; \ - dst[2] = src[2]; \ - dst[3] = src[3]; \ - src += 6; \ - dst += 4; \ - } \ - } - - /* this function only cares about typesize, and data as a block of bits. */ - switch (SDL_AUDIO_BITSIZE(format)) { - case 8: - strip_chans_6_to_4(Uint8); - break; - case 16: - strip_chans_6_to_4(Uint16); - break; - case 32: - strip_chans_6_to_4(Uint32); - break; - } - -#undef strip_chans_6_to_4 - - cvt->len_cvt /= 6; - cvt->len_cvt *= 4; - if (cvt->filters[++cvt->filter_index]) { - cvt->filters[cvt->filter_index] (cvt, format); - } -} - -/* Duplicate a mono channel to both stereo channels */ -static void SDLCALL -SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format) -{ - int i; - -#ifdef DEBUG_CONVERT - fprintf(stderr, "Converting to stereo\n"); -#endif - -#define dup_chans_1_to_2(type) \ - { \ - const type *src = (const type *) (cvt->buf + cvt->len_cvt); \ - type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \ - for (i = cvt->len_cvt / sizeof(type); i; --i) { \ - src -= 1; \ - dst -= 2; \ - dst[0] = dst[1] = *src; \ - } \ - } - - /* this function only cares about typesize, and data as a block of bits. */ - switch (SDL_AUDIO_BITSIZE(format)) { - case 8: - dup_chans_1_to_2(Uint8); - break; - case 16: - dup_chans_1_to_2(Uint16); - break; - case 32: - dup_chans_1_to_2(Uint32); - break; - } - -#undef dup_chans_1_to_2 - - cvt->len_cvt *= 2; - if (cvt->filters[++cvt->filter_index]) { - cvt->filters[cvt->filter_index] (cvt, format); - } -} - - -/* Duplicate a stereo channel to a pseudo-5.1 stream */ -static void SDLCALL -SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format) -{ - int i; - -#ifdef DEBUG_CONVERT - fprintf(stderr, "Converting stereo to surround\n"); -#endif - - switch (format & (SDL_AUDIO_MASK_SIGNED | - SDL_AUDIO_MASK_BITSIZE | - SDL_AUDIO_MASK_DATATYPE)) { - case AUDIO_U8: - { - Uint8 *src, *dst, lf, rf, ce; - - src = (Uint8 *) (cvt->buf + cvt->len_cvt); - dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3); - for (i = cvt->len_cvt; i; --i) { - dst -= 6; - src -= 2; - lf = src[0]; - rf = src[1]; - ce = (lf / 2) + (rf / 2); - dst[0] = lf; - dst[1] = rf; - dst[2] = lf - ce; - dst[3] = rf - ce; - dst[4] = ce; - dst[5] = ce; - } - } - break; - - case AUDIO_S8: - { - Sint8 *src, *dst, lf, rf, ce; - - src = (Sint8 *) cvt->buf + cvt->len_cvt; - dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3; - for (i = cvt->len_cvt; i; --i) { - dst -= 6; - src -= 2; - lf = src[0]; - rf = src[1]; - ce = (lf / 2) + (rf / 2); - dst[0] = lf; - dst[1] = rf; - dst[2] = lf - ce; - dst[3] = rf - ce; - dst[4] = ce; - dst[5] = ce; - } - } - break; - - case AUDIO_U16: - { - Uint8 *src, *dst; - Uint16 lf, rf, ce, lr, rr; - - src = cvt->buf + cvt->len_cvt; - dst = cvt->buf + cvt->len_cvt * 3; - - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 4; i; --i) { - dst -= 12; - src -= 4; - lf = (Uint16) ((src[0] << 8) | src[1]); - rf = (Uint16) ((src[2] << 8) | src[3]); - ce = (lf / 2) + (rf / 2); - rr = lf - ce; - lr = rf - ce; - dst[1] = (lf & 0xFF); - dst[0] = ((lf >> 8) & 0xFF); - dst[3] = (rf & 0xFF); - dst[2] = ((rf >> 8) & 0xFF); - - dst[1 + 4] = (lr & 0xFF); - dst[0 + 4] = ((lr >> 8) & 0xFF); - dst[3 + 4] = (rr & 0xFF); - dst[2 + 4] = ((rr >> 8) & 0xFF); - - dst[1 + 8] = (ce & 0xFF); - dst[0 + 8] = ((ce >> 8) & 0xFF); - dst[3 + 8] = (ce & 0xFF); - dst[2 + 8] = ((ce >> 8) & 0xFF); - } - } else { - for (i = cvt->len_cvt / 4; i; --i) { - dst -= 12; - src -= 4; - lf = (Uint16) ((src[1] << 8) | src[0]); - rf = (Uint16) ((src[3] << 8) | src[2]); - ce = (lf / 2) + (rf / 2); - rr = lf - ce; - lr = rf - ce; - dst[0] = (lf & 0xFF); - dst[1] = ((lf >> 8) & 0xFF); - dst[2] = (rf & 0xFF); - dst[3] = ((rf >> 8) & 0xFF); - - dst[0 + 4] = (lr & 0xFF); - dst[1 + 4] = ((lr >> 8) & 0xFF); - dst[2 + 4] = (rr & 0xFF); - dst[3 + 4] = ((rr >> 8) & 0xFF); - - dst[0 + 8] = (ce & 0xFF); - dst[1 + 8] = ((ce >> 8) & 0xFF); - dst[2 + 8] = (ce & 0xFF); - dst[3 + 8] = ((ce >> 8) & 0xFF); - } - } - } - break; - - case AUDIO_S16: - { - Uint8 *src, *dst; - Sint16 lf, rf, ce, lr, rr; - - src = cvt->buf + cvt->len_cvt; - dst = cvt->buf + cvt->len_cvt * 3; - - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 4; i; --i) { - dst -= 12; - src -= 4; - lf = (Sint16) ((src[0] << 8) | src[1]); - rf = (Sint16) ((src[2] << 8) | src[3]); - ce = (lf / 2) + (rf / 2); - rr = lf - ce; - lr = rf - ce; - dst[1] = (lf & 0xFF); - dst[0] = ((lf >> 8) & 0xFF); - dst[3] = (rf & 0xFF); - dst[2] = ((rf >> 8) & 0xFF); - - dst[1 + 4] = (lr & 0xFF); - dst[0 + 4] = ((lr >> 8) & 0xFF); - dst[3 + 4] = (rr & 0xFF); - dst[2 + 4] = ((rr >> 8) & 0xFF); - - dst[1 + 8] = (ce & 0xFF); - dst[0 + 8] = ((ce >> 8) & 0xFF); - dst[3 + 8] = (ce & 0xFF); - dst[2 + 8] = ((ce >> 8) & 0xFF); - } - } else { - for (i = cvt->len_cvt / 4; i; --i) { - dst -= 12; - src -= 4; - lf = (Sint16) ((src[1] << 8) | src[0]); - rf = (Sint16) ((src[3] << 8) | src[2]); - ce = (lf / 2) + (rf / 2); - rr = lf - ce; - lr = rf - ce; - dst[0] = (lf & 0xFF); - dst[1] = ((lf >> 8) & 0xFF); - dst[2] = (rf & 0xFF); - dst[3] = ((rf >> 8) & 0xFF); - - dst[0 + 4] = (lr & 0xFF); - dst[1 + 4] = ((lr >> 8) & 0xFF); - dst[2 + 4] = (rr & 0xFF); - dst[3 + 4] = ((rr >> 8) & 0xFF); - - dst[0 + 8] = (ce & 0xFF); - dst[1 + 8] = ((ce >> 8) & 0xFF); - dst[2 + 8] = (ce & 0xFF); - dst[3 + 8] = ((ce >> 8) & 0xFF); - } - } - } - break; - - case AUDIO_S32: - { - Sint32 lf, rf, ce; - const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt); - Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 3); - - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 8; i; --i) { - dst -= 6; - src -= 2; - lf = (Sint32) SDL_SwapBE32(src[0]); - rf = (Sint32) SDL_SwapBE32(src[1]); - ce = (lf / 2) + (rf / 2); - dst[0] = SDL_SwapBE32((Uint32) lf); - dst[1] = SDL_SwapBE32((Uint32) rf); - dst[2] = SDL_SwapBE32((Uint32) (lf - ce)); - dst[3] = SDL_SwapBE32((Uint32) (rf - ce)); - dst[4] = SDL_SwapBE32((Uint32) ce); - dst[5] = SDL_SwapBE32((Uint32) ce); - } - } else { - for (i = cvt->len_cvt / 8; i; --i) { - dst -= 6; - src -= 2; - lf = (Sint32) SDL_SwapLE32(src[0]); - rf = (Sint32) SDL_SwapLE32(src[1]); - ce = (lf / 2) + (rf / 2); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = SDL_SwapLE32((Uint32) (lf - ce)); - dst[3] = SDL_SwapLE32((Uint32) (rf - ce)); - dst[4] = SDL_SwapLE32((Uint32) ce); - dst[5] = SDL_SwapLE32((Uint32) ce); - } - } - } - break; - - case AUDIO_F32: - { - float lf, rf, ce; - const float *src = (const float *) (cvt->buf + cvt->len_cvt); - float *dst = (float *) (cvt->buf + cvt->len_cvt * 3); - - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 8; i; --i) { - dst -= 6; - src -= 2; - lf = SDL_SwapFloatBE(src[0]); - rf = SDL_SwapFloatBE(src[1]); - ce = (lf * 0.5f) + (rf * 0.5f); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = SDL_SwapFloatBE(lf - ce); - dst[3] = SDL_SwapFloatBE(rf - ce); - dst[4] = dst[5] = SDL_SwapFloatBE(ce); - } - } else { - for (i = cvt->len_cvt / 8; i; --i) { - dst -= 6; - src -= 2; - lf = SDL_SwapFloatLE(src[0]); - rf = SDL_SwapFloatLE(src[1]); - ce = (lf * 0.5f) + (rf * 0.5f); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = SDL_SwapFloatLE(lf - ce); - dst[3] = SDL_SwapFloatLE(rf - ce); - dst[4] = dst[5] = SDL_SwapFloatLE(ce); - } - } - } - break; - - } - cvt->len_cvt *= 3; - if (cvt->filters[++cvt->filter_index]) { - cvt->filters[cvt->filter_index] (cvt, format); - } -} - - -/* Duplicate a stereo channel to a pseudo-4.0 stream */ -static void SDLCALL -SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format) -{ - int i; - -#ifdef DEBUG_CONVERT - fprintf(stderr, "Converting stereo to quad\n"); -#endif - - switch (format & (SDL_AUDIO_MASK_SIGNED | - SDL_AUDIO_MASK_BITSIZE | - SDL_AUDIO_MASK_DATATYPE)) { - case AUDIO_U8: - { - Uint8 *src, *dst, lf, rf, ce; - - src = (Uint8 *) (cvt->buf + cvt->len_cvt); - dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2); - for (i = cvt->len_cvt; i; --i) { - dst -= 4; - src -= 2; - lf = src[0]; - rf = src[1]; - ce = (lf / 2) + (rf / 2); - dst[0] = lf; - dst[1] = rf; - dst[2] = lf - ce; - dst[3] = rf - ce; - } - } - break; - - case AUDIO_S8: - { - Sint8 *src, *dst, lf, rf, ce; - - src = (Sint8 *) cvt->buf + cvt->len_cvt; - dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2; - for (i = cvt->len_cvt; i; --i) { - dst -= 4; - src -= 2; - lf = src[0]; - rf = src[1]; - ce = (lf / 2) + (rf / 2); - dst[0] = lf; - dst[1] = rf; - dst[2] = lf - ce; - dst[3] = rf - ce; - } - } - break; - - case AUDIO_U16: - { - Uint8 *src, *dst; - Uint16 lf, rf, ce, lr, rr; - - src = cvt->buf + cvt->len_cvt; - dst = cvt->buf + cvt->len_cvt * 2; - - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 4; i; --i) { - dst -= 8; - src -= 4; - lf = (Uint16) ((src[0] << 8) | src[1]); - rf = (Uint16) ((src[2] << 8) | src[3]); - ce = (lf / 2) + (rf / 2); - rr = lf - ce; - lr = rf - ce; - dst[1] = (lf & 0xFF); - dst[0] = ((lf >> 8) & 0xFF); - dst[3] = (rf & 0xFF); - dst[2] = ((rf >> 8) & 0xFF); - - dst[1 + 4] = (lr & 0xFF); - dst[0 + 4] = ((lr >> 8) & 0xFF); - dst[3 + 4] = (rr & 0xFF); - dst[2 + 4] = ((rr >> 8) & 0xFF); - } - } else { - for (i = cvt->len_cvt / 4; i; --i) { - dst -= 8; - src -= 4; - lf = (Uint16) ((src[1] << 8) | src[0]); - rf = (Uint16) ((src[3] << 8) | src[2]); - ce = (lf / 2) + (rf / 2); - rr = lf - ce; - lr = rf - ce; - dst[0] = (lf & 0xFF); - dst[1] = ((lf >> 8) & 0xFF); - dst[2] = (rf & 0xFF); - dst[3] = ((rf >> 8) & 0xFF); - - dst[0 + 4] = (lr & 0xFF); - dst[1 + 4] = ((lr >> 8) & 0xFF); - dst[2 + 4] = (rr & 0xFF); - dst[3 + 4] = ((rr >> 8) & 0xFF); - } - } - } - break; - - case AUDIO_S16: - { - Uint8 *src, *dst; - Sint16 lf, rf, ce, lr, rr; - - src = cvt->buf + cvt->len_cvt; - dst = cvt->buf + cvt->len_cvt * 2; - - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 4; i; --i) { - dst -= 8; - src -= 4; - lf = (Sint16) ((src[0] << 8) | src[1]); - rf = (Sint16) ((src[2] << 8) | src[3]); - ce = (lf / 2) + (rf / 2); - rr = lf - ce; - lr = rf - ce; - dst[1] = (lf & 0xFF); - dst[0] = ((lf >> 8) & 0xFF); - dst[3] = (rf & 0xFF); - dst[2] = ((rf >> 8) & 0xFF); - - dst[1 + 4] = (lr & 0xFF); - dst[0 + 4] = ((lr >> 8) & 0xFF); - dst[3 + 4] = (rr & 0xFF); - dst[2 + 4] = ((rr >> 8) & 0xFF); - } - } else { - for (i = cvt->len_cvt / 4; i; --i) { - dst -= 8; - src -= 4; - lf = (Sint16) ((src[1] << 8) | src[0]); - rf = (Sint16) ((src[3] << 8) | src[2]); - ce = (lf / 2) + (rf / 2); - rr = lf - ce; - lr = rf - ce; - dst[0] = (lf & 0xFF); - dst[1] = ((lf >> 8) & 0xFF); - dst[2] = (rf & 0xFF); - dst[3] = ((rf >> 8) & 0xFF); - - dst[0 + 4] = (lr & 0xFF); - dst[1 + 4] = ((lr >> 8) & 0xFF); - dst[2 + 4] = (rr & 0xFF); - dst[3 + 4] = ((rr >> 8) & 0xFF); - } - } - } - break; - - case AUDIO_S32: - { - const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt); - Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2); - Sint32 lf, rf, ce; - - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 8; i; --i) { - dst -= 4; - src -= 2; - lf = (Sint32) SDL_SwapBE32(src[0]); - rf = (Sint32) SDL_SwapBE32(src[1]); - ce = (lf / 2) + (rf / 2); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = SDL_SwapBE32((Uint32) (lf - ce)); - dst[3] = SDL_SwapBE32((Uint32) (rf - ce)); - } - } else { - for (i = cvt->len_cvt / 8; i; --i) { - dst -= 4; - src -= 2; - lf = (Sint32) SDL_SwapLE32(src[0]); - rf = (Sint32) SDL_SwapLE32(src[1]); - ce = (lf / 2) + (rf / 2); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = SDL_SwapLE32((Uint32) (lf - ce)); - dst[3] = SDL_SwapLE32((Uint32) (rf - ce)); - } - } - } - break; - - case AUDIO_F32: - { - const float *src = (const float *) (cvt->buf + cvt->len_cvt); - float *dst = (float *) (cvt->buf + cvt->len_cvt * 2); - float lf, rf, ce; - - if (SDL_AUDIO_ISBIGENDIAN(format)) { - for (i = cvt->len_cvt / 8; i; --i) { - dst -= 4; - src -= 2; - lf = SDL_SwapFloatBE(src[0]); - rf = SDL_SwapFloatBE(src[1]); - ce = (lf / 2) + (rf / 2); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = SDL_SwapFloatBE(lf - ce); - dst[3] = SDL_SwapFloatBE(rf - ce); - } - } else { - for (i = cvt->len_cvt / 8; i; --i) { - dst -= 4; - src -= 2; - lf = SDL_SwapFloatLE(src[0]); - rf = SDL_SwapFloatLE(src[1]); - ce = (lf / 2) + (rf / 2); - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = SDL_SwapFloatLE(lf - ce); - dst[3] = SDL_SwapFloatLE(rf - ce); - } - } - } - break; - } - cvt->len_cvt *= 2; - if (cvt->filters[++cvt->filter_index]) { - cvt->filters[cvt->filter_index] (cvt, format); - } -} - - -int -SDL_ConvertAudio(SDL_AudioCVT * cvt) -{ - /* !!! FIXME: (cvt) should be const; stack-copy it here. */ - /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */ - - /* Make sure there's data to convert */ - if (cvt->buf == NULL) { - SDL_SetError("No buffer allocated for conversion"); - return (-1); - } - /* Return okay if no conversion is necessary */ - cvt->len_cvt = cvt->len; - if (cvt->filters[0] == NULL) { - return (0); - } - - /* Set up the conversion and go! */ - cvt->filter_index = 0; - cvt->filters[0] (cvt, cvt->src_format); - return (0); -} - - -static SDL_AudioFilter -SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt) -{ - /* - * Fill in any future conversions that are specialized to a - * processor, platform, compiler, or library here. - */ - - return NULL; /* no specialized converter code available. */ -} - - -/* - * Find a converter between two data types. We try to select a hand-tuned - * asm/vectorized/optimized function first, and then fallback to an - * autogenerated function that is customized to convert between two - * specific data types. - */ -static int -SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt, - SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt) -{ - if (src_fmt != dst_fmt) { - const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt); - const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt); - SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt); - - /* No hand-tuned converter? Try the autogenerated ones. */ - if (filter == NULL) { - int i; - for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) { - const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i]; - if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) { - filter = filt->filter; - break; - } - } - - if (filter == NULL) { - SDL_SetError("No conversion available for these formats"); - return -1; - } - } - - /* Update (cvt) with filter details... */ - cvt->filters[cvt->filter_index++] = filter; - if (src_bitsize < dst_bitsize) { - const int mult = (dst_bitsize / src_bitsize); - cvt->len_mult *= mult; - cvt->len_ratio *= mult; - } else if (src_bitsize > dst_bitsize) { - cvt->len_ratio /= (src_bitsize / dst_bitsize); - } - - return 1; /* added a converter. */ - } - - return 0; /* no conversion necessary. */ -} - - -static SDL_AudioFilter -SDL_HandTunedResampleCVT(SDL_AudioCVT * cvt, int dst_channels, - int src_rate, int dst_rate) -{ - /* - * Fill in any future conversions that are specialized to a - * processor, platform, compiler, or library here. - */ - - return NULL; /* no specialized converter code available. */ -} - -static int -SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate) -{ - int retval = 0; - - /* If we only built with the arbitrary resamplers, ignore multiples. */ -#if !LESS_RESAMPLERS - int lo, hi; - int div; - - SDL_assert(src_rate != 0); - SDL_assert(dst_rate != 0); - SDL_assert(src_rate != dst_rate); - - if (src_rate < dst_rate) { - lo = src_rate; - hi = dst_rate; - } else { - lo = dst_rate; - hi = src_rate; - } - - /* zero means "not a supported multiple" ... we only do 2x and 4x. */ - if ((hi % lo) != 0) - return 0; /* not a multiple. */ - - div = hi / lo; - retval = ((div == 2) || (div == 4)) ? div : 0; -#endif - - return retval; -} - -static int -SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, int dst_channels, - int src_rate, int dst_rate) -{ - if (src_rate != dst_rate) { - SDL_AudioFilter filter = SDL_HandTunedResampleCVT(cvt, dst_channels, - src_rate, dst_rate); - - /* No hand-tuned converter? Try the autogenerated ones. */ - if (filter == NULL) { - int i; - const int upsample = (src_rate < dst_rate) ? 1 : 0; - const int multiple = - SDL_FindFrequencyMultiple(src_rate, dst_rate); - - for (i = 0; sdl_audio_rate_filters[i].filter != NULL; i++) { - const SDL_AudioRateFilters *filt = &sdl_audio_rate_filters[i]; - if ((filt->fmt == cvt->dst_format) && - (filt->channels == dst_channels) && - (filt->upsample == upsample) && - (filt->multiple == multiple)) { - filter = filt->filter; - break; - } - } - - if (filter == NULL) { - SDL_SetError("No conversion available for these rates"); - return -1; - } - } - - /* Update (cvt) with filter details... */ - cvt->filters[cvt->filter_index++] = filter; - if (src_rate < dst_rate) { - const double mult = ((double) dst_rate) / ((double) src_rate); - cvt->len_mult *= (int) SDL_ceil(mult); - cvt->len_ratio *= mult; - } else { - cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate); - } - - return 1; /* added a converter. */ - } - - return 0; /* no conversion necessary. */ -} - - -/* Creates a set of audio filters to convert from one format to another. - Returns -1 if the format conversion is not supported, 0 if there's - no conversion needed, or 1 if the audio filter is set up. -*/ - -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) -{ - /* - * !!! FIXME: reorder filters based on which grow/shrink the buffer. - * !!! FIXME: ideally, we should do everything that shrinks the buffer - * !!! FIXME: first, so we don't have to process as many bytes in a given - * !!! FIXME: filter and abuse the CPU cache less. This might not be as - * !!! FIXME: good in practice as it sounds in theory, though. - */ - - /* Sanity check target pointer */ - if (cvt == NULL) { - return SDL_InvalidParamError("cvt"); - } - - /* there are no unsigned types over 16 bits, so catch this up front. */ - if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) { - return SDL_SetError("Invalid source format"); - } - if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) { - return SDL_SetError("Invalid destination format"); - } - - /* prevent possible divisions by zero, etc. */ - if ((src_channels == 0) || (dst_channels == 0)) { - return SDL_SetError("Source or destination channels is zero"); - } - if ((src_rate == 0) || (dst_rate == 0)) { - return SDL_SetError("Source or destination rate is zero"); - } -#ifdef DEBUG_CONVERT - printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n", - src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate); -#endif - - /* Start off with no conversion necessary */ - SDL_zerop(cvt); - cvt->src_format = src_fmt; - cvt->dst_format = dst_fmt; - cvt->needed = 0; - cvt->filter_index = 0; - cvt->filters[0] = NULL; - cvt->len_mult = 1; - cvt->len_ratio = 1.0; - cvt->rate_incr = ((double) dst_rate) / ((double) src_rate); - - /* Convert data types, if necessary. Updates (cvt). */ - if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1) { - return -1; /* shouldn't happen, but just in case... */ - } - - /* Channel conversion */ - if (src_channels != dst_channels) { - if ((src_channels == 1) && (dst_channels > 1)) { - cvt->filters[cvt->filter_index++] = SDL_ConvertStereo; - cvt->len_mult *= 2; - src_channels = 2; - cvt->len_ratio *= 2; - } - if ((src_channels == 2) && (dst_channels == 6)) { - cvt->filters[cvt->filter_index++] = SDL_ConvertSurround; - src_channels = 6; - cvt->len_mult *= 3; - cvt->len_ratio *= 3; - } - if ((src_channels == 2) && (dst_channels == 4)) { - cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4; - src_channels = 4; - cvt->len_mult *= 2; - cvt->len_ratio *= 2; - } - while ((src_channels * 2) <= dst_channels) { - cvt->filters[cvt->filter_index++] = SDL_ConvertStereo; - cvt->len_mult *= 2; - src_channels *= 2; - cvt->len_ratio *= 2; - } - if ((src_channels == 6) && (dst_channels <= 2)) { - cvt->filters[cvt->filter_index++] = SDL_ConvertStrip; - src_channels = 2; - cvt->len_ratio /= 3; - } - if ((src_channels == 6) && (dst_channels == 4)) { - cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2; - src_channels = 4; - cvt->len_ratio /= 2; - } - /* This assumes that 4 channel audio is in the format: - Left {front/back} + Right {front/back} - so converting to L/R stereo works properly. - */ - while (((src_channels % 2) == 0) && - ((src_channels / 2) >= dst_channels)) { - cvt->filters[cvt->filter_index++] = SDL_ConvertMono; - src_channels /= 2; - cvt->len_ratio /= 2; - } - if (src_channels != dst_channels) { - /* Uh oh.. */ ; - } - } - - /* Do rate conversion, if necessary. Updates (cvt). */ - if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) == - -1) { - return -1; /* shouldn't happen, but just in case... */ - } - - /* Set up the filter information */ - if (cvt->filter_index != 0) { - cvt->needed = 1; - cvt->src_format = src_fmt; - cvt->dst_format = dst_fmt; - cvt->len = 0; - cvt->buf = NULL; - cvt->filters[cvt->filter_index] = NULL; - } - return (cvt->needed); -} - - -/* vi: set ts=4 sw=4 expandtab: */ |