233 lines
6.3 KiB
C
233 lines
6.3 KiB
C
/*
|
|
Copyright (C) 2015 Marco "eukara" Hladik
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
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 the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
#ifdef DUMB
|
|
#include "globaldef.h"
|
|
#include "dumb.h"
|
|
#include <AL/al.h>
|
|
#include <AL/alc.h>
|
|
|
|
// eukara - added in tracker playback using DUMB - UNIX ONLY!
|
|
char name[256];
|
|
DUH *trackmod; // The music file ~eukara
|
|
DUH_SIGRENDERER *sr; // The DUMB renderer
|
|
ALCdevice *oss_device;
|
|
ALuint oss_source;
|
|
ALuint oss_buffer;
|
|
static qboolean bTracker_Initialized = false;
|
|
|
|
// Set up the renderer options
|
|
static int depth = 16; // by default 16bit, only affects output not internal 32bit processing
|
|
static int unsign = 0;
|
|
static int freq = 22050;// 22050 is enough for most music
|
|
static int n_channels = 2; // stereo action
|
|
static float trackervolume = 1.0f; // default volume...?
|
|
static float delay = 0.0f; // You shouldn't need to touch this.
|
|
static float delta; // For the speed, combination of frequency
|
|
static int bufsize;
|
|
static qboolean playing = false;// Is the music playing or not?
|
|
extern cvar_t *midivolume;
|
|
|
|
union {
|
|
short s16[2048]; // was 8192
|
|
char s8[4096]; // was twice as the thing above
|
|
} tracker_buffer;
|
|
|
|
void Tracker_Play(byte track, qboolean looping)
|
|
{
|
|
if(bTracker_Initialized == false)
|
|
return;
|
|
|
|
alGenSources((ALuint)1, &oss_source);
|
|
alSourcef(oss_source, AL_PITCH, 1);
|
|
alSourcef(oss_source, AL_GAIN, 1);
|
|
alSource3f(oss_source, AL_POSITION, 0, 0, 0);
|
|
alSource3f(oss_source, AL_VELOCITY, 0, 0, 0);
|
|
alSourcei(oss_source, AL_LOOPING, AL_FALSE);
|
|
alGenBuffers((ALuint)1, &oss_buffer);
|
|
|
|
dumb_register_stdfiles(); // Initialize loading files
|
|
|
|
// Attempt to load every format imaginable, TODO: better method?
|
|
sprintf (name, "%s/music/track%d.it", com_gamedir, track);
|
|
trackmod = dumb_load_it(name);
|
|
if (!trackmod) {
|
|
sprintf (name, "%s/music/track%d.xm", com_gamedir, track);
|
|
trackmod = dumb_load_xm(name);
|
|
if (!trackmod) {
|
|
sprintf (name, "%s/music/track%d.s3m", com_gamedir, track);
|
|
trackmod = dumb_load_s3m(name);
|
|
if (!trackmod) {
|
|
sprintf (name, "%s/music/track%d.mod", com_gamedir, track);
|
|
trackmod = dumb_load_mod(name);
|
|
if (!trackmod) {
|
|
fprintf(stderr, "Unable to open %s!\n", name);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Let us know which track you are playing
|
|
Con_Printf("Playing %s\n", name);
|
|
sr = duh_start_sigrenderer(trackmod, 0, n_channels, 0); // start rendering, action happens in Tracker_Update
|
|
if (!sr) { // If it doesn't want to render, stop it before it's too late
|
|
unload_duh(trackmod); // Unload the track safely
|
|
fprintf(stderr, "Unable to play file!\n");
|
|
return;
|
|
}
|
|
|
|
delta = 61536.0f / freq; // This affects the speed
|
|
bufsize = depth == 16 ? 2048 : 4096; // Buffer size, small buffer = laggy music; big buff = laggy game
|
|
bufsize /= n_channels; // Tell him we are hopefully stereo
|
|
playing = true; // Announce that we have a track playing
|
|
}
|
|
|
|
void Tracker_Stop(void)
|
|
{
|
|
if(bTracker_Initialized == false || playing == false)
|
|
return;
|
|
if(!trackmod || !sr)
|
|
return;
|
|
|
|
playing = false; // Not playing the song anymore to prevent Tracker_Update
|
|
Con_Printf("Stopping %s\n", name); // Just print that we are stopping whatever track
|
|
duh_end_sigrenderer(sr); // Stop the renderer safely
|
|
unload_duh(trackmod); // Unload the song!
|
|
}
|
|
|
|
void Tracker_Pause(void)
|
|
{
|
|
if(bTracker_Initialized == false)
|
|
return;
|
|
|
|
playing = false; // Prevent from Tracker_Update from happening
|
|
Con_Printf("Paused %s\n", name);
|
|
}
|
|
|
|
void Tracker_Resume(void)
|
|
{
|
|
if(bTracker_Initialized == false)
|
|
return;
|
|
|
|
// Just making sure we aren't calling Tracker_Update with no song...
|
|
if(!trackmod || !sr)
|
|
return;
|
|
|
|
playing = true; // Tracker_Update should now be triggered again
|
|
Con_Printf("Resuming %s\n", name);
|
|
}
|
|
|
|
static void Tracker_f (void)
|
|
{
|
|
char *command;
|
|
int ret;
|
|
int n;
|
|
|
|
if (Cmd_Argc() < 2)
|
|
return;
|
|
|
|
command = Cmd_Argv (1);
|
|
|
|
if (Q_strcasecmp(command, "play") == 0)
|
|
{
|
|
Tracker_Play((byte)Q_atoi(Cmd_Argv (2)), false);
|
|
return;
|
|
}
|
|
|
|
if (Q_strcasecmp(command, "stop") == 0)
|
|
{
|
|
Tracker_Stop();
|
|
return;
|
|
}
|
|
|
|
if (Q_strcasecmp(command, "frequency") == 0)
|
|
{
|
|
freq = (int)Q_atoi(Cmd_Argv (2));
|
|
return;
|
|
}
|
|
|
|
if (Q_strcasecmp(command, "pause") == 0)
|
|
{
|
|
Tracker_Pause();
|
|
return;
|
|
}
|
|
|
|
if (Q_strcasecmp(command, "resume") == 0)
|
|
{
|
|
Tracker_Resume();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void Tracker_Update(void)
|
|
{
|
|
int i;
|
|
|
|
// Only update when a song is playing and the renderer works...
|
|
if (!sr)
|
|
return;
|
|
if(playing == false)
|
|
return;
|
|
|
|
if (midivolume->value != trackervolume)
|
|
trackervolume = midivolume->value;
|
|
|
|
// Render the song
|
|
int l = duh_render(sr, depth, unsign, trackervolume, delta, bufsize, &tracker_buffer);
|
|
if (depth == 16) { // On 16 bit, fill the buffer accordingly
|
|
for (i = 0; i < l * n_channels; i++) {
|
|
short val = tracker_buffer.s16[i];
|
|
tracker_buffer.s8[i*2] = (char)val;
|
|
tracker_buffer.s8[i*2+1] = (char)(val >> 8);
|
|
}
|
|
}
|
|
|
|
alBufferData(oss_buffer, AL_FORMAT_STEREO16, &tracker_buffer.s8, 4096, freq);
|
|
alSourceQueueBuffers(oss_source, 1, &oss_buffer);
|
|
alSourcePlay(oss_source);
|
|
}
|
|
|
|
int Tracker_Init(void)
|
|
{
|
|
if (COM_CheckParm("-notracker"))
|
|
return -1;
|
|
|
|
oss_device = alcOpenDevice(NULL);
|
|
if (!oss_device)
|
|
{
|
|
perror("/dev/dsp");
|
|
return 0; // just get out if there's none
|
|
}
|
|
|
|
Cmd_AddCommand ("dumb", Tracker_f); // link DUMB
|
|
bTracker_Initialized = true;
|
|
Con_Printf("DUMB Initialized\n"); // Tell them we are ready
|
|
return 1; // return that we have successfully initialised
|
|
}
|
|
|
|
void Tracker_Shutdown(void)
|
|
{
|
|
Tracker_Stop(); // First stop the track
|
|
dumb_exit(); // Kill DUMB
|
|
alcCloseDevice(oss_device);
|
|
}
|
|
#endif
|