Jump to content
Sign in to follow this  
MajorModz

Need music looping solution

Recommended Posts

I have areas where I want looping theme music, easy right ?

I can either hard code a trigger to do the work, or I can execute an external script from within the trigger.

Player enters trigger area, music fades in, music plays, music loops as expected, music fades on exiting trigger area.

Problem: Player exiting the trigger area and returning before the sleep timer is complete causes the next playback (or loops if the player bounced in and out of the trigger area more then once) to be cut short by the duration the player was outside the trigger area. Looping then returns to normal.

I've tried assigning a value to the sleep timer, then resetting it when the player leaves the trigger area. I've tried to terminate script; both from the trigger de act and from within the external script itself (if I use external scripting).

I'm looking for a simple way to start and stop the looping so that every time the player enters or re-enters the area, the trigger and script are fresh. You'd think that calling to terminate an executed external script would do the trick, but nope.

Seems odd that in my searching of "loop music" I have never seen anyone note this issue.

Edit:

Nero WaveEditor is a very nice tool for creating your sound files. It allows direct manipulation of the sample ie. pitch / stretch / effects, etc. and saves files to .ogg!

Edited by MajorModz
Useful information added

Share this post


Link to post
Share on other sites

Quick and dirty, but at least it does work: ;)

// Music_Trigger.sqf
// by Wiggum
// nul=[unit, name of trigger, "Music", fadetime] execVM "Music_Trigger.sqf";


if !(isServer) exitWith {};
private ["_musicover","_unit","_musicarea","_trigger","_mymusic","_fadetime"];

_unit = _this select 0;
_trigger = _this select 1;
_mymusic = _this select 2;
_fadetime = _this select 3;

_musicarea = list _trigger;
_musicover = 0;
0 fadeMusic 0;

while {true} do {
if ((_musicover == 0) && (_unit in _musicarea)) then {
_musicover = 1;
playmusic _mymusic;
_fadetime fadeMusic 1;
sleep _fadetime + 1;
waitUntil {!(_unit in _musicarea)};
_musicover = 0;
_fadetime fadeMusic 0;
sleep _fadetime + 1;
waitUntil {(_unit in _musicarea)};
};
};

EDIT: Ups, you want to loop the music...mhh thats a bigger problem then...

You would need a command to detect if the music is over, with a simple sleep it will not work.

Edited by Wiggum

Share this post


Link to post
Share on other sites
you want to loop the music...mhh thats a bigger problem then

Yeh, looked like a fastball....turned out to be a slider!

Just talking pure asthetics here. But then isn't that what it's really all about?

The joy I experienced from learning how easy it was to loop sound/music lasted approximately 1 minute and 46 seconds. Followed by two days of hair pulling and cursing. Crunching code while I sleep is exhausting....*sigh*

Perhaps I should just stick to my favorite motto's

1: If at first you don't succeed, give up and move on to something else.

2: Aim for the ditch, it's hard to miss.

Interesting to have commands like "playmusic" and "playsound" without the corresponding opposites "stopmusic" and "stopsound". A fademusic command executed on a running sound loop using sleep does not stop the player, you just can't hear it anymore haha.

Pure logic

Place a repeatable trigger.

Trigger on act:

music = true;

[] execvm musicloop.sqf; // standard while true playmusic sleep

Trigger on deact:

music = false;

terminate musicloop;

I guess that's just to damn logical?

Apparently you can't terminate a script that is sleeping? Even from outside the script?

Edit

Take a look at this script, maybe it works for you:

http://forums.bistudio.com/showthread.php?t=108535&highlight=jukebox

I've seen that, but I got scared and ran away. I think I used the words "easy" and "simple" in my first post.

I'm not looking for new issues, I already have one!

Edited by MajorModz
new reply

Share this post


Link to post
Share on other sites

Maybe you can terminate the music by playing silence. Create a half second of silence with Audacity or whatever sound software and play that to terminate the sound that is currently playing.

I have no idea if that works but seems like it should.

Edited by twirly
Added link to Audacity

Share this post


Link to post
Share on other sites

First, make sure you read this thread, it may have your solution or at least give you some insight:

Localized Sound

As I mentioned in that thread, the only way I have been able to interrupt a sound loop is to use the say command (normally from a game logic) and then delete the logic when the sound is supposed to stop. Of course, you then have to re-create the object and use the say command again to start it again. This is how I stop and then re-start transformer humming in my electrical grids scripts.

I can post some example code if you are interested.

Share this post


Link to post
Share on other sites

@ twirly,

