• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[GUI-friendly] Rapid Sound v1.91

Level 10
Joined
Aug 21, 2010
Messages
316
I expect that this is pure gui version.
This is not a gui version.
This is normal jass version.
Well, does not require jngp and it's ok but everything else is pretty much the same.
The only difference is shitty UDG.
Well, not really the only difference but generally, this is it.
 
Last edited:
Level 5
Joined
May 2, 2015
Messages
109
I have to use JASS as long as this system handles sound and I think JASS is better when creating a system for GUI user.
This system may not a GUI, but it supports GUI (GUI-friendly)

EDIT: If you really want a pure GUI system, just give me one or two system and I will try to convert it. (vJass > GUI)
 
Last edited:
Level 10
Joined
Aug 21, 2010
Messages
316
I have to use JASS as long as this system handles sound and I think JASS is better when creating a system for GUI user.
This system may not a GUI, but it supports GUI (GUI-friendly)

EDIT: If you really want a pure GUI system, just give me one or two system and I will try to convert it. (vJass > GUI)
I do not need a GUI system.
I'm just saying that this is not a gui
GUI and GUI-friendly are not the same
 
Level 38
Joined
Sep 6, 2013
Messages
6,743
It should include a little guide only for GUI users /it's variables.

For example I was pretty confused about the meaning of "Set gRSParam_Which" until I looked it up inside the code.
By the way "_Which" allown is not a well chosen name for it's purpose. I suggest to choose something like "State" or "Flag", or ... you got the idea. But not simple "which" to define method of an operation.

The user has to keep track of the sounds by himself at the moment which isn't really flexible and can be bothering to destinguish in GUI if one have lots of sounds.
I believe the system would be able to take take some workload from this aspect. The idea is that you internaly store the created sounds and bind them to the sound name (string).
Then when the user wants to play the sound:

Init:
  • Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set HolyBoltPath = test\HolyBolt.wav
      • ....
      • ....
And on use:
  • Set gRSParam_fileName = HolyBoltPath
  • Set gRSParam_Which = gRS_Play
  • ...
  • Trigger - Run GUI RapidSound <gen> (ignoring conditions)
The other way, the user has needs to keep track of an un-intuitive counter by himself, like in the demo example:

  • Actions
    • Set gRSParam_RapidSound = rp[1]
    • Set gRSParam_Which = gRS_Play
    • ....
    • Trigger - Run GUI RapidSound <gen> (ignoring conditions)
I believe the first one is a bit more clear and easier to follow for GUI users.
 
Level 5
Joined
May 2, 2015
Messages
109
It should include a little guide only for GUI users /it's variables.
Ow! I forgot:p. Thanks for reminding me
I'll update ASAP

The user has to keep track of the sounds by himself at the moment which isn't really flexible and can be bothering to destinguish in GUI if one have lots of sounds.
I believe the system would be able to take take some workload from this aspect. The idea is that you internaly store the created sounds and bind them to the sound name (string).
Then when the user wants to play the sound:

Init:
  • base.gif
    Init
    • joinminus.gif
      events.gif
      Events
      • line.gif
        joinbottom.gif
        folder.gif
        Map initialization
    • join.gif
      cond.gif
      Conditions
    • joinbottomminus.gif
      actions.gif
      Actions
      • empty.gif
        join.gif
        set.gif
        Set HolyBoltPath = test\HolyBolt.wav
      • empty.gif
        join.gif
        if.gif
        ....
      • empty.gif
        joinbottom.gif
        if.gif
        ....


And on use:
  • set.gif
    Set gRSParam_fileName = HolyBoltPath
  • set.gif
    Set gRSParam_Which = gRS_Play
  • if.gif
    ...
  • page.gif
    Trigger - Run GUI RapidSound <gen> (ignoring conditions)
So, I have to use loop to get the instance, right?
 
Level 5
Joined
May 2, 2015
Messages
109
Why? It's a good idea. I've updated the system

Updated! v1.1
  • added guide for GUI user
  • added the feature to play sound by using the sound file name
Next update v1.5
  • the system automatically create RapidSound when user want to play a sound that is still not registered.
  • will add the feature to create RapidSound with various kind of sound (4-16 sound max).
  • will add sound preloading feature
  • will add debugging option
 
Last edited:
Level 10
Joined
Aug 21, 2010
Messages
316
Perhaps it would be better if the changelog found in the description and not in the comments.
In this case, would be located at the top of the page and not somewhere at the bottom.
How anyone could possibly know if you update something.Many users do not read all the comments.
 
Last edited:
Level 38
Joined
Sep 6, 2013
Messages
6,743
The auto-create on first use with unknown string can be handy.

Why I meant this:
Forget my idea with the strings.
... is because my example didn't make much sense. When the user bothers to create a string variable for each sound, he also can bother to create an integer variable (with same descriptive name) for each sound which will be the sound instance/index.
 
Level 5
Joined
May 2, 2015
Messages
109
Why I meant this:
... is because my example didn't make much sense. When the user bothers to create a string variable for each sound, he also can bother to create an integer variable (with same descriptive name) for each sound which will be the sound instance/index.

