public ActiveSound PlaySimpleInternal(SoundEffect sfx, bool loop) { Func <ActiveSound> playSound = () => { ActiveSound actsfx = new ActiveSound(sfx) { Engine = this, Position = Location.NaN, Pitch = 1.0f, Gain = 1.0f, Loop = loop }; actsfx.Create(); actsfx.Play(); return(actsfx); }; lock (sfx) { if (sfx.Internal == -1) { return(null); // TODO: Enforce load-NOW? } } return(playSound()); }
/// <summary> /// NOTE: *NOT* guaranteed to play a sound effect immediately, regardless of input! Some sound effects will be delayed! /// </summary> public void Play(SoundEffect sfx, bool loop, Location pos, float pitch = 1, float volume = 1, float seek_seconds = 0, Action <ActiveSound> callback = null) { if (sfx.Internal == -2) { Play(GetSound(sfx.Name), loop, pos, pitch, volume, seek_seconds, callback); return; } if (pitch <= 0 || pitch > 2) { throw new ArgumentException("Must be between 0 and 2", "pitch"); } if (volume == 0) { return; } if (volume <= 0 || volume > 1) { throw new ArgumentException("Must be between 0 and 1", "volume"); } Action playSound = () => { ActiveSound actsfx = new ActiveSound(sfx); actsfx.Engine = this; actsfx.Position = pos; actsfx.Pitch = pitch * CVars.a_globalpitch.ValueF; actsfx.Gain = volume; actsfx.Loop = loop; actsfx.Create(); actsfx.Play(); if (seek_seconds != 0) { actsfx.Seek(seek_seconds); } PlayingNow.Add(actsfx); if (callback != null) { callback(actsfx); } }; lock (sfx) { if (sfx.Internal == -1) { sfx.Loaded += (o, e) => { playSound(); }; return; } } playSound(); }
public bool CanClean() { bool cleaned = false; for (int i = 0; i < PlayingNow.Count; i++) { ActiveSound sound = PlayingNow[i]; if (sound.Gain < 0.05 || (sound.Position.DistanceSquared(CPosition) > 30 * 30)) { sound.Destroy(); PlayingNow.RemoveAt(i); i--; cleaned = true; } } return(cleaned); }
/// <summary> /// Plays the backgrond music. Will restart music if already playing. /// </summary> void BackgroundMusic() { if (CurrentMusic != null) { CurrentMusic.Destroy(); } SoundEffect mus = Sounds.GetSound(CVars.a_music.Value); Sounds.Play(mus, true, Location.NaN, CVars.a_musicpitch.ValueF, CVars.a_musicvolume.ValueF, 0, (asfx) => { CurrentMusic = asfx; if (CurrentMusic != null) { CurrentMusic.IsBackground = true; } }); }
public void onMusicVolumeChanged(object obj, EventArgs e) { if (CurrentMusic != null) { float vol = CVars.a_musicvolume.ValueF; if (vol <= 0 || vol > 1) { CurrentMusic.Destroy(); CurrentMusic = null; } else { CurrentMusic.Gain = vol; CurrentMusic.UpdateGain(); } } else { BackgroundMusic(); } }
/// <summary> /// NOTE: *NOT* guaranteed to play a sound effect immediately, regardless of input! Some sound effects will be delayed! If too many audible sounds are already playing, this will refuse to play. /// </summary> public void Play(SoundEffect sfx, bool loop, Location pos, float pitch = 1, float volume = 1, float seek_seconds = 0, Action <ActiveSound> callback = null) { if (sfx == null) { //SysConsole.Output(OutputType.DEBUG, "Audio / null"); return; } if (PlayingNow.Count > 200 && AudioInternal == null) { if (!CanClean()) { //SysConsole.Output(OutputType.DEBUG, "Audio / count"); return; } } if (sfx.Internal == -2) { Play(GetSound(sfx.Name), loop, pos, pitch, volume, seek_seconds, callback); return; } if (pitch <= 0 || pitch > 2) { throw new ArgumentException("Must be between 0 and 2", "pitch"); } if (volume == 0) { SysConsole.Output(OutputType.DEBUG, "Audio / volume"); return; } if (volume <= 0 || volume > 1) { throw new ArgumentException("Must be between 0 and 1", "volume"); } Action playSound = () => { if (sfx.Clip == null && sfx.Internal < 0) { //SysConsole.Output(OutputType.DEBUG, "Audio / clip"); return; } ActiveSound actsfx = new ActiveSound(sfx) { Engine = this, Position = pos, Pitch = pitch * CVars.a_globalpitch.ValueF, Gain = volume, Loop = loop }; actsfx.Create(); if (actsfx.AudioInternal == null && actsfx.Src < 0) { //SysConsole.Output(OutputType.DEBUG, "Audio / src"); return; } CheckError("Create:" + sfx.Name); if (TimeDeaf > 0.0) { actsfx.IsDeafened = true; if (AudioInternal == null) { AL.Source(actsfx.Src, ALSourcef.Gain, 0.0001f); } else { actsfx.AudioInternal.Gain = 0.0001f; } } if (seek_seconds != 0) { actsfx.Seek(seek_seconds); } CheckError("Preconfig:" + sfx.Name); actsfx.Play(); CheckError("Play:" + sfx.Name); //SysConsole.Output(OutputType.DEBUG, "Audio / sucess"); PlayingNow.Add(actsfx); callback?.Invoke(actsfx); }; lock (sfx) { if (sfx.Clip == null && sfx.Internal == -1) { //SysConsole.Output(OutputType.DEBUG, "Audio / delay"); sfx.Loaded += (o, e) => { playSound(); }; return; } } playSound(); }
public void Update(Location position, Location forward, Location up, Location velocity, bool selected) { CPosition = position; if (AudioInternal == null) { ALError err = AL.GetError(); if (err != ALError.NoError) { SysConsole.Output(OutputType.WARNING, "Found audio error " + err + "!"); //init(TheClient, CVars); return; } } bool sel = CVars.a_quietondeselect.ValueB ? selected : true; Selected = sel; if (DeafenTime > 0.0) { TimeDeaf += TheClient.Delta; DeafenTime -= TheClient.Delta; if (DeafNoise == null) { DeafNoise = PlaySimpleInternal(DeafLoop, true); if (DeafNoise == null) { DeafenTime = 0; TimeDeaf = 0; } } if (DeafenTime < 0) { TimeDeaf = 0; DeafenTime = 0; DeafNoise.Stop(); DeafNoise.Destroy(); DeafNoise = null; } } if (TimeDeaf > 0.001 && DeafenTime > 0.001) { float weaken = (float)Math.Min(DeafenTime, TimeDeaf); if (weaken < 1.0) { DeafNoise.Gain = (float)weaken * 0.5f; DeafNoise.UpdateGain(); } else { DeafNoise.Gain = 0.5f; DeafNoise.UpdateGain(); } } DeafLoop.LastUse = TheClient.GlobalTickTimeLocal; for (int i = 0; i < PlayingNow.Count; i++) { if (!PlayingNow[i].Exists || PlayingNow[i].Src < 0 || (AudioInternal == null ? AL.GetSourceState(PlayingNow[i].Src) == ALSourceState.Stopped : PlayingNow[i].AudioInternal.State == AudioState.DONE)) { PlayingNow[i].Destroy(); if (AudioInternal == null) { CheckError("Destroy:" + PlayingNow[i].Effect.Name); } PlayingNow.RemoveAt(i); i--; continue; } PlayingNow[i].Effect.LastUse = TheClient.GlobalTickTimeLocal; if ((TimeDeaf > 0.0) && sel && !PlayingNow[i].IsBackground) { PlayingNow[i].IsDeafened = true; float lesser = (float)Math.Min(DeafenTime, TimeDeaf); if (lesser < 0.999) { if (AudioInternal == null) { AL.Source(PlayingNow[i].Src, ALSourcef.Gain, PlayingNow[i].Gain * (1.0f - lesser)); } else { PlayingNow[i].AudioInternal.Gain = PlayingNow[i].Gain * (1.0f - lesser); } } else { if (AudioInternal == null) { AL.Source(PlayingNow[i].Src, ALSourcef.Gain, 0.0001f); } else { PlayingNow[i].AudioInternal.Gain = 0.0001f; } } } else if ((TimeDeaf <= 0.0) && sel && !PlayingNow[i].IsBackground) { if (AudioInternal == null) { AL.Source(PlayingNow[i].Src, ALSourcef.Gain, PlayingNow[i].Gain); } else { } PlayingNow[i].IsDeafened = false; } if ((TimeDeaf <= 0.0) && !sel && PlayingNow[i].IsBackground && !PlayingNow[i].Backgrounded) { if (AudioInternal == null) { AL.Source(PlayingNow[i].Src, ALSourcef.Gain, 0.0001f); } else { PlayingNow[i].AudioInternal.Gain = 0.0001f; } PlayingNow[i].Backgrounded = true; } else if ((TimeDeaf <= 0.0) && sel && PlayingNow[i].Backgrounded) { if (AudioInternal == null) { AL.Source(PlayingNow[i].Src, ALSourcef.Gain, PlayingNow[i].Gain); } else { PlayingNow[i].AudioInternal.Gain = PlayingNow[i].Gain; } PlayingNow[i].Backgrounded = false; PlayingNow[i].IsDeafened = false; } } CheckError("Setup"); if (Microphone != null) { Microphone.Tick(); } CheckError("Microphone"); float globvol = CVars.a_globalvolume.ValueF; globvol = globvol <= 0 ? 0.001f : (globvol > 1 ? 1 : globvol); if (AudioInternal == null) { Vector3 pos = ClientUtilities.Convert(position); Vector3 forw = ClientUtilities.Convert(forward); Vector3 upvec = ClientUtilities.Convert(up); Vector3 vel = ClientUtilities.Convert(velocity); AL.Listener(ALListener3f.Position, ref pos); AL.Listener(ALListenerfv.Orientation, ref forw, ref upvec); AL.Listener(ALListener3f.Velocity, ref vel); CheckError("Positioning"); AL.Listener(ALListenerf.Gain, globvol); CheckError("Gain"); } else { // TODO: vel AudioInternal.Left = CVars.a_left.ValueB; AudioInternal.Right = CVars.a_right.ValueB; AudioInternal.Position = position; AudioInternal.ForwardDirection = forward; AudioInternal.UpDirection = up; AudioInternal.Volume = globvol; } TimeTowardsNextClean += TheClient.Delta; if (TimeTowardsNextClean > 10.0) { CleanTick(); TimeTowardsNextClean = 0.0; } }
/// <summary> /// NOTE: *NOT* guaranteed to play a sound effect immediately, regardless of input! Some sound effects will be delayed! /// </summary> public void Play(SoundEffect sfx, bool loop, Location pos, float pitch = 1, float volume = 1, float seek_seconds = 0, Action<ActiveSound> callback = null) { if (sfx.Internal == -2) { Play(GetSound(sfx.Name), loop, pos, pitch, volume, seek_seconds, callback); return; } if (pitch <= 0 || pitch > 2) { throw new ArgumentException("Must be between 0 and 2", "pitch"); } if (volume == 0) { return; } if (volume <= 0 || volume > 1) { throw new ArgumentException("Must be between 0 and 1", "volume"); } Action playSound = () => { ActiveSound actsfx = new ActiveSound(sfx); actsfx.Engine = this; actsfx.Position = pos; actsfx.Pitch = pitch * CVars.a_globalpitch.ValueF; actsfx.Gain = volume; actsfx.Loop = loop; actsfx.Create(); actsfx.Play(); if (seek_seconds != 0) { actsfx.Seek(seek_seconds); } PlayingNow.Add(actsfx); if (callback != null) { callback(actsfx); } }; lock (sfx) { if (sfx.Internal == -1) { sfx.Loaded += (o, e) => { playSound(); }; return; } } playSound(); }