Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[System] SoundTools

Discussion in 'JASS Resources' started by Magtheridon96, Nov 19, 2011.

  1. Cokemonkey11

    Cokemonkey11

    Wurst Reviewer

    Joined:
    May 9, 2006
    Messages:
    3,271
    Resources:
    18
    Tools:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    2
    JASS:
    7
    Resources:
    18
    Yes, suggestion: Use T&S Section
     
  2. pred1980

    pred1980

    Joined:
    Mar 19, 2010
    Messages:
    842
    Resources:
    1
    Maps:
    1
    Resources:
    1
    but the "SoundTools Snippet Thread" is here and i think that's the best place because here's the creater of the code. Or not?
     
  3. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,003
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    The creator of the code is no longer capable of maintaining the resource.

    He moved on.
     
  4. pred1980

    pred1980

    Joined:
    Mar 19, 2010
    Messages:
    842
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Why not? You created the code... why can't you try to fix it? I uploaded a simple testversion where you can try to test and fix it? No time to do it?
     
  5. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,003
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    I think the entire API is flawed.

    You can't run a sound on a unit for a player for example.

    SoundTools 4.0.0.0 would need to be written with a new API.
     
  6. pred1980

    pred1980

    Joined:
    Mar 19, 2010
    Messages:
    842
    Resources:
    1
    Maps:
    1
    Resources:
    1
    LOL?

    ok. i'll change to cokemonkey's script.

    Reg.
     
  7. BPower

    BPower

    Joined:
    Mar 18, 2012
    Messages:
    1,709
    Resources:
    21
    Spells:
    15
    Tutorials:
    1
    JASS:
    5
    Resources:
    21
    If you run a sound file for only one or a group of players, the sound volume will be set to 0
    and never reset for this sound handle.
    Either when getting or pushing the handle from/into the stack you have to set the volume
    back to default.
     
  8. BPower

    BPower

    Joined:
    Mar 18, 2012
    Messages:
    1,709
    Resources:
    21
    Spells:
    15
    Tutorials:
    1
    JASS:
    5
    Resources:
    21
    Reset the volume to the default volume, when popping a sound file from the stack.
    Otherwise the handle may be muted for x players.

    method release could required extra safety, so you don't push a sound handle to the stack,
    which is already part of the stack.

    I really like SoundTools, we should brainstorm a bit to improve it.
     
  9. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,003
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    I'm not an active member of this community anymore.

    Feel free to edit my posts and resources however you want.
     
  10. Cokemonkey11

    Cokemonkey11

    Wurst Reviewer

    Joined:
    May 9, 2006
    Messages:
    3,271
    Resources:
    18
    Tools:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    2
    JASS:
    7
    Resources:
    18
    bae don't lie you can't leave. we always come back eventually :p
     
  11. Ruke

    Ruke

    Joined:
    Sep 19, 2011
    Messages:
    517
    Resources:
    7
    Tools:
    1
    Spells:
    5
    Wurst:
    1
    Resources:
    7
    so true that hurts
     
  12. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,003
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    I'm not lying, look at how I responded to your post approximately a month later.
    I only come here to reply to private messages asking me about resources.
    I tell people to message someone else.
     
  13. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,375
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    You burned yourself out and are sick of it, huh? Too much efficiency and optimizations;)
     
  14. BPower

    BPower

    Joined:
    Mar 18, 2012
    Messages:
    1,709
    Resources:
    21
    Spells:
    15
    Tutorials:
    1
    JASS:
    5
    Resources:
    21
    I had the idea to use the
    force
    native in the entire API.
    Everything we need is already available in the blizzad.j
    Code (vJASS):
        force              bj_FORCE_ALL_PLAYERS        = null
        force array        bj_FORCE_PLAYER

    by default a sound volume within the stack is 0.
    If a player is in passed in force "audience", the volume gets adjusted.
    This adds a small overhead in contrast to SoundTools 3.x, but solves all API problems
    i.e. playing a sound on a unit for a player, etc...
    in method this.run(audience)
    Code (vJASS):
                if IsPlayerInForce(GetLocalPlayer(), audience) then
                    call SetSoundVolume(media[this], DEFAULT_SOUND_VOLUME)
                endif


    Something like this:
    Code (vJASS):
    /***********************************************
    *
    *   SoundTools
    *   v4.0
    *   By -
    *
    *   (Special Thanks to Rising_Dusk, Magtheridon96)
    *
    *   - Allows you to play sounds immediately after creating them.
    *   - Uses a sound recycler to increase efficiency and save RAM.
    *
    *   Requirements:
    *   -------------
    *
    *       - Table by Bribe
    *           - hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
    *       - TimerUtils by Vexorian
    *           - wc3c.net/showthread.php?t=101322
    *
    *   API:
    *   ----
    *
    *       constant boolean DEFAULT_SOUND_STOPS_ON_LEAVE_RANGE
    *       constant integer DEFAULT_SOUND_FADE_IN_RATE
    *       constant integer DEFAULT_SOUND_FADE_OUT_RATE
    *       constant string  DEFAULT_SOUND_EAX_SETTINGS
    *       constant integer DEFAULT_SOUND_VOLUME
    *       constant integer DEFAULT_SOUND_PITCH
    *
    *       struct Sound extends array
    *
    *           readonly string file
    *           readonly integer duration
    *           readonly boolean looping
    *           readonly boolean is3D
    *           readonly boolean stopOnLeaveRange
    *           readonly integer fadeIn
    *           readonly integer fadeOut
    *           readonly string eaxSetting
    *
    *           static method create takes string fileName, integer duration, boolean looping, boolean is3D returns thistype
    *               - Creates a sound struct given the filepath, the duration in milliseconds, whether it is looping or not, and whether it is 3D or not.
    *           static method createEx takes string fileName, integer duration, boolean looping, boolean is3D, boolean stopOnExitRange, integer fadeIn, integer fadeOut, string eaxSetting returns thistype
    *               - In addition to static method create, this allows you to specificy whether the sound stops when the player leaves range, the fadeIn/fadeOut rates and the EAX Setting.
    *           static method release takes sound s returns boolean
    *               - Releases a sound and throws it into the recycler. Also stops the sound.
    *
    *           method run takes nothing returns sound
    *               - Plays the sound.
    *           method runUnit takes unit whichUnit returns sound
    *               - Plays the sound on a unit.
    *           method runPoint takes real x, real y, real z returns sound
    *               - Plays the sound at a point.
    *           method runPlayer takes player whichPlayer returns sound
    *               - Plays the sound for a player.
    *
    *           method runEx takes integer volume, integer pitch returns sound
    *               - Plays the sound. This function allows you to pass in extra arguments.
    *           method runUnitEx takes unit whichUnit, integer volume, integer pitch returns sound
    *               - Plays the sound on a unit. This function allows you to pass in extra arguments.
    *           method runPointEx takes real x, real y, real z, integer volume, integer pitch returns sound
    *               - Plays the sound at a point. This function allows you to pass in extra arguments.
    *           method runPlayerEx takes player whichPlayer, integer volume, integer pitch returns sound
    *               - Plays the sound for a player. This function allows you to pass in extra arguments.
    *
    *       function NewSound takes string fileName, integer duration, boolean looping, boolean is3D returns Sound
    *           - Creates a sound struct given the filepath, the duration in milliseconds, whether it is looping or not, and whether it is 3D or not.
    *       function NewSoundEx takes string fileName, integer duration, boolean looping, boolean is3D, boolean stop, integer fadeInRate, integer fadeOutRate, string eax returns Sound
    *           - In addition to static method create, this allows you to specificy whether the sound stops when the player leaves range, the fadeIn/fadeOut rates and the EAX Setting.
    *       function ReleaseSound takes sound s returns boolean
    *           - Releases a sound and throws it into the recycler. Also stops the sound.
    *       function RunSound takes Sound this returns sound
    *           - Plays the sound.
    *       function RunSoundEx takes Sound this, integer volume, integer pitch returns sound
    *           - Plays the sound. This function allows you to pass in extra arguments.
    *       function RunSoundOnUnit takes Sound this, unit whichUnit returns sound
    *           - Plays the sound on a unit.
    *       function RunSoundAtPoint takes Sound this, real x, real y, real z returns sound
    *           - Plays the sound at a point.
    *       function RunSoundForPlayer takes Sound this, player p returns sound
    *           - Plays the sound for a player.
    *       function RunSoundOnUnitEx takes Sound this, unit whichUnit, integer volume, real pitch returns sound
    *           - Plays the sound on a unit. This function allows you to pass in extra arguments.
    *       function RunSoundAtPointEx takes Sound this, real x, real y, real z, integer volume, real pitch returns sound
    *           - Plays the sound at a point. This function allows you to pass in extra arguments.
    *       function RunSoundForPlayerEx takes Sound this, player p, integer volume, real pitch returns sound
    *           - Plays the sound for a player. This function allows you to pass in extra arguments.
    *
    *   Credits:
    *   --------
    *
    *       - Rising_Dusk (The original system)
    *       - Zwiebelchen (Research - He found a ton of Wc3 sound bugs and ways to fix them)
    *
    ***********************************************/

    library SoundTools requires Table, TimerUtils
       
        /*
        *   Configuration
        */

       
        globals
            constant boolean DEFAULT_SOUND_STOPS_ON_LEAVE_RANGE = true
            constant integer DEFAULT_SOUND_FADE_IN_RATE = 10
            constant integer DEFAULT_SOUND_FADE_OUT_RATE = 10
            constant string  DEFAULT_SOUND_EAX_SETTINGS = "CombatSoundsEAX"
            constant integer DEFAULT_SOUND_VOLUME = 127
            constant integer DEFAULT_SOUND_PITCH = 1
        endglobals
       
        globals
            private constant integer SOUND_CHANNEL  = 5
            private constant integer SOUND_MIN_DIST = 600
            private constant integer SOUND_MAX_DIST = 10000
            private constant integer SOUND_DIST_CUT = 3000
        endglobals
       
        /*
        *   End of Configuration
        */

       
        private module Inits
            private static method onInit takes nothing returns nothing
                call thistype.init()
            endmethod
        endmodule
        struct Sound extends array

            private static Table tb = 0
            private static Table pt = 0
            private static method init takes nothing returns nothing
                set tb = Table.create()
                set pt = Table.create()
            endmethod
            implement Inits

            private static integer alloc = 0
           
            //*  Stack per instance:
            //*  ===================
            private Table   stack
            private integer size
           
            readonly string  file
            readonly integer duration
            readonly boolean looping
            readonly boolean is3D
            readonly boolean stopOnLeaveRange
            readonly integer fadeIn
            readonly integer fadeOut
            readonly string  eaxSetting
           
            private real pitch
           
            static method createEx takes string fileName, integer dur, boolean loopng, boolean isTD, boolean stop, integer fadeInRate, integer fadeOutRate, string eax returns thistype
                local thistype this = alloc + 1
                set thistype.alloc  = integer(this)
               
                set pitch = 1
                set file = fileName
                set duration = dur
                set looping = loopng
                set is3D = isTD
                set fadeIn = fadeInRate
                set fadeOut = fadeOutRate
                set eaxSetting = eax
                set stopOnLeaveRange = stop
               
                set stack = Table.create()
               
                return this
            endmethod
           
            static method create takes string fileName, integer dur, boolean loopng, boolean isTD returns thistype
                return createEx(fileName, dur, loopng, isTD, DEFAULT_SOUND_STOPS_ON_LEAVE_RANGE, DEFAULT_SOUND_FADE_IN_RATE, DEFAULT_SOUND_FADE_OUT_RATE, DEFAULT_SOUND_EAX_SETTINGS)
            endmethod
           
            // Credits to Zwiebelchen for this function
            // He discovered a bug with sound pitches and this function was written to fix that.
            method setSoundPitch takes sound s, real newPitch returns nothing
                if GetSoundIsPlaying(s) or GetSoundIsLoading(s) then
                    call SetSoundPitch(s, 1/pitch)
                    call SetSoundPitch(s, newPitch)
                    set pitch = newPitch
                elseif newPitch == 1 then
                    call SetSoundPitch(s, 1.0001)
                    set pitch = 1.0001
                else
                    call SetSoundPitch(s, newPitch)
                    set pitch = newPitch
                endif
            endmethod
           
            private static sound snd
           
            private method get takes nothing returns sound
                if (0 == size) then
               
                    /**
                    *   Create new sound and point it to
                    *   Sound struct instance.
                    */

                    set snd = CreateSound(file, looping, is3D, stopOnLeaveRange, fadeIn, fadeOut, eaxSetting)
                    set pt[GetHandleId(snd)] = this
                   
                    /**
                    *   Configure sound
                    */

                    call SetSoundDuration(snd, duration)
                    call SetSoundChannel(snd, SOUND_CHANNEL)
                    call SetSoundVolume(snd, 0)
                    call setSoundPitch(snd, DEFAULT_SOUND_PITCH)
                   
                    /**
                    *   Proper 3D sound configuration
                    */

                    if is3D then
                        call SetSoundDistances(snd, SOUND_MIN_DIST, SOUND_MAX_DIST)
                        call SetSoundDistanceCutoff(snd, SOUND_DIST_CUT)
                        call SetSoundConeAngles(snd, 0, 0, DEFAULT_SOUND_VOLUME)
                        call SetSoundConeOrientation(snd, 0, 0, 0)
                    endif
                   
                    return snd
                endif
               
                //*  Pop:
                //*  ====
                set size = size - 1
                return stack.sound[size]
            endmethod
           
            private method push takes sound s returns nothing
                call SetSoundVolume(s, 0)
                set stack.sound[size] = s
                set size = size + 1
            endmethod
           
            private static method recycle takes nothing returns nothing
                local timer t = GetExpiredTimer()
                local sound s = tb.sound[GetHandleId(t)]
               
                /**
                *   Stop sound and push to the
                *   stack.
                */

                call StopSound(s, false, true)
                call thistype(GetTimerData(t)).push(s)
                call ReleaseTimer(t)
               
                set t = null
                set s = null
            endmethod
           
            private static integer array next
            private static sound array media
           
            private static method runSounds takes nothing returns nothing
                local thistype this = next[0]
                local timer t
               
                call ReleaseTimer(GetExpiredTimer())
               
                loop
                    exitwhen (0 == this)
                   
                    /**
                    *   Play the sound.
                    */

                    call StartSound(media[this])
                   
                    /*
                    *   If it is not looping,
                    *   we can recycle it when
                    *   it finishes playing.
                    */

                    if not looping then
                        set t = NewTimerEx(this)
                        set tb.sound[GetHandleId(t)] = media[this]
                        call TimerStart(t, duration * 0.001, false, function thistype.recycle)
                    endif
                   
                    set media[this] = null
                    set this = next[this]
                endloop
               
                set next[0] = 0
               
                set t = null
            endmethod
           
            method run takes force audience returns sound
                debug if (0 == this) then
                    debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[SoundTools]Error: Attempted to play null sound.")
                    debug return null
                debug endif
               
                if next[0] == 0 then
                    call TimerStart(NewTimer(), 0, false, function thistype.runSounds)
                endif
               
                if media[this] == null then
                    set next[this] = next[0]
                    set next[0] = this
                    set media[this] = this.get()
                debug else
                    debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[SoundTools]Warning: Attempted to run the same sound twice.")
                endif
                if IsPlayerInForce(GetLocalPlayer(), audience) then
                    call SetSoundVolume(media[this], DEFAULT_SOUND_VOLUME)
                endif
                return media[this]
            endmethod
           
            method runEx takes integer volume, integer newPitch, force audience returns sound
                set snd = this.run(audience)
                if IsPlayerInForce(GetLocalPlayer(), audience) then
                    call SetSoundVolume(media[this], volume)
                    call setSoundPitch(snd, newPitch)
                endif
                return snd
            endmethod
           
            static method release takes sound s returns boolean
                local integer id = GetHandleId(s)
               
                if s == null then
                    debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[SoundTools]Error: Attempted to release a null sound.")
                    return false
                elseif pt[id] == 0 then
                    debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[SoundTools]Error: Attempted to release a sound not allocated by RunSound.")
                    return false
                endif
               
                /**
                *   Stop the sound and push it
                *   to the stack.
                */

                call StopSound(s, false, true)
                call thistype(pt[id]).push(s)
               
                return true
            endmethod
           
            method runUnit takes unit whichUnit, force audience returns sound
                set snd = run(audience)
                call AttachSoundToUnit(snd, whichUnit)
                return snd
            endmethod
           
            method runUnitEx takes unit whichUnit, integer volume, integer newPitch. force audience returns sound
                set snd = runUnit(whichUnit)
                if IsPlayerInForce(GetLocalPlayer(), audience) then
                    call SetSoundVolume(snd, volume)
                    call setSoundPitch(snd, newPitch)
                endif
                return snd
            endmethod
           
            method runPoint takes real x, real y, real z, force audience returns sound
                set snd = run(audience)
                call SetSoundPosition(snd, x, y, z)
                return snd
            endmethod
           
            method runPointEx takes real x, real y, real z, integer volume, integer newPitch, force audience returns sound
                set snd = runPoint(audience, x, y, z)
                if IsPlayerInForce(GetLocalPlayer(), audience) then
                    call SetSoundVolume(snd, volume)
                    call setSoundPitch(snd, newPitch)
                endif
                return snd
            endmethod
           
        endstruct
       
        function NewSoundEx takes string fileName, integer duration, boolean looping, boolean is3D, boolean stop, integer fadeInRate, integer fadeOutRate, string eax returns Sound
            return Sound.createEx(fileName, duration, looping, is3D, stop, fadeInRate, fadeOutRate, eax)
        endfunction
       
        function NewSound takes string fileName, integer duration, boolean looping, boolean is3D returns Sound
            return Sound.create(fileName, duration, looping, is3D)
        endfunction
       
        function RunSound takes Sound this, force audience returns sound
            return this.run(audience)
        endfunction
       
        function RunSoundEx takes Sound this, integer volume, integer pitch, force audience returns sound
            return this.runEx(volume, pitch, audience)
        endfunction
       
        function ReleaseSound takes sound s returns boolean
            return Sound.release(s)
        endfunction
       
        function RunSoundOnUnit takes Sound this, unit whichUnit, force audience returns sound
            return this.runUnit(audience, whichUnit, audience)
        endfunction
       
        function RunSoundOnUnitEx takes Sound this, unit whichUnit, integer volume, integer pitch, force audience returns sound
            return this.runUnitEx(whichUnit, volume, pitch, audience)
        endfunction
       
        function RunSoundAtPoint takes Sound this, real x, real y, real z, force audience returns sound
            return this.runPoint(x, y, z, audience)
        endfunction
       
        function RunSoundAtPointEx takes Sound this, real x, real y, real z, integer volume, integer pitch, force audience returns sound
            return this.runPointEx(x, y, z, volume, pitch, audience)
        endfunction
       
    endlibrary
     
     
  15. EdwardElric

    EdwardElric

    Joined:
    Jun 19, 2010
    Messages:
    49
    Resources:
    0
    Resources:
    0
    ah, sad...
    i just wanted to ask whether it is possible to add an option for delaying sounds so users don't need to create timers themself...