float LOUDNESS = 1.0;
integer SHORTEST = 10;
integer LONGEST = 600;

float   c_check_interval=0.5;
integer s_running_timers=0;
list    s_timers_nexts=[];
list    s_timers_intervals=[];
startTimer(integer x_id,float x_interval){
    integer shift=1<<x_id;
    if(s_running_timers==0)llSetTimerEvent(c_check_interval);
    if(!(s_running_timers&shift)){
        while(llGetListLength(s_timers_nexts)<=x_id){s_timers_nexts+=0.0;s_timers_intervals+=60.0;}
        s_timers_nexts=llListReplaceList(s_timers_nexts,[llGetTime()+x_interval],x_id,x_id);
        s_timers_intervals=llListReplaceList(s_timers_intervals,[x_interval],x_id,x_id);
        s_running_timers=s_running_timers|shift;
    }
}
stopTimer(integer x){//
    integer shift=1<<x;
    if(s_running_timers&shift)s_running_timers=s_running_timers&(~shift);
    if(s_running_timers==0)llSetTimerEvent(0);
}
quickTimer(integer x){
    s_timers_nexts=llListReplaceList(s_timers_nexts,[llGetTime()],x,x);
}
restartTimer(integer x){
    if(s_running_timers&(1<<x)){
        stopTimer(x);
        startTimer(x,llList2Float(s_timers_intervals,x));
    }
}
integer checkTimer(integer x_timer){
    if(s_running_timers&(1<<x_timer)){
        float now=llGetTime();
        float next=llList2Float(s_timers_nexts,x_timer);
        if(now>next){
            float interval=llList2Float(s_timers_intervals,x_timer);
            next=next+interval;
            if(now>next+interval)next=now+interval;
            s_timers_nexts=llListReplaceList(s_timers_nexts,[next],x_timer,x_timer);
            return 1;
        }
    }
    return 0;
}

default
{
    changed(integer change) {
     if (change & (CHANGED_REGION_START | CHANGED_REGION)) {     
            llResetScript();
        }
}

state_entry()
{
    if (SHORTEST < 10 )     SHORTEST = 10;
    if (LONGEST < 10 )      LONGEST = 10;
    if (SHORTEST > LONGEST) SHORTEST = LONGEST;
    
    startTimer(1, 1.0);
}
timer() {
        if(checkTimer(1)) {
                stopTimer(1);
                state noisy;
        }       
    }

on_rez(integer start_param)
{
    startTimer(1, 1.0); 
}

}

state noisy
{
     changed(integer change) {
        if (change & (CHANGED_REGION_START | CHANGED_REGION)) {     
            state default;
        }
    }

state_entry()
{ 

    vector sun_point = llGetSunDirection();
    if ( sun_point.z < 0.0 ) state silent;
    
    integer sounds = llGetInventoryNumber(INVENTORY_SOUND);
    if ( sounds <= 0 ) state default;

    string soundname = llGetInventoryName( INVENTORY_SOUND, llFloor(llFrand(sounds)) );
    if ( soundname != "" )
    {
        llPlaySound( soundname, LOUDNESS );
    }
    
    state silent;
}

on_rez(integer start_param)
{
    state default;
}

}

state silent
{
     changed(integer change) {
        if (change & (CHANGED_REGION_START | CHANGED_REGION)) {     
            state default;
        }
    }

state_entry()
{    
    startTimer(1, (float)(llFloor(llFrand(LONGEST - SHORTEST)) + SHORTEST));  
    }
     timer() {
        if(checkTimer(1)) {
                stopTimer(1);
                state noisy;
        }      
}

on_rez(integer start_param)
{
    state default;
}

}