Staredit Network > Forums > SC1 UMS Mapmaking Assistance > Topic: A consistent music system
A consistent music system
Mar 10 2017, 6:14 pm
By: Pr0nogo  

Mar 10 2017, 6:14 pm Pr0nogo Post #1



I've been trying to get an operational, consistent music system for like 2 years now on and off and every experiment I've done has ended without success, so at this point I think it would be better if I forget what I think I know about them and just ask SEN for help, since clearly whatever I'm doing isn't working. Instead of posting example maps I'll just explain exactly what I'm looking to accomplish.

I need a system that will play ten-second wavs in sequence, and keep track of that sequence externally so that it can be referenced later in order to play a fading-out version of the ten-second wav that's up next. e.g. the system plays the first six wavs, but the player triggers the fade-out in the middle of the sixth wav, so instead of playing the regular seventh wav, the system would play a version of the seventh wav that's been faded out. The idea is to make the system dynamic enough to fade different songs out if the player enters an area that has a different song associated with it, or if they trigger a cutscene that has its own song.

Since I'm not sure if I've given a good enough explanation I'll give a specific example. Mission 1 opens with a cutscene, which has a song that's been timed out to just play and doesn't need to fade. After that, the player takes control of their starting units and begins phase 1 of gameplay. Song 1 begins playing. Since the player can then enter into the next phase of gameplay at variable times (some players will do it quicker than others), it's impossible to accurately time Song 1. Instead, I must trigger the song to fade out over a reasonable amount of time (in this case, ten seconds) in order to artificially end Song 1 and make way for Song 2. This process would continue for however many phases of gameplay there were in a given map, although I wouldn't need to fade out for songs that play during cutscenes because cutscenes are much easier to time consistently. What is the best system for this and how do I implement it?

Thanks in advance for any help. I appreciate it.




Mar 10 2017, 7:35 pm zsnakezz Post #2



generally I try to get music loops to around 4 seconds. I set an actual object to spawn and disappear every 4 seconds (this trigger functions under an unused player but effects whomever)

main point is to set the conditional to exactly one object, so it ends the loop when it despawns.

Though I have a ghetto way of doing things, so what you are looking for might be more complicated.

You can also add in more objects or more of the same object to be identified as different soundtracks.

For example, 1 zergling = 4 second cave loop 2 zergling = 4 second battle loop etc.

This can be applied deeper for sequential purposes, but requires more raw spawn ins on top of locations, which could be inefficient as apposed to a more code and switch driven solution.

Post has been edited 1 time(s), last time on Mar 10 2017, 7:44 pm by zsnakezz.



I made the following maps; Hyperion 2, The Undead, The Undead Coop, Realm Rpg beta, and Overlords.

Mar 10 2017, 7:48 pm Pr0nogo Post #3



I will not be making use of spawning units for this system because players will be able to explore the entirety of the map with air units or scanner sweeps.




Mar 10 2017, 8:04 pm Swampfox Post #4



It seems simple enough to have a single incrementing death counter to keep track of the samples. Let's say each sample is 100 DCs long for sake of ease.

For instance:



if (always) {DC++}

if (mission1start) {set DC=100}

if (mission1 && DC==100 && switch==0) {play wav1-1}
if (mission1 && DC==200 && switch==0) {play wav1-2}
if (mission1 && DC==300 && switch==0) {play wav1-3}

if (mission2start) {set switch}

if (mission1 && DC==100 && switch==1) {play wav1-1fade, clear switch, set DC=0, clear mission1 conditions}
if (mission1 && DC==200 && switch==1) {play wav1-2fade, clear switch, set DC=0, clear mission1 conditions}
if (mission1 && DC==300 && switch==1) {play wav1-3fade, clear switch, set DC=0, clear mission1 conditions}

if (mission2 && DC==100 && switch==0) then {play wav2-1}
if (mission2 && DC==100 && switch==1) then {play wav2-1fade, clear switch, set DC=0}



where mission1/mission1start/mission2 are just whatever death counts or conditions you want to use to indicate those states

EDIT: that was kinda wrong lemme fix that
EDIT: ok, i think that works?

Post has been edited 9 time(s), last time on Mar 10 2017, 8:41 pm by Swampfox.



None.

