Files
2011-02-07 12:59:02 +00:00

176 lines
4.7 KiB
C

/*
* SDL_sound -- An abstract sound format decoding API.
* Copyright (C) 2001 Ryan C. Gordon.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* MIDI decoder for SDL_sound.
*
* This driver handles MIDI data through a stripped-down version of TiMidity.
* See the documentation in the timidity subdirectory.
*
* Please see the file COPYING in the source's root directory.
*
* This file written by Torbjörn Andersson. (d91tan@Update.UU.SE)
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef SOUND_SUPPORTS_MIDI
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL_sound.h"
#define __SDL_SOUND_INTERNAL__
#include "SDL_sound_internal.h"
#include "timidity.h"
static int MIDI_init(void);
static void MIDI_quit(void);
static int MIDI_open(Sound_Sample *sample, const char *ext);
static void MIDI_close(Sound_Sample *sample);
static Uint32 MIDI_read(Sound_Sample *sample);
static int MIDI_rewind(Sound_Sample *sample);
static int MIDI_seek(Sound_Sample *sample, Uint32 ms);
static const char *extensions_midi[] = { "MIDI", "MID", NULL };
const Sound_DecoderFunctions __Sound_DecoderFunctions_MIDI =
{
{
extensions_midi,
"MIDI decoder, using a subset of TiMidity",
"Torbjörn Andersson <d91tan@Update.UU.SE>",
"http://www.icculus.org/SDL_sound/"
},
MIDI_init, /* init() method */
MIDI_quit, /* quit() method */
MIDI_open, /* open() method */
MIDI_close, /* close() method */
MIDI_read, /* read() method */
MIDI_rewind, /* rewind() method */
MIDI_seek /* seek() method */
};
static int MIDI_init(void)
{
BAIL_IF_MACRO(Timidity_Init() < 0, "MIDI: Could not initialise", 0);
return(1);
} /* MIDI_init */
static void MIDI_quit(void)
{
Timidity_Exit();
} /* MIDI_quit */
static int MIDI_open(Sound_Sample *sample, const char *ext)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
SDL_RWops *rw = internal->rw;
SDL_AudioSpec spec;
MidiSong *song;
spec.channels = 2;
spec.format = AUDIO_S16SYS;
spec.freq = 44100;
spec.samples = 4096;
song = Timidity_LoadSong(rw, &spec);
BAIL_IF_MACRO(song == NULL, "MIDI: Not a MIDI file.", 0);
Timidity_SetVolume(song, 100);
Timidity_Start(song);
SNDDBG(("MIDI: Accepting data stream.\n"));
internal->decoder_private = (void *) song;
sample->actual.channels = 2;
sample->actual.rate = 44100;
sample->actual.format = AUDIO_S16SYS;
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
return(1); /* we'll handle this data. */
} /* MIDI_open */
static void MIDI_close(Sound_Sample *sample)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
MidiSong *song = (MidiSong *) internal->decoder_private;
Timidity_FreeSong(song);
} /* MIDI_close */
static Uint32 MIDI_read(Sound_Sample *sample)
{
Uint32 retval;
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
MidiSong *song = (MidiSong *) internal->decoder_private;
retval = Timidity_PlaySome(song, internal->buffer, internal->buffer_size);
/* Make sure the read went smoothly... */
if (retval == 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);
} /* MIDI_read */
static int MIDI_rewind(Sound_Sample *sample)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
MidiSong *song = (MidiSong *) internal->decoder_private;
Timidity_Start(song);
return(1);
} /* MIDI_rewind */
static int MIDI_seek(Sound_Sample *sample, Uint32 ms)
{
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
MidiSong *song = (MidiSong *) internal->decoder_private;
Timidity_Seek(song, ms);
return(1);
} /* MIDI_seek */
#endif /* SOUND_SUPPORTS_MIDI */
/* end of midi.c ... */