Skip to content

Commit

Permalink
Modified to more easily allow for different compression types.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Dec 7, 2001
1 parent 6765330 commit 4d3f2fa
Showing 1 changed file with 206 additions and 82 deletions.
288 changes: 206 additions & 82 deletions decoders/aiff.c
Expand Up @@ -57,6 +57,9 @@
#define __SDL_SOUND_INTERNAL__
#include "SDL_sound_internal.h"

static Uint32 SANE_to_Uint32 (Uint8 *sanebuf);


static int AIFF_init(void);
static void AIFF_quit(void);
static int AIFF_open(Sound_Sample *sample, const char *ext);
Expand All @@ -81,21 +84,60 @@ const Sound_DecoderFunctions __Sound_DecoderFunctions_AIFF =
};


/* this is what we store in our internal->decoder_private field... */
typedef struct {
/*****************************************************************************
* aiff_t is what we store in our internal->decoder_private field... *
*****************************************************************************/
typedef struct S_AIFF_FMT_T
{
Uint32 type;
void (*free)(struct S_AIFF_FMT_T *fmt);
Uint32(*read_sample)(Sound_Sample *sample);

#if 0
/*
this is ripped from wav.c as ann example of format-specific data.
please replace with something more appropriate when the need arises.
*/
union
{
struct
{
Uint16 cbSize;
Uint16 wSamplesPerBlock;
Uint16 wNumCoef;
ADPCMCOEFSET *aCoeff;
} adpcm;

/* put other format-specific data here... */
} fmt;
#endif
} fmt_t;


typedef struct
{
fmt_t fmt;
Sint32 bytesLeft;
} aiff_t;



/* Chunk management code... */

#define formID 0x4d524f46 /* "FORM", in ascii. */
#define formID 0x4D524F46 /* "FORM", in ascii. */
#define aiffID 0x46464941 /* "AIFF", in ascii. */
#define aifcID 0x43464941 /* "AIFC", in ascii. */
#define ssndID 0x444e5353 /* "SSND", in ascii. */
#define commID 0x4d4d4f43 /* "COMM", in ascii. */
#define ssndID 0x444E5353 /* "SSND", in ascii. */

#define noneID 0x454e4f4e /* "NONE", in ascii. */

/*****************************************************************************
* The COMM chunk... *
*****************************************************************************/

#define commID 0x4D4D4F43 /* "COMM", in ascii. */

/* format/compression types... */
#define noneID 0x454E4F4E /* "NONE", in ascii. */

typedef struct
{
Expand Down Expand Up @@ -139,43 +181,6 @@ typedef struct
} comm_t;



static int AIFF_init(void)
{
return(1); /* always succeeds. */
} /* AIFF_init */


static void AIFF_quit(void)
{
/* it's a no-op. */
} /* AIFF_quit */


/*
* Sample rate is encoded as an "80 bit IEEE Standard 754 floating point
* number (Standard Apple Numeric Environment [SANE] data type Extended)".
* Whose bright idea was that?
*
* This function was adapted from libsndfile, and while I do know a little
* bit about the IEEE floating point standard I don't pretend to fully
* understand this.
*/

static Uint32 SANE_to_Uint32 (Uint8 *sanebuf)
{
/* Is the frequency outside of what we can represent with Uint32? */
if ( (sanebuf[0] & 0x80)
|| (sanebuf[0] <= 0x3F)
|| (sanebuf[0] > 0x40)
|| (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C) )
return 0;

return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7)
| (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
} /* SANE_to_Uint32 */


/*
* Read in a comm_t from disk. This makes this process safe regardless of
* the processor's byte order or how the comm_t structure is packed.
Expand Down Expand Up @@ -220,11 +225,19 @@ static int read_comm_chunk(SDL_RWops *rw, comm_t *comm)
comm->compressionType = SDL_SwapBE32(comm->compressionType);
} /* if */
else
{
comm->compressionType = noneID;
} /* else */

return(1);
} /* read_comm_chunk */



/*****************************************************************************
* The SSND chunk... *
*****************************************************************************/

typedef struct
{
Uint32 ckID;
Expand Down Expand Up @@ -264,6 +277,100 @@ static int read_ssnd_chunk(SDL_RWops *rw, ssnd_t *ssnd)
} /* read_ssnd_chunk */



/*****************************************************************************
* Normal, uncompressed aiff handler... *
*****************************************************************************/

static Uint32 read_sample_fmt_normal(Sound_Sample *sample)
{
Uint32 retval;
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
aiff_t *a = (aiff_t *) internal->decoder_private;
Uint32 max = (internal->buffer_size < (Uint32) a->bytesLeft) ?
internal->buffer_size : (Uint32) a->bytesLeft;

assert(max > 0);

/*
* We don't actually do any decoding, so we read the AIFF data
* directly into the internal buffer...
*/
retval = SDL_RWread(internal->rw, internal->buffer, 1, max);

a->bytesLeft -= retval;

/* Make sure the read went smoothly... */
if ((retval == 0) || (a->bytesLeft == 0))
sample->flags |= SOUND_SAMPLEFLAG_EOF;

else if (retval == -1)
sample->flags |= SOUND_SAMPLEFLAG_ERROR;

/* (next call this EAGAIN may turn into an EOF or error.) */
else if (retval < internal->buffer_size)
sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;

return(retval);
} /* read_sample_fmt_normal */


static void free_fmt_normal(fmt_t *fmt)
{
/* it's a no-op. */
} /* free_fmt_normal */


static int read_fmt_normal(SDL_RWops *rw, fmt_t *fmt)
{
/* (don't need to read more from the RWops...) */
fmt->free = free_fmt_normal;
fmt->read_sample = read_sample_fmt_normal;
return(1);
} /* read_fmt_normal */




