mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
added SND_NoResampleStereo so that streams that don't need resampling aren't forced to, also added midi support via libWildMidi, MIDI FILES RULE
This commit is contained in:
parent
89833cb4d7
commit
392902f5af
5 changed files with 311 additions and 3 deletions
19
configure.ac
19
configure.ac
|
@ -507,6 +507,24 @@ case "$target_os" in
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(wildmidi,
|
||||
[ --disable-wildmidi disable libWildMidi support],
|
||||
)
|
||||
HAVE_WILDMIDI=no
|
||||
WM_LIBS=
|
||||
if test "x$enable_wildmidi" != "xno"; then
|
||||
AC_CHECK_LIB(WildMidi, WildMidi_GetString, HAVE_WILDMIDI=yes, HAVE_WILDMIDI=no)
|
||||
if test "x$HAVE_WILDMIDI" = "xyes"; then
|
||||
AC_CHECK_HEADER(wildmidi_lib.h, HAVE_WILDMIDI=yes, HAVE_WILDMIDI=no)
|
||||
if test "x$HAVE_WILDMIDI" = "xyes"; then
|
||||
WM_LIBS="-lWildMidi"
|
||||
AC_DEFINE(HAVE_WILDMIDI, 1, [Define if you have WildMidi])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(WM_LIBS)
|
||||
|
||||
AC_ARG_ENABLE(vorbis,
|
||||
[ --disable-vorbis disable ogg vorbis support],
|
||||
)
|
||||
|
@ -2196,6 +2214,7 @@ AC_MSG_RESULT([
|
|||
Global configuration file : $globalconf
|
||||
User configuration file : $userconf
|
||||
OpenGL dynamic lib : $gl_driver
|
||||
libWildMidi Support : $HAVE_WILDMIDI
|
||||
])
|
||||
|
||||
if test -d $srcdir/CVS; then
|
||||
|
|
|
@ -126,6 +126,7 @@ void SND_UnblockSound (void);
|
|||
|
||||
void SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length, void *prev);
|
||||
void SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length, void *prev);
|
||||
void SND_NoResampleStereo (sfxbuffer_t *sc, byte *data, int length, void *prev);
|
||||
sfxbuffer_t *SND_GetCache (long samples, int rate, int inwidth, int channels,
|
||||
sfxblock_t *block, cache_allocator_t allocator);
|
||||
|
||||
|
@ -139,6 +140,7 @@ void SND_Load (sfx_t *sfx);
|
|||
void SND_CallbackLoad (void *object, cache_allocator_t allocator);
|
||||
void SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname);
|
||||
void SND_LoadWav (QFile *file, sfx_t *sfx, char *realname);
|
||||
void SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname);
|
||||
|
||||
wavinfo_t *SND_CacheWavinfo (sfx_t *sfx);
|
||||
wavinfo_t *SND_StreamWavinfo (sfx_t *sfx);
|
||||
|
|
|
@ -13,11 +13,11 @@ EXTRA_PROGRAMS= snd_render_default.la
|
|||
noinst_PROGRAMS= @SND_REND_STATIC@
|
||||
|
||||
snd_render_default_la_LDFLAGS= $(plugin_ldflags)
|
||||
snd_render_default_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c vorbis.c wav.c
|
||||
snd_render_default_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c vorbis.c wav.c midi.c
|
||||
if ASM_ARCH
|
||||
snd_render_default_la_LDADD= $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(OGG_LIBS)
|
||||
snd_render_default_la_LDADD= $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(OGG_LIBS) $(WM_LIBS)
|
||||
snd_render_default_la_DEPENDENCIES=
|
||||
else
|
||||
snd_render_default_la_LDADD= $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(OGG_LIBS)
|
||||
snd_render_default_la_LDADD= $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(OGG_LIBS) $(WM_LIBS)
|
||||
snd_render_default_la_DEPENDENCIES=
|
||||
endif
|
||||
|
|
212
libs/audio/renderer/midi.c
Normal file
212
libs/audio/renderer/midi.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
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__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#ifdef HAVE_WILDMIDI
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <wildmidi_lib.h>
|
||||
|
||||
#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;
|
||||
|
||||
cvar_t * wildmidi_volume;
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
// FIXME: need to check what the return of this function /should/ be
|
||||
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;
|
||||
|
||||
// FIXME: need to check what the return of this function /should/ be
|
||||
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 = stream->file;
|
||||
|
||||
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 = file;
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
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 = handle;
|
||||
stream->wavinfo = info;
|
||||
}
|
||||
#endif // HAVE_WILDMIDI
|
|
@ -327,6 +327,13 @@ SND_Load (sfx_t *sfx)
|
|||
SND_LoadOgg (file, sfx, realname);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_WILDMIDI
|
||||
if (strnequal ("MThd", buf, 4)) {
|
||||
Sys_DPrintf ("SND_Load: midi file\n");
|
||||
SND_LoadMidi (file, sfx, realname);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (strnequal ("RIFF", buf, 4)) {
|
||||
Sys_DPrintf ("SND_Load: wav file\n");
|
||||
|
@ -655,3 +662,71 @@ SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length, void *prev)
|
|||
x[0], x[1], x[2], x[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SND_NoResampleStereo (sfxbuffer_t *sc, byte *data, int length, void *prev)
|
||||
{
|
||||
int outcount, i;
|
||||
stereo8_t *ib, *ob;
|
||||
stereo16_t *is, *os;
|
||||
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||
int inwidth = info->width;
|
||||
int outwidth;
|
||||
|
||||
is = (stereo16_t *) data;
|
||||
os = (stereo16_t *) sc->data;
|
||||
ib = (stereo8_t *) data;
|
||||
ob = (stereo8_t *) sc->data;
|
||||
|
||||
os += sc->head;
|
||||
ob += sc->head;
|
||||
|
||||
outcount = length;
|
||||
|
||||
sc->sfx->length = info->samples;
|
||||
if (info->loopstart != (unsigned int)-1)
|
||||
sc->sfx->loopstart = info->loopstart;
|
||||
else
|
||||
sc->sfx->loopstart = (unsigned int)-1;
|
||||
|
||||
if (snd_loadas8bit->int_val) {
|
||||
outwidth = 1;
|
||||
sc->paint = SND_PaintChannelStereo8;
|
||||
sc->bps = 2;
|
||||
} else {
|
||||
outwidth = 2;
|
||||
sc->paint = SND_PaintChannelStereo16;
|
||||
sc->bps = 4;
|
||||
}
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
if (inwidth == 1 && outwidth == 1) {
|
||||
for (i = 0; i < outcount; i++, ob++, ib++) {
|
||||
ob->left = ib->left - 128;
|
||||
ob->right = ib->right - 128;
|
||||
}
|
||||
} else if (inwidth == 1 && outwidth == 2) {
|
||||
for (i = 0; i < outcount; i++, os++, ib++) {
|
||||
os->left = (ib->left - 128) << 8;
|
||||
os->right = (ib->right - 128) << 8;
|
||||
}
|
||||
} else if (inwidth == 2 && outwidth == 1) {
|
||||
for (i = 0; i < outcount; i++, ob++, ib++) {
|
||||
ob->left = LittleShort (is->left) >> 8;
|
||||
ob->right = LittleShort (is->right) >> 8;
|
||||
}
|
||||
} else if (inwidth == 2 && outwidth == 2) {
|
||||
for (i = 0; i < outcount; i++, os++, is++) {
|
||||
os->left = LittleShort (is->left);
|
||||
os->right = LittleShort (is->right);
|
||||
}
|
||||
}
|
||||
{
|
||||
byte *x = sc->data + sc->length * outwidth * 2;
|
||||
if (memcmp (x, "\xde\xad\xbe\xef", 4))
|
||||
Sys_Error ("SND_ResampleStereo screwed the pooch %02x%02x%02x%02x",
|
||||
x[0], x[1], x[2], x[3]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue