Jump to content
rekkless

How to make music loop

Recommended Posts

Ok so I've searched everywhere for a proper example on how to efficiently make music loop.

I have a track that is actually ambient sounds that goes for 6:15.

 

at the end of the 6 minutes and 15 seconds I want to track to replay and keep replaying until the end of the mission.

Now I would specifically like it to be classed as a music track so players can adjust the volume using their music volume controls instead of sound effect controls.

 

That was plays can have the option of turning the ambient sounds all the way off, just down a little or have them full blast.

I have the music set up already

 

Music 1 in a music folder

 

and I have the music set up already in the description:
 

 class CfgMusic {
    tracks[]={};

class music1
{name = "music1"; sound[] = {"\music\music1.ogg", db+3, 1.0};
    };
};

and I know how to get it to play using a trigger. The problem is getting it to loop once the track has finished. Can anyone point me in the right direction please.

Share this post


Link to post
Share on other sites

A simple loop like this:

my_music_handle = [] spawn
	{
	while {true} do
		{
		playMusic "music1";
		sleep 675
		}
	};

may be pasted in the any place in the code, you want, or eg in the trigger's exec/act window to start, when required. Pause is in seconds, may be longer, if interval is required.

 

my_music_handle additionally may be used to terminate the loop any time from any place:

terminate my_music_handle;

Another way involves this EH

Share this post


Link to post
Share on other sites

A simple loop like this:

my_music_handle = [] spawn
	{
	while {true} do
		{
		playMusic "music1";
		sleep 675
		}
	};

may be pasted in the any place in the code, you want, or eg in the trigger's exec/act window to start, when required. Pause is in seconds, may be longer, if interval is required.

 

Where do I post this? In the trigger?

I would like the ambient music to start 3 minutes after spawn and continue to play until the end of the mission. The current track is 6 minutes 15 seconds.

Share this post


Link to post
Share on other sites

 

 

may be pasted in the any place in the code, you want, or eg in the trigger's exec/act window to start, when required. 

 

So, if you paste in into the trigger, all to do is set properly condition of this trigger to be activated 3 minutes after mission start:

time > 180;

Note, if this is for multiplayer mission, some things may differ - MP can make simple things difficult, so it's important to point, if this is SP or MP. My assumption always is SP.  Not sure about MP - ask someone else in such case. 

Share this post


Link to post
Share on other sites

So, if you paste in into the trigger, all to do is set properly condition of this trigger to be activated 3 minutes after mission start:

time > 180;

Note, if this is for multiplayer mission, some things may differ - MP can make simple things difficult, so it's important to point, if this is SP or MP. My assumption always is SP.  Not sure about MP - ask someone else in such case. 

 

Yeah sorry I missed that part. So far so good, thanks mate.

Can you tell me what the Sleep 675 means?

If I should choose to change the track to something else other than renaming the new track to music1 is there anything else I need to do?

Share this post


Link to post
Share on other sites

Sleeping for 675 seconds does not guarantee that after 675 seconds the scope will end, it could be 765 seconds for example or 699 or.. this is very very very unreliable and I would advise not to do this. Instead there is a dedicated Music EH that can execute given code EXACTLY when music stops

 

https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#addMusicEventHandler

  • Like 1

Share this post


Link to post
Share on other sites

 

 

Can you tell me what the Sleep 675 means?

 

It means: wait 675 seconds before go further. It's inside infinite loop, so the logic is:

 

"Ad infinitum" do following: 1. Play music track; 2. Wait 675 seconds.

 

So the code will repeat subsequently these two steps all the time, till end of mission or terminating whole code. 

Share this post


Link to post
Share on other sites

 

 

Sleeping for 675 seconds does not guarantee that after 675 seconds the scope will end, it could be 765 seconds for example or 699 or.. this is very very very unreliable

 

So far worked just fine for me. May be enough for simplicity - why to complicate. From the other hand, music EH sometimes failed for me in my tests, so not sure, what's more reliable. Let him try simplier way first. 