I've actually done something like that. Playmusic ""; with no file name starts a new instance, and I believe terminates the 1st....and since there's no file name it terminates immediately.

Reading through some of the older threads I saw a lot of folks complaining about multiple instances of "playmusic" running simultaniously when they didn't get the code syntax correct. But it would seem only one instance of "playmusic" is allowed in the later versions Arma 2? I haven't had any reason to try running more then one instance of "playmusic" so I'm not sure about this.

My issue is having the trigger deactivated and then re-activated before the sleep timer in the loop has cycled. Which causes the next instance of "playmusic" to cut short the audio by an amount of time equal to how long the activating unit was outside the trigger area. Assuming the activating unit was outside the trigger area for less time then remained in the sleep line. This would not be an issue if I could simply "terminate" the script from the trigger de-act.

Again let me state that this is pure asthetics. Having the music cut-out even once is undesirable.

I've even tried various "if", "then", "else" combinations from the trigger and within the playmusic.sqf......with no satisfactory results.

@ Loyalguard,

An interesting read, but you must remember that in the "code pool" I'm the guy in the shallow end with the floaties on his arms! Most of this stuff looks like Chinese to me. One look at my Avatar should say it all.....that's me trying to decipher a block of code!

Arma 2 Free is my first experience with a BIS product. It and this community will be major factors in my descision to purchase future BIS products. It's like test driving a new car. No matter how much I like the vehicle, if I can't even turn on the radio then chances are I'm not gonna buy it.

Thanks guys for the input.

Edited by MajorModz

Share this post


Link to post
Share on other sites

Another try:

EDIT: ...does not work too.

Edited by Wiggum

Share this post


Link to post
Share on other sites

Here is what I'm trying to do.

Trigger on act: music = true; nul = [] execvm "music1.sqf";

Trigger on deact: music = false;

music1.sqf

scopename "start";

while {true} do {playmusic "score"};

a = 1;

scopename "loop";

if (false) then {terminate music1};

a + 1;

b = a;

sleep 1;

if (b > 144) then {breakto "start"} else {breakto "loop"};

This script should play the music and then check every second to see if the trigger has been deactivated, at which time it will terminate the script. After 143 seconds it should play the music again and repeat the proccess until the trigger has been deactivated/false.

I understand the the code but don't know how to structure it. Can anybody type this out in proper form please. Thank you.

Edited by MajorModz

Share this post


Link to post
Share on other sites
Most of this stuff looks like Chinese to me.

Actually, Chinese is easier than this Scripting stuff.:eek:

Share this post


Link to post
Share on other sites

I got it... :D

// MusicLoop_Trigger.sqf
// by Wiggum
// Make a trigger and name it, as condition use whatever you want (the presence of the unit which will trigger the music loop for example), no need to make him activate repeatedly !
// In the "On Act" field of the trigger:
// nul=[unit, name of trigger, "Music", tracktime, fadetime] execVM "MusicLoop_Trigger.sqf";


if !(isServer) exitWith {};
private ["_unit","_musicarea","_trigger","_mymusic","_fadetime","_tracktime","_i"];

_unit = _this select 0;
_trigger = _this select 1;
_mymusic = _this select 2;
_tracktime = _this select 3;
_fadetime = _this select 4;

_musicarea = list _trigger;
0 fadeMusic 0;
_i = 0;

scopeName "main";
while {true} do {
scopeName "Play";
while {true} do {
if ((_unit in _musicarea) && (_i < (_tracktime - _fadetime))) then {
if (_i == 0) then {
playmusic _mymusic;
_fadetime fadeMusic 1;
};
sleep 1;
_i = _i + 1;
};
if (((_unit in _musicarea) && (_i == (_tracktime - _fadetime))) || !(_unit in _musicarea)) then {breakTo "Play"};
};
// If unit is inside the trigger area and the music track is nearly over or if he is out of the area then fade out and terminate the music
_i = 0;
_fadetime fadeMusic 0;
sleep _fadetime;
playmusic "";
// Wait until unit is inside the trigger area again or loop if he is still inside
waitUntil {_unit in _musicarea};
};

Edited by Wiggum

Share this post


Link to post
Share on other sites

Ok. So right away I'm wondering,

// Make a trigger, give him a name
Do you mean name the trigger or name the unit already known as "player"? If I go by your exact words, then I have a named trigger that can't be activated but has a condition, and on-act values? Thus a trigger that never runs the script because it's never active. Assuming I opt to activate the trigger in some manner, what would be your recommended method. By "side" or "grouped" to player; activation "vehicle"?

