I've written these instructions as plainly as I know how, so don't ask me to help you set it up! Also, I will not give you any music to play through this, so don't ask.
Purpose
This can be used to play a sound clip from multiple prims in perfect synchronization. The speaker prims HAVE to all be linked together for this to work. The player is in its own separate prim. It chats the keys of sound to be played on a private channel. (That is the SNDCHAN variable in two of the scripts below - you'll want to change it to something harder to guess.)
Player
First, the player. Put your sound clips into a prim. The sound clip names should be set up alphabetically, so that they play in the correct order, i.e.:
Cool_Song_clip0
Cool_Song_clip1
Cool_Song_clip2
BEFORE you copy the sounds into the player prim, you will need to open them in your inventory and set full permissions on them. This is so that they can be played by prims other than those they are in.
etc...
In that same prim, put this script:
CODE
// The Sound of Music
// Original script by Sausage Turner (posted here with his permission)
// Modified to work with sound slave functions by Huns Valen
integer clips;
integer toggle = TRUE;
float clip_length = 10;//in seconds
float last_clip_length = 6;//length of last clip in seconds
integer cycle;
integer SNDCHAN = -12345;
string TenSecsQuiet = "634ad819-1b04-51de-dccd-696a670cd64d";
init() {
toggle = TRUE;
llSetTimerEvent(0);
llSetSoundQueueing(FALSE);
llStopSound();
llTargetOmega(<0,0,1>,1,1);
llSay(0,"Loading clip 1 please wait.");
llSetSoundQueueing(TRUE);
clips = llGetInventoryNumber(INVENTORY_SOUND);
llPreloadSound(llGetInventoryName(INVENTORY_SOUND,0));
llSleep(clip_length);
llLoopSoundMaster(TenSecsQuiet, 1);
llSay(0,"Touch to start.");
}
default {
state_entry() {
init();
}
on_rez(integer param) {
init();
}
touch_start(integer total_number) {
if(llDetectedKey(0)!=llGetOwner())
return;
if(toggle){
toggle = FALSE;
llSay(0,"Starting Player");
llSetSoundQueueing(TRUE);
llSay(SNDCHAN, (string)llGetInventoryKey( llGetInventoryName(INVENTORY_SOUND,0)));
llSay(SNDCHAN, (string)llGetInventoryKey( llGetInventoryName(INVENTORY_SOUND,0)));
//llTriggerSound(llGetInventoryName(INVENTORY_SOUND,0),1);
llPreloadSound(llGetInventoryName(INVENTORY_SOUND,1));
cycle = 1;
llSetTimerEvent(clip_length/2);
} else {
toggle = TRUE;
llSetTimerEvent(0);
llSay(0,"Player Stopped");
llSetSoundQueueing(FALSE);
llStopSound();
}
}
timer() {
if(cycle < clips ){
llSay(SNDCHAN, (string)llGetInventoryKey( llGetInventoryName(INVENTORY_SOUND,cycle)));
// llPlaySound( llGetInventoryName(INVENTORY_SOUND,cycle),1);
cycle = cycle + 1;
if(cycle < clips){
llSetTimerEvent(clip_length);
llPreloadSound( llGetInventoryName(INVENTORY_SOUND,cycle));
} else {
llSetTimerEvent(0);//last_clip_length);
llPreloadSound( llGetInventoryName(INVENTORY_SOUND,0));
}
}
else {
llSetTimerEvent(clip_length);
llSay(SNDCHAN, (string)llGetInventoryKey( llGetInventoryName(INVENTORY_SOUND,0)));
// llPlaySound( llGetInventoryName(INVENTORY_SOUND,0),1);
llPreloadSound( llGetInventoryName(INVENTORY_SOUND,1));
cycle = 1;
}
}
}
Now, that will be your sound player. It is separate from the "speaker" prims, so that you can have multiple players driving the same speakers at different times.
Speakers
In the ROOT PRIM of the speakers, put this script:
CODE
// Speakers, Root Prim
// By Huns Valen
integer SNDCHAN = -12345;
default {
state_entry() {
llListen(SNDCHAN, "", "", "");
}
listen(integer chan, string name, key id, string msg) {
llMessageLinked(LINK_SET, 0, msg, "");
}
}
In every prim in the speaker set that you want to act as a speaker, put this script:
CODE
// Speakers, put this in whatever prim you want to act as a speaker
// By Huns Valen
float volume = 1;
default {
state_entry() {
llSetSoundQueueing(TRUE);
}
link_message(integer snum, integer num, string str, key id) {
llPlaySoundSlave(str, volume);
}
}