static snd() { for (int i = 0; i < _KnownSfx.Length; i++) { _KnownSfx[i] = new sfx_t(); } }
// S_SoundList private static void SoundList() { int total = 0; for (int i = 0; i < _NumSfx; i++) { sfx_t sfx = _KnownSfx[i]; sfxcache_t sc = (sfxcache_t)Cache.Check(sfx.cache); if (sc == null) { continue; } int size = sc.length * sc.width * (sc.stereo + 1); total += size; if (sc.loopstart >= 0) { Con.Print("L"); } else { Con.Print(" "); } Con.Print("({0:d2}b) {1:g6} : {2}\n", sc.width * 8, size, sfx.name); } Con.Print("Total resident: {0}\n", total); }
// S_FindName private static sfx_t FindName(string name) { if (String.IsNullOrEmpty(name)) { sys.Error("S_FindName: NULL or empty\n"); } if (name.Length >= QDef.MAX_QPATH) { sys.Error("Sound name too long: {0}", name); } // see if already loaded for (int i = 0; i < _NumSfx; i++) { if (_KnownSfx[i].name == name) // !Q_strcmp(known_sfx[i].name, name)) { return(_KnownSfx[i]); } } if (_NumSfx == MAX_SFX) { sys.Error("S_FindName: out of sfx_t"); } sfx_t sfx = _KnownSfx[_NumSfx]; sfx.name = name; _NumSfx++; return(sfx); }
// S_TouchSound (char *sample) public static void TouchSound(string sample) { if (!_Controller.IsInitialized) { return; } sfx_t sfx = FindName(sample); Cache.Check(sfx.cache); }
// S_LoadSound private static sfxcache_t LoadSound(sfx_t s) { // see if still in memory sfxcache_t sc = (sfxcache_t)Cache.Check(s.cache); if (sc != null) { return(sc); } // load it in string namebuffer = "sound/" + s.name; byte[] data = common.LoadFile(namebuffer); if (data == null) { Con.Print("Couldn't load {0}\n", namebuffer); return(null); } wavinfo_t info = GetWavInfo(s.name, data); if (info.channels != 1) { Con.Print("{0} is a stereo sample\n", s.name); return(null); } float stepscale = info.rate / (float)_shm.speed; int len = (int)(info.samples / stepscale); len *= info.width * info.channels; s.cache = Cache.Alloc(len, s.name); if (s.cache == null) { return(null); } sc = new sfxcache_t(); sc.length = info.samples; sc.loopstart = info.loopstart; sc.speed = info.rate; sc.width = info.width; sc.stereo = info.channels; s.cache.data = sc; ResampleSfx(s, sc.speed, sc.width, new ByteArraySegment(data, info.dataofs)); return(sc); }
public int master_vol; // 0-255 master volume public void Clear() { sfx = null; leftvol = 0; rightvol = 0; end = 0; pos = 0; looping = 0; entnum = 0; entchannel = 0; origin = Vector3.Zero; dist_mult = 0; master_vol = 0; }
// S_Play private static void Play() { for (int i = 1; i < cmd.Argc; i++) { string name = cmd.Argv(i); int k = name.IndexOf('.'); if (k == -1) { name += ".wav"; } sfx_t sfx = PrecacheSound(name); StartSound(_PlayHash++, 0, sfx, ref _ListenerOrigin, 1.0f, 1.0f); } }
// S_PlayVol private static void PlayVol() { for (int i = 1; i < cmd.Argc; i += 2) { string name = cmd.Argv(i); int k = name.IndexOf('.'); if (k == -1) { name += ".wav"; } sfx_t sfx = PrecacheSound(name); float vol = float.Parse(cmd.Argv(i + 1)); StartSound(_PlayVolHash++, 0, sfx, ref _ListenerOrigin, vol, 1.0f); } }
// SND_Spatialize private static void Spatialize(channel_t ch) { // anything coming from the view entity will allways be full volume if (ch.entnum == client.cl.viewentity) { ch.leftvol = ch.master_vol; ch.rightvol = ch.master_vol; return; } // calculate stereo seperation and distance attenuation sfx_t snd = ch.sfx; Vector3 source_vec = ch.origin - _ListenerOrigin; float dist = mathlib.Normalize(ref source_vec) * ch.dist_mult; float dot = Vector3.Dot(_ListenerRight, source_vec); float rscale, lscale; if (_shm.channels == 1) { rscale = 1.0f; lscale = 1.0f; } else { rscale = 1.0f + dot; lscale = 1.0f - dot; } // add in distance effect float scale = (1.0f - dist) * rscale; ch.rightvol = (int)(ch.master_vol * scale); if (ch.rightvol < 0) { ch.rightvol = 0; } scale = (1.0f - dist) * lscale; ch.leftvol = (int)(ch.master_vol * scale); if (ch.leftvol < 0) { ch.leftvol = 0; } }
// sfx_t *S_PrecacheSound (char *sample) public static sfx_t PrecacheSound(string sample) { if (!_IsInitialized || _NoSound.Value != 0) { return(null); } sfx_t sfx = FindName(sample); // cache it in if (_Precache.Value != 0) { LoadSound(sfx); } return(sfx); }
private static sfx_t _SfxRExp3; // cl_sfx_r_exp3 // CL_InitTEnts private static void InitTempEntities() { _SfxWizHit = snd.PrecacheSound("wizard/hit.wav"); _SfxKnigtHit = snd.PrecacheSound("hknight/hit.wav"); _SfxTink1 = snd.PrecacheSound("weapons/tink1.wav"); _SfxRic1 = snd.PrecacheSound("weapons/ric1.wav"); _SfxRic2 = snd.PrecacheSound("weapons/ric2.wav"); _SfxRic3 = snd.PrecacheSound("weapons/ric3.wav"); _SfxRExp3 = snd.PrecacheSound("weapons/r_exp3.wav"); for (int i = 0; i < _TempEntities.Length; i++) { _TempEntities[i] = new entity_t(); } for (int i = 0; i < _Beams.Length; i++) { _Beams[i] = new beam_t(); } }
// void S_LocalSound (char *s) public static void LocalSound(string sound) { if (_NoSound.Value != 0) { return; } if (!_Controller.IsInitialized) { return; } sfx_t sfx = PrecacheSound(sound); if (sfx == null) { Con.Print("S_LocalSound: can't cache {0}\n", sound); return; } StartSound(client.cl.viewentity, -1, sfx, ref common.ZeroVector, 1, 1); }
// S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) public static void StaticSound(sfx_t sfx, ref Vector3 origin, float vol, float attenuation) { if (sfx == null) { return; } if (_TotalChannels == MAX_CHANNELS) { Con.Print("total_channels == MAX_CHANNELS\n"); return; } channel_t ss = _Channels[_TotalChannels]; _TotalChannels++; sfxcache_t sc = LoadSound(sfx); if (sc == null) { return; } if (sc.loopstart == -1) { Con.Print("Sound {0} not looped\n", sfx.name); return; } ss.sfx = sfx; ss.origin = origin; ss.master_vol = (int)vol; ss.dist_mult = (attenuation / 64) / _SoundNominalClipDist; ss.end = _PaintedTime + sc.length; Spatialize(ss); }
// S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) public static void StartSound(int entnum, int entchannel, sfx_t sfx, ref Vector3 origin, float fvol, float attenuation) { if (!_SoundStarted || sfx == null) { return; } if (_NoSound.Value != 0) { return; } int vol = (int)(fvol * 255); // pick a channel to play on channel_t target_chan = PickChannel(entnum, entchannel); if (target_chan == null) { return; } // spatialize //memset (target_chan, 0, sizeof(*target_chan)); target_chan.origin = origin; target_chan.dist_mult = attenuation / _SoundNominalClipDist; target_chan.master_vol = vol; target_chan.entnum = entnum; target_chan.entchannel = entchannel; Spatialize(target_chan); if (target_chan.leftvol == 0 && target_chan.rightvol == 0) { return; // not audible at all } // new channel sfxcache_t sc = LoadSound(sfx); if (sc == null) { target_chan.sfx = null; return; // couldn't load the sound's data } target_chan.sfx = sfx; target_chan.pos = 0; target_chan.end = _PaintedTime + sc.length; // if an identical sound has also been started this frame, offset the pos // a bit to keep it from just making the first one louder for (int i = Ambients.NUM_AMBIENTS; i < Ambients.NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS; i++) { channel_t check = _Channels[i]; if (check == target_chan) { continue; } if (check.sfx == sfx && check.pos == 0) { int skip = sys.Random((int)(0.1 * _shm.speed)); // rand() % (int)(0.1 * shm->speed); if (skip >= target_chan.end) { skip = target_chan.end - 1; } target_chan.pos += skip; target_chan.end -= skip; break; } } }
// ResampleSfx private static void ResampleSfx(sfx_t sfx, int inrate, int inwidth, ByteArraySegment data) { sfxcache_t sc = (sfxcache_t)Cache.Check(sfx.cache); if (sc == null) { return; } float stepscale = (float)inrate / _shm.speed; // this is usually 0.5, 1, or 2 int outcount = (int)(sc.length / stepscale); sc.length = outcount; if (sc.loopstart != -1) { sc.loopstart = (int)(sc.loopstart / stepscale); } sc.speed = _shm.speed; if (_LoadAs8bit.Value != 0) { sc.width = 1; } else { sc.width = inwidth; } sc.stereo = 0; sc.data = new byte[outcount * sc.width]; // uze: check this later!!! // resample / decimate to the current source rate byte[] src = data.Data; if (stepscale == 1 && inwidth == 1 && sc.width == 1) { // fast special case for (int i = 0; i < outcount; i++) { int v = src[data.StartIndex + i] - 128; sc.data[i] = (byte)((sbyte)v); //((signed char *)sc.data)[i] = (int)( (unsigned char)(data[i]) - 128); } } else { // general case int samplefrac = 0; int fracstep = (int)(stepscale * 256); int sample; short[] sa = new short[1]; for (int i = 0; i < outcount; i++) { int srcsample = samplefrac >> 8; samplefrac += fracstep; if (inwidth == 2) { Buffer.BlockCopy(src, data.StartIndex + srcsample * 2, sa, 0, 2); sample = Common.LittleShort(sa[0]); // ((short *)data)[srcsample] ); } else { sample = (int)(src[data.StartIndex + srcsample] - 128) << 8; //sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; } if (sc.width == 2) { sa[0] = (short)sample; Buffer.BlockCopy(sa, 0, sc.data, i * 2, 2); //((short *)sc->data)[i] = sample; } else { sc.data[i] = (byte)(sbyte)(sample >> 8); //((signed char *)sc->data)[i] = sample >> 8; } } } }