Mar 10 2017, 8:23 pm Zoan Post #5

Math + Physics + StarCraft = Zoan

First off, lets recap what we know:

Each trigger cycle == (1/11.9) seconds, so in 1 cycles thats 0.084 seconds.

So, lets say you have a song which last 10 seconds.

Step 1:
calculate 10*11.9 = 119.
This is the total number of trigger cycles you will need for this song.

Step 2:
Lets say you want to split this song into 3 wavs.
calculate 119 / 3 = 39.6666...

Step 3:
Using the 39.66... from before as guidance, split 119 into the following:

119 = 40 + 40 + 39.

Step 4:
Calculate the length each wav needs to be:

Since 1 cycle is (1/11.9) seconds, we get the following

Length of segment 1 = 40/11.9 = 3.36134 seconds
Length of segment 2 = 40/11.9 = 3.36134 seconds
Length of segment 3 = 39/11.9 = 3.27731 seconds

Thus we have the following:

segment 1 = time from 0 seconds to 3.36134 seconds
segment 2 = time from 3.36134 seconds to 6.722689 seconds
segment 3 = time from 6.722689 seconds to 10 seconds



You will need 6 wavs for each song:
wav 1 == segment 1 of song - This has length 3.36134 seconds and corresponds to 40 trigger cycles.
wav 2 == segment 2 of song - This has length 3.36134 seconds and corresponds to 40 trigger cycles.
wav 3 == segment 3 of song - This has length 3.27731 seconds and corresponds to 39 trigger cycles.
wav 4 == fade-out during seg. 1 of song - This has length 3.36134 seconds and corresponds to 40 trigger cycles.
wav 5 == fade-out during seg. 2 of song - This has length 3.36134 seconds and corresponds to 40 trigger cycles.
wav 6 == fade-out during seg. 3 of song - This has length 3.27731 seconds and corresponds to 39 trigger cycles.


Here's the important bit - You need these three deathcounters:
DC1 == holds what song is being played
DC2 == holds song timer
DC3 == holds what song is up next

The triggers would be like this:

//This subtracts from DC2 always, ofc.
if(
DC2 is at least 1
)
then(
Subtract 1 from DC2
)


//This is needed up here, and allows player to start playing song 1 after they have finished fading out whatever song was playing before.
if(
DC1 is exactly -number corresponding to "Currently Fading out Last Song"-
DC2 is exactly 0
DC3 is exactly -number corresponding to song 1-
)
then(
DC1 set to -number corresponding to song 1-
DC3 set to 0
)

//This just plays the song 1 is there is no song up next.
if(
DC1 is exactly -number corresponding to song 1-
DC2 is exactly 0
DC3 is exactly 0
)
then(
play seg1 of song1
DC2 set to 119
)

if(
DC1 is exactly -number corresponding to song 1-
DC2 is exactly 79 //This is 119 - 40, since 119 == length of song, 40 == length of first segment of song
DC3 is exactly 0
)
then(
play seg2 of song1
)

if(
DC1 is exactly -number corresponding to song 1-
DC2 is exactly 39 //This comes from 39 = 119 - 40 - 40
DC3 is exactly 0
)
then(
play seg3 of song1
)

//This lets you transition from song 1 to other songs
if(
DC1 is exactly -number corresponding to song 1-
DC2 is exactly 0
DC3 is at least 1
)
then(
play fadeout-seg1 of song1
DC1 set to -number corresponding to "Currently Fading out Last Song"-
DC2 set to 39 //This to the length of the last song cycle
)

if(
DC1 is exactly -number corresponding to song 1-
DC2 is exactly 79
DC3 is at least 1
)
then(
play fadeout-seg2 of song1
DC1 set to -number corresponding to "Currently Fading out Last Song"-
DC2 set to 39
)

if(
DC1 is exactly -number corresponding to "Currently Fading out Last Song"-
DC2 is exactly 39
DC3 is at least 1
)
then(
play fadeout-seg3 of song1
DC1 set to -number corresponding to "Currently Fading out Last Song"-
DC2 set to 39
)

Now just copy-paste the 'song1' triggers for other songs.

Edit: Actually now that I think about it, this would work fine if you had a bunch of different songs with different lengths, assuming you take care of making sure the wav lengths correspond correctly to the number of cycles they run for.

