Accurate Audio Time (Milliseconds)

Hello,

I am trying to write a script that will trigger a new audio file at certain loop points within an original file if a key has been pressed (or some such event). In this case, the time of the original file has been divided by 6, and is just set to play the next section of music when it hits that time point, but seconds are not nearly accurate enough for a tidy loop, unless music is at 120bpm.

Is there another way?

Does audioSource output a flag when it loops or finishes?

var otherClip: AudioClip;
var playNow = false;
var segments = 6;

yield WaitForSeconds ((audio.clip.samples / 441000) / segments);
playNow = true;

function Update () 
{

 if(playNow)
 {
  audio.clip = otherClip; 
  audio.Play(); 
  playNow = false;
 }

}

Any help would be greatly appreciated.

thanks.

You can accurately set the starting point of a sound in audio.time or audio.timeSamples (this refers to the original sample rate), but Unity provided no means to set a stop or loop mark. You can stop it at certain time or sample count comparing the current audio.time or audio.timeSamples to the desired limit in FixedUpdate or Update, but there will always exist some uncertainty, since these functions are called at discrete time intervals (20mS for FixedUpdate, and fairly variable in Update). If you want to loop precisely, you must edit the sound to make it a seamless, continuous loop, and set Loop at the AudioSource. I use this to make ambient sounds, and call Play/Stop to use mute on/off to turn the sound on and off.

The AudioSource.isPlaying flag tells when the sound is playing. It can’t help in this loop feature, but is useful - for instance - to avoid start playing the sound again while it’s already playing. NOTE: it only works with Play; PlayOneShot or PlayClipAtPoint don’t affect audio.isPlaying.

EDITED: I think the best alternative is to have 3 separated audio files, and change the audio.clip variable when you want to play a different sound. It’s better for looped sounds, because they can play continuously without noticeable breaks. You could use the function below to fade out the current sound and start a new one (remember to clear or set audio.loop after calling this function, if necessary):

var sound1: AudioClip; // define the sounds in the Inspector
var sound2: AudioClip;
var sound3: AudioClip;

function FadeAndChange(newSound: AudioClip, fadeTime: float){
    var iniVol = audio.volume;
    for (var t:float = 1; t > 0; ){ // fade out cur sound during fadeTime seconds
        t -= Time.deltaTime/fadeTime;
        audio.volume = iniVol * t;
        yield; // return here next frame
    }
    audio.clip = newSound; // change to the new sound
    audio.volume = iniVol; // restore volume
    audio.Play(); // make sure the new sound is playing 
}

But if you want to have one single file and play different sections, you can use this:

var startSound1: int;   // set these variables in the Inspector
var endSound1: int;
var startSound2: int;
var endSound2: int;
var startSound3: int;
var endSound3: int;

var loop: boolean; // loops if true

private var startSound: int;
private var endSound: int;

// you can loop or just stop at the endSound with this code
function FixedUpdate(){
    if (audio.timeSamples >= endSound){
        if (loop){
            audio.timeSamples = startSound;
        } else {
            audio.Stop();
        }
    }
}

// use this function to fade out a segment and start a new one

function FadeAndChange(newStart: int, newEnd: int, fadeTime: float){
    var iniVol = audio.volume;
    for (var t:float = 1; t > 0; ){ // fade out current sound
        t -= Time.deltaTime/fadeTime;
        audio.volume = iniVol * t;
        yield; // return here next frame
    }
    startSound = newStart; // change to the new start/end
    endSound = newEnd;
    audio.volume = iniVol;  // restore volume
    audio.Play();
}