diff --git a/src/libs/decoders/SDL_sound.c b/src/libs/decoders/SDL_sound.c index 49ee3f87..017a2a62 100644 --- a/src/libs/decoders/SDL_sound.c +++ b/src/libs/decoders/SDL_sound.c @@ -333,8 +333,7 @@ int __Sound_strcasecmp(const char *x, const char *y) * Allocate a Sound_Sample, and fill in most of its fields. Those that need * to be filled in later, by a decoder, will be initialized to zero. */ -static Sound_Sample *alloc_sample(SDL_RWops *rw, Sound_AudioInfo *desired, - Uint32 bufferSize) +static Sound_Sample *alloc_sample(SDL_RWops *rw, Sound_AudioInfo *desired) { /* * !!! FIXME: We're going to need to pool samples, since the mixer @@ -356,18 +355,6 @@ static Sound_Sample *alloc_sample(SDL_RWops *rw, Sound_AudioInfo *desired, memset(retval, '\0', sizeof (Sound_Sample)); memset(internal, '\0', sizeof (Sound_SampleInternal)); - assert(bufferSize > 0); - retval->buffer = malloc(bufferSize); /* pure ugly. */ - if (!retval->buffer) - { - __Sound_SetError(ERR_OUT_OF_MEMORY); - free(internal); - free(retval); - return(NULL); - } /* if */ - memset(retval->buffer, '\0', bufferSize); - retval->buffer_size = bufferSize; - if (desired != NULL) memcpy(&retval->desired, desired, sizeof (Sound_AudioInfo)); @@ -426,8 +413,6 @@ static int init_sample(const Sound_DecoderFunctions *funcs, /* success; we've got a decoder! */ - /* Now we need to set up the conversion buffer... */ - memcpy(&desired, (_desired != NULL) ? _desired : &sample->actual, sizeof (Sound_AudioInfo)); @@ -438,40 +423,9 @@ static int init_sample(const Sound_DecoderFunctions *funcs, if (desired.rate == 0) desired.rate = sample->actual.rate; - if (Sound_BuildAudioCVT(&internal->sdlcvt, - sample->actual.format, - sample->actual.channels, - sample->actual.rate, - desired.format, - desired.channels, - desired.rate, - sample->buffer_size) == -1) - { - __Sound_SetError(SDL_GetError()); - funcs->close(sample); - SDL_RWseek(internal->rw, pos, SEEK_SET); /* set for next try... */ - return(0); - } /* if */ - - if (internal->sdlcvt.len_mult > 1) - { - void *rc = realloc(sample->buffer, - sample->buffer_size * internal->sdlcvt.len_mult); - if (rc == NULL) - { - funcs->close(sample); - SDL_RWseek(internal->rw, pos, SEEK_SET); /* set for next try... */ - return(0); - } /* if */ - - sample->buffer = rc; - } /* if */ /* these pointers are all one and the same. */ memcpy(&sample->desired, &desired, sizeof (Sound_AudioInfo)); - internal->sdlcvt.buf = internal->buffer = sample->buffer; - internal->buffer_size = sample->buffer_size / internal->sdlcvt.len_mult; - internal->sdlcvt.len = internal->buffer_size; /* Prepend our new Sound_Sample to the sample_list... */ SDL_LockMutex(samplelist_mutex); @@ -490,16 +444,12 @@ static int init_sample(const Sound_DecoderFunctions *funcs, fmt_to_str(sample->actual.format), sample->actual.rate, sample->actual.channels)); - - SNDDBG(("On-the-fly conversion: %s.\n", - internal->sdlcvt.needed ? "ENABLED" : "DISABLED")); - return(1); } /* init_sample */ Sound_Sample *Sound_NewSample(SDL_RWops *rw, const char *ext, - Sound_AudioInfo *desired, Uint32 bSize) + Sound_AudioInfo *desired) { Sound_Sample *retval; decoder_element *decoder; @@ -508,7 +458,7 @@ Sound_Sample *Sound_NewSample(SDL_RWops *rw, const char *ext, BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, NULL); BAIL_IF_MACRO(rw == NULL, ERR_INVALID_ARGUMENT, NULL); - retval = alloc_sample(rw, desired, bSize); + retval = alloc_sample(rw, desired); if (!retval) return(NULL); /* alloc_sample() sets error message... */ @@ -562,8 +512,6 @@ Sound_Sample *Sound_NewSample(SDL_RWops *rw, const char *ext, /* nothing could handle the sound data... */ free(retval->opaque); - if (retval->buffer != NULL) - free(retval->buffer); free(retval); SDL_RWclose(rw); __Sound_SetError(ERR_UNSUPPORTED_FORMAT); @@ -572,8 +520,7 @@ Sound_Sample *Sound_NewSample(SDL_RWops *rw, const char *ext, Sound_Sample *Sound_NewSampleFromFile(const char *filename, - Sound_AudioInfo *desired, - Uint32 bufferSize) + Sound_AudioInfo *desired) { const char *ext; SDL_RWops *rw; @@ -593,30 +540,9 @@ Sound_Sample *Sound_NewSampleFromFile(const char *filename, if (ext != NULL) ext++; - return(Sound_NewSample(rw, ext, desired, bufferSize)); + return(Sound_NewSample(rw, ext, desired)); } /* Sound_NewSampleFromFile */ - -Sound_Sample *Sound_NewSampleFromMem(const Uint8 *data, - Uint32 size, - const char *ext, - Sound_AudioInfo *desired, - Uint32 bufferSize) -{ - SDL_RWops *rw; - - BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, NULL); - BAIL_IF_MACRO(data == NULL, ERR_INVALID_ARGUMENT, NULL); - BAIL_IF_MACRO(size == 0, ERR_INVALID_ARGUMENT, NULL); - - rw = SDL_RWFromConstMem(data, size); - /* !!! FIXME: rw = RWops_FromMem(data, size);*/ - BAIL_IF_MACRO(rw == NULL, SDL_GetError(), NULL); - - return(Sound_NewSample(rw, ext, desired, bufferSize)); -} /* Sound_NewSampleFromMem */ - - void Sound_FreeSample(Sound_Sample *sample) { Sound_SampleInternal *internal; @@ -665,42 +591,13 @@ void Sound_FreeSample(Sound_Sample *sample) if (internal->rw != NULL) /* this condition is a "just in case" thing. */ SDL_RWclose(internal->rw); - if ((internal->buffer != NULL) && (internal->buffer != sample->buffer)) - free(internal->buffer); - free(internal); - - if (sample->buffer != NULL) - free(sample->buffer); - free(sample); } /* Sound_FreeSample */ - -int Sound_SetBufferSize(Sound_Sample *sample, Uint32 newSize) -{ - void *newBuf = NULL; - Sound_SampleInternal *internal = NULL; - - BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); - BAIL_IF_MACRO(sample == NULL, ERR_INVALID_ARGUMENT, 0); - internal = ((Sound_SampleInternal *) sample->opaque); - newBuf = realloc(sample->buffer, newSize * internal->sdlcvt.len_mult); - BAIL_IF_MACRO(newBuf == NULL, ERR_OUT_OF_MEMORY, 0); - - internal->sdlcvt.buf = internal->buffer = sample->buffer = newBuf; - sample->buffer_size = newSize; - internal->buffer_size = newSize / internal->sdlcvt.len_mult; - internal->sdlcvt.len = internal->buffer_size; - - return(1); -} /* Sound_SetBufferSize */ - - -Uint32 Sound_Decode(Sound_Sample *sample) +Uint32 Sound_Decode_Direct(Sound_Sample *sample, void* buffer, Uint32 desired_frames) { Sound_SampleInternal *internal = NULL; - Uint32 retval = 0; /* a boatload of sanity checks... */ BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); @@ -710,73 +607,12 @@ Uint32 Sound_Decode(Sound_Sample *sample) internal = (Sound_SampleInternal *) sample->opaque; - assert(sample->buffer != NULL); - assert(sample->buffer_size > 0); - assert(internal->buffer != NULL); - assert(internal->buffer_size > 0); - /* reset EAGAIN. Decoder can flip it back on if it needs to. */ sample->flags &= ~SOUND_SAMPLEFLAG_EAGAIN; - retval = internal->funcs->read(sample); - - if (retval > 0 && internal->sdlcvt.needed) - { - internal->sdlcvt.len = retval; - Sound_ConvertAudio(&internal->sdlcvt); - retval = internal->sdlcvt.len_cvt; - } /* if */ - - return(retval); + return internal->funcs->read(sample, buffer, desired_frames); } /* Sound_Decode */ -Uint32 Sound_DecodeAll(Sound_Sample *sample) -{ - Sound_SampleInternal *internal = NULL; - void *buf = NULL; - Uint32 newBufSize = 0; - - BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); - BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_EOF, ERR_PREV_EOF, 0); - BAIL_IF_MACRO(sample->flags & SOUND_SAMPLEFLAG_ERROR, ERR_PREV_ERROR, 0); - - internal = (Sound_SampleInternal *) sample->opaque; - - while ( ((sample->flags & SOUND_SAMPLEFLAG_EOF) == 0) && - ((sample->flags & SOUND_SAMPLEFLAG_ERROR) == 0) ) - { - Uint32 br = Sound_Decode(sample); - void *ptr = realloc(buf, newBufSize + br); - if (ptr == NULL) - { - sample->flags |= SOUND_SAMPLEFLAG_ERROR; - __Sound_SetError(ERR_OUT_OF_MEMORY); - } /* if */ - else - { - buf = ptr; - memcpy( ((char *) buf) + newBufSize, sample->buffer, br ); - newBufSize += br; - } /* else */ - } /* while */ - - if (buf == NULL) /* ...in case first call to realloc() fails... */ - return(sample->buffer_size); - - if (internal->buffer != sample->buffer) - free(internal->buffer); - - free(sample->buffer); - - internal->sdlcvt.buf = internal->buffer = sample->buffer = buf; - sample->buffer_size = newBufSize; - internal->buffer_size = newBufSize / internal->sdlcvt.len_mult; - internal->sdlcvt.len = internal->buffer_size; - - return(newBufSize); -} /* Sound_DecodeAll */ - - int Sound_Rewind(Sound_Sample *sample) { Sound_SampleInternal *internal; @@ -825,4 +661,3 @@ Sint32 Sound_GetDuration(Sound_Sample *sample) } /* Sound_GetDuration */ /* end of SDL_sound.c ... */ - diff --git a/src/libs/decoders/SDL_sound.h b/src/libs/decoders/SDL_sound.h index 8c9cf94e..9ee21df1 100644 --- a/src/libs/decoders/SDL_sound.h +++ b/src/libs/decoders/SDL_sound.h @@ -94,7 +94,6 @@ extern "C" { * \sa Sound_SampleNew * \sa Sound_SampleNewFromFile * \sa Sound_SampleDecode - * \sa Sound_SampleDecodeAll * \sa Sound_SampleSeek */ typedef enum @@ -174,8 +173,6 @@ typedef struct const Sound_DecoderInfo *decoder; /**< Decoder used for this sample. */ Sound_AudioInfo desired; /**< Desired audio format for conversion. */ Sound_AudioInfo actual; /**< Actual audio format of sample. */ - void *buffer; /**< Decoded sound data lands in here. */ - Uint32 buffer_size; /**< Current size of (buffer), in bytes (Uint8). */ Uint32 flags; /**< Flags relating to this sample. */ } Sound_Sample; @@ -440,41 +437,7 @@ SNDDECLSPEC void SDLCALL Sound_ClearError(void); */ SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSample(SDL_RWops *rw, const char *ext, - Sound_AudioInfo *desired, - Uint32 bufferSize); - -/** - * \fn Sound_Sample *Sound_NewSampleFromMem(const Uint8 *data, Sound_AudioInfo *desired, Uint32 bufferSize) - * \brief Start decoding a new sound sample from a file on disk. - * - * This is identical to Sound_NewSample(), but it creates an SDL_RWops for you - * from the (size) bytes of memory referenced by (data). - * - * This can pool RWops structures, so it may fragment the heap less over time - * than using SDL_RWFromMem(). - * - * \param filename file containing sound data. - * \param desired Format to convert sound data into. Can usually be NULL, - * if you don't need conversion. - * \param bufferSize size, in bytes, of initial read buffer. - * \return Sound_Sample pointer, which is used as a handle to several other - * SDL_sound APIs. NULL on error. If error, use - * Sound_GetError() to see what went wrong. - * - * \sa Sound_NewSample - * \sa Sound_SetBufferSize - * \sa Sound_Decode - * \sa Sound_DecodeAll - * \sa Sound_Seek - * \sa Sound_Rewind - * \sa Sound_FreeSample - */ -SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSampleFromMem(const Uint8 *data, - Uint32 size, - const char *ext, - Sound_AudioInfo *desired, - Uint32 bufferSize); - + Sound_AudioInfo *desired); /** * \fn Sound_Sample *Sound_NewSampleFromFile(const char *filename, Sound_AudioInfo *desired, Uint32 bufferSize) @@ -507,8 +470,7 @@ SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSampleFromMem(const Uint8 *data, * \sa Sound_FreeSample */ SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSampleFromFile(const char *fname, - Sound_AudioInfo *desired, - Uint32 bufferSize); + Sound_AudioInfo *desired); /** * \fn void Sound_FreeSample(Sound_Sample *sample) @@ -551,93 +513,27 @@ SNDDECLSPEC void SDLCALL Sound_FreeSample(Sound_Sample *sample); */ SNDDECLSPEC Sint32 SDLCALL Sound_GetDuration(Sound_Sample *sample); - /** - * \fn int Sound_SetBufferSize(Sound_Sample *sample, Uint32 new_size) - * \brief Change the current buffer size for a sample. + * \fn Uint32 Sound_Decode_Direct(Sound_Sample *sample) + * \brief Decode more of the sound data in a Sound_Sample directly into + * the supplied buffer. * - * If the buffer size could be changed, then the sample->buffer and - * sample->buffer_size fields will reflect that. If they could not be - * changed, then your original sample state is preserved. If the buffer is - * shrinking, the data at the end of buffer is truncated. If the buffer is - * growing, the contents of the new space at the end is undefined until you - * decode more into it or initialize it yourself. - * - * The buffer size specified must be a multiple of the size of a single - * sample point. So, if you want 16-bit, stereo samples, then your sample - * point size is (2 channels * 16 bits), or 32 bits per sample, which is four - * bytes. In such a case, you could specify 128 or 132 bytes for a buffer, - * but not 129, 130, or 131 (although in reality, you'll want to specify a - * MUCH larger buffer). - * - * \param sample The Sound_Sample whose buffer to modify. - * \param new_size The desired size, in bytes, of the new buffer. - * \return non-zero if buffer size changed, zero on failure. - * - * \sa Sound_Decode - * \sa Sound_DecodeAll - */ -SNDDECLSPEC int SDLCALL Sound_SetBufferSize(Sound_Sample *sample, - Uint32 new_size); - - -/** - * \fn Uint32 Sound_Decode(Sound_Sample *sample) - * \brief Decode more of the sound data in a Sound_Sample. - * - * It will decode at most sample->buffer_size bytes into sample->buffer in the - * desired format, and return the number of decoded bytes. - * If sample->buffer_size bytes could not be decoded, then please refer to + * It will decode at most desired_frames into buffer, and return the number + * frames decoded. + * If the number of desired_frames could not be decoded, then please refer to * sample->flags to determine if this was an end-of-stream or error condition. * * \param sample Do more decoding to this Sound_Sample. - * \return number of bytes decoded into sample->buffer. If it is less than - * sample->buffer_size, then you should check sample->flags to see + * \param buffer PCM frames into this buffer. + * \param desired_frames indicates how many PCM should be decoded. + * \return number of frames decoded into buffer. If it is less than + * desired_frames, then you should check sample->flags to see * what the current state of the sample is (EOF, error, read again). * - * \sa Sound_DecodeAll - * \sa Sound_SetBufferSize * \sa Sound_Seek * \sa Sound_Rewind */ -SNDDECLSPEC Uint32 SDLCALL Sound_Decode(Sound_Sample *sample); - - -/** - * \fn Uint32 Sound_DecodeAll(Sound_Sample *sample) - * \brief Decode the remainder of the sound data in a Sound_Sample. - * - * This will dynamically allocate memory for the ENTIRE remaining sample. - * sample->buffer_size and sample->buffer will be updated to reflect the - * new buffer. Please refer to sample->flags to determine if the decoding - * finished due to an End-of-stream or error condition. - * - * Be aware that sound data can take a large amount of memory, and that - * this function may block for quite awhile while processing. Also note - * that a streaming source (for example, from a SDL_RWops that is getting - * fed from an Internet radio feed that doesn't end) may fill all available - * memory before giving up...be sure to use this on finite sound sources - * only! - * - * When decoding the sample in its entirety, the work is done one buffer at a - * time. That is, sound is decoded in sample->buffer_size blocks, and - * appended to a continually-growing buffer until the decoding completes. - * That means that this function will need enough RAM to hold approximately - * sample->buffer_size bytes plus the complete decoded sample at most. The - * larger your buffer size, the less overhead this function needs, but beware - * the possibility of paging to disk. Best to make this user-configurable if - * the sample isn't specific and small. - * - * \param sample Do all decoding for this Sound_Sample. - * \return number of bytes decoded into sample->buffer. You should check - * sample->flags to see what the current state of the sample is - * (EOF, error, read again). - * - * \sa Sound_Decode - * \sa Sound_SetBufferSize - */ -SNDDECLSPEC Uint32 SDLCALL Sound_DecodeAll(Sound_Sample *sample); - +SNDDECLSPEC Uint32 SDLCALL Sound_Decode_Direct(Sound_Sample *sample, void* buffer, Uint32 desired_frames); /** * \fn int Sound_Rewind(Sound_Sample *sample) diff --git a/src/libs/decoders/SDL_sound_internal.h b/src/libs/decoders/SDL_sound_internal.h index d3d981d7..b479e311 100644 --- a/src/libs/decoders/SDL_sound_internal.h +++ b/src/libs/decoders/SDL_sound_internal.h @@ -126,9 +126,6 @@ typedef struct __SOUND_DECODERFUNCTIONS__ * Sound_Sample *prev; (offlimits) * SDL_RWops *rw; (can use, but do NOT close it) * const Sound_DecoderFunctions *funcs; (that's this structure) - * Sound_AudioCVT sdlcvt; (offlimits) - * void *buffer; (offlimits until read() method) - * Uint32 buffer_size; (offlimits until read() method) * void *decoder_private; (read and write access) * * in rest of Sound_Sample: @@ -136,8 +133,6 @@ typedef struct __SOUND_DECODERFUNCTIONS__ * const Sound_DecoderInfo *decoder; (read only) * Sound_AudioInfo desired; (read only, usually not needed here) * Sound_AudioInfo actual; (please fill this in) - * void *buffer; (offlimits) - * Uint32 buffer_size; (offlimits) * Sound_SampleFlags flags; (set appropriately) */ int (*open)(Sound_Sample *sample, const char *ext); @@ -157,15 +152,12 @@ typedef struct __SOUND_DECODERFUNCTIONS__ * Sound_SampleInternal *internal; * internal = (Sound_SampleInternal *) sample->opaque; * - * ...and then start decoding. Fill in up to internal->buffer_size - * bytes of decoded sound in the space pointed to by - * internal->buffer. The encoded data is read in from internal->rw. - * Data should be decoded in the format specified during the - * decoder's open() method in the sample->actual field. The - * conversion to the desired format is done at a higher level. + * ...and then start decoding. Fill in up to desired_frames + * PCM frames of decoded sound into the space pointed to by + * buffer. The encoded data is read in from internal->rw. * - * The return value is the number of bytes decoded into - * internal->buffer, which can be no more than internal->buffer_size, + * The return value is the number of frames decoded into + * buffer, which can be no more than desired_frames, * but can be less. If it is less, you should set a state flag: * * If there's just no more data (end of file, etc), then do: @@ -186,7 +178,7 @@ typedef struct __SOUND_DECODERFUNCTIONS__ * SOUND_SAMPLEFLAG_EAGAIN flag is reset before each call to this * method. */ - Uint32 (*read)(Sound_Sample *sample); + Uint32 (*read)(Sound_Sample *sample, void* buffer, Uint32 desired_frames); /* * Reset the decoding to the beginning of the stream. Nonzero on @@ -223,31 +215,6 @@ typedef struct __SOUND_DECODERFUNCTIONS__ int (*seek)(Sound_Sample *sample, Uint32 ms); } Sound_DecoderFunctions; - -/* A structure to hold a set of audio conversion filters and buffers */ -typedef struct Sound_AudioCVT -{ - int needed; /* Set to 1 if conversion possible */ - Uint16 src_format; /* Source audio format */ - Uint16 dst_format; /* Target audio format */ - double rate_incr; /* Rate conversion increment */ - Uint8 *buf; /* Buffer to hold entire audio data */ - int len; /* Length of original audio buffer */ - int len_cvt; /* Length of converted audio buffer */ - int len_mult; /* buffer must be len*len_mult big */ - double len_ratio; /* Given len, final size is len*len_ratio */ - void (*filters[20])(struct Sound_AudioCVT *cvt, Uint16 *format); - int filter_index; /* Current audio conversion function */ -} Sound_AudioCVT; - -extern SNDDECLSPEC int Sound_BuildAudioCVT(Sound_AudioCVT *cvt, - Uint16 src_format, Uint8 src_channels, Uint32 src_rate, - Uint16 dst_format, Uint8 dst_channels, Uint32 dst_rate, - Uint32 dst_size); - -extern SNDDECLSPEC int Sound_ConvertAudio(Sound_AudioCVT *cvt); - - typedef void (*MixFunc)(float *dst, void *src, Uint32 frames, float *gains); typedef struct __SOUND_SAMPLEINTERNAL__ @@ -256,7 +223,6 @@ typedef struct __SOUND_SAMPLEINTERNAL__ Sound_Sample *prev; SDL_RWops *rw; const Sound_DecoderFunctions *funcs; - Sound_AudioCVT sdlcvt; void *buffer; Uint32 buffer_size; void *decoder_private; diff --git a/src/libs/decoders/audio_convert.c b/src/libs/decoders/audio_convert.c deleted file mode 100644 index 5cce6c5b..00000000 --- a/src/libs/decoders/audio_convert.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@devolution.com -*/ - -/* - * This file was derived from SDL's SDL_audiocvt.c and is an attempt to - * address the shortcomings of it. - * - * Perhaps we can adapt some good filters from SoX? - */ - -#if HAVE_CONFIG_H -# include -#endif - -#include "SDL_sound.h" -#define __SDL_SOUND_INTERNAL__ -#include "SDL_sound_internal.h" - -/* Functions for audio drivers to perform runtime conversion of audio format */ - - -/* - * Toggle endianness. This filter is, of course, only applied to 16-bit - * audio data. - */ - -static void Sound_ConvertEndian(Sound_AudioCVT *cvt, Uint16 *format) -{ - int i; - Uint8 *data, tmp; - - /* SNDDBG(("Converting audio endianness\n")); */ - - data = cvt->buf; - - for (i = cvt->len_cvt / 2; i; --i) - { - tmp = data[0]; - data[0] = data[1]; - data[1] = tmp; - data += 2; - } /* for */ - - *format = (*format ^ 0x1000); -} /* Sound_ConvertEndian */ - - -/* - * Toggle signed/unsigned. Apparently this is done by toggling the most - * significant bit of each sample. - */ - -static void Sound_ConvertSign(Sound_AudioCVT *cvt, Uint16 *format) -{ - int i; - Uint8 *data; - - /* SNDDBG(("Converting audio signedness\n")); */ - - data = cvt->buf; - - /* 16-bit sound? */ - if ((*format & 0xFF) == 16) - { - /* Little-endian? */ - if ((*format & 0x1000) != 0x1000) - ++data; - - for (i = cvt->len_cvt / 2; i; --i) - { - *data ^= 0x80; - data += 2; - } /* for */ - } /* if */ - else - { - for (i = cvt->len_cvt; i; --i) - *data++ ^= 0x80; - } /* else */ - - *format = (*format ^ 0x8000); -} /* Sound_ConvertSign */ - - -/* - * Convert 16-bit to 8-bit. This is done by taking the most significant byte - * of each 16-bit sample. - */ - -static void Sound_Convert8(Sound_AudioCVT *cvt, Uint16 *format) -{ - int i; - Uint8 *src, *dst; - - /* SNDDBG(("Converting to 8-bit\n")); */ - - src = cvt->buf; - dst = cvt->buf; - - /* Little-endian? */ - if ((*format & 0x1000) != 0x1000) - ++src; - - for (i = cvt->len_cvt / 2; i; --i) - { - *dst = *src; - src += 2; - dst += 1; - } /* for */ - - *format = ((*format & ~0x9010) | AUDIO_U8); - cvt->len_cvt /= 2; -} /* Sound_Convert8 */ - - -/* Convert 8-bit to 16-bit - LSB */ - -static void Sound_Convert16LSB(Sound_AudioCVT *cvt, Uint16 *format) -{ - int i; - Uint8 *src, *dst; - - /* SNDDBG(("Converting to 16-bit LSB\n")); */ - - src = cvt->buf + cvt->len_cvt; - dst = cvt->buf + cvt->len_cvt * 2; - - for (i = cvt->len_cvt; i; --i) - { - src -= 1; - dst -= 2; - dst[1] = *src; - dst[0] = 0; - } /* for */ - - *format = ((*format & ~0x0008) | AUDIO_U16LSB); - cvt->len_cvt *= 2; -} /* Sound_Convert16LSB */ - - -/* Convert 8-bit to 16-bit - MSB */ - -static void Sound_Convert16MSB(Sound_AudioCVT *cvt, Uint16 *format) -{ - int i; - Uint8 *src, *dst; - - /* SNDDBG(("Converting to 16-bit MSB\n")); */ - - src = cvt->buf + cvt->len_cvt; - dst = cvt->buf + cvt->len_cvt * 2; - - for (i = cvt->len_cvt; i; --i) - { - src -= 1; - dst -= 2; - dst[0] = *src; - dst[1] = 0; - } /* for */ - - *format = ((*format & ~0x0008) | AUDIO_U16MSB); - cvt->len_cvt *= 2; -} /* Sound_Convert16MSB */ - - -/* Duplicate a mono channel to both stereo channels */ - -static void Sound_ConvertStereo(Sound_AudioCVT *cvt, Uint16 *format) -{ - int i; - - /* SNDDBG(("Converting to stereo\n")); */ - - /* 16-bit sound? */ - if ((*format & 0xFF) == 16) - { - Uint16 *src, *dst; - - src = (Uint16 *) (cvt->buf + cvt->len_cvt); - dst = (Uint16 *) (cvt->buf + cvt->len_cvt * 2); - - for (i = cvt->len_cvt/2; i; --i) - { - dst -= 2; - src -= 1; - dst[0] = src[0]; - dst[1] = src[0]; - } /* for */ - } /* if */ - else - { - Uint8 *src, *dst; - - src = cvt->buf + cvt->len_cvt; - dst = cvt->buf + cvt->len_cvt * 2; - - for (i = cvt->len_cvt; i; --i) - { - dst -= 2; - src -= 1; - dst[0] = src[0]; - dst[1] = src[0]; - } /* for */ - } /* else */ - - cvt->len_cvt *= 2; -} /* Sound_ConvertStereo */ - - -/* Effectively mix right and left channels into a single channel */ - -static void Sound_ConvertMono(Sound_AudioCVT *cvt, Uint16 *format) -{ - int i; - Sint32 sample; - Uint8 *u_src, *u_dst; - Sint8 *s_src, *s_dst; - - /* SNDDBG(("Converting to mono\n")); */ - - switch (*format) - { - case AUDIO_U8: - u_src = cvt->buf; - u_dst = cvt->buf; - - for (i = cvt->len_cvt / 2; i; --i) - { - sample = u_src[0] + u_src[1]; - *u_dst = (sample > 255) ? 255 : sample; - u_src += 2; - u_dst += 1; - } /* for */ - break; - - case AUDIO_S8: - s_src = (Sint8 *) cvt->buf; - s_dst = (Sint8 *) cvt->buf; - - for (i = cvt->len_cvt / 2; i; --i) - { - sample = s_src[0] + s_src[1]; - if (sample > 127) - *s_dst = 127; - else if (sample < -128) - *s_dst = -128; - else - *s_dst = sample; - - s_src += 2; - s_dst += 1; - } /* for */ - break; - - case AUDIO_U16MSB: - u_src = cvt->buf; - u_dst = cvt->buf; - - for (i = cvt->len_cvt / 4; i; --i) - { - sample = (Uint16) ((u_src[0] << 8) | u_src[1]) - + (Uint16) ((u_src[2] << 8) | u_src[3]); - if (sample > 65535) - { - u_dst[0] = 0xFF; - u_dst[1] = 0xFF; - } /* if */ - else - { - u_dst[1] = (sample & 0xFF); - sample >>= 8; - u_dst[0] = (sample & 0xFF); - } /* else */ - u_src += 4; - u_dst += 2; - } /* for */ - break; - - case AUDIO_U16LSB: - u_src = cvt->buf; - u_dst = cvt->buf; - - for (i = cvt->len_cvt / 4; i; --i) - { - sample = (Uint16) ((u_src[1] << 8) | u_src[0]) - + (Uint16) ((u_src[3] << 8) | u_src[2]); - if (sample > 65535) - { - u_dst[0] = 0xFF; - u_dst[1] = 0xFF; - } /* if */ - else - { - u_dst[0] = (sample & 0xFF); - sample >>= 8; - u_dst[1] = (sample & 0xFF); - } /* else */ - u_src += 4; - u_dst += 2; - } /* for */ - break; - - case AUDIO_S16MSB: - u_src = cvt->buf; - u_dst = cvt->buf; - - for (i = cvt->len_cvt / 4; i; --i) - { - sample = (Sint16) ((u_src[0] << 8) | u_src[1]) - + (Sint16) ((u_src[2] << 8) | u_src[3]); - if (sample > 32767) - { - u_dst[0] = 0x7F; - u_dst[1] = 0xFF; - } /* if */ - else if (sample < -32768) - { - u_dst[0] = 0x80; - u_dst[1] = 0x00; - } /* else if */ - else - { - u_dst[1] = (sample & 0xFF); - sample >>= 8; - u_dst[0] = (sample & 0xFF); - } /* else */ - u_src += 4; - u_dst += 2; - } /* for */ - break; - - case AUDIO_S16LSB: - u_src = cvt->buf; - u_dst = cvt->buf; - - for (i = cvt->len_cvt / 4; i; --i) - { - sample = (Sint16) ((u_src[1] << 8) | u_src[0]) - + (Sint16) ((u_src[3] << 8) | u_src[2]); - if (sample > 32767) - { - u_dst[1] = 0x7F; - u_dst[0] = 0xFF; - } /* if */ - else if (sample < -32768) - { - u_dst[1] = 0x80; - u_dst[0] = 0x00; - } /* else if */ - else - { - u_dst[0] = (sample & 0xFF); - sample >>= 8; - u_dst[1] = (sample & 0xFF); - } /* else */ - u_src += 4; - u_dst += 2; - } /* for */ - break; - } /* switch */ - - cvt->len_cvt /= 2; -} /* Sound_ConvertMono */ - - -/* Convert rate up by multiple of 2 */ - -static void Sound_RateMUL2(Sound_AudioCVT *cvt, Uint16 *format) -{ - int i; - Uint8 *src, *dst; - - /* SNDDBG(("Converting audio rate * 2\n")); */ - - src = cvt->buf + cvt->len_cvt; - dst = cvt->buf + cvt->len_cvt*2; - - /* 8- or 16-bit sound? */ - switch (*format & 0xFF) - { - case 8: - for (i = cvt->len_cvt; i; --i) - { - src -= 1; - dst -= 2; - dst[0] = src[0]; - dst[1] = src[0]; - } /* for */ - break; - - case 16: - for (i = cvt->len_cvt / 2; i; --i) - { - src -= 2; - dst -= 4; - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[0]; - dst[3] = src[1]; - } /* for */ - break; - } /* switch */ - - cvt->len_cvt *= 2; -} /* Sound_RateMUL2 */ - - -/* Convert rate down by multiple of 2 */ - -static void Sound_RateDIV2(Sound_AudioCVT *cvt, Uint16 *format) -{ - int i; - Uint8 *src, *dst; - - /* SNDDBG(("Converting audio rate / 2\n")); */ - - src = cvt->buf; - dst = cvt->buf; - - /* 8- or 16-bit sound? */ - switch (*format & 0xFF) - { - case 8: - for (i = cvt->len_cvt / 2; i; --i) - { - dst[0] = src[0]; - src += 2; - dst += 1; - } /* for */ - break; - - case 16: - for (i = cvt->len_cvt / 4; i; --i) - { - dst[0] = src[0]; - dst[1] = src[1]; - src += 4; - dst += 2; - } - break; - } /* switch */ - - cvt->len_cvt /= 2; -} /* Sound_RateDIV2 */ - - -/* Very slow rate conversion routine */ - -static void Sound_RateSLOW(Sound_AudioCVT *cvt, Uint16 *format) -{ - double ipos; - int i, clen; - Uint8 *output8; - Uint16 *output16; - - /* SNDDBG(("Converting audio rate * %4.4f\n", 1.0/cvt->rate_incr)); */ - - clen = (int) ((double) cvt->len_cvt / cvt->rate_incr); - - if (cvt->rate_incr > 1.0) - { - /* 8- or 16-bit sound? */ - switch (*format & 0xFF) - { - case 8: - output8 = cvt->buf; - - ipos = 0.0; - for (i = clen; i; --i) - { - *output8 = cvt->buf[(int) ipos]; - ipos += cvt->rate_incr; - output8 += 1; - } /* for */ - break; - - case 16: - output16 = (Uint16 *) cvt->buf; - - clen &= ~1; - ipos = 0.0; - for (i = clen / 2; i; --i) - { - *output16 = ((Uint16 *) cvt->buf)[(int) ipos]; - ipos += cvt->rate_incr; - output16 += 1; - } /* for */ - break; - } /* switch */ - } /* if */ - else - { - /* 8- or 16-bit sound */ - switch (*format & 0xFF) - { - case 8: - output8 = cvt->buf + clen; - - ipos = (double) cvt->len_cvt; - for (i = clen; i; --i) - { - ipos -= cvt->rate_incr; - output8 -= 1; - *output8 = cvt->buf[(int) ipos]; - } /* for */ - break; - - case 16: - clen &= ~1; - output16 = (Uint16 *) (cvt->buf + clen); - ipos = (double) cvt->len_cvt / 2; - for (i = clen / 2; i; --i) - { - ipos -= cvt->rate_incr; - output16 -= 1; - *output16 = ((Uint16 *) cvt->buf)[(int) ipos]; - } /* for */ - break; - } /* switch */ - } /* else */ - - cvt->len_cvt = clen; -} /* Sound_RateSLOW */ - - -int Sound_ConvertAudio(Sound_AudioCVT *cvt) -{ - Uint16 format; - - /* Make sure there's data to convert */ - if (cvt->buf == NULL) - { - __Sound_SetError("No buffer allocated for conversion"); - return(-1); - } /* if */ - - /* 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! */ - format = cvt->src_format; - for (cvt->filter_index = 0; cvt->filters[cvt->filter_index]; - cvt->filter_index++) - { - cvt->filters[cvt->filter_index](cvt, &format); - } - return(0); -} /* Sound_ConvertAudio */ - - -/* - * Creates a set of audio filters to convert from one format to another. - * Returns -1 if the format conversion is not supported, or 1 if the - * audio filter is set up. - */ - -int Sound_BuildAudioCVT(Sound_AudioCVT *cvt, - Uint16 src_format, Uint8 src_channels, Uint32 src_rate, - Uint16 dst_format, Uint8 dst_channels, Uint32 dst_rate, - Uint32 dst_size) -{ - /* Start off with no conversion necessary */ - cvt->needed = 0; - cvt->filter_index = 0; - cvt->filters[0] = NULL; - cvt->len_mult = 1; - cvt->len_ratio = 1.0; - - /* First filter: Endian conversion from src to dst */ - if ((src_format & 0x1000) != (dst_format & 0x1000) && - ((src_format & 0xff) != 8)) - { - SNDDBG(("Adding filter: Sound_ConvertEndian\n")); - cvt->filters[cvt->filter_index++] = Sound_ConvertEndian; - } /* if */ - - /* Second filter: Sign conversion -- signed/unsigned */ - if ((src_format & 0x8000) != (dst_format & 0x8000)) - { - SNDDBG(("Adding filter: Sound_ConvertSign\n")); - cvt->filters[cvt->filter_index++] = Sound_ConvertSign; - } /* if */ - - /* Next filter: Convert 16 bit <--> 8 bit PCM. */ - if ((src_format & 0xFF) != (dst_format & 0xFF)) - { - switch (dst_format & 0x10FF) - { - case AUDIO_U8: - SNDDBG(("Adding filter: Sound_Convert8\n")); - cvt->filters[cvt->filter_index++] = Sound_Convert8; - cvt->len_ratio /= 2; - break; - - case AUDIO_U16LSB: - SNDDBG(("Adding filter: Sound_Convert16LSB\n")); - cvt->filters[cvt->filter_index++] = Sound_Convert16LSB; - cvt->len_mult *= 2; - cvt->len_ratio *= 2; - break; - - case AUDIO_U16MSB: - SNDDBG(("Adding filter: Sound_Convert16MSB\n")); - cvt->filters[cvt->filter_index++] = Sound_Convert16MSB; - cvt->len_mult *= 2; - cvt->len_ratio *= 2; - break; - } /* switch */ - } /* if */ - - /* Next filter: Mono/Stereo conversion */ - if (src_channels != dst_channels) - { - while ((src_channels * 2) <= dst_channels) - { - SNDDBG(("Adding filter: Sound_ConvertStereo\n")); - cvt->filters[cvt->filter_index++] = Sound_ConvertStereo; - cvt->len_mult *= 2; - src_channels *= 2; - cvt->len_ratio *= 2; - } /* while */ - - /* 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)) - { - SNDDBG(("Adding filter: Sound_ConvertMono\n")); - cvt->filters[cvt->filter_index++] = Sound_ConvertMono; - src_channels /= 2; - cvt->len_ratio /= 2; - } /* while */ - - if ( src_channels != dst_channels ) { - /* Uh oh.. */; - } /* if */ - } /* if */ - - /* Do rate conversion */ - cvt->rate_incr = 0.0; - if ((src_rate / 100) != (dst_rate / 100)) - { - Uint32 hi_rate, lo_rate; - int len_mult; - double len_ratio; - void (*rate_cvt)(Sound_AudioCVT *cvt, Uint16 *format); - - if (src_rate > dst_rate) - { - hi_rate = src_rate; - lo_rate = dst_rate; - SNDDBG(("Adding filter: Sound_RateDIV2\n")); - rate_cvt = Sound_RateDIV2; - len_mult = 1; - len_ratio = 0.5; - } /* if */ - else - { - hi_rate = dst_rate; - lo_rate = src_rate; - SNDDBG(("Adding filter: Sound_RateMUL2\n")); - rate_cvt = Sound_RateMUL2; - len_mult = 2; - len_ratio = 2.0; - } /* else */ - - /* If hi_rate = lo_rate*2^x then conversion is easy */ - while (((lo_rate * 2) / 100) <= (hi_rate / 100)) - { - cvt->filters[cvt->filter_index++] = rate_cvt; - cvt->len_mult *= len_mult; - lo_rate *= 2; - cvt->len_ratio *= len_ratio; - } /* while */ - - /* We may need a slow conversion here to finish up */ - if ((lo_rate / 100) != (hi_rate / 100)) - { - if (src_rate < dst_rate) - { - cvt->rate_incr = (double) lo_rate / hi_rate; - cvt->len_mult *= 2; - cvt->len_ratio /= cvt->rate_incr; - } /* if */ - else - { - cvt->rate_incr = (double) hi_rate / lo_rate; - cvt->len_ratio *= cvt->rate_incr; - } /* else */ - SNDDBG(("Adding filter: Sound_RateSLOW\n")); - cvt->filters[cvt->filter_index++] = Sound_RateSLOW; - } /* if */ - } /* if */ - - /* Set up the filter information */ - if (cvt->filter_index != 0) - { - cvt->needed = 1; - cvt->src_format = src_format; - cvt->dst_format = dst_format; - cvt->len = 0; - cvt->buf = NULL; - cvt->filters[cvt->filter_index] = NULL; - } /* if */ - - return(cvt->needed); -} /* Sound_BuildAudioCVT */ - -/* end of audio_convert.c ... */ -