IMPORTANT EDIT:
I went through and fixed all of the terribly inaccurate numbers I had for the amounts of DC2. They are correct now.

Post has been edited 8 time(s), last time on Mar 10 2017, 9:38 pm by Zoan.



\:rip\:ooooo\:wob\:ooooo \:angel\: ooooo\:wob\:ooooo\:rip\:

Mar 10 2017, 8:37 pm Swampfox Post #6



Oh I what you're doing zoan. That's better than what I was doing since I would say I was essentially "hardcoding" the song lengths into the triggers, whereas yours allows easy input for different song lengths.



None.

Mar 10 2017, 8:43 pm Zoan Post #7

Math + Physics + StarCraft = Zoan

Quote from Swampfox
Oh I what you're doing zoan. That's better than what I was doing since I would say I was essentially "hardcoding" the song lengths into the triggers, whereas yours allows easy input for different song lengths.

Idk, my method takes 3 death counters (though if you think about it long enough you could probably get away with only using 2, or even 1 if you use some other method of storing what song is currently being played aside from what I called DC1).



\:rip\:ooooo\:wob\:ooooo \:angel\: ooooo\:wob\:ooooo\:rip\:

Mar 10 2017, 8:49 pm Swampfox Post #8



Mine is essentially using 2 DCs and a switch. I assume though there is already some sort of variable pronogo is using to indicate the current mission/song so that could somehow be integrated.



None.

Mar 10 2017, 8:55 pm Pr0nogo Post #9



I'm trying and failing to understand the way Zoan has laid it out since I only use the GUI and not text triggers, but from what I understand I need to calculate how many cycles my song is and time it out that way. I assume there's no way to make the song lengths cleaner? I was using 10 second clips before and it was a lot easier to separate the song into individual clips that way.

In what cases do trigger orders matter for this system?

I do have a variable (DC) for what song should be playing.




Mar 10 2017, 9:00 pm Zoan Post #10

Math + Physics + StarCraft = Zoan

I'm not familiar with GUI programming. You are still only allowed to do the things you can do with triggers, right?

The trigger order doesn't matter apart from two things:

1. You need to subtract 1 from the DC which basically stores the time (What I called DC2) before everything else.

2. The trigger which allows you to go from -number corresponding to "Fading out Last Song"- to -number corresponding to song X- must be before all the triggers which play the wavs for that song.

Edit: Oh, by GUI do you mean with like SCMDraft2?

If thats the case, then just replace the following:

"ifs" -> "Conditions"

"thens" -> "Actions"

"DC1 Exactly 'blah'" -> "Current Player Suffers Exactly 'blah' Deaths of -DC1 unit-"

etc.

Edit2: Pronogo, I edited my original comment to give a better idea on how to calculate the lengths of each song segment.

Post has been edited 3 time(s), last time on Mar 10 2017, 9:42 pm by Zoan.



\:rip\:ooooo\:wob\:ooooo \:angel\: ooooo\:wob\:ooooo\:rip\:

Mar 10 2017, 10:42 pm NudeRaider Post #11

We can't explain the universe, just describe it; and we don't know whether our theories are true, we just know they're not wrong. >Harald Lesch

The best system is the always the simplest system. In sc terms this means everything will be controlled death counters. Make sure to avoid wait blocks, as obviously this would throw off any timing, or worse, trigger order. As for hyper triggers, it's best to give them to a computer that runs no waits and is never defeated, as the timing requires to run them at all times. I will try to outline a trigger system that is easily organized, with simple logic and clear role of triggers. However it requires having a sound understanding of death counters, trigger order and proper use of Current Player (=> Every trigger is owned by the player force and all dc modifications are done for Current Player).

1) You have a counter Music_Counter that counts down from 10s / 84ms/1000ms/s per trigger loop = 119 death counts. The counter is decreased only whenever music plays (i.e. it stays at 119 when the music is off). This trigger must be at the bottom of the list.

2) When the counter reaches zero it gets reset to 119, and there's a number of triggers BELOW it in the trigger order that play the next piece when the counter is at exactly 119. (see step 5)

