Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Running a looped soundtrack with intro

Discussion in 'Editor & General Support' started by Stagnant, Sep 2, 2013.

  1. Stagnant

    Stagnant

    Joined:
    Jan 21, 2013
    Posts:
    3
    I have a piece of music I'm trying to use as a soundtrack. I want to loop between the end of the track and a point midway through. However, I have no idea how to do this in Unity, as all that is offered is "loop", and I have no idea how to manually tell unity to jump to a certain point in the song via code. Any help would be much appreciated.
     
  2. Xane

    Xane

    Joined:
    May 16, 2013
    Posts:
    3
    It is puzzling to me too that barely any game engine nowadays has proper support of loop-point built-in forcing you to use 3rd party frameworks like FMOD to achieve something as simple as that.

    This is one of my top-requested features.
     
  3. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,684
    Why not download a free audio editor, create your loops, yourself.
     
  4. Stagnant

    Stagnant

    Joined:
    Jan 21, 2013
    Posts:
    3
    I did. I just don't know how to implement them. I could cut off the intro and make that it's own file, but I don't know how to tell the system to run that, then immediately start the part I want to have looped when that's done. That's what I'm asking for help with.
     
  5. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,303
    You can use AudioSource.timeSamples to seek to a position in the current audio clip associated with that source.

    If you're using 44100 sample rate, and you're playing at pitch 1.0 then seeking to 44100 would seek to the first second of the clip.
     
  6. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,303
    Code (csharp):
    1.  
    2. //Start playing the intro in half a second
    3. AudioSourceForIntoClip.PlayScheduled(0.5f);
    4. //Start playing the loop in (half a second + the length of the Intro)
    5. AudioSourceForLoopedClip.PlayScheduled(0.5f + AudioSourceForIntoClip.length);
    6.  
    http://docs.unity3d.com/Documentation/ScriptReference/AudioSource.PlayScheduled.html
     
    Last edited: Sep 4, 2013
  7. MrMetwurst2

    MrMetwurst2

    Joined:
    Jul 16, 2009
    Posts:
    253
    I'm working on a built in Music solution for Unity. Keep an eye out for UniTracker in the Asset Store in the near future.
     
  8. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,554
    I made a solution for this problem called Introloop. You don't even have to cut your audio into 2 pieces for this, just provide it the loop points and the rest will be handled. http://forum.unity3d.com/threads/378370/

    If you want to implement it yourself, the idea is you should have 2 AudioSources and do a baton-passing continuously. And you should use AudioSettings.dspTime-related function like AudioSource.PlayScheduled
    , AudioSource.SetScheduledEndTime and AudioSource.SetScheduledStartTime instead of coroutines or PlayDelayed.

    The first one play intro and immediately call SetScheduledEndTime on it to stop at the passing point. Where the second one is being SetScheduledStartTime-ed to start at that exact time, and SetScheduledEndTime to stop at the loop's end too. When the transfer is successful, the just-stopped first one should be waiting at the loop end point with SetScheduledStartTime to prepare for the next loop. Repeat for infinite loop. In my case I used 4 AudioSources to handle cross-fading between music with intro. (that's 2 pair of AudioSource)

    If you want to pause the music, things will get a bit more complicated because you need to cancel all the already-scheduled audio source, and reschedule them all on resume with regard to what time you are on now on the audio clip before pause. (On the development of my script I remembered having much trouble in pausing-resuming)
     
    forestrf likes this.
  9. Josiah_Kunz

    Josiah_Kunz

    Joined:
    Jun 8, 2017
    Posts:
    9
    This looks like it's still the only way to play audio with intro in 2023? (Correct me when I'm wrong!)

    Based on the advice from @Hikiko66 and @5argon even a slowpoke like me went from 0 to working in 30 minutes using the Unity API:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. /// <summary>
    4. /// A script that plays the intro <see cref="AudioClip"/> and, after <see cref="introToLoopDelay"/> seconds,
    5. /// plays the loop <see cref="AudioClip"/> on repeat. To acquire these <see cref="AudioClip"/>s, I used Audacity and
    6. /// manually cut them from a source mp3 myself. That's pretty inefficient if you have a lot of these to do, if you're
    7. /// bad at it, or if you can't figure out Audacity. In that case, use the paid version (IntroLoop), which is much, much
    8. /// nicer.
    9. ///
    10. /// Based on a useful post from 5argon at:
    11. ///     https://forum.unity.com/threads/running-a-looped-soundtrack-with-intro.198648/
    12. /// 5argon is also the author of IntroLoop:
    13. ///     https://forum.unity.com/threads/introloop-easily-play-looping-music-with-intro-section.378370/
    14. ///     https://exceed7.com/introloop/
    15. /// </summary>
    16. public class AudioWithIntro : MonoBehaviour{
    17.  
    18.     public AudioSource introSource, loopSource;
    19.  
    20.     public AudioClip introClip, loopClip;
    21.  
    22.     /// <summary>
    23.     /// If true, plays the sequence of clips when the script <see cref="Awake"/>ns. Otherwise, you'll have to manually
    24.     /// execute <see cref="Play"/> from an external source.
    25.     /// </summary>
    26.     public bool playOnAwake;
    27.  
    28.     /// <summary>
    29.     /// Time in seconds between the intro and the loop. Zero should be seamless, but if there's a gap in the clips, you
    30.     /// might want this to be negative.
    31.     /// </summary>
    32.     public double introToLoopDelay = 0;
    33.  
    34.     /// <summary>
    35.     /// <see cref="Play"/>s if appropriate.
    36.     /// </summary>
    37.     private void Awake(){
    38.         if (playOnAwake)
    39.             Play();
    40.     }
    41.  
    42.     /// <summary>
    43.     /// Plays the intro <see cref="AudioClip"/> and then plays the loop <see cref="AudioClip"/> after. Delay time for
    44.     /// the loop is introClip.Length + <see cref="introToLoopDelay"/>.
    45.     /// </summary>
    46.     public void Play(){
    47.      
    48.         // Stop previous
    49.         introSource.Stop();
    50.         loopSource.Stop();
    51.      
    52.         // Get timing right
    53.         double batonPassTime = AudioSettings.dspTime + introClip.length + introToLoopDelay;
    54.  
    55.         // Play intro
    56.         introSource.PlayOneShot(introClip);
    57.         introSource.SetScheduledEndTime(batonPassTime);
    58.      
    59.         // Schedule loop
    60.         loopSource.clip = loopClip;
    61.         loopSource.loop = true;
    62.         loopSource.PlayScheduled(batonPassTime);
    63.     }
    64. }
    65.  
    However, I gotta stress, @5argon 's IntroLoop (
    https://forum.unity.com/threads/introloop-easily-play-looping-music-with-intro-section.378370/) seems much much better. I only had 5 or so tracks, so I could cut them by hand (via Audacity), but if you have much more, it's a really inefficient use of your time. Pay $20 to get IntroLoop and save yourself $40 in labor hours.

    Edit: not everyone uses Odin Inspector, so I took some tags out.