/* 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 #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_internal.h" #define FRAMES 1024 #define CHANNELS 2 #define WIDTH 2 typedef struct { float data[FRAMES * CHANNELS]; midi *handle; } midi_file_t; 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, snd_shm->speed, 0) == -1) return 1; midi_intiialized = 1; return 0; } static wavinfo_t midi_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 = snd_shm->speed; info.width = 2; info.channels = 2; info.loopstart = -1; info.frames = wm_info->approx_total_samples; info.dataofs = 0; info.datalen = info.frames * info.channels * info.width; return info; } static long midi_stream_read (void *file, float **buf) { sfxstream_t *stream = (sfxstream_t *) file; midi_file_t *mf = (midi_file_t *) stream->file; int size = FRAMES * CHANNELS * WIDTH; int res; byte *data = alloca (size); res = WildMidi_GetOutput (mf->handle, (char *)data, size); if (res <= 0) { stream->error = 1; return 0; } res /= CHANNELS * WIDTH; SND_Convert (data, mf->data, res, CHANNELS, WIDTH); *buf = mf->data; return res; } static int midi_stream_seek (sfxstream_t *stream, int pos) { unsigned long int new_pos; pos *= stream->wavinfo.width * stream->wavinfo.channels; pos += stream->wavinfo.dataofs; new_pos = pos; return WildMidi_FastSeek(stream->file, &new_pos); } static void midi_stream_close (sfx_t *sfx) { sfxstream_t *stream = sfx->data.stream; midi_file_t *mf = (midi_file_t *) stream->file; WildMidi_Close (mf->handle); free (mf); SND_SFX_StreamClose (sfx); } static sfx_t * midi_stream_open (sfx_t *sfx) { sfxstream_t *stream = sfx->data.stream; QFile *file; midi *handle; unsigned char *local_buffer; unsigned long int local_buffer_size; midi_file_t *mf; 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; mf = calloc (sizeof (midi_file_t), 1); mf->handle = handle; return SND_SFX_StreamOpen (sfx, mf, midi_stream_read, midi_stream_seek, midi_stream_close); } int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname) { wavinfo_t info; midi *handle; unsigned char *local_buffer; unsigned long int local_buffer_size = Qfilesize (file); if (!midi_intiialized) { if (midi_init ()) { return -1; } } 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 -1; info = midi_get_info (handle); WildMidi_Close (handle); Sys_MaskPrintf (SYS_DEV, "stream %s\n", realname); // we init stream here cause we will only ever stream SND_SFX_Stream (sfx, realname, info, midi_stream_open); return 0; }