284 lines
5.2 KiB
C
284 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
|