You are wanting me to rename items in these array to suit my specifications, except for "_i"?

// nul=[unit, name of trigger, "Music", tracktime, fadetime]

private ["_unit","_musicarea","_trigger","_mymusic","_fadetime","_tracktime","_i"]

If I rename these to my specs then the next problems are here.

_mymusic = _this select 2;

This would point to the 3rd item in the array with the value "_trigger"?

_tracktime = _this select 3;

this would point to the 4th item in the array with the value "_mymusic"?

I don't know enough about code to point out any further errors (should they exist). And I'm instictively aginst adding extra sound/music files to the folder. It has been my experience that simply starting a new "playmusic" command with nothing between the quotation marks serves the same purpose. Using the command in this manner gives no errors, and it self terminates immediately.

I'm very grateful for any time you've spent chewing on this issue. But a chunk of code this size to play some looping music seems absurd.

I might also mention again at this point, that this is a SP mission made in A2Free. So any extra code you may be using for other modes is only leading to the onset of your carpal tunnel syndrome. Thanks Wig for trying thus far.

Peek again at my previous post. I know the syntax is way off, but the logic is there. I just need to figure out how to get the script to check once per second to see if the trigger has been deactivated/false, and then to terminate. I'm not so much worried about the fades and such. Those can be manipulated in the trigger on act and deact's prior to and subsequent of the script.

It's freaking me out that a simple [0 + 1 per second repeat on (condition, "track length"), terminate script on (condition, "false")] block of code is impossible to write?

Perhaps you guys that have become accustomed to working on "Ferrari's" have forgotten how to work on the "lawnmower"? Maybe the artist who needs only to sketch an "apple", but instead paints a picture of an entire "fruit basket"?

---------- Post added at 12:56 AM ---------- Previous post was Yesterday at 11:59 PM ----------

Yes bro, you got it (with some minor corrections).

I will attempt to put it up.....

Trigger name: "music"

Trigger activated by: "grouped, vehicle", "once"

Condition: "none"

Trigger On Act.: nul = [player, music, "score", 144, 4] execVM "MusicLoop_Trigger.sqf";

// MusicLoop_Trigger.sqf
// by Wiggum


private ["player","music","score","144","4","_i"];

_unit = _this select 0;
_trigger = _this select 1;
_mymusic = _this select 2;
_tracktime = _this select 3;
_fadetime = _this select 4;

_musicarea = list _trigger;
0 fadeMusic 1;
_i = 0;

scopeName "main";
while {true} do {
scopeName "Play";
while {true} do {
if ((_unit in _musicarea) && (_i < (_tracktime - _fadetime))) then {
if (_i == 0) then {
playmusic _mymusic;
_fadetime fadeMusic 1;
};
sleep 1;
_i = _i + 1;
};
if (((_unit in _musicarea) && (_i == (_tracktime - _fadetime))) || !(_unit in _musicarea)) then {breakTo "Play"};
};
// If unit is inside the trigger area and the music track is nearly over or if he is out of the area then fade out and terminate the music
_i = 0;
_fadetime fadeMusic 0;
sleep _fadetime;
playmusic "";
// Wait until unit is inside the trigger area again or loop if he is still inside
waitUntil {_unit in _musicarea};
};

I removed the first line of code....dont know why?

I removed a value from the array.

Re-arranged the array and list #'s.

Changed the first fademusic from 0,0 to 0,1

And used playmusic "";...............works just like I said.

Though I dont understand how to format the syntax of the code, I do understand the funtion. The Basic I learned messing about on old Texas Intruments, Commodore, and Apple computers way back in they day helps.....Yikes, did I just date myself ?

Yeh, I owned an Atari 2600 the 1st year they came out. I musta been around 13 years old. The Commodore Vic20 was my first computer. Plus I worked on the first gen Apples in highschool. I was playing Wizardry on a IBM PC Portable that weighed 50 lbs and sported a monochrome screen before you were even born most likely.

The reason I was so adamant about proper loop funtion is, I plan on composing custom music tracks and sounds for my missions. I have a vintage Ensoniq ASR-10 sampling keyboard. If you know what that is, you should be jealous hehe.

Cheers Mate, You Rock !

Oh, I suppose somebody should Sticky his code (modified appropriately of course). It will actually play music without jacking it up!

Edited by MajorModz

Share this post


