static SND_MIX( ) { for (var i = 0; i < MAX_CHANNELS; i++) { channels[i] = new channel_t(); } }
static void PaintChannelFrom8(channel_t ch, sfxcache_t sc, Int32 count, Int32 offset) { Int32 data; Int32[] lscale; Int32[] rscale; Int32 sfx; Int32 i; portable_samplepair_t samp; if (ch.leftvol > 255) { ch.leftvol = 255; } if (ch.rightvol > 255) { ch.rightvol = 255; } lscale = snd_scaletable[ch.leftvol >> 3]; rscale = snd_scaletable[ch.rightvol >> 3]; sfx = ch.pos; for (i = 0; i < count; i++, offset++) { var left = paInt32Buffer.Get(offset * 2); var right = paInt32Buffer.Get(offset * 2 + 1); data = sc.data[sfx + i]; left += lscale[data]; right += rscale[data]; paInt32Buffer.Put(offset * 2, left); paInt32Buffer.Put(offset * 2 + 1, right); } ch.pos += count; }
static void PaintChannelFrom16(channel_t ch, sfxcache_t sc, Int32 count, Int32 offset) { Int32 data; Int32 left, right; Int32 leftvol, rightvol; Int32 sfx; Int32 i; portable_samplepair_t samp; leftvol = ch.leftvol * snd_vol; rightvol = ch.rightvol * snd_vol; ByteBuffer bb = ByteBuffer.Wrap(sc.data); bb.Order = ByteOrder.LittleEndian; sb = bb.AsInt16Buffer(); sfx = ch.pos; for (i = 0; i < count; i++, offset++) { left = paInt32Buffer.Get(offset * 2); right = paInt32Buffer.Get(offset * 2 + 1); data = sb.Get(sfx + i); left += (data * leftvol) >> 8; right += (data * rightvol) >> 8; paInt32Buffer.Put(offset * 2, left); paInt32Buffer.Put(offset * 2 + 1, right); } ch.pos += count; }
static void SND_PaintChannelFrom8(channel_t ch, sfxcache_t sc, int count) { if (ch.leftvol > 255) { ch.leftvol = 255; } if (ch.rightvol > 255) { ch.rightvol = 255; } int lscale = ch.leftvol >> 3; int rscale = ch.rightvol >> 3; byte[] sfx = sc.data; int offset = ch.pos; for (int i = 0; i < count; i++) { int data = sfx[offset + i]; paintbuffer[i].left += _ScaleTable[lscale, data]; paintbuffer[i].right += _ScaleTable[rscale, data]; } ch.pos += count; }
//------------------------------------------------- // device_post_load - handle updating after a // restore //------------------------------------------------- protected override void device_post_load() { // loop over channels for (int channel = 0; channel < m_channels; channel++) { // attach any samples that were loaded and playing channel_t chan = m_channel[channel]; if (chan.source_num >= 0 && chan.source_num < m_sample.Count) { sample_t sample = m_sample[chan.source_num]; chan.source = sample.data; chan.source_length = sample.data.Count; if (sample.data.Count == 0) { chan.source_num = -1; } } // validate the position against the length in case the sample is smaller if (chan.source != null && chan.pos >= chan.source_length) { if (chan.loop) { chan.pos %= (UInt32)chan.source_length; } else { chan.source = null; chan.source_num = -1; } } } }
// device_sound_interface overrides //------------------------------------------------- // sound_stream_update - update a sound stream //------------------------------------------------- void device_sound_interface_sound_stream_update(sound_stream stream, std.vector <read_stream_view> inputs, std.vector <write_stream_view> outputs) //virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; { // find the channel with this stream stream_buffer_sample_t sample_scale = (stream_buffer_sample_t)(1.0 / 32768.0); for (int channel = 0; channel < m_channels; channel++) { if (stream == m_channel[channel].stream) { channel_t chan = m_channel[channel]; var buffer = outputs[0]; // process if we still have a source and we're not paused if (chan.source != null && !chan.paused) { // load some info locally double step = (double)chan.curfreq / (double)buffer.sample_rate(); double endpos = chan.source_len; Pointer <int16_t> sample = new Pointer <int16_t>(chan.source); //const int16_t *sample = chan.source; for (int sampindex = 0; sampindex < buffer.samples(); sampindex++) { // do a linear interp on the sample double pos_floor = std.floor(chan.pos); double frac = chan.pos - pos_floor; int32_t ipos = (int32_t)pos_floor; stream_buffer_sample_t sample1 = (stream_buffer_sample_t)sample[ipos++]; stream_buffer_sample_t sample2 = (stream_buffer_sample_t)sample[(ipos + 1) % (int)chan.source_len]; buffer.put(sampindex, (stream_buffer_sample_t)(sample_scale * ((1.0 - frac) * sample1 + frac * sample2))); // advance chan.pos += step; // handle looping/ending if (chan.pos >= endpos) { if (chan.loop) { chan.pos -= endpos; } else { chan.source = null; chan.source_num = -1; buffer.fill(0, sampindex); break; } } } } else { buffer.fill(0); } break; } } }
static void S_UpdateAmbientSounds() { if (!snd_ambient) { return; } // calc ambient sound levels if (cl.worldmodel == null) { return; } mleaf_t l = Mod_PointInLeaf(ref listener_origin, cl.worldmodel); if (l == null || ambient_level.value == 0) { for (int i = 0; i < q_shared.NUM_AMBIENTS; i++) { channels[i].sfx = null; } return; } for (int i = 0; i < q_shared.NUM_AMBIENTS; i++) { channel_t chan = channels[i]; chan.sfx = ambient_sfx[i]; float vol = ambient_level.value * l.ambient_sound_level[i]; if (vol < 8) { vol = 0; } // don't adjust volume too fast if (chan.master_vol < vol) { chan.master_vol += (int)(host_framtime * ambient_fade.value); if (chan.master_vol > vol) { chan.master_vol = (int)vol; } } else if (chan.master_vol > vol) { chan.master_vol -= (int)(host_framtime * ambient_fade.value); if (chan.master_vol < vol) { chan.master_vol = (int)vol; } } chan.leftvol = chan.rightvol = chan.master_vol; } }
static void media_MediaEnded2(object sender, System.Windows.RoutedEventArgs e) { MediaElement media = (MediaElement)sender; media.Stop(); channel_t ch = (channel_t)media.Tag; Page.thePage.parentCanvas.Children.Remove(media); ch.sfx = null; }
// configuration helpers //void set_channels(uint8_t channels) { m_channels = channels; } //void set_samples_names(const char *const *names) { m_names = names; } // start callback helpers //template <typename... T> void set_samples_start_callback(T &&...args) { m_samples_start_cb.set(std::forward<T>(args)...); } // getters //bool playing(UINT8 channel) const; //UINT32 base_frequency(UINT8 channel) const; // start/stop helpers //void start(UINT8 channel, UINT32 samplenum, bool loop = false); //void start_raw(UINT8 channel, const INT16 *sampledata, UINT32 samples, UINT32 frequency, bool loop = false); //void pause(UINT8 channel, bool pause = true); //------------------------------------------------- // stop - stop playback on a channel //------------------------------------------------- void stop(uint8_t channel) { assert(channel < m_channels); // force an update before we start channel_t chan = m_channel[channel]; chan.source = null; chan.source_num = -1; }
public static int _PlayVolHash = 543; // hash S_PlayVol public static void S_Init() { Con_Printf("\nSound Initialization\n"); for (int i = 0; i < _KnownSfx.Length; i++) { _KnownSfx[i] = new sfx_t(); } bgmvolume = new cvar_t("bgmvolume", "1", true); volume = new cvar_t("volume", "0.7", true); nosound = new cvar_t("nosound", "0"); precache = new cvar_t("precache", "1"); loadas8bit = new cvar_t("loadas8bit", "0"); bgmbuffer = new cvar_t("bgmbuffer", "4096"); ambient_level = new cvar_t("ambient_level", "0.3"); ambient_fade = new cvar_t("ambient_fade", "100"); snd_noextraupdate = new cvar_t("snd_noextraupdate", "0"); snd_show = new cvar_t("snd_show", "0"); _snd_mixahead = new cvar_t("_snd_mixahead", "0.1", true); if (HasParam("-nosound")) { return; } for (int i = 0; i < channels.Length; i++) { channels[i] = new channel_t(); } Cmd_AddCommand("play", S_Play); Cmd_AddCommand("playvol", S_PlayVol); Cmd_AddCommand("stopsound", S_StopAllSoundsC); Cmd_AddCommand("soundlist", S_SoundList); Cmd_AddCommand("soundinfo", S_SoundInfo_f); snd_initialized = true; S_Startup(); SND_InitScaletable(); num_sfx = 0; Con_Printf("Sound sampling rate: {0}\n", shm.speed); // provides a tick sound until washed clean ambient_sfx[q_shared.AMBIENT_WATER] = S_PrecacheSound("ambience/water1.wav"); ambient_sfx[q_shared.AMBIENT_SKY] = S_PrecacheSound("ambience/wind2.wav"); S_StopAllSounds(true); }
public static void SetVolume(channel_t ch) { if (ch.leftvol == 0 && ch.rightvol == 0) ch.media.Volume = 0; else { double max = ch.rightvol; if (ch.leftvol > max) max = ch.leftvol; ch.media.Volume = ch.master_vol / 255.0; ch.media.Balance = (ch.rightvol - ch.leftvol) / max; } }
public static void SetVolume(channel_t ch) { if (ch.leftvol == 0 && ch.rightvol == 0) ch.media.Volume = 0; else { double max = ch.rightvol; if (ch.leftvol > max) max = ch.leftvol; ch.media.Volume = ch.master_vol / 255.0; ch.media.Balance = (ch.rightvol - ch.leftvol) / max; } var configVolume = cvar_t.Cvar_VariableValue("volume"); ch.media.Volume = configVolume; }
static void SND_Spatialize(channel_t ch) { // anything coming from the view entity will allways be full volume if (ch.entnum == 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 - listener_origin; float dist = Mathlib.Normalize(ref source_vec) * ch.dist_mult; float dot = Vector3.Dot(listener_right, 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; } }
public static void SetVolume(channel_t ch) { if (ch.leftvol == 0 && ch.rightvol == 0) { ch.media.Volume = 0; } else { double max = ch.rightvol; if (ch.leftvol > max) { max = ch.leftvol; } ch.media.Volume = ch.master_vol / 255.0; ch.media.Balance = (ch.rightvol - ch.leftvol) / max; } }
/* * ================= * SND_Spatialize * ================= */ public static void SND_Spatialize(channel_t ch) { double dot; double ldist, rdist, dist; double lscale, rscale, scale; double[] source_vec = new double[3]; sfx_t snd; // 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 snd = ch.sfx; mathlib.VectorSubtract(ch.origin, listener_origin, ref source_vec); dist = mathlib.VectorNormalize(ref source_vec) * ch.dist_mult; dot = mathlib.DotProduct(listener_right, source_vec); rscale = 1.0 + dot; lscale = 1.0 - dot; // add in distance effect scale = (1.0 - dist) * rscale; ch.rightvol = (int)(ch.master_vol * scale); if (ch.rightvol < 0) { ch.rightvol = 0; } scale = (1.0 - dist) * lscale; ch.leftvol = (int)(ch.master_vol * scale); if (ch.leftvol < 0) { ch.leftvol = 0; } }
// SND_PaintChannelFrom16 static void PaintChannelFrom16(channel_t ch, sfxcache_t sc, int count) { int leftvol = ch.leftvol; int rightvol = ch.rightvol; byte[] sfx = sc.data; int offset = ch.pos * 2; // sfx = (signed short *)sc->data + ch->pos; for (int i = 0; i < count; i++) { int data = (short)((ushort)sfx[offset] + ((ushort)sfx[offset + 1] << 8)); // Uze: check is this is right!!! int left = (data * leftvol) >> 8; int right = (data * rightvol) >> 8; _PaintBuffer[i].left += left; _PaintBuffer[i].right += right; offset += 2; } ch.pos += count; }
static void Spatialize(channel_t ch) { Single[] origin = new Single[] { 0, 0, 0 }; if (ch.entnum == cl.playernum + 1) { ch.leftvol = ch.master_vol; ch.rightvol = ch.master_vol; return; } if (ch.fixed_origin) { Math3D.VectorCopy(ch.origin, origin); } else { CL_ents.GetEntitySoundOrigin(ch.entnum, origin); } SpatializeOrigin(origin, ( Single )ch.master_vol, ch.dist_mult, ch); }
static void SND_PaintChannelFrom16(channel_t ch, sfxcache_t sc, int count) { int leftvol = ch.leftvol; int rightvol = ch.rightvol; byte[] sfx = sc.data; int offset = ch.pos * 2; // sfx = (signed short *)sc->data + ch->pos; for (int i = 0; i < count; i++) { int data = (short)((ushort)sfx[offset] + ((ushort)sfx[offset + 1] << 8)); // Uze: check is this is right!!! int left = (data * leftvol) >> 8; int right = (data * rightvol) >> 8; paintbuffer[i].left += left; paintbuffer[i].right += right; offset += 2; } ch.pos += count; }
// SND_PaintChannelFrom8 static void PaintChannelFrom8(channel_t ch, sfxcache_t sc, int count) { if (ch.leftvol > 255) ch.leftvol = 255; if (ch.rightvol > 255) ch.rightvol = 255; int lscale = ch.leftvol >> 3; int rscale = ch.rightvol >> 3; byte[] sfx = sc.data; int offset = ch.pos; for (int i = 0; i < count; i++) { int data = sfx[offset + i]; _PaintBuffer[i].left += _ScaleTable[lscale, data]; _PaintBuffer[i].right += _ScaleTable[rscale, data]; } ch.pos += count; }
public static void S_StaticSound(sfx_t sfx, ref Vector3 origin, float vol, float attenuation) { if (sfx == null) { return; } if (total_channels == q_shared.MAX_CHANNELS) { Con_Printf("total_channels == MAX_CHANNELS\n"); return; } channel_t ss = channels[total_channels]; total_channels++; sfxcache_t sc = S_LoadSound(sfx); if (sc == null) { return; } if (sc.loopstart == -1) { Con_Printf("Sound {0} not looped\n", sfx.name); return; } ss.sfx = sfx; ss.origin = origin; ss.master_vol = (int)vol; ss.dist_mult = (attenuation / 64) / sound_nominal_clip_dist; ss.end = paintedtime + sc.length; SND_Spatialize(ss); }
// device-level overrides //------------------------------------------------- // device_start - handle device startup //------------------------------------------------- protected override void device_start() { m_disound = GetClassInterface <device_sound_interface_namco>(); // read audio samples load_samples(); // allocate channels m_channel.resize(m_channels); for (int channel = 0; channel < m_channels; channel++) { // initialize channel channel_t chan = m_channel[channel]; chan.stream = m_disound.stream_alloc(0, 1, machine().sample_rate()); chan.source = null; chan.source_num = -1; chan.step = 0; chan.loop = false; chan.paused = false; // register with the save state system save_item(chan.source_length, "chan.source_length", channel); save_item(chan.source_num, "chan.source_num", channel); save_item(chan.pos, "chan.pos", channel); save_item(chan.frac, "chan.frac", channel); save_item(chan.step, "chan.step", channel); save_item(chan.loop, "chan.loop", channel); save_item(chan.paused, "chan.paused", channel); } // initialize any custom handlers //m_samples_start_cb.bind_relative_to(owner()); if (m_samples_start_cb != null) { m_samples_start_cb(); } }
//------------------------------------------------- // device_post_load - handle updating after a // restore //------------------------------------------------- protected override void device_post_load() { // loop over channels for (int channel = 0; channel < m_channels; channel++) { // attach any samples that were loaded and playing channel_t chan = m_channel[channel]; if (chan.source_num >= 0 && chan.source_num < m_sample.Count) { sample_t sample = m_sample[chan.source_num]; chan.source = new Pointer <int16_t>(sample.data); //chan.source = &sample.data[0]; chan.source_len = (u32)sample.data.size(); if (sample.data.Count == 0) { chan.source_num = -1; } } // validate the position against the length in case the sample is smaller double endpos = chan.source_len; if (chan.source != null && chan.pos >= endpos) { if (chan.loop) { double posfloor = std.floor(chan.pos); chan.pos -= posfloor; chan.pos += (double)((int32_t)posfloor % chan.source_len); } else { chan.source = null; chan.source_num = -1; } } } }
// device-level overrides //------------------------------------------------- // device_start - handle device startup //------------------------------------------------- protected override void device_start() { m_disound = GetClassInterface <device_sound_interface_samples>(); // read audio samples load_samples(); // allocate channels m_channel.resize(m_channels); for (int channel = 0; channel < m_channels; channel++) { // initialize channel channel_t chan = m_channel[channel]; chan.stream = m_disound.stream_alloc(0, 1, SAMPLE_RATE_OUTPUT_ADAPTIVE); chan.source = null; chan.source_num = -1; chan.pos = 0; chan.loop = false; chan.paused = false; // register with the save state system save_item(NAME(new { chan.source_num }), channel); save_item(NAME(new { chan.source_len }), channel); save_item(NAME(new { chan.pos }), channel); save_item(NAME(new { chan.loop }), channel); save_item(NAME(new { chan.paused }), channel); } // initialize any custom handlers //m_samples_start_cb.resolve(); if (m_samples_start_cb != null) { m_samples_start_cb(); } }
public static void S_Update(ref Vector3 origin, ref Vector3 forward, ref Vector3 right, ref Vector3 up) { if (!snd_initialized || (snd_blocked > 0)) { return; } listener_origin = origin; listener_forward = forward; listener_right = right; listener_up = up; // update general area ambient sound sources S_UpdateAmbientSounds(); channel_t combine = null; // update spatialization for static and dynamic sounds //channel_t ch = channels + NUM_AMBIENTS; for (int i = q_shared.NUM_AMBIENTS; i < total_channels; i++) { channel_t ch = channels[i];// channels + NUM_AMBIENTS; if (ch.sfx == null) { continue; } SND_Spatialize(ch); // respatialize channel if (ch.leftvol == 0 && ch.rightvol == 0) { continue; } // try to combine static sounds with a previous channel of the same // sound effect so we don't mix five torches every frame if (i >= q_shared.MAX_DYNAMIC_CHANNELS + q_shared.NUM_AMBIENTS) { // see if it can just use the last one if (combine != null && combine.sfx == ch.sfx) { combine.leftvol += ch.leftvol; combine.rightvol += ch.rightvol; ch.leftvol = ch.rightvol = 0; continue; } // search for one combine = channels[q_shared.MAX_DYNAMIC_CHANNELS + q_shared.NUM_AMBIENTS];// channels + MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; int j; for (j = q_shared.MAX_DYNAMIC_CHANNELS + q_shared.NUM_AMBIENTS; j < i; j++) { combine = channels[j]; if (combine.sfx == ch.sfx) { break; } } if (j == total_channels) { combine = null; } else { if (combine != ch) { combine.leftvol += ch.leftvol; combine.rightvol += ch.rightvol; ch.leftvol = ch.rightvol = 0; } continue; } } } // // debugging output // if (snd_show.value != 0) { int total = 0; for (int i = 0; i < total_channels; i++) { channel_t ch = channels[i]; if (ch.sfx != null && (ch.leftvol > 0 || ch.rightvol > 0)) { total++; } } Con_Printf("----({0})----\n", total); } // mix some sound S_Update_(); }
static void AddLoopSounds( ) { Int32 i, j; Int32[] sounds = new Int32[Defines.MAX_EDICTS]; Int32 left, right, left_total, right_total; channel_t ch; sfx_t sfx; sfxcache_t sc; Int32 num; entity_state_t ent; if (cl_paused.value != 0F) { 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] == 0) { continue; } sfx = cl.sound_precache[sounds[i]]; if (sfx == null) { continue; } sc = sfx.cache; if (sc == null) { continue; } num = (cl.frame.parse_entities + i) & (MAX_PARSE_ENTITIES - 1); ent = cl_parse_entities[num]; channel_t tch = new channel_t(); SpatializeOrigin(ent.origin, 255F, SOUND_LOOPATTENUATE, tch); left_total = tch.leftvol; right_total = tch.rightvol; for (j = i + 1; j < cl.frame.num_entities; j++) { if (sounds[j] != sounds[i]) { continue; } sounds[j] = 0; num = (cl.frame.parse_entities + j) & (MAX_PARSE_ENTITIES - 1); ent = cl_parse_entities[num]; SpatializeOrigin(ent.origin, 255F, SOUND_LOOPATTENUATE, tch); left_total += tch.leftvol; right_total += tch.rightvol; } if (left_total == 0 && right_total == 0) { continue; } ch = PickChannel(0, 0); if (ch == null) { 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; ch.sfx = sfx; ch.pos = paintedtime % sc.length; ch.end = paintedtime + sc.length - ch.pos; } }
/* ================= SND_Spatialize ================= */ public static void SND_Spatialize(channel_t ch) { double dot; double ldist, rdist, dist; double lscale, rscale, scale; double[] source_vec = new double[3]; sfx_t snd; // 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 snd = ch.sfx; mathlib.VectorSubtract(ch.origin, listener_origin, ref source_vec); dist = mathlib.VectorNormalize(ref source_vec) * ch.dist_mult; dot = mathlib.DotProduct(listener_right, source_vec); rscale = 1.0 + dot; lscale = 1.0 - dot; // add in distance effect scale = (1.0 - dist) * rscale; ch.rightvol = (int) (ch.master_vol * scale); if (ch.rightvol < 0) ch.rightvol = 0; scale = (1.0 - dist) * lscale; ch.leftvol = (int) (ch.master_vol * scale); if (ch.leftvol < 0) ch.leftvol = 0; }
/* ================ S_Init ================ */ public static void S_Init() { int kk; for (kk = 0; kk < MAX_CHANNELS; kk++) channels[kk] = new channel_t(); console.Con_Printf("\nSound Initialization\n"); if (common.COM_CheckParm("-nosound") != 0) return; cmd.Cmd_AddCommand("play", S_Play); cmd.Cmd_AddCommand("playvol", S_PlayVol); cmd.Cmd_AddCommand("stopsound", S_StopAllSoundsC); cmd.Cmd_AddCommand("soundlist", S_SoundList); cmd.Cmd_AddCommand("soundinfo", S_SoundInfo_f); cvar_t.Cvar_RegisterVariable(nosound); cvar_t.Cvar_RegisterVariable(volume); cvar_t.Cvar_RegisterVariable(precache); cvar_t.Cvar_RegisterVariable(loadas8bit); cvar_t.Cvar_RegisterVariable(bgmvolume); cvar_t.Cvar_RegisterVariable(bgmbuffer); cvar_t.Cvar_RegisterVariable(ambient_level); cvar_t.Cvar_RegisterVariable(ambient_fade); cvar_t.Cvar_RegisterVariable(snd_noextraupdate); cvar_t.Cvar_RegisterVariable(snd_show); cvar_t.Cvar_RegisterVariable(_snd_mixahead); /*if (host_parms.memsize < 0x800000) { Cvar_Set ("loadas8bit", "1"); Con_Printf ("loading all sounds as 8bit\n"); }*/ snd_initialized = true; S_Startup (); known_sfx = new sfx_t[MAX_SFX]; for(kk = 0; kk < MAX_SFX; kk++) known_sfx[kk] = new sfx_t(); num_sfx = 0; // provides a tick sound until washed clean // if (shm.buffer) // shm.buffer[4] = shm.buffer[5] = 0x7f; // force a pop for debugging for(kk = 0; kk < bspfile.NUM_AMBIENTS; kk++) ambient_sfx[kk] = new sfx_t(); ambient_sfx[bspfile.AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav"); ambient_sfx[bspfile.AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav"); S_StopAllSounds (true); }
public static void Update(Single[] origin, Single[] forward, Single[] right, Single[] up) { if (!sound_started) { return; } if (cls.disable_screen != 0F) { ClearBuffer(); return; } if (s_volume.modified) { InitScaletable(); } Math3D.VectorCopy(origin, listener_origin); Math3D.VectorCopy(forward, listener_forward); Math3D.VectorCopy(right, listener_right); Math3D.VectorCopy(up, listener_up); channel_t combine = null; channel_t ch; for (var i = 0; i < MAX_CHANNELS; i++) { ch = channels[i]; if (ch.sfx == null) { continue; } if (ch.autosound) { ch.Clear(); continue; } Spatialize(ch); if (ch.leftvol == 0 && ch.rightvol == 0) { ch.Clear(); continue; } } AddLoopSounds(); if (s_show.value != 0F) { var total = 0; for (var i = 0; i < MAX_CHANNELS; i++) { ch = channels[i]; if (ch.sfx != null && (ch.leftvol != 0 || ch.rightvol != 0)) { Com.Printf(ch.leftvol + " " + ch.rightvol + " " + ch.sfx.name + "\\n"); total++; } } } Update_(); }
static void SpatializeOrigin(Single[] origin, Single master_vol, Single dist_mult, channel_t ch) { Single dot; Single dist; Single lscale, rscale, scale; Single[] source_vec = new Single[] { 0, 0, 0 }; if (cls.state != ca_active) { ch.leftvol = ch.rightvol = 255; return; } Math3D.VectorSubtract(origin, listener_origin, source_vec); dist = Math3D.VectorNormalize(source_vec); dist -= SOUND_FULLVOLUME; if (dist < 0) { dist = 0; } dist *= dist_mult; dot = Math3D.DotProduct(listener_right, source_vec); if (dma.channels == 1 || dist_mult == 0F) { rscale = 1F; lscale = 1F; } else { rscale = 0.5F * (1F + dot); lscale = 0.5F * (1F - dot); } scale = (1F - dist) * rscale; ch.rightvol = ( Int32 )(master_vol * scale); if (ch.rightvol < 0) { ch.rightvol = 0; } scale = (1F - dist) * lscale; ch.leftvol = ( Int32 )(master_vol * scale); if (ch.leftvol < 0) { ch.leftvol = 0; } }
public static void S_StartSound(int entnum, int entchannel, sfx_t sfx, ref Vector3 origin, float fvol, float attenuation) { if (!sound_started || sfx == null) { return; } if (nosound.value != 0) { return; } int vol = (int)(fvol * 255); // pick a channel to play on channel_t target_chan = SND_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 / sound_nominal_clip_dist; target_chan.master_vol = vol; target_chan.entnum = entnum; target_chan.entchannel = entchannel; SND_Spatialize(target_chan); if (target_chan.leftvol == 0 && target_chan.rightvol == 0) { return; // not audible at all } // new channel sfxcache_t sc = S_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 = q_shared.NUM_AMBIENTS; i < q_shared.NUM_AMBIENTS + q_shared.MAX_DYNAMIC_CHANNELS; i++) { channel_t check = channels[i]; if (check == target_chan) { continue; } if (check.sfx == sfx && check.pos == 0) { int skip = 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; } } }
/* * ================ * S_Init * ================ */ public static void S_Init() { int kk; for (kk = 0; kk < MAX_CHANNELS; kk++) { channels[kk] = new channel_t(); } console.Con_Printf("\nSound Initialization\n"); if (common.COM_CheckParm("-nosound") != 0) { return; } cmd.Cmd_AddCommand("play", S_Play); cmd.Cmd_AddCommand("playvol", S_PlayVol); cmd.Cmd_AddCommand("stopsound", S_StopAllSoundsC); cmd.Cmd_AddCommand("soundlist", S_SoundList); cmd.Cmd_AddCommand("soundinfo", S_SoundInfo_f); cvar_t.Cvar_RegisterVariable(nosound); cvar_t.Cvar_RegisterVariable(volume); cvar_t.Cvar_RegisterVariable(precache); cvar_t.Cvar_RegisterVariable(loadas8bit); cvar_t.Cvar_RegisterVariable(bgmvolume); cvar_t.Cvar_RegisterVariable(bgmbuffer); cvar_t.Cvar_RegisterVariable(ambient_level); cvar_t.Cvar_RegisterVariable(ambient_fade); cvar_t.Cvar_RegisterVariable(snd_noextraupdate); cvar_t.Cvar_RegisterVariable(snd_show); cvar_t.Cvar_RegisterVariable(_snd_mixahead); /*if (host_parms.memsize < 0x800000) * { * Cvar_Set ("loadas8bit", "1"); * Con_Printf ("loading all sounds as 8bit\n"); * }*/ snd_initialized = true; S_Startup(); known_sfx = new sfx_t[MAX_SFX]; for (kk = 0; kk < MAX_SFX; kk++) { known_sfx[kk] = new sfx_t(); } num_sfx = 0; // provides a tick sound until washed clean // if (shm.buffer) // shm.buffer[4] = shm.buffer[5] = 0x7f; // force a pop for debugging for (kk = 0; kk < bspfile.NUM_AMBIENTS; kk++) { ambient_sfx[kk] = new sfx_t(); } ambient_sfx[bspfile.AMBIENT_WATER] = S_PrecacheSound("ambience/water1.wav"); ambient_sfx[bspfile.AMBIENT_SKY] = S_PrecacheSound("ambience/wind2.wav"); S_StopAllSounds(true); }
static void S_PaintChannels(int endtime) { while (paintedtime < endtime) { // if paintbuffer is smaller than DMA buffer int end = endtime; if (endtime - paintedtime > q_shared.PAINTBUFFER_SIZE) { end = paintedtime + q_shared.PAINTBUFFER_SIZE; } // clear the paint buffer Array.Clear(paintbuffer, 0, end - paintedtime); // paint in the channels. for (int i = 0; i < total_channels; i++) { channel_t ch = channels[i]; if (ch.sfx == null) { continue; } if (ch.leftvol == 0 && ch.rightvol == 0) { continue; } sfxcache_t sc = S_LoadSound(ch.sfx); if (sc == null) { continue; } int count, ltime = paintedtime; while (ltime < end) { // paint up to end if (ch.end < end) { count = ch.end - ltime; } else { count = end - ltime; } if (count > 0) { if (sc.width == 1) { SND_PaintChannelFrom8(ch, sc, count); } else { SND_PaintChannelFrom16(ch, sc, count); } ltime += count; } // if at end of loop, restart if (ltime >= ch.end) { if (sc.loopstart >= 0) { ch.pos = sc.loopstart; ch.end = ltime + sc.length - ch.pos; } else { // channel just stopped ch.sfx = null; break; } } } } // transfer out according to DMA format S_TransferPaintBuffer(end); paintedtime = end; } }