/* Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2015 Marco "eukara" Hladik 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. */ #include "globaldef.h" #include "dumb.h" #include #include #include #include #include #include #include #include #include #include #include // eukara - added in tracker playback using DUMB - UNIX ONLY! char name[256]; DUH *trackmod; // The music file ~eukara DUH_SIGRENDERER *sr; // The DUMB renderer int oss_device; // output device (by default /dev/dsp for OSS) 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; 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); } } // TODO: Write this into the engine's soundbuffer instead for speed! write (oss_device, &tracker_buffer, 4096); } int Tracker_Init(void) { if (COM_CheckParm("-notracker")) return -1; if((oss_device = open ("/dev/dsp", O_RDWR)) == -1){ // /dev/dsp is the standard OSS output 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 close(oss_device); // Close the device }