Link to post
Share on other sites
Ok. So right away I'm wondering, Do you mean name the trigger or name the unit already known as "player"? If I go by your exact words, then I have a named trigger that can't be activated but has a condition, and on-act values? Thus a trigger that never runs the script because it's never active. Assuming I opt to activate the trigger in some manner, what would be your recommended method. By "side" or "grouped" to player; activation "vehicle"?

Make a trigger, give him a name and as condition the presence of the unit (player or p1 or whatever the name is) which will trigger the music loop, no need to make him activate repeatedly !

So just name your trigger and how you activate him is up to you, most likely you will group your unit (player) with the trigger and make the condition "vehicle present".

You are wanting me to rename items in these array to suit my specifications, except for "_i"?

No, take a look at this:

http://community.bistudio.com/wiki/private

I don't know enough about code to point out any further errors (should they exist).

There were no errors in my script, you just added some with your changes (the private stuff)... ;)

I'm very grateful for any time you've spent chewing on this issue. But a chunk of code this size to play some looping music seems absurd.

If you find a way to do it with less code please tell me.

Sure you dont need the isServer stuff if its only SP but there is no reason to delete this line.

What is correct is that you dont seem to need another music file to terminate the music, playmusic ""; works the same way.

Edited by Wiggum

Share this post


Link to post
Share on other sites

Wow, thats odd because the script as presented, implemented as you described did not work for me. In fact the line you wanted me to put in the Trigger On Act field could not even be placed without returning "Missing ]" error.

Anyhow, "your script" that I re-did works perfectly.....exactly as you expected. I am using it as posted above.....while I type this.

So again, Thanks.

Edited by MajorModz

Share this post


Link to post
Share on other sites

Just take a look at it, the first line is from my description, the second is how i call the script and the last is how you call the script:

nul=[unit, name of trigger, "Music", tracktime, fadetime] execVM "MusicLoop_Trigger.sqf";

nul=[p1,t1,"EP1_Track12",30,10] execVM "MusicLoop_Trigger.sqf";

nul = [player, music, "score", 144, 4] execVM "MusicLoop_Trigger.sqf";

I cant see why you should get a "Missing ]" error, most likely just a copy&past issue by you. ;)

And yes, your deformed version works because all you did was making the "private" part useless, just delete the whole private [...]; line and it will still work.

Share this post


Link to post
Share on other sites

If I made a part of the script "useless" and it still works, am I safe in assuming that it was already "useless", and that I have done exactly this

If you find a way to do it with less code please tell me.

Excuse my stupidity, but what's with all the underscores. Is this more MP Mode jargon that can be done without?

I'm not knocking the script, it works and I'm impressed.

Share this post


Link to post
Share on other sites
Excuse my stupidity, but what's with all the underscores. Is this more MP Mode jargon that can be done without?

They denote local variables that can't used in other scripts.

Share this post


Link to post
Share on other sites
If I made a part of the script "useless" and it still works, am I safe in assuming that it was already "useless", and that I have done exactly this

Excuse my stupidity, but what's with all the underscores. Is this more MP Mode jargon that can be done without?

I'm not knocking the script, it works and I'm impressed.

No, just inform yourselfe about the basics of MP scripting, variables and the private command !

If it works for you that way and you are happy with it thats fine for me, but it sounded like my script was flawed and you fixed it which is not the case.

All you did was deleting/deforming the part of the script that makes it work in MP and keeps the variables local to the script.

Thats why it still works for you, just because as long as you only use the script (and its variables) once and in SP you will not notice that you did something wrong.

The "private" part of the script had a signification for the script (variable locality), but what you did with it was making it totally useless, thats why i told you to delete it completly. ;)

As long as you dont really understand sqf scripting you should not just delete stuff from scripts just because you think its useless...

EDIT:

Oh, no offense !

I hope you understand that i just try to help you. :)

EDIT:2

And you should not change 0 fadeMusic 0 to fadeMusic 1 !

This way the initial fade In will be...useless too.

Because if its already 1 ther is no point in fading it smoothly to 1.

Edited by Wiggum

Share this post


Link to post
Share on other sites

No, you da man a la mode with awesome sauce there's no doubt.

Just be aware, when a man asks for a hatchet and you hand him a chainsaw there could be trouble!

Am I the only one who has Napoleon Dynamite quotes running through my head every time I see Wiggums' avatar?

Share this post


Link to post
Share on other sites

Just be aware, when a man asks for a hatchet and you hand him a chainsaw there could be trouble!

Then you better ask what these lines actually do next time or just make sure there is no copy&past issue by you before you tell someone his script does not work for you.

So please just try the script i posted again and you will see it works even better then your badly deformed version...:p

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×