/* midi.c midi file loading for use with libWildMidi Copyright (C) 2003 Chris Ison This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif static __attribute__ ((used)) const char rcsid[] = "$Id$"; #ifdef HAVE_WILDMIDI #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #include #include #include "QF/cvar.h" #include "QF/sound.h" #include "QF/sys.h" #include "QF/quakefs.h" #include "snd_render.h" static int midi_intiialized = 0; static cvar_t *wildmidi_volume; static cvar_t *wildmidi_config; static int midi_init ( void ) { wildmidi_volume = Cvar_Get ("wildmidi_volume", "100", CVAR_ARCHIVE, NULL, "Set the Master Volume"); wildmidi_config = Cvar_Get ("wildmidi_config", "/etc/timidity.cfg", CVAR_ROM, NULL, "path/filename of timidity.cfg"); if (WildMidi_Init (wildmidi_config->string, shm->speed, 0) == -1) return 1; midi_intiialized = 1; return 0; } static wavinfo_t get_info (void * handle) { wavinfo_t info; struct _WM_Info *wm_info; memset (&info, 0, sizeof (info)); if ((wm_info = WildMidi_GetInfo (handle)) == NULL) { Sys_Printf ("Could not obtain midi information\n"); return info; } info.rate = shm->speed; info.width = 2; info.channels = 2; info.loopstart = -1; info.samples = wm_info->approx_total_samples; info.dataofs = 0; info.datalen = info.samples * 4; return info; } static int midi_stream_read (void *file, byte *buf, int count, wavinfo_t *info) { return WildMidi_GetOutput (file, (char *)buf, (unsigned long int)count); } static int midi_stream_seek (void *file, int pos, wavinfo_t *info) { unsigned long int new_pos; pos *= info->width * info->channels; pos += info->dataofs; new_pos = pos; return WildMidi_SampledSeek(file, &new_pos); } static void midi_stream_close (sfx_t *sfx) { sfxstream_t *stream = (sfxstream_t *)sfx->data; WildMidi_Close (stream->file); free (stream); free (sfx); } /* * Note: we only set the QF stream up here. * The WildMidi stream was setup when SND_OpenMidi was called * so stream->file contains the WildMidi handle for the midi */ static sfx_t * midi_stream_open (sfx_t *_sfx) { sfx_t *sfx; sfxstream_t *stream = (sfxstream_t *) _sfx->data; wavinfo_t *info = &stream->wavinfo; int samples; int size; QFile *file; midi *handle; unsigned char *local_buffer; unsigned long int local_buffer_size; QFS_FOpenFile (stream->file, &file); local_buffer_size = Qfilesize (file); local_buffer = malloc (local_buffer_size); Qread (file, local_buffer, local_buffer_size); Qclose (file); handle = WildMidi_OpenBuffer(local_buffer, local_buffer_size); if (handle == NULL) return NULL; sfx = calloc (1, sizeof (sfx_t)); samples = shm->speed * 0.3; size = samples = (samples + 255) & ~255; // WildMidi audio data is 16bit stereo size *= 4; stream = calloc (1, sizeof (sfxstream_t) + size); memcpy (stream->buffer.data + size, "\xde\xad\xbe\xef", 4); sfx->name = _sfx->name; sfx->data = stream; sfx->wavinfo = SND_CacheWavinfo; sfx->touch = sfx->retain = SND_StreamRetain; sfx->release = SND_StreamRelease; sfx->close = midi_stream_close; stream->sfx = sfx; stream->file = handle; stream->resample = SND_NoResampleStereo; stream->read = midi_stream_read; stream->seek = midi_stream_seek; stream->wavinfo = *info; stream->buffer.length = samples; stream->buffer.advance = SND_StreamAdvance; stream->buffer.setpos = SND_StreamSetPos; stream->buffer.sfx = sfx; stream->seek (stream->file, 0, &stream->wavinfo); stream->buffer.advance (&stream->buffer, 0); stream->resample (&stream->buffer, 0, 0, 0); return sfx; } void SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname) { wavinfo_t info; sfxstream_t *stream = calloc (1, sizeof (sfxstream_t)); midi *handle; unsigned char *local_buffer; unsigned long int local_buffer_size = Qfilesize (file); if (!midi_intiialized) { if (midi_init ()) { return; } } local_buffer = malloc (local_buffer_size); Qread (file, local_buffer, local_buffer_size); Qclose (file); // WildMidi takes ownership, so be damned if you touch it handle = WildMidi_OpenBuffer (local_buffer, local_buffer_size); if (handle == NULL) return; info = get_info (handle); WildMidi_Close (handle); Sys_DPrintf ("stream %s\n", realname); // we init stream here cause we will only ever stream sfx->open = midi_stream_open; sfx->wavinfo = SND_CacheWavinfo; sfx->touch = sfx->retain = SND_StreamRetain; sfx->release = SND_StreamRelease; sfx->data = stream; stream->file = realname; stream->wavinfo = info; } #endif // HAVE_WILDMIDI