package SoundHelper import Stack import Simulate3dSound import TimedLoop constant boolean DEFAULT_SOUND_STOPS_ON_LEAVE_RANGE = true constant int DEFAULT_SOUND_FADE_IN_RATE = 10 constant int DEFAULT_SOUND_FADE_OUT_RATE = 10 constant string DEFAULT_SOUND_EAX_SETTINGS = "CombatSoundsEAX" constant int DEFAULT_SOUND_VOLUME = 127 constant real DEFAULT_SOUND_PITCH = 1 constant int SOUND_CHANNEL = 5 constant real SOUND_MIN_DIST = 600 constant real SOUND_MAX_DIST = 8000 constant real SOUND_DIST_CUT = 1500 class SData sound snd Sound soundData unit onUnit player p Sim3DSound s3s = null public class Sound Stack soundStack = new Stack() string file int duration boolean looping boolean is3D boolean stopOnLeaveRange int fadeIn int fadeOut string eaxSetting vec2 emuPos = vec2(0,0) unit emuUnit = null construct(string file, int duration, boolean looping, boolean is3D, boolean stopOnLeaveRange, int fadeIn, int fadeOut, string eaxSetting ) this.file = file this.duration = duration this.looping = looping this.is3D = is3D this.stopOnLeaveRange = stopOnLeaveRange this.fadeIn = fadeIn this.fadeOut = fadeOut this.eaxSetting = eaxSetting construct(string file, int duration, boolean looping ) this.file = file this.duration = duration this.looping = looping this.is3D = false this.stopOnLeaveRange = false this.fadeIn = DEFAULT_SOUND_FADE_IN_RATE this.fadeOut = DEFAULT_SOUND_FADE_OUT_RATE this.eaxSetting = DEFAULT_SOUND_EAX_SETTINGS construct(string file, int duration, boolean looping, boolean is3D ) this.file = file this.duration = duration this.looping = looping this.is3D = is3D this.stopOnLeaveRange = true this.fadeIn = DEFAULT_SOUND_FADE_IN_RATE this.fadeOut = DEFAULT_SOUND_FADE_OUT_RATE this.eaxSetting = DEFAULT_SOUND_EAX_SETTINGS private function getSound() returns SData // If there is a handle on the stack if soundStack.getSize() > 0 return soundStack.pop() else // No free handle, create a new one /* * Create new sound and point it to * Sound class instance. */ var sdata = new SData() sdata.snd = CreateSound(this.file, this.looping, this.is3D, this.stopOnLeaveRange, this.fadeIn, this.fadeOut, this.eaxSetting) sdata.soundData = this /* * Configure sound */ SetSoundDuration(sdata.snd, this.duration) SetSoundChannel(sdata.snd, SOUND_CHANNEL) SetSoundVolume(sdata.snd, DEFAULT_SOUND_VOLUME) SetSoundPitch(sdata.snd, DEFAULT_SOUND_PITCH) /* * Proper 3D sound configuration */ if this.is3D SetSoundDistances(sdata.snd, SOUND_MIN_DIST, SOUND_MAX_DIST) SetSoundDistanceCutoff(sdata.snd, SOUND_DIST_CUT) SetSoundConeAngles(sdata.snd, 0, 0, DEFAULT_SOUND_VOLUME) SetSoundConeOrientation(sdata.snd, 0, 0, 0) return sdata function play() returns SData let snd = getSound() getTimer() ..setData(snd castTo int) ..start(0., function Sound.playSound) return snd function playSimulatePoint(vec2 point) emuPos = point getTimer() ..setData(getSound() castTo int) ..start(0., function Sound.playSound) function playSimulateUnit(unit u) emuUnit = u getTimer() ..setData(getSound() castTo int) ..start(0., function Sound.playSound) function playOnUnit(unit u) var s = getSound() s.onUnit = u getTimer() ..setData(s castTo int) ..start(0., function Sound.playSound) function playOnPoint(real x, real y, real z) var s = getSound() SetSoundPosition(s.snd, x, y, z) getTimer() ..setData(s castTo int) ..start(0., function Sound.playSound) function playOnPoint(vec3 pos) var s = getSound() SetSoundPosition(s.snd, pos.x, pos.y, pos.z) getTimer() ..setData(s castTo int) ..start(0., function Sound.playSound) function playForPlayer(player p) var s = getSound() s.p = p getTimer() ..setData(s castTo int) ..start(0., function Sound.playSound) private static function playSound() var tm = GetExpiredTimer() var sdata = tm.getData() castTo SData if sdata.onUnit != null AttachSoundToUnit(sdata.snd, sdata.onUnit) if sdata.soundData.emuPos.x != 0 let data = sdata.soundData sdata.s3s = bindSoundToPoint(sdata.snd, data.emuPos.x, data.emuPos.y, SOUND_MIN_DIST, SOUND_MAX_DIST, SOUND_DIST_CUT) print("created 3dsound") else if sdata.soundData.emuUnit != null let data = sdata.soundData sdata.s3s = bindSoundToUnit(sdata.snd, data.emuUnit, SOUND_MIN_DIST, SOUND_MAX_DIST, SOUND_DIST_CUT) else SetSoundVolume(sdata.snd, 100) if sdata.p != null if GetLocalPlayer() == sdata.p StartSound(sdata.snd) else StartSound(sdata.snd) tm.release() getTimer() ..setData(sdata castTo int) ..start(sdata.soundData.duration * 0.001, function Sound.recycle) private static function recycle() var tm = GetExpiredTimer() var sdata = tm.getData() castTo SData sdata.p = null if sdata.s3s != null destroy sdata.s3s if sdata.soundData.soundStack.getSize() < 4 sdata.soundData.soundStack.push(sdata) else StopSound(sdata.snd, true, true) destroy sdata tm.release() public class DynamicSound use TimedLoop real targetPitch = 1.0 real currentPitch = 1.0 real smoothness = 0.015 real minimumLength = 0.5 SData soundData Sound soundHandle construct(Sound soundHandle) this.soundHandle = soundHandle this.minimumLength = soundHandle.duration * 0.001 function setTargetPitch(real pitch) targetPitch = pitch function play() soundData = soundHandle.play() startTimedLoop() function setAbsolutePitch(real pitch) if not soundData.snd.isPlaying() if pitch == 1 soundData.snd.setPitch(1.0001) else soundData.snd.setPitch(pitch) else soundData.snd.setPitch(1/currentPitch) soundData.snd.setPitch(pitch) currentPitch = pitch override function onTimedLoop() if soundData != null setAbsolutePitch(currentPitch.lerp(targetPitch, smoothness)) minimumLength -= ANIMATION_PERIOD if not soundData.snd.isPlaying() and minimumLength <= 0 stopTimedLoopAndDestroy()