Share this post


Link to post
Share on other sites

 

 

If I should choose to change the track to something else other than renaming the new track to music1 is there anything else I need to do?

 

With "sleep method" obviously the lenght of the sleep should be adjusted to fit the song length. For music EH way - not required. In this way code awaits specifically for the end of playing music instead of awaiting given amount of time. Exemplary approach would be then:

ehID = addMusicEventHandler ["MusicStop", {music_isPlaying = false}];

my_music_handle = [] spawn
	{
	while {true} do
		{
		music_isPlaying = true;
		playMusic "music1";
		waitUntil
			{
			sleep 1;
			
			not music_isPlaying
			}
		}
	};

Share this post


Link to post
Share on other sites

IIRC, play your music as an environment sound through a trigger.

Use the extra screen in the trigger screen - Effects button then choose "environment" (3rd list in this arma 2 screen: https://community.bistudio.com/wikidata/images/0/04/Arma2_editor_effects.jpg).

 

 

The file will be looped until the end of the mission.

Share this post


Link to post
Share on other sites

 

With "sleep method" obviously the lenght of the sleep should be adjusted to fit the song length. For music EH way - not required. In this way code awaits specifically for the end of playing music instead of awaiting given amount of time. Exemplary approach would be then:

ehID = addMusicEventHandler ["MusicStop", {music_isPlaying = false}];

my_music_handle = [] spawn
	{
	while {true} do
		{
		music_isPlaying = true;
		playMusic "music1";
		waitUntil
			{
			sleep 1;
			
			not music_isPlaying
			}
		}
	};

 

Why so complicated?

ehID = addMusicEventHandler ["MusicStop", {playMusic "music1";}];

Share this post


Link to post
Share on other sites

Works for me just fine and is much simpler than using unreliable sleep:

addMusicEventHandler ["MusicStop", {playMusic ["RadioAmbient3", 8]}]; playMusic ["RadioAmbient3", 8];

Share this post


Link to post
Share on other sites

 

 

Why so complicated?

 

In this particular case - redundant indeed. Examples by me was pasted from something more complex and adapted for required use. 

 

 

 

The file will be looped until the end of the mission.

 

If so, that would be a simpliest way for someone, that don't want to hassle with any scripting.

Share this post


Link to post
Share on other sites

Things I forgot about envSound:

Those are looped until the end of the mission BUT they are not music, you need to put them in class CfgEnvSounds.

I don't think you can manually adjust the sound through the music slider (or script command).

 

rekkless, do you need your environment music to be less loud when indoor ? If yes, I have a small script, courtesy of JSRS, that does the detection and lower the music level.

Share this post


Link to post
Share on other sites

Things I forgot about envSound:

Those are looped until the end of the mission BUT they are not music, you need to put them in class CfgEnvSounds.

I don't think you can manually adjust the sound through the music slider (or script command).

 

rekkless, do you need your environment music to be less loud when indoor ? If yes, I have a small script, courtesy of JSRS, that does the detection and lower the music level.

 

There is always https://community.bistudio.com/wiki/setMusicEffect

Share this post


Link to post
Share on other sites

A copy paste of Antistasi's situational music script, may be useful:

_normaldia = ["LeadTrack01_F", "LeadTrack01a_F", "LeadTrack01b_F", "LeadTrack02_F", "AmbientTrack03_F", "BackgroundTrack01_F", "BackgroundTrack01a_F", "Track02_SolarPower"];
_normalnoche = ["Track08_Night_ambient", "Track09_Night_percussions","Track11_StageB_stealth"];
_combat = ["LeadTrack03_F", "LeadTrack04_F", "LeadTrack04a_F", "LeadTrack05_F", "BackgroundTrack03_F", "Track01_Proteus", "Track07_ActionDark","Track10_StageB_action"];
_stealth = ["LeadTrack06_F", "AmbientTrack01_F", "AmbientTrack01a_F", "AmbientTrack01b_F", "AmbientTrack04a_F", "AmbientTrack04_F", "Track04_Underwater1","Track05_Underwater2"];


_stance = behaviour player;
_newstance = _stance;
cambioMUS = true;
_cancion = "LeadTrack01_F";


while {musicON} do

	{
	sleep 3;
	_newstance = behaviour player;
	//hint format ["El jugador está en esta stance: %1", _newstance]; sleep 3;
	if ((_newstance != _stance) or (cambioMUS)) then
		{
		removeAllMusicEventHandlers "MusicStop";
		_stance = _newstance;
		if (_newstance == "COMBAT") then
			{
			_cancion = _combat call BIS_Fnc_selectRandom;
			cambioMUS = true;
			};
		if (_newstance == "STEALTH") then
			{
			_cancion = _stealth call BIS_Fnc_selectRandom;
			cambioMUS = true;
			};
		if ((_newstance == "AWARE") or (_newstance == "SAFE")) then
			{
			if ((daytime > 18) or (daytime < 6)) then
				{
				_cancion = _normalnoche call BIS_Fnc_selectRandom;
				cambioMUS = true;
				};
			if ((daytime > 5) or (daytime < 19)) then
				{
				_cancion = _normaldia call BIS_Fnc_selectRandom;
				cambioMUS = true;
				};
			};
		5 fadeMusic 0;
		};

	if (cambioMUS) then
		{
		_EH = addMusicEventHandler ["MusicStop", {cambioMUS = true}];
		cambioMUS = false;
		sleep 5;
		1 fadeMusic 0.5;
		playmusic _cancion;
		};
	if (!musicON) then
		{
		1 fadeMusic 0.5;
		sleep 0;
		playMusic "";
		};
	};

musicON is the variable that turns on or off the music, use radio trigger, dialog or whatever. On act: musicON = true and execute the script, on deact: musicON = false;

 

Don't know if it's good or not, but worked for ages.

  • Like 1

Share this post


Link to post
Share on other sites

Oh boy, you guys have posted a lot of information and I'm not sure I'm any more clear on what to do than before.

The "track" (it isn't music but ambient sound) i want to be controlled by the players music volume not their sound effects volume.

 

I want the track to start 3 minutes after the mission has started and repeat until the end of the mission. Terminating the track is not necessary I just need it to efficiently and reliably keep playing after all like I said it is ambient sounds.

 

the track goes for 6 minutes and 15 seconds.

 

 

What exactly do I have to put in the trigger to make "Music1" (the ambient sound) play and repeat. and if I don't post the code in the trigger where do I post it?

 

 

If I post this in the activ part of the trigger with a delay of 180 seconds will the track "music1" play and repeat?

ehID = addMusicEventHandler ["MusicStop", {playMusic "music1";}];

Share this post


Link to post
Share on other sites

 

 

If I post this in the activ part of the trigger with a delay of 180 seconds will the track "music1" play and repeat?

 

To be exact: like killzone_kid pasted:

ehID = addMusicEventHandler ["MusicStop", {playMusic "music1";}];playMusic "music1";

Because "MusicStop" awaits, till... music stops :) before will run contained code, so you have to run the music once after adding this music EH, or "musicStop" will have no opportunity to be activated due to lack of music playing.

 

That one indeed should be best for your use. 

 

 

 

and if I don't post the code in the trigger where do I post it?

 

Init.sqf is usual way. Just

 

1. go to your mission foler saved by editor,

2. create a new text file there,

3. paste directly such code into this file:

sleep 180;

ehID = addMusicEventHandler ["MusicStop", {playMusic "music1";}];playMusic "music1";

or, if you too don't trust "sleep", alternatively:

waitUntil
	{
	sleep 1;
	
	(time > 180)
	};

ehID = addMusicEventHandler ["MusicStop", {playMusic "music1";}];playMusic "music1";

4. save, then rename the file to init.sqf

 

3 and 4 order can be swapped, sqf files may be edited via notepad. 

Share this post


Link to post
Share on other sites

I've written a simple script for looping and randomizing music. It works really well and you can just execute it again with different arguments so you can use it in triggers to change between calm/suspicious/battle music... etc. It's old, so the writing is messy but it works.

 

private "_track";
private "_previous";
private "_random";
private "_tracknumber";

_fade = 1.5;						// set the fade duration
_tracks = _this select 0; 				// tracks array
_repeat = _this select 1; 				// Play indefinitely? true/false
_onload = _this select 2; 				// Play after loading a save? true/false
if (count _this > 3) then  {_random = _this select 3}; 	// 0 = seqence, 1 = random track each time, 2 = random track repeatedly
if (count _this > 4) then  {_previous = _this select 4}; // define this to start from the next track / other random track, otherwise do not define it

/*
examples for in-game use: 
_nul = [["track1", "track2", "track3"], false, true, 1, "track2"] execVM "music.sqf" - randomly play a track, also play it after a save is loaded
_nul = [["track1", "track2", "track3"], true, true] execVM "music.sqf" - play all tracks sequentially until overwritten or aborted with playmusic ""
*/

if (typeName _tracks != "ARRAY") then {_tracks = [_tracks]};
if (isNil "_random") then {_random = 0};
if (isNil "_previous") then {if (_random == 0) then {_previous = _tracks select (count _tracks - 1)} else {_previous = selectRandom _tracks};};

switch (_random) do {
	case 0: {
		_tracknumber = (_tracks find _previous) + 1;
		if (_tracknumber > count _tracks - 1) then {_tracknumber = 0};
		_track = _tracks select _tracknumber;
	};
	case 1: {if (count _tracks > 1) then {_track = selectRandom (_tracks - [_previous])} else {_track = _tracks select 0};};
	case 2: {_track = _previous;};
	default {hint "Music Error"};
};

//hint format ["Tracklist: %1\nCurrent track: %2\nPrevious track: %3\nList progress: %4/%5\nRandom: %6", _tracks, _track, _previous, (_tracks find _track) + 1, count _tracks, _random]; // debug

removeAllMusicEventHandlers "MusicStop";
removeAllMissionEventHandlers "Loaded";

if (_repeat) then {call compile format ["addMusicEventHandler ['MusicStop',{[%1, %2, %3, %4, '%5'] execVM 'music.sqf';}]", _tracks, _repeat, _onload, _random, _track];};
if (_onload) then {call compile format ["addMissionEventHandler ['Loaded',{[%1, %2, %3, %4, '%5'] execVM 'music.sqf';}]", _tracks, _repeat, _onload, _random, _track];};

[_fade, _track] spawn {(_this select 0) fademusic 0; sleep ((_this select 0) + 0.2); playmusic format ["%1",(_this select 1)]; (_this select 0) fademusic 1;};

Share this post


Link to post
Share on other sites

Awesome thread eventhandler works like a charm.  

I have it set up where upon entering and leaving a house the music is played on loop.  

Once I leave the house I fade the music to 0.  However once the other music at the objectives is finished playing it reverts back to the music loop I have reserved for only inside the house....

Any ideas?  

Share this post


Link to post
Share on other sites

Just to complete this good collection, there is also the script Cly_Jukebox by @celery. Awesome script - playlist, looping, random order and it does even resume the track when loading a saved game.

 

(sorry @badpr1m3r, I didn't really reply to your post...)

Share this post


Link to post
Share on other sites

I know you already figured it out with the music eh but just wanted to throw this out there. 

iirc sleep is unreliable when using large numbers. I believe this is the best way to call a long sleep.

 

for "_i" from 1 to 180 do 
{
	sleep 1;
};

 

  • Like 1

Share this post


Link to post
Share on other sites
On 11/23/2015 at 4:23 PM, killzone_kid said:

Works for me just fine and is much simpler than using unreliable sleep:


addMusicEventHandler ["MusicStop", {playMusic ["RadioAmbient3", 8]}]; playMusic ["RadioAmbient3", 8];

 

"Error, invalid number in expression"

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

×