aboutsummaryrefslogtreecommitdiffstats
path: root/src/jake2/client/SND_DMA.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jake2/client/SND_DMA.java')
-rw-r--r--src/jake2/client/SND_DMA.java1247
1 files changed, 1247 insertions, 0 deletions
diff --git a/src/jake2/client/SND_DMA.java b/src/jake2/client/SND_DMA.java
new file mode 100644
index 0000000..fba94c1
--- /dev/null
+++ b/src/jake2/client/SND_DMA.java
@@ -0,0 +1,1247 @@
+/*
+ * S_DMA.java
+ * Copyright (C) 2004
+ *
+ * $Id: SND_DMA.java,v 1.1 2004-07-07 19:58:51 hzi Exp $
+ */
+/*
+Copyright (C) 1997-2001 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.
+
+*/
+
+// Created on 26.01.2004 by RST.
+
+package jake2.client;
+
+import jake2.game.Cmd;
+import jake2.game.cvar_t;
+import jake2.qcommon.*;
+import jake2.util.Vargs;
+
+
+
+/**
+ * SND_DMA
+ * TODO implement sound system
+ */
+public class SND_DMA extends SND_MIX {
+//// snd_dma.c -- main control for any streaming sound output device
+//
+// #include "client.h"
+// #include "snd_loc.h"
+//
+// void S_Play(void);
+// void S_SoundList(void);
+// void S_Update_();
+// void S_StopAllSounds(void);
+//
+//
+//// =======================================================================
+//// Internal sound data & structures
+//// =======================================================================
+//
+//// only begin attenuating sound volumes when outside the FULLVOLUME range
+// #define SOUND_FULLVOLUME 80
+//
+// #define SOUND_LOOPATTENUATE 0.003
+//
+ static int s_registration_sequence;
+//
+// channel_t channels[MAX_CHANNELS];
+//
+// qboolean snd_initialized = false;
+ static boolean sound_started = false;
+//
+
+
+//
+// vec3_t listener_origin;
+// vec3_t listener_forward;
+// vec3_t listener_right;
+// vec3_t listener_up;
+//
+ static boolean s_registering;
+//
+ static int soundtime; // sample PAIRS
+ static int paintedtime; // sample PAIRS
+//
+//// during registration it is possible to have more sounds
+//// than could actually be referenced during gameplay,
+//// because we don't want to free anything until we are
+//// sure we won't need it.
+ static final int MAX_SFX = (MAX_SOUNDS*2);
+ static sfx_t[] known_sfx = new sfx_t[MAX_SFX];
+ static {
+ for (int i = 0; i< known_sfx.length; i++)
+ known_sfx[i] = new sfx_t();
+ }
+ static int num_sfx;
+//
+// #define MAX_PLAYSOUNDS 128
+// playsound_t s_playsounds[MAX_PLAYSOUNDS];
+// playsound_t s_freeplays;
+// playsound_t s_pendingplays;
+//
+// int s_beginofs;
+//
+ static cvar_t s_volume;
+ static cvar_t s_testsound;
+ static cvar_t s_loadas8bit;
+ static cvar_t s_khz;
+ static cvar_t s_show;
+ static cvar_t s_mixahead;
+ static cvar_t s_primary;
+//
+//
+// int s_rawend;
+// portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
+//
+//
+// ====================================================================
+// User-setable variables
+// ====================================================================
+
+
+ static void SoundInfo_f()
+ {
+ if (!sound_started)
+ {
+ Com.Printf ("sound system not started\n");
+ return;
+ }
+
+ Com.Printf("%5d stereo\n", new Vargs(1).add(dma.channels - 1));
+ Com.Printf("%5d samples\n", new Vargs(1).add(dma.samples));
+ Com.Printf("%5d samplepos\n", new Vargs(1).add(dma.samplepos));
+ Com.Printf("%5d samplebits\n", new Vargs(1).add(dma.samplebits));
+ Com.Printf("%5d submission_chunk\n", new Vargs(1).add(dma.submission_chunk));
+ Com.Printf("%5d speed\n", new Vargs(1).add(dma.speed));
+ }
+
+ /*
+ ================
+ S_Init
+ ================
+ */
+ public static void Init() {
+ cvar_t cv;
+
+ Com.Printf("\n------- sound initialization -------\n");
+
+ cv = Cvar.Get("s_initsound", "1", 0);
+ if (cv.value == 0.0f)
+ Com.Printf("not initializing.\n");
+ else {
+ s_volume = Cvar.Get("s_volume", "0.7", CVAR_ARCHIVE);
+ s_khz = Cvar.Get("s_khz", "11", CVAR_ARCHIVE);
+ s_loadas8bit = Cvar.Get("s_loadas8bit", "1", CVAR_ARCHIVE);
+ s_mixahead = Cvar.Get("s_mixahead", "0.2", CVAR_ARCHIVE);
+ s_show = Cvar.Get("s_show", "0", 0);
+ s_testsound = Cvar.Get("s_testsound", "0", 0);
+ s_primary = Cvar.Get("s_primary", "0", CVAR_ARCHIVE); // win32 specific
+
+ Cmd.AddCommand("play", new xcommand_t() {
+ public void execute() {
+ S.Play();
+ }
+ });
+ Cmd.AddCommand("stopsound", new xcommand_t() {
+ public void execute() {
+ S.StopAllSounds();
+ }
+ });
+ Cmd.AddCommand("soundlist", new xcommand_t() {
+ public void execute() {
+ S.SoundList();
+ }
+ });
+ Cmd.AddCommand("soundinfo", new xcommand_t() {
+ public void execute() {
+ S.SoundInfo_f();
+ }
+ });
+
+ if (!SNDDMA_Init())
+ return;
+
+ S.InitScaletable();
+
+ sound_started = true;
+ num_sfx = 0;
+
+ soundtime = 0;
+ paintedtime = 0;
+
+ Com.Printf("sound sampling rate: " + dma.speed + "\n");
+
+ S.StopAllSounds();
+ }
+S.SoundInfo_f();
+ Com.Printf("------------------------------------\n");
+ }
+
+
+// =======================================================================
+// Shutdown sound engine
+// =======================================================================
+
+ static void Shutdown()
+ {
+ int i;
+ sfx_t[] sfx;
+
+ if (!sound_started)
+ return;
+
+ SNDDMA_Shutdown();
+
+ sound_started = false;
+
+ Cmd.RemoveCommand("play");
+ Cmd.RemoveCommand("stopsound");
+ Cmd.RemoveCommand("soundlist");
+ Cmd.RemoveCommand("soundinfo");
+
+ // free all sounds
+ for (i=0, sfx=known_sfx ; i < num_sfx ; i++)
+ {
+ if (sfx[i].name == null)
+ continue;
+
+ //memset (sfx, 0, sizeof(*sfx));
+ sfx[i].clear();
+ }
+
+ num_sfx = 0;
+ }
+
+// =======================================================================
+// Load a sound
+// =======================================================================
+
+ /*
+ ==================
+ S_FindName
+
+ ==================
+ */
+ static sfx_t FindName(String name, boolean create) {
+ int i;
+ sfx_t sfx = null;
+
+ if (name == null)
+ Com.Error(ERR_FATAL, "S_FindName: NULL\n");
+ if (name.length() == 0)
+ Com.Error(ERR_FATAL, "S_FindName: empty name\n");
+
+ if (strlen(name) >= MAX_QPATH)
+ Com.Error(ERR_FATAL, "Sound name too long: " + name);
+
+ // see if already loaded
+ for (i = 0; i < num_sfx; i++)
+ if (name.equals(known_sfx[i].name)) {
+ return known_sfx[i];
+ }
+
+ if (!create)
+ return null;
+
+ // find a free sfx
+ for (i = 0; i < num_sfx; i++)
+ if (known_sfx[i].name == null)
+ // registration_sequence < s_registration_sequence)
+ break;
+
+ if (i == num_sfx) {
+ if (num_sfx == MAX_SFX)
+ Com.Error(ERR_FATAL, "S_FindName: out of sfx_t");
+ num_sfx++;
+ }
+
+ sfx = known_sfx[i];
+ //memset (sfx, 0, sizeof(*sfx));
+ sfx.clear();
+ sfx.name = name;
+ sfx.registration_sequence = s_registration_sequence;
+
+ return sfx;
+ }
+//
+//
+// /*
+// ==================
+// S_AliasName
+//
+// ==================
+// */
+// sfx_t *S_AliasName (char *aliasname, char *truename)
+// {
+// sfx_t *sfx;
+// char *s;
+// int i;
+//
+// s = Z_Malloc (MAX_QPATH);
+// strcpy (s, truename);
+//
+// // find a free sfx
+// for (i=0 ; i < num_sfx ; i++)
+// if (!known_sfx[i].name[0])
+// break;
+//
+// if (i == num_sfx)
+// {
+// if (num_sfx == MAX_SFX)
+// Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
+// num_sfx++;
+// }
+//
+// sfx = &known_sfx[i];
+// memset (sfx, 0, sizeof(*sfx));
+// strcpy (sfx->name, aliasname);
+// sfx->registration_sequence = s_registration_sequence;
+// sfx->truename = s;
+//
+// return sfx;
+// }
+//
+//
+ /*
+ =====================
+ S_BeginRegistration
+
+ =====================
+ */
+ static void BeginRegistration() {
+ s_registration_sequence++;
+ s_registering = true;
+ }
+
+ /*
+ ==================
+ S_RegisterSound
+
+ ==================
+ */
+ static sfx_t RegisterSound(String name) {
+ sfx_t sfx = null;
+
+// if (!sound_started)
+// return null;
+//
+// sfx = S.FindName(name, true);
+// sfx.registration_sequence = s_registration_sequence;
+//
+// if (!s_registering)
+// S.LoadSound(sfx);
+
+ return sfx;
+ }
+
+
+ /*
+ =====================
+ S_EndRegistration
+
+ =====================
+ */
+ static void EndRegistration ()
+ {
+// int i;
+// sfx_t *sfx;
+// int size;
+//
+// // free any sounds not from this registration sequence
+// for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
+// {
+// if (!sfx->name[0])
+// continue;
+// if (sfx->registration_sequence != s_registration_sequence)
+// { // don't need this sound
+// if (sfx->cache) // it is possible to have a leftover
+// Z_Free (sfx->cache); // from a server that didn't finish loading
+// memset (sfx, 0, sizeof(*sfx));
+// }
+// else
+// { // make sure it is paged in
+// if (sfx->cache)
+// {
+// size = sfx->cache->length*sfx->cache->width;
+// Com_PageInMemory ((byte *)sfx->cache, size);
+// }
+// }
+//
+// }
+//
+// // load everything in
+// for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
+// {
+// if (!sfx->name[0])
+// continue;
+// S_LoadSound (sfx);
+// }
+//
+// s_registering = false;
+ }
+//
+//
+//// =============================================================================
+//
+// /*
+// =================
+// S_PickChannel
+// =================
+// */
+// channel_t *S_PickChannel(int entnum, int entchannel)
+// {
+// int ch_idx;
+// int first_to_die;
+// int life_left;
+// channel_t *ch;
+//
+// if (entchannel<0)
+// Com_Error (ERR_DROP, "S_PickChannel: entchannel<0");
+//
+//// Check for replacement sound, or find the best one to replace
+// first_to_die = -1;
+// life_left = 0x7fffffff;
+// for (ch_idx=0 ; ch_idx < MAX_CHANNELS ; ch_idx++)
+// {
+// if (entchannel != 0 // channel 0 never overrides
+// && channels[ch_idx].entnum == entnum
+// && channels[ch_idx].entchannel == entchannel)
+// { // always override sound from same entity
+// first_to_die = ch_idx;
+// break;
+// }
+//
+// // don't let monster sounds override player sounds
+// if (channels[ch_idx].entnum == cl.playernum+1 && entnum != cl.playernum+1 && channels[ch_idx].sfx)
+// continue;
+//
+// if (channels[ch_idx].end - paintedtime < life_left)
+// {
+// life_left = channels[ch_idx].end - paintedtime;
+// first_to_die = ch_idx;
+// }
+// }
+//
+// if (first_to_die == -1)
+// return NULL;
+//
+// ch = &channels[first_to_die];
+// memset (ch, 0, sizeof(*ch));
+//
+// return ch;
+// }
+//
+// /*
+// =================
+// S_SpatializeOrigin
+//
+// Used for spatializing channels and autosounds
+// =================
+// */
+// void S_SpatializeOrigin (vec3_t origin, float master_vol, float dist_mult, int *left_vol, int *right_vol)
+// {
+// vec_t dot;
+// vec_t dist;
+// vec_t lscale, rscale, scale;
+// vec3_t source_vec;
+//
+// if (cls.state != ca_active)
+// {
+// *left_vol = *right_vol = 255;
+// return;
+// }
+//
+//// calculate stereo seperation and distance attenuation
+// VectorSubtract(origin, listener_origin, source_vec);
+//
+// dist = VectorNormalize(source_vec);
+// dist -= SOUND_FULLVOLUME;
+// if (dist < 0)
+// dist = 0; // close enough to be at full volume
+// dist *= dist_mult; // different attenuation levels
+//
+// dot = DotProduct(listener_right, source_vec);
+//
+// if (dma.channels == 1 || !dist_mult)
+// { // no attenuation = no spatialization
+// rscale = 1.0;
+// lscale = 1.0;
+// }
+// else
+// {
+// rscale = 0.5 * (1.0 + dot);
+// lscale = 0.5*(1.0 - dot);
+// }
+//
+// // add in distance effect
+// scale = (1.0 - dist) * rscale;
+// *right_vol = (int) (master_vol * scale);
+// if (*right_vol < 0)
+// *right_vol = 0;
+//
+// scale = (1.0 - dist) * lscale;
+// *left_vol = (int) (master_vol * scale);
+// if (*left_vol < 0)
+// *left_vol = 0;
+// }
+//
+// /*
+// =================
+// S_Spatialize
+// =================
+// */
+// void S_Spatialize(channel_t *ch)
+// {
+// vec3_t origin;
+//
+// // anything coming from the view entity will always be full volume
+// if (ch->entnum == cl.playernum+1)
+// {
+// ch->leftvol = ch->master_vol;
+// ch->rightvol = ch->master_vol;
+// return;
+// }
+//
+// if (ch->fixed_origin)
+// {
+// VectorCopy (ch->origin, origin);
+// }
+// else
+// CL_GetEntitySoundOrigin (ch->entnum, origin);
+//
+// S_SpatializeOrigin (origin, ch->master_vol, ch->dist_mult, &ch->leftvol, &ch->rightvol);
+// }
+//
+//
+// /*
+// =================
+// S_AllocPlaysound
+// =================
+// */
+// playsound_t *S_AllocPlaysound (void)
+// {
+// playsound_t *ps;
+//
+// ps = s_freeplays.next;
+// if (ps == &s_freeplays)
+// return NULL; // no free playsounds
+//
+// // unlink from freelist
+// ps->prev->next = ps->next;
+// ps->next->prev = ps->prev;
+//
+// return ps;
+// }
+//
+//
+// /*
+// =================
+// S_FreePlaysound
+// =================
+// */
+// void S_FreePlaysound (playsound_t *ps)
+// {
+// // unlink from channel
+// ps->prev->next = ps->next;
+// ps->next->prev = ps->prev;
+//
+// // add to free list
+// ps->next = s_freeplays.next;
+// s_freeplays.next->prev = ps;
+// ps->prev = &s_freeplays;
+// s_freeplays.next = ps;
+// }
+//
+//
+//
+// /*
+// ===============
+// S_IssuePlaysound
+//
+// Take the next playsound and begin it on the channel
+// This is never called directly by S_Play*, but only
+// by the update loop.
+// ===============
+// */
+// void S_IssuePlaysound (playsound_t *ps)
+// {
+// channel_t *ch;
+// sfxcache_t *sc;
+//
+// if (s_show->value)
+// Com_Printf ("Issue %i\n", ps->begin);
+// // pick a channel to play on
+// ch = S_PickChannel(ps->entnum, ps->entchannel);
+// if (!ch)
+// {
+// S_FreePlaysound (ps);
+// return;
+// }
+//
+// // spatialize
+// if (ps->attenuation == ATTN_STATIC)
+// ch->dist_mult = ps->attenuation * 0.001;
+// else
+// ch->dist_mult = ps->attenuation * 0.0005;
+// ch->master_vol = ps->volume;
+// ch->entnum = ps->entnum;
+// ch->entchannel = ps->entchannel;
+// ch->sfx = ps->sfx;
+// VectorCopy (ps->origin, ch->origin);
+// ch->fixed_origin = ps->fixed_origin;
+//
+// S_Spatialize(ch);
+//
+// ch->pos = 0;
+// sc = S_LoadSound (ch->sfx);
+// ch->end = paintedtime + sc->length;
+//
+// // free the playsound
+// S_FreePlaysound (ps);
+// }
+//
+// struct sfx_s *S_RegisterSexedSound (entity_state_t *ent, char *base)
+// {
+// int n;
+// char *p;
+// struct sfx_s *sfx;
+// FILE *f;
+// char model[MAX_QPATH];
+// char sexedFilename[MAX_QPATH];
+// char maleFilename[MAX_QPATH];
+//
+// // determine what model the client is using
+// model[0] = 0;
+// n = CS_PLAYERSKINS + ent->number - 1;
+// if (cl.configstrings[n][0])
+// {
+// p = strchr(cl.configstrings[n], '\\');
+// if (p)
+// {
+// p += 1;
+// strcpy(model, p);
+// p = strchr(model, '/');
+// if (p)
+// *p = 0;
+// }
+// }
+// // if we can't figure it out, they're male
+// if (!model[0])
+// strcpy(model, "male");
+//
+// // see if we already know of the model specific sound
+// Com_sprintf (sexedFilename, sizeof(sexedFilename), "#players/%s/%s", model, base+1);
+// sfx = S_FindName (sexedFilename, false);
+//
+// if (!sfx)
+// {
+// // no, so see if it exists
+// FS_FOpenFile (&sexedFilename[1], &f);
+// if (f)
+// {
+// // yes, close the file and register it
+// FS_FCloseFile (f);
+// sfx = S_RegisterSound (sexedFilename);
+// }
+// else
+// {
+// // no, revert to the male sound in the pak0.pak
+// Com_sprintf (maleFilename, sizeof(maleFilename), "player/%s/%s", "male", base+1);
+// sfx = S_AliasName (sexedFilename, maleFilename);
+// }
+// }
+//
+// return sfx;
+// }
+//
+//
+//// =======================================================================
+//// Start a sound effect
+//// =======================================================================
+//
+ /*
+ ====================
+ S_StartSound
+
+ Validates the parms and ques the sound up
+ if pos is NULL, the sound will be dynamically sourced from the entity
+ Entchannel 0 will never override a playing sound
+ ====================
+ */
+ static void StartSound(float[] origin, int entnum, int entchannel, sfx_t sfx, float fvol, float attenuation, float timeofs)
+ {
+// sfxcache_t *sc;
+// int vol;
+// playsound_t *ps, *sort;
+// int start;
+//
+// if (!sound_started)
+// return;
+//
+// if (!sfx)
+// return;
+//
+// if (sfx->name[0] == '*')
+// sfx = S_RegisterSexedSound(&cl_entities[entnum].current, sfx->name);
+//
+// // make sure the sound is loaded
+// sc = S_LoadSound (sfx);
+// if (!sc)
+// return; // couldn't load the sound's data
+//
+// vol = fvol*255;
+//
+// // make the playsound_t
+// ps = S_AllocPlaysound ();
+// if (!ps)
+// return;
+//
+// if (origin)
+// {
+// VectorCopy (origin, ps->origin);
+// ps->fixed_origin = true;
+// }
+// else
+// ps->fixed_origin = false;
+//
+// ps->entnum = entnum;
+// ps->entchannel = entchannel;
+// ps->attenuation = attenuation;
+// ps->volume = vol;
+// ps->sfx = sfx;
+//
+// // drift s_beginofs
+// start = cl.frame.servertime * 0.001 * dma.speed + s_beginofs;
+// if (start < paintedtime)
+// {
+// start = paintedtime;
+// s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
+// }
+// else if (start > paintedtime + 0.3 * dma.speed)
+// {
+// start = paintedtime + 0.1 * dma.speed;
+// s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
+// }
+// else
+// {
+// s_beginofs-=10;
+// }
+//
+// if (!timeofs)
+// ps->begin = paintedtime;
+// else
+// ps->begin = start + timeofs * dma.speed;
+//
+// // sort into the pending sound list
+// for (sort = s_pendingplays.next ;
+// sort != &s_pendingplays && sort->begin < ps->begin ;
+// sort = sort->next)
+// ;
+//
+// ps->next = sort;
+// ps->prev = sort->prev;
+//
+// ps->next->prev = ps;
+// ps->prev->next = ps;
+ }
+
+//
+// /*
+// ==================
+// S_StartLocalSound
+// ==================
+// */
+ static void StartLocalSound(String sound) {
+// sfx_t *sfx;
+//
+// if (!sound_started)
+// return;
+//
+// sfx = S_RegisterSound (sound);
+// if (!sfx)
+// {
+// Com_Printf ("S_StartLocalSound: can't cache %s\n", sound);
+// return;
+// }
+// S_StartSound (NULL, cl.playernum+1, 0, sfx, 1, 1, 0);
+ }
+//
+//
+// /*
+// ==================
+// S_ClearBuffer
+// ==================
+// */
+// void S_ClearBuffer (void)
+// {
+// int clear;
+//
+// if (!sound_started)
+// return;
+//
+// s_rawend = 0;
+//
+// if (dma.samplebits == 8)
+// clear = 0x80;
+// else
+// clear = 0;
+//
+// SNDDMA_BeginPainting ();
+// if (dma.buffer)
+// memset(dma.buffer, clear, dma.samples * dma.samplebits/8);
+// SNDDMA_Submit ();
+// }
+//
+ /*
+ ==================
+ S_StopAllSounds
+ ==================
+ */
+ static void StopAllSounds()
+ {
+// int i;
+//
+// if (!sound_started)
+// return;
+//
+// // clear all the playsounds
+// memset(s_playsounds, 0, sizeof(s_playsounds));
+// s_freeplays.next = s_freeplays.prev = &s_freeplays;
+// s_pendingplays.next = s_pendingplays.prev = &s_pendingplays;
+//
+// for (i=0 ; i<MAX_PLAYSOUNDS ; i++)
+// {
+// s_playsounds[i].prev = &s_freeplays;
+// s_playsounds[i].next = s_freeplays.next;
+// s_playsounds[i].prev->next = &s_playsounds[i];
+// s_playsounds[i].next->prev = &s_playsounds[i];
+// }
+//
+// // clear all the channels
+// memset(channels, 0, sizeof(channels));
+//
+// S_ClearBuffer ();
+ }
+//
+// /*
+// ==================
+// S_AddLoopSounds
+//
+// Entities with a ->sound field will generated looped sounds
+// that are automatically started, stopped, and merged together
+// as the entities are sent to the client
+// ==================
+// */
+// void S_AddLoopSounds (void)
+// {
+// int i, j;
+// int sounds[MAX_EDICTS];
+// int left, right, left_total, right_total;
+// channel_t *ch;
+// sfx_t *sfx;
+// sfxcache_t *sc;
+// int num;
+// entity_state_t *ent;
+//
+// if (cl_paused->value)
+// return;
+//
+// if (cls.state != ca_active)
+// return;
+//
+// if (!cl.sound_prepped)
+// return;
+//
+// for (i=0 ; i<cl.frame.num_entities ; i++)
+// {
+// num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
+// ent = &cl_parse_entities[num];
+// sounds[i] = ent->sound;
+// }
+//
+// for (i=0 ; i<cl.frame.num_entities ; i++)
+// {
+// if (!sounds[i])
+// continue;
+//
+// sfx = cl.sound_precache[sounds[i]];
+// if (!sfx)
+// continue; // bad sound effect
+// sc = sfx->cache;
+// if (!sc)
+// continue;
+//
+// num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
+// ent = &cl_parse_entities[num];
+//
+// // find the total contribution of all sounds of this type
+// S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE,
+// &left_total, &right_total);
+// for (j=i+1 ; j<cl.frame.num_entities ; j++)
+// {
+// if (sounds[j] != sounds[i])
+// continue;
+// sounds[j] = 0; // don't check this again later
+//
+// num = (cl.frame.parse_entities + j)&(MAX_PARSE_ENTITIES-1);
+// ent = &cl_parse_entities[num];
+//
+// S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE,
+// &left, &right);
+// left_total += left;
+// right_total += right;
+// }
+//
+// if (left_total == 0 && right_total == 0)
+// continue; // not audible
+//
+// // allocate a channel
+// ch = S_PickChannel(0, 0);
+// if (!ch)
+// return;
+//
+// if (left_total > 255)
+// left_total = 255;
+// if (right_total > 255)
+// right_total = 255;
+// ch->leftvol = left_total;
+// ch->rightvol = right_total;
+// ch->autosound = true; // remove next frame
+// ch->sfx = sfx;
+// ch->pos = paintedtime % sc->length;
+// ch->end = paintedtime + sc->length - ch->pos;
+// }
+// }
+//
+//// =============================================================================
+//
+// /*
+// ============
+// S_RawSamples
+//
+// Cinematic streaming and voice over network
+// ============
+// */
+// void S_RawSamples (int samples, int rate, int width, int channels, byte *data)
+// {
+// int i;
+// int src, dst;
+// float scale;
+//
+// if (!sound_started)
+// return;
+//
+// if (s_rawend < paintedtime)
+// s_rawend = paintedtime;
+// scale = (float)rate / dma.speed;
+//
+//// Com_Printf ("%i < %i < %i\n", soundtime, paintedtime, s_rawend);
+// if (channels == 2 && width == 2)
+// {
+// if (scale == 1.0)
+// { // optimized case
+// for (i=0 ; i<samples ; i++)
+// {
+// dst = s_rawend&(MAX_RAW_SAMPLES-1);
+// s_rawend++;
+// s_rawsamples[dst].left =
+// LittleShort(((short *)data)[i*2]) << 8;
+// s_rawsamples[dst].right =
+// LittleShort(((short *)data)[i*2+1]) << 8;
+// }
+// }
+// else
+// {
+// for (i=0 ; ; i++)
+// {
+// src = i*scale;
+// if (src >= samples)
+// break;
+// dst = s_rawend&(MAX_RAW_SAMPLES-1);
+// s_rawend++;
+// s_rawsamples[dst].left =
+// LittleShort(((short *)data)[src*2]) << 8;
+// s_rawsamples[dst].right =
+// LittleShort(((short *)data)[src*2+1]) << 8;
+// }
+// }
+// }
+// else if (channels == 1 && width == 2)
+// {
+// for (i=0 ; ; i++)
+// {
+// src = i*scale;
+// if (src >= samples)
+// break;
+// dst = s_rawend&(MAX_RAW_SAMPLES-1);
+// s_rawend++;
+// s_rawsamples[dst].left =
+// LittleShort(((short *)data)[src]) << 8;
+// s_rawsamples[dst].right =
+// LittleShort(((short *)data)[src]) << 8;
+// }
+// }
+// else if (channels == 2 && width == 1)
+// {
+// for (i=0 ; ; i++)
+// {
+// src = i*scale;
+// if (src >= samples)
+// break;
+// dst = s_rawend&(MAX_RAW_SAMPLES-1);
+// s_rawend++;
+// s_rawsamples[dst].left =
+// ((char *)data)[src*2] << 16;
+// s_rawsamples[dst].right =
+// ((char *)data)[src*2+1] << 16;
+// }
+// }
+// else if (channels == 1 && width == 1)
+// {
+// for (i=0 ; ; i++)
+// {
+// src = i*scale;
+// if (src >= samples)
+// break;
+// dst = s_rawend&(MAX_RAW_SAMPLES-1);
+// s_rawend++;
+// s_rawsamples[dst].left =
+// (((byte *)data)[src]-128) << 16;
+// s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16;
+// }
+// }
+// }
+//
+//// =============================================================================
+//
+// /*
+// ============
+// S_Update
+//
+// Called once each time through the main loop
+// ============
+// */
+ static void Update(float[] origin, float[] forward, float[] right, float[] up) {
+// int i;
+// int total;
+// channel_t *ch;
+// channel_t *combine;
+//
+// if (!sound_started)
+// return;
+//
+// // if the laoding plaque is up, clear everything
+// // out to make sure we aren't looping a dirty
+// // dma buffer while loading
+// if (cls.disable_screen)
+// {
+// S_ClearBuffer ();
+// return;
+// }
+//
+// // rebuild scale tables if volume is modified
+// if (s_volume->modified)
+// S_InitScaletable ();
+//
+// VectorCopy(origin, listener_origin);
+// VectorCopy(forward, listener_forward);
+// VectorCopy(right, listener_right);
+// VectorCopy(up, listener_up);
+//
+// combine = NULL;
+//
+// // update spatialization for dynamic sounds
+// ch = channels;
+// for (i=0 ; i<MAX_CHANNELS; i++, ch++)
+// {
+// if (!ch->sfx)
+// continue;
+// if (ch->autosound)
+// { // autosounds are regenerated fresh each frame
+// memset (ch, 0, sizeof(*ch));
+// continue;
+// }
+// S_Spatialize(ch); // respatialize channel
+// if (!ch->leftvol && !ch->rightvol)
+// {
+// memset (ch, 0, sizeof(*ch));
+// continue;
+// }
+// }
+//
+// // add loopsounds
+// S_AddLoopSounds ();
+//
+// //
+// // debugging output
+// //
+// if (s_show->value)
+// {
+// total = 0;
+// ch = channels;
+// for (i=0 ; i<MAX_CHANNELS; i++, ch++)
+// if (ch->sfx && (ch->leftvol || ch->rightvol) )
+// {
+// Com_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
+// total++;
+// }
+//
+// Com_Printf ("----(%i)---- painted: %i\n", total, paintedtime);
+// }
+//
+//// mix some sound
+// S_Update_();
+ }
+
+//
+// void GetSoundtime(void)
+// {
+// int samplepos;
+// static int buffers;
+// static int oldsamplepos;
+// int fullsamples;
+//
+// fullsamples = dma.samples / dma.channels;
+//
+//// it is possible to miscount buffers if it has wrapped twice between
+//// calls to S_Update. Oh well.
+// samplepos = SNDDMA_GetDMAPos();
+//
+// if (samplepos < oldsamplepos)
+// {
+// buffers++; // buffer wrapped
+//
+// if (paintedtime > 0x40000000)
+// { // time to chop things off to avoid 32 bit limits
+// buffers = 0;
+// paintedtime = fullsamples;
+// S_StopAllSounds ();
+// }
+// }
+// oldsamplepos = samplepos;
+//
+// soundtime = buffers*fullsamples + samplepos/dma.channels;
+// }
+//
+//
+// void S_Update_(void)
+// {
+// unsigned endtime;
+// int samps;
+//
+// if (!sound_started)
+// return;
+//
+// SNDDMA_BeginPainting ();
+//
+// if (!dma.buffer)
+// return;
+//
+//// Updates DMA time
+// GetSoundtime();
+//
+//// check to make sure that we haven't overshot
+// if (paintedtime < soundtime)
+// {
+// Com_DPrintf ("S_Update_ : overflow\n");
+// paintedtime = soundtime;
+// }
+//
+//// mix ahead of current position
+// endtime = soundtime + s_mixahead->value * dma.speed;
+//// endtime = (soundtime + 4096) & ~4095;
+//
+// // mix to an even submission block size
+// endtime = (endtime + dma.submission_chunk-1)
+// & ~(dma.submission_chunk-1);
+// samps = dma.samples >> (dma.channels-1);
+// if (endtime - soundtime > samps)
+// endtime = soundtime + samps;
+//
+// S_PaintChannels (endtime);
+//
+// SNDDMA_Submit ();
+// }
+//
+ /*
+ ===============================================================================
+
+ console functions
+
+ ===============================================================================
+ */
+
+ static void Play()
+ {
+// int i;
+// char name[256];
+// sfx_t *sfx;
+//
+// i = 1;
+// while (i<Cmd_Argc())
+// {
+// if (!strrchr(Cmd_Argv(i), '.'))
+// {
+// strcpy(name, Cmd_Argv(i));
+// strcat(name, ".wav");
+// }
+// else
+// strcpy(name, Cmd_Argv(i));
+// sfx = S_RegisterSound(name);
+// S_StartSound(NULL, cl.playernum+1, 0, sfx, 1.0, 1.0, 0);
+// i++;
+// }
+ }
+//
+ static void SoundList() {
+// int i;
+// sfx_t *sfx;
+// sfxcache_t *sc;
+// int size, total;
+//
+// total = 0;
+// for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
+// {
+// if (!sfx->registration_sequence)
+// continue;
+// sc = sfx->cache;
+// if (sc)
+// {
+// size = sc->length*sc->width*(sc->stereo+1);
+// total += size;
+// if (sc->loopstart >= 0)
+// Com_Printf ("L");
+// else
+// Com_Printf (" ");
+// Com_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name);
+// }
+// else
+// {
+// if (sfx->name[0] == '*')
+// Com_Printf(" placeholder : %s\n", sfx->name);
+// else
+// Com_Printf(" not loaded : %s\n", sfx->name);
+// }
+// }
+// Com_Printf ("Total resident: %i\n", total);
+ }
+
+}