No no, users don't have to do that to make things happen.

In this version (v1.1), the user can either store the created RSound instance (for maximum performance) into integer variable or just use the sound path to play the sound (uses loop to find the instance, slow).
In the demo/guide I given in the description, I stored the sound path into variable to make the code looks clean.
 
Last edited:
Level 38
Joined
Sep 6, 2013
Messages
6,743
I understood. :) I just say that my example made no sense.
I suggested to use string variables over int variables basicly, which makes absolutly no sense in storing. He directly can use integers and store the sound properly without the string workaround.
 
Level 39
Joined
Feb 27, 2007
Messages
5,031
I'm unsure how to stress test this in a way that the performance difference between using the integer reference vs. string (requiring loop lookup) would be readily apparent. I don't really see anything glaringly wrong with this. Add in creating the sound on unknown string and I would approve it (but I'm just a spell reviewer so take that as you will).
 
Level 5
Joined
May 2, 2015
Messages
109
Actually, I decided to replace the loop with hashtable in the next update.

But if you want to see the performance difference, create thousands of RapidSound instance and test using both method (integer, string), you'll see. When using string, the system will search any instance that match with the string. If 5000 instance exist, the system will loop 5000 time.

Add in creating the sound on unknown string and I would approve it (but I'm just a spell reviewer so take that as you will).

You mean, auto creating. Already on my next update list

EDIT: I've been thinking (hardly), how to make system rejects invalid sound path when creating or playing?
 
Last edited:
Level 38
Joined
Sep 6, 2013
Messages
6,743
But if you want to see the performance difference, create thousands of RapidSound instance and test using both method (integer, string), you'll see. When using string, the system will search any instance that match with the string. If 5000 instance exist, the system will loop 5000 time.
Could you elaborate what you mean by example?
 
Level 5
Joined
May 2, 2015
Messages
109
From the system code,

JASS:
function RSStack_Create takes nothing returns integer
    local integer this
    if (udg_gRSStack_Recycle[0] == 0) then
        set udg_gRSStack_InstanceCount = udg_gRSStack_InstanceCount + 1
        set this = udg_gRSStack_InstanceCount
    else
        set this = udg_gRSStack_Recycle[0]
        set udg_gRSStack_Recycle[0] = udg_gRSStack_Recycle[this]
        set udg_gRSStack_First[this] = 0
    endif
    return this
endfunction
this is the function that I used to create the RapidSound instance.
From what you see, everytime I use this function, the udg_gRSStack_InstanceCount will increase by +1

JASS:
function gRS_GetRapidSound takes string fileName returns integer
    local integer i = udg_gRSStack_InstanceCount
    loop
        exitwhen udg_gRS_SoundName[i] == fileName or i == 0
        set i = i - 1
    endloop
    return i
endfunction
this is the function that I used to find RapidSound instance by string.

Let say the current udg_gRSStack_InstanceCount is 5000. The function will work like this
JASS:
function gRS_GetRapidSound takes string fileName returns integer
    local integer i = 5000
    //loops until finished decreasing 5000 to 0 or when it found matching instance
    loop
        exitwhen udg_gRS_SoundName[i] == fileName or i == 0
        set i = i - 1
    endloop
    return i
endfunction
If the matching instance/index is 1, can you imagine. The system will loop 4999x(how many times the user play the sound)

EDIT: I've been thinking (hardly), how to make system rejects invalid sound path when creating or playing?
Any answer?
 
Last edited:
Level 5
Joined
May 2, 2015
Messages
109
Actually, I decided to replace the loop with hashtable in the next update.
I already said that :)
Also, in the next update, users don't have to store RapidSound instance anymore. Only use sound file path as system reference.

EDIT:
Any answer?
Solved!

Updated! v1.7
  • added debug mode
  • added sound preload method
  • added auto create feature
  • added auto preload feature
  • removed integer as system reference, replaced with string
  • removed loop to search instance, replaced with hashtable
  • the system now rejects invalid sound file
  • reconstructed the
    gRS_Actions
    function code
  • fixed some minor bug
 
Last edited:
Level 38
Joined
Sep 6, 2013
Messages
6,743
Usage seems really neat.
Though some naming seems not constant. Publics use "gRS", some internal "RS", some none. Make everything use a prefix, and just make it the same.
For exmaple "udg_gRSParam_State" can just be "udg_GRS_State" and function CreateRapidSound then just function GRS_Create, and so on.
 
Level 5
Joined
May 2, 2015
Messages
109
I'll update,
And can I ask, what if I want to change "udg_gRSParam_State" to "GRS_Param_State".
The variables name need to have some different so it wont give user headache. I will explain more in the upcoming guide.
 
Level 38
Joined
Sep 6, 2013
Messages
6,743
"GRS_Param_State"
^We would accept it, yes.
For me personaly it's not perfect, and I would just call it "GRS_State".
If you have the same variable used privatly by the system I would do following to avoid collision. "GRS_State_p" or so (for internal variable), so it just indicates the "private" with "p" for you.
But that's just style, you may go swim your own way through the ocean.

I'll update
Wanted to update something else, or only because of the naming?

I'm unsure why a API is listed, as the functions are not wrapped into a library.
Your call, but I personaly would just require JassHelper to use vjass, but still make it GUI-useable, so all have benefits, and JNGP is anyways a must have for map makers.

JASS:
function StopRapidSound takes integer this, boolean fadeOut returns nothing
    local integer i

    loop
        exitwhen i == MAX_COUNT()
        call StopSound(udg_gRS_Sound[udg_gRS_List[udg_gRS_First[this] + i]], false, fadeOut)
        set i = i + 1
    endloop
endfunction
^i isn't initialisized, and would crash the running thread.

Can't test it right now, but else all looks good for me. I would approve if mentioned things are changed, and you become happy with the namings and such.
Just check everything again and if you're happy we can go. :}
 
Level 38
Joined
Sep 6, 2013
Messages
6,743
Ok, so as you didn't decide to put it into a library some names need to changed.

"constant function MAX_COUNT takes nothing returns integer"

^that's too generic, and might come in conflict. Please use your system prefix for all names.
Next update v2.0
  • add vJass version
There already exists vjass version. Maybe you want to suggest something at Quilnez thread if it's not good enough.
 
Level 38
Joined
Sep 6, 2013
Messages
6,743
Hm, the name collision is still a thing. Just make every function with the prefix, and then the generic names are okay, too. Awaiting Update.
 

Kazeon

Hosted Project: EC
Level 34
Joined
Oct 12, 2011
Messages
3,449
You should've used queue instead of stack, given the order of played sound should've been.
 

Kazeon

Hosted Project: EC
Level 34
Joined
Oct 12, 2011
Messages
3,449
I thought it's very obvious, unless you don't even understand how it works.

0. Initial state
sound 1 | sound 2 | sound 3 | sound 4

1. call play function => dequeue and enqueue sound 1
sound 2 | sound 3 | sound 4 | sound 1

2. call play function again => dequeue and enqueue sound 2
sound 3 | sound 4 | sound 1 | sound 2

and so on.. If a sound is about to be dequeued and it's still playing, stop it first then replay.
That's the sole reason why it sounds like the sound is played rapidly (more than 4 handles at once).

If you are using stack then:

0. Same initial state
sound 1 | sound 2 | sound 3 | sound 4

1. call play function => pop and push sound 1
(after pop) sound 2 | sound 3 | sound 4
(after push) sound 1 | sound 2 | sound 3 | sound 4 => back to initial state again thus the rapid playing effect isn't achieved because you are only playing 1 sound handle all the time.

and so on.
 
Level 5
Joined
May 2, 2015
Messages
109
I thought it's very obvious, unless you don't even understand how it works.

0. Initial state
sound 1 | sound 2 | sound 3 | sound 4

1. call play function => dequeue and enqueue sound 1
sound 2 | sound 3 | sound 4 | sound 1

2. call play function again => dequeue and enqueue sound 2
sound 3 | sound 4 | sound 1 | sound 2

and so on.. If a sound is about to be dequeued and it's still playing, stop it first then replay.
That's the sole reason why it sounds like the sound is played rapidly (more than 4 handles at once).
This system works just like you say.

In this system, 4 sound will be created for each sound file name and each one of them have their own index. (from 1 to 8190)
So, the max Rapid Sound instance is 8190/4. I use stack to group the sounds. For example,


User create a Rapid Sound (RS) > user get 5 as index for the created RS.

sound 1 [41] | sound 2 [42] | sound 3 [43] | sound 4 [44] created. 41,42,43,44 (the sound index)

The system store 41 into a variable to define the first sound instance of the RS[5].
When user want to play it, the system will take the first instance (sound 1 [41]) from the stack and play it. When user "call play" again,
the system will take the next instance (sound 2 [42]). When all the 4 sound has been played, the system will go back to the first instance and just like you said, the system stops the sounds before replay.

1. call play function => pop and push sound 1
(after pop) sound 2 | sound 3 | sound 4
(after push) sound 1 | sound 2 | sound 3 | sound 4 => back to initial state again thus the rapid playing effect isn't achieved because you are only playing 1 sound handle all the time.
Please download the test map and rapidly press Esc when you test it.
 
Last edited:

Kazeon

Hosted Project: EC
Level 34
Joined
Oct 12, 2011
Messages
3,449
I haven't tested it, haven't read the code properly, and don't have time for it. But if you are indeed using a stack structure, I guarantee it won't work... Unless it's not actually a stack.
 
Level 38
Joined
Sep 6, 2013
Messages
6,743
If it's something like a complete rewrite, I believe, then it's possible. If only some structure is changed, then not necessary. Why to awating update? (better VM/PM/Staff contact me, or other spell guys)
 
Level 5
Joined
May 2, 2015
Messages
109
Currently working on update v2.0:
  • RapidSound playlist (New feature)
  • Use percentage as sound volume parameter instead 127
  • rename all variable
 
Top