3) Then you have another variable Play_Next that keeps track of which song snippet should be played next. Say you have 5 songs, 30 snippets each, you could apply the values in this fashion:
0 = music off
1 = song1, snippet1
2 = song1, snippet2
...
30 = song1, snippet30
31 = song2, snippet1
...
150 = song5, snippet30


4) For the sake of intuitivity I'll assume the user brings a civ to a beacon to switch the music on or off, which resets the civ just outside the beacon location. But of course you can use any other method to switch without changing how the system works. Triggers would change slightly if you want a system where the civ remains in location A for music on, and bringing it to B turns it off (or something that resembles that logic). It's slightly more complicated to do but if you insist on doing it that way, just ask and I'll see how to modify.

5) So now comes the crucial part: Making sure Play_Next always stores the intended state. Lets look at the possible cases:
Music is off: (Play_Next = 0)
- Map initialization: set Play_Next to 1
- User brings civ to beacon: set Play_Next to 1, 31, ... or 121, depending on further conditions (e.g. map progress).

Music is playing: (Play_Next = 1-150)

- Music_Counter is 119: Play wav according to above table and
__ · if Play_Next = 30 / 60 / ... / 150 set Play_Next to 1 / 31 / ... / 121
__ · else add 1 to Play_Next
Clarification: if .. else is not an actual condition, but rather tells you which of the play wav triggers contains which modification to Play_Next as an action.

- User brings civ to beacon: add to Play_Next: 1000, display text "music will turn off shortly"
This creates the following table for the fade outs:
1001 = song1, fadeout1 (=music of snippet2, but getting silenced towards the end)
1002 = song1, fadeout2 (=music of snippet3, but getting silenced towards the end)
...
1030 = nothing
1031 = song2, fadeout1
...
1150 = nothing


Fade out requested (Play_Next = 1001-1150)
- Music_Counter is 119: Play wav according to above table and
__ · if Play_Next = 1030 / 1060 / ... / 1150 set Play_Next to 0
__ · else set Play_Next to 1000

- User brings civ to beacon: subtract from Play_Next: 1000, display text "music will continue"

Fade out is playing: (Play_Next = 1000)
- Music_Counter is 119: set Play_Next to 0
This trigger has to be above the (Play_Next = 1001-1150)-section

- User brings civ to beacon: Do not do anything. Civ will trigger as soon as Play_Next is 0, which restarts the music as defined in the (Play_Next = 0)-section.
(When things are running you can modify this in a way that resets the civ and displays "music will continue" but this may throw things off if done the wrong way, so I kept it simple for now.)


Getting the states right (in theory) was more work than I anticipated and so I don't feel like providing example triggers at the moment. I just hope I thought of everything. But if you choose to use that system I suggest you try to implement the triggers as outlined in an actual map, and if it doesn't work right off the bat we can work from there and root out the bugs. Of course feel free to ask whatever questions you may have.

EDIT:
Oh and in case it wasn't obvious already: Play_Next can be modified by any additional trigger without breaking things. Such changes will be applied after the currently playing snippet finished.

For your intro nothing is stopping you to initialize the Music_Counter at a higher value to match the length of your intro song. This alters the Play_Next table so 2 = 2nd song, 1st snippet. Just 1 catch: While the last 10s of your intro play, the Counter would hit 119 and start playing the 2nd song as Play_Next is already set to it. Just add a condition to avoid that bug.

Post has been edited 1 time(s), last time on Mar 10 2017, 11:03 pm by NudeRaider.




Mar 28 2017, 10:43 pm Azrael Post #12



I thought it might be helpful to see an example, so I created a map to show it being implemented.

Music Fader.scx

When the map begins, battle music starts to play (it will eventually loop). You control a civilian, and there is a beacon.



When you move the civilian onto the beacon, the battle music will fade out, and a different song will fade in.

If you leave the beacon, the map will reset back to the battle music, so you can test the fade out effect multiple times.

Note that the audio clips are much shorter than 10 seconds, in order to make the music fade out more responsively. However, you can adjust the timer values to match audio clips of any length.

Please let me know if you have any questions.




Mar 29 2017, 5:57 am NudeRaider Post #13

We can't explain the universe, just describe it; and we don't know whether our theories are true, we just know they're not wrong. >Harald Lesch

Quote from Azrael
When you move the civilian onto the beacon, the battle music will fade out, and a different song will fade in.
I feel like the harder part of the job wasn't forking which music is supposed to play, but to have the ability to completely stop and then restart the song you last played.