/*****************************************************************************
* Everything else... *
*****************************************************************************/

static int AIFF_init(void)
{
return(1); /* always succeeds. */
} /* AIFF_init */


static void AIFF_quit(void)
{
/* it's a no-op. */
} /* AIFF_quit */


/*
* Sample rate is encoded as an "80 bit IEEE Standard 754 floating point
* number (Standard Apple Numeric Environment [SANE] data type Extended)".
* Whose bright idea was that?
*
* This function was adapted from libsndfile, and while I do know a little
* bit about the IEEE floating point standard I don't pretend to fully
* understand this.
*/
static Uint32 SANE_to_Uint32 (Uint8 *sanebuf)
{
/* Is the frequency outside of what we can represent with Uint32? */
if ( (sanebuf[0] & 0x80)
|| (sanebuf[0] <= 0x3F)
|| (sanebuf[0] > 0x40)
|| (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C) )
return 0;

return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7)
| (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
} /* SANE_to_Uint32 */


static int find_chunk(SDL_RWops *rw, Uint32 id)
{
Sint32 siz = 0;
Expand All @@ -285,6 +392,31 @@ static int find_chunk(SDL_RWops *rw, Uint32 id)
} /* find_chunk */


static int read_fmt(SDL_RWops *rw, comm_t *c, fmt_t *fmt)
{
fmt->type = c->compressionType;

/* if it's in this switch statement, we support the format. */
switch (fmt->type)
{
case noneID:
SNDDBG(("AIFF: Appears to be uncompressed audio.\n"));
return(read_fmt_normal(rw, fmt));

/* add other types here. */

default:
SNDDBG(("AIFF: Format %lu is unknown.\n",
(unsigned int) fmt->type));
Sound_SetError("AIFF: Unsupported format");
return(0); /* not supported whatsoever. */
} /* switch */

assert(0); /* shouldn't hit this point. */
return(0);
} /* read_fmt */


static int AIFF_open(Sound_Sample *sample, const char *ext)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
Expand All @@ -310,12 +442,6 @@ static int AIFF_open(Sound_Sample *sample, const char *ext)
BAIL_IF_MACRO(!read_comm_chunk(rw, &c),
"AIFF: Can't read common chunk.", 0);

/* !!! FIXME: This will have to change for compression types... */
BAIL_IF_MACRO(c.compressionType != noneID,
"AIFF: Unsupported encoding.", 0);

BAIL_IF_MACRO(c.sampleRate == 0, "AIFF: Unsupported sample rate.", 0);

sample->actual.channels = (Uint8) c.numChannels;
sample->actual.rate = c.sampleRate;

Expand All @@ -330,16 +456,37 @@ static int AIFF_open(Sound_Sample *sample, const char *ext)
bytes_per_sample = 2;
} /* if */
else
{
BAIL_MACRO("AIFF: Unsupported sample size.", 0);
} /* else */

SDL_RWseek(rw, pos, SEEK_SET);

BAIL_IF_MACRO(!find_chunk(rw, ssndID), "AIFF: No sound data chunk.", 0);
BAIL_IF_MACRO(!read_ssnd_chunk(rw, &s),
"AIFF: Can't read sound data chunk.", 0);
BAIL_IF_MACRO(c.sampleRate == 0, "AIFF: Unsupported sample rate.", 0);

a = (aiff_t *) malloc(sizeof(aiff_t));
BAIL_IF_MACRO(a == NULL, ERR_OUT_OF_MEMORY, 0);

if (!read_fmt(rw, &c, &(a->fmt)))
{
free(a);
return(0);
} /* if */

SDL_RWseek(rw, pos, SEEK_SET); /* if the seek fails, let it go... */

if (!find_chunk(rw, ssndID))
{
Sound_SetError("AIFF: No sound data chunk.");
free(a);
return(0);
} /* if */

if (!read_ssnd_chunk(rw, &s))
{
Sound_SetError("AIFF: Can't read sound data chunk.");
free(a);
return(0);
} /* if */

a->bytesLeft = bytes_per_sample * c.numSampleFrames;
internal->decoder_private = (void *) a;

Expand All @@ -353,43 +500,20 @@ static int AIFF_open(Sound_Sample *sample, const char *ext)
static void AIFF_close(Sound_Sample *sample)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
free(internal->decoder_private);
aiff_t *a = (aiff_t *) internal->decoder_private;
a->fmt.free(&(a->fmt));
free(a);
} /* WAV_close */


static Uint32 AIFF_read(Sound_Sample *sample)
{
Uint32 retval;
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
aiff_t *a = (aiff_t *) internal->decoder_private;
Uint32 max = (internal->buffer_size < (Uint32) a->bytesLeft) ?
internal->buffer_size : (Uint32) a->bytesLeft;

assert(max > 0);

/*
* We don't actually do any decoding, so we read the AIFF data
* directly into the internal buffer...
*/
retval = SDL_RWread(internal->rw, internal->buffer, 1, max);

a->bytesLeft -= retval;

/* Make sure the read went smoothly... */
if ((retval == 0) || (a->bytesLeft == 0))
sample->flags |= SOUND_SAMPLEFLAG_EOF;

else if (retval == -1)
sample->flags |= SOUND_SAMPLEFLAG_ERROR;

/* (next call this EAGAIN may turn into an EOF or error.) */
else if (retval < internal->buffer_size)
sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;

return(retval);
return(a->fmt.read_sample(sample));
} /* AIFF_read */

#endif /* SOUND_SUPPORTS_AIFF */


/* end of aiff.c ... */

0 comments on commit 4d3f2fa

Please sign in to comment.