Files
illusion-arena-engine/code/client/snd_codec_xmp.c

273 lines
5.2 KiB
C

/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
Copyright (C) 2014 leilei
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
int xmpspeed = 22050; // assume 22050hz unless........
#ifdef USE_CODEC_XMP
// includes for the Q3 sound system
#include "client.h"
#include "snd_codec.h"
// includes for XMP
#include <xmp.h>
// leilei - XMP
xmp_context xmpsong;
//int sound_init(int, int);
void sound_play(void *, int);
void sound_deinit(void);
extern int samplingrate; // from snd_dma
void S_XMP_StartSong ( void )
{
}
void S_XMP_EndSong ( void )
{
}
int aintistreaming = 0;
char *streamilename;
/*
=================
S_XMP_CodecLoad
=================
*/
void *S_XMP_CodecLoad(const char *filename, snd_info_t *info)
{
// This is not a codec for sound effects
return NULL;
}
/*
=================
S_XMP_CodecOpenStream
=================
*/
// FIXME: there's a memory leak here if you start the same song many many many many times.
snd_stream_t *S_XMP_CodecOpenStream(const char *filename)
{
// First let's close whatever song we had....
// Open
snd_stream_t *rv = S_CodecUtilOpen(filename, &xmp_codec);
if(!rv) {
return NULL;
}
// Com_Printf("OPENSTREAM %s\n", filename);
{
fileHandle_t file;
// Try to open the file
FS_FOpenFileRead(filename, &file, qtrue);
if(!file) {
Com_Printf( S_COLOR_RED "ERROR: No.\"%s\"\n",filename);
return NULL;
}
// Allocate some memory
long thelength = FS_ReadFile(filename, NULL);
void *buffer = Hunk_AllocateTempMemory(thelength);
if(!buffer) {
FS_FCloseFile(file);
Com_Printf( S_COLOR_RED "ERROR: Out of memory reading \"%s\"\n", filename);
return NULL;
}
FS_Read(buffer, thelength, file);
// OK!
struct xmp_module_info mi;
xmpsong = xmp_create_context();
int itsloaded = 0;
itsloaded = xmp_load_module_from_memory(xmpsong, buffer, 0);
// Free our memory and close the file.
Hunk_FreeTempMemory(buffer);
FS_FCloseFile(file); // unfortunately these do not help with the leak
if (itsloaded == 0)
itsloaded = xmp_start_player(xmpsong, xmpspeed, 0); // TODO: do sample rate of the mixer.
if (itsloaded == 0) {
// Com_Printf("XMP loaded our buffer of the file %s which is %i long \n", filename, thelength);
xmp_get_module_info(xmpsong, &mi);
// Com_Printf("Song Name: %s\n", mi.mod->name);
// Com_Printf("CODECLOAD %s\n", filename);
}
}
rv->info.size = 1337; // This doesn't matter!
rv->pos = 0;
rv->info.rate = xmpspeed;
rv->info.width = 2;
rv->info.channels = 2;
rv->info.samples = 12;
return rv;
}
/*
=================
S_XMP_CodecCloseStream
=================
*/
void S_XMP_CodecCloseStream(snd_stream_t *stream)
{
xmp_end_player(xmpsong);
xmp_release_module(xmpsong);
xmp_free_context(xmpsong);
S_CodecUtilClose(&stream);
}
/*
=================
S_OGG_CodecReadStream
=================
*/
int S_XMP_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
{
// buffer handling
struct xmp_module_info mi;
struct xmp_frame_info fi;
// check if input is valid
if(!(stream && buffer)) {
return 0;
}
if(bytes <= 0) {
return 0;
}
int bytesRead = 0;
int bytesLeft = bytes;
char* bufPtr = buffer;
// cycle until we have the requested or all available bytes read
while(-1) {
int yeah=xmp_play_buffer(xmpsong, buffer, bytesLeft, 0);
if (yeah == 0) { // if we can play it...
xmp_get_frame_info(xmpsong, &fi);
int c = fi.buffer_size;
// no more bytes are left
if(c <= 0) {
break;
}
bytesRead += c;
bytesLeft -= c;
bufPtr += c;
xmp_get_module_info(xmpsong, &mi);
// we have enough bytes
if(bytesLeft <= 0) {
break;
}
}
else { // if we can't play it JUST STOP OK
break;
}
}
return bytes;
}
snd_codec_t xmp_codec = {
"umx",
S_XMP_CodecLoad,
S_XMP_CodecOpenStream,
S_XMP_CodecReadStream,
S_XMP_CodecCloseStream,
NULL
};
snd_codec_t xmp_mod_codec = {
"mod",
S_XMP_CodecLoad,
S_XMP_CodecOpenStream,
S_XMP_CodecReadStream,
S_XMP_CodecCloseStream,
NULL
};
snd_codec_t xmp_it_codec = {
"it",
S_XMP_CodecLoad,
S_XMP_CodecOpenStream,
S_XMP_CodecReadStream,
S_XMP_CodecCloseStream,
NULL
};
snd_codec_t xmp_s3m_codec = {
"s3m",
S_XMP_CodecLoad,
S_XMP_CodecOpenStream,
S_XMP_CodecReadStream,
S_XMP_CodecCloseStream,
NULL
};
snd_codec_t xmp_xm_codec = {
"xm",
S_XMP_CodecLoad,
S_XMP_CodecOpenStream,
S_XMP_CodecReadStream,
S_XMP_CodecCloseStream,
NULL
};
#endif // USE_CODEC_XMP