Given that OP is a competent mapper, and knows the principle, but fails somewhere along the way, maybe it would be worth it to extend the demo map to include that.




Mar 29 2017, 6:41 am Pr0nogo Post #14



While I appreciate everyone's efforts, I am going to wait on the remastered update before pursuing something like this, since much of it may change significantly if the behavior of waits are at all different.




Mar 29 2017, 12:44 pm Azrael Post #15



Quote from NudeRaider
I feel like the harder part of the job wasn't forking which music is supposed to play, but to have the ability to completely stop and then restart the song you last played.
I'm not sure what you mean. If you've used the demo map, could you give a specific example related to it?

The map does this: "I need a system that will play wavs in sequence, and keep track of that sequence externally so that it can be referenced later in order to play a fading-out version of the wav that's up next. e.g. the system plays the first six wavs, but the player triggers the fade-out in the middle of the sixth wav, so instead of playing the regular seventh wav, the system would play a version of the seventh wav that's been faded out. The idea is to make the system dynamic enough to fade different songs out if the player enters an area that has a different song associated with it, or if they trigger a cutscene that has its own song."

Quote from Pr0nogo
While I appreciate everyone's efforts, I am going to wait on the remastered update before pursuing something like this, since much of it may change significantly if the behavior of waits are at all different.
Not a terrible idea since we don't know what the update's going to change, although it should be noted that the demo map doesn't use Wait actions (outside of hyper triggers). If hyper triggers get killed by the update then most UMS maps from the last 15 years will break, so hopefully that won't be the case.

Post has been edited 1 time(s), last time on Mar 29 2017, 1:00 pm by Azrael.




Mar 29 2017, 10:54 pm lil-Inferno Post #16

Just here for the pie

Quote from Azrael
snip
Thanks for putting in the effort there, I bet people in the future who have a similar question will find it to be a valuable resource. I'm guessing you recycled the system from Autocracy?




Mar 30 2017, 7:18 pm Azrael Post #17



Quote from lil-Inferno
Thanks for putting in the effort there, I bet people in the future who have a similar question will find it to be a valuable resource.
No problem :)

Quote from lil-Inferno
I'm guessing you recycled the system from Autocracy?
Yeah, I took some time to rip out relevant parts from Autocracy RPG and retooled them to be used in the demo map. I already had the trigger timings and audio editing done, so when I saw this question I thought it'd be a waste to not make a functional example.

Anyways, I'm glad you liked the demo ^^

Post has been edited 2 time(s), last time on Mar 30 2017, 7:38 pm by Azrael.




Apr 22 2017, 9:30 pm Dungeon-Master Post #18



I doubt they'll toy with anything that has to do with timings and wait actions, they aren't looking to change anything about the engine.

If they do, may Tuxlar have mercy for our poor souls.



None.

Options
  Back to forum
Please log in to reply to this topic or to report it.
Members in this topic: None.
[10:41 am]
v9bettel -- Nice
[01:39 am]
Ultraviolet -- no u elky skeleton guy, I'll use em better
[10:50 pm]
Vrael -- Ultraviolet
Ultraviolet shouted: How about you all send me your minerals instead of washing them into the gambling void? I'm saving up for a new name color and/or glow
hey cut it out I'm getting all the minerals
[10:11 pm]
Ultraviolet -- :P
[10:11 pm]
Ultraviolet -- How about you all send me your minerals instead of washing them into the gambling void? I'm saving up for a new name color and/or glow
[2024-4-17. : 11:50 pm]
O)FaRTy1billion[MM] -- nice, now i have more than enough
[2024-4-17. : 11:49 pm]
O)FaRTy1billion[MM] -- if i don't gamble them away first
[2024-4-17. : 11:49 pm]
O)FaRTy1billion[MM] -- o, due to a donation i now have enough minerals to send you minerals
[2024-4-17. : 3:26 am]
O)FaRTy1billion[MM] -- i have to ask for minerals first tho cuz i don't have enough to send
[2024-4-17. : 1:53 am]
Vrael -- bet u'll ask for my minerals first and then just send me some lousy vespene gas instead
Please log in to shout.


Members Online: Roy, Excalibur