Skip to content

Commit

Permalink
Torbj?rn Andersson - Tue Sep 11 11:22:29 PDT 2001
Browse files Browse the repository at this point in the history
 * Added support for loading AIFF audio chunks
  • Loading branch information
slouken committed Sep 11, 2001
1 parent db3635a commit dd972d1
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 77 deletions.
2 changes: 2 additions & 0 deletions CHANGES
@@ -1,5 +1,7 @@

1.2.1:
Torbj�rn Andersson - Tue Sep 11 11:22:29 PDT 2001
* Added support for loading AIFF audio chunks
Max Horn - Tue Sep 4 20:38:11 PDT 2001
* Added native MIDI music support on MacOS and MacOS X
Florian Schulze - Sun Aug 19 14:55:37 PDT 2001
Expand Down
8 changes: 5 additions & 3 deletions Makefile.am
Expand Up @@ -10,16 +10,18 @@ libSDL_mixerinclude_HEADERS = \
SDL_mixer.h

libSDL_mixer_la_SOURCES = \
load_aiff.c \
load_aiff.h \
load_voc.c \
load_voc.h \
mixer.c \
music.c \
music_cmd.c \
music_cmd.h \
music_ogg.c \
music_ogg.h \
wave.h \
wavestream.c \
wavestream.h \
voc.c
wavestream.h

if USE_MIKMOD
MIKMOD_LIB = mikmod/libmikmod.la
Expand Down
203 changes: 203 additions & 0 deletions load_aiff.c
@@ -0,0 +1,203 @@
/*
SDL_mixer: An audio mixer library based on the SDL library
Copyright (C) 1997-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
This is the source needed to decode an AIFF file into a waveform.
It's pretty straightforward once you get going. The only
externally-callable function is Mix_LoadAIFF_RW(), which is meant to
act as identically to SDL_LoadWAV_RW() as possible.
This file by Torbjörn Andersson (torbjorn.andersson@eurotime.se)
*/

#include "SDL_mutex.h"
#include "SDL_endian.h"
#include "SDL_timer.h"

#include "SDL_mixer.h"
#include "load_aiff.h"

/*********************************************/
/* Define values for AIFF (IFF audio) format */
/*********************************************/
#define FORM 0x4d524f46 /* "FORM" */
#define AIFF 0x46464941 /* "AIFF" */
#define SSND 0x444e5353 /* "SSND" */
#define COMM 0x4d4d4f43 /* "COMM" */

/* This function was taken from libsndfile. I don't pretend to fully
* understand it.
*/

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]);
}

/* This function is based on SDL_LoadWAV_RW(). */

SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, int freesrc,
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
{
int was_error;
int found_SSND;
int found_COMM;
long start;

Uint32 chunk_type;
Uint32 chunk_length;
long next_chunk;

/* AIFF magic header */
Uint32 FORMchunk;
Uint32 AIFFmagic;

/* SSND chunk */
Uint32 offset;
Uint32 blocksize;

/* COMM format chunk */
Uint16 channels;
Uint32 numsamples;
Uint16 samplesize;
Uint8 sane_freq[10];
Uint32 frequency;

/* Make sure we are passed a valid data source */
was_error = 0;
if ( src == NULL ) {
was_error = 1;
goto done;
}

FORMchunk = SDL_ReadLE32(src);
chunk_length = SDL_ReadBE32(src);
if ( chunk_length == AIFF ) { /* The FORMchunk has already been read */
AIFFmagic = chunk_length;
chunk_length = FORMchunk;
FORMchunk = FORM;
} else {
AIFFmagic = SDL_ReadLE32(src);
}
if ( (FORMchunk != FORM) || (AIFFmagic != AIFF) ) {
SDL_SetError("Unrecognized file type (not AIFF)");
was_error = 1;
goto done;
}

/* TODO: Better santity-checking. */

found_SSND = 0;
found_COMM = 0;

do {
chunk_type = SDL_ReadLE32(src);
chunk_length = SDL_ReadBE32(src);
next_chunk = SDL_RWtell(src) + chunk_length;

/* Paranoia to avoid infinite loops */
if (chunk_length == 0)
break;

switch (chunk_type) {
case SSND:
found_SSND = 1;
offset = SDL_ReadBE32(src);
blocksize = SDL_ReadBE32(src);
start = SDL_RWtell(src) + offset;
break;

case COMM:
found_COMM = 1;
channels = SDL_ReadBE16(src);
numsamples = SDL_ReadBE32(src);
samplesize = SDL_ReadBE16(src);
SDL_RWread(src, sane_freq, sizeof(sane_freq), 1);
frequency = SANE_to_Uint32(sane_freq);
if (frequency == 0) {
SDL_SetError("Bad AIFF sample frequency");
was_error = 1;
goto done;
}
break;

default:
break;
}
} while ( ( !found_SSND || !found_COMM )
&& SDL_RWseek(src, next_chunk, SEEK_SET) != 1 );

if ( !found_SSND ) {
SDL_SetError("Bad AIFF (no SSND chunk)");
was_error = 1;
goto done;
}

if ( !found_COMM ) {
SDL_SetError("Bad AIFF (no COMM chunk)");
was_error = 1;
goto done;
}

/* Decode the audio data format */
memset(spec, 0, sizeof(*spec));
spec->freq = frequency;
switch (samplesize) {
case 8:
spec->format = AUDIO_S8;
break;
case 16:
spec->format = AUDIO_S16MSB;
break;
default:
SDL_SetError("Unsupported AIFF samplesize");
was_error = 1;
goto done;
}
spec->channels = (Uint8) channels;
spec->samples = 4096; /* Good default buffer size */

*audio_len = channels * numsamples * (samplesize / 8);
*audio_buf = (Uint8 *)malloc(*audio_len);
if ( *audio_buf == NULL ) {
SDL_SetError("Out of memory");
return(NULL);
}
SDL_RWseek(src, start, SEEK_SET);
if ( SDL_RWread(src, *audio_buf, *audio_len, 1) != 1 ) {
SDL_SetError("Unable to read audio data");
return(NULL);
}

/* Don't return a buffer that isn't a multiple of samplesize */
*audio_len &= ~((samplesize / 8) - 1);

done:
if ( freesrc && src ) {
SDL_RWclose(src);
}
if ( was_error ) {
spec = NULL;
}
return(spec);
}
31 changes: 31 additions & 0 deletions load_aiff.h
@@ -0,0 +1,31 @@
/*
SDL_mixer: An audio mixer library based on the SDL library
Copyright (C) 1997-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
This is the source needed to decode an AIFF file into a waveform.
It's pretty straightforward once you get going. The only
externally-callable function is Mix_LoadAIFF_RW(), which is meant to
act as identically to SDL_LoadWAV_RW() as possible.
This file by Torbjörn Andersson (torbjorn.andersson@eurotime.se)
*/

/* $Id$ */

/* Don't call this directly; use Mix_LoadWAV_RW() for now. */
SDL_AudioSpec *Mix_LoadAIFF_RW (SDL_RWops *src, int freesrc,
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
15 changes: 12 additions & 3 deletions voc.c → load_voc.c
@@ -1,6 +1,6 @@
/*
SDL_mixer: An audio mixer library based on the SDL library
Copyright (C) 1997-1999 Sam Lantinga
Copyright (C) 1997-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
Expand Down Expand Up @@ -38,6 +38,7 @@
#include "SDL_timer.h"

#include "SDL_mixer.h"
#include "load_voc.h"

#ifdef VOC_SAMPLES

Expand Down Expand Up @@ -457,7 +458,15 @@ SDL_AudioSpec *Mix_LoadVOC_RW (SDL_RWops *src, int freesrc,
return(spec);
} /* Mix_LoadVOC_RW */

#endif /* VOC_SAMPLES */
#else

/* end of voc.c ... */
SDL_AudioSpec *Mix_LoadVOC_RW (SDL_RWops *src, int freesrc,
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
{
SDL_SetError("VOC file loading not supported");
return(NULL);
}

#endif /* VOC_SAMPLES */

/* end of load_voc.c ... */
34 changes: 34 additions & 0 deletions load_voc.h
@@ -0,0 +1,34 @@
/*
SDL_mixer: An audio mixer library based on the SDL library
Copyright (C) 1997-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
This is the source needed to decode a Creative Labs VOC file into a
waveform. It's pretty straightforward once you get going. The only
externally-callable function is Mix_LoadVOC_RW(), which is meant to
act as identically to SDL_LoadWAV_RW() as possible.
This file by Ryan C. Gordon (icculus@linuxgames.com).
Heavily borrowed from sox v12.17.1's voc.c.
(http://www.freshmeat.net/projects/sox/)
*/

/* $Id$ */

/* Don't call this directly; use Mix_LoadWAV_RW() for now. */
SDL_AudioSpec *Mix_LoadVOC_RW (SDL_RWops *src, int freesrc,
SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);

0 comments on commit dd972d1

Please sign in to comment.