Search Unity

Audio Problem Making Event Based Music System

Discussion in 'Audio & Video' started by duojet, Jan 22, 2020.

  1. duojet

    duojet

    Joined:
    Jan 23, 2019
    Posts:
    6
    Hello,

    I am trying to make an interactive music system that simply tracks a songs bpm on start and can play an audiosource clip on the beat. So for each downbeat (1,2,3,4) my music class sends out a music event which is listened for by a script which then can play from the selected AudioSource.

    However, I am having problems with this system. I am providing the two classes I am using:

    BPM Tracker which sends out the event and contains the logic

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System;
    5.  
    6. public class BpmTracker : MonoBehaviour
    7. {
    8.     public int bpm;
    9.     public static event Action onBeat;
    10.     public static event Action playMusic;
    11.     private float beatInterval, beatIntervalCount = 0.1f;
    12.     private int musicCount = 0;
    13.  
    14.  
    15.     void Start()
    16.     {
    17.         beatInterval = 60f/(float)bpm;
    18.        
    19.     }
    20.  
    21.  
    22.     void FixedUpdate()
    23.     {
    24.         if (beatIntervalCount <= Time.time)
    25.         {
    26.             onBeat?.Invoke();
    27.             if (musicCount == 0)
    28.             {
    29.                 playMusic?.Invoke();
    30.                 musicCount++;
    31.             }
    32.             beatIntervalCount = Time.time + beatInterval;
    33.         }
    34.     }
    35. }
    36.  
    And this is my script for listening/playing the sounds

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Music : MonoBehaviour
    6. {
    7.  
    8.  
    9.     public AudioSource kick, hat, snare, synth;
    10.  
    11.     void Awake()
    12.     {
    13.  
    14.     }
    15.  
    16.     void FixedUpdate()
    17.     {
    18.      
    19.  
    20.     }
    21.  
    22.     private void OnEnable()
    23.     {
    24.         BpmTracker.onBeat += kick.Play;
    25.         BpmTracker.onBeat += snare.Play;
    26.         BpmTracker.playMusic += synth.Play;
    27.     }
    28.  
    29.     private void OnDisable()
    30.     {
    31.         BpmTracker.onBeat -= kick.Play;
    32.         BpmTracker.playMusic += synth.Play;
    33.         BpmTracker.onBeat += snare.Play;
    34.     }
    35. }
    36.  
    This mostly works as expected but there is one critical problem. My BPM Tracker does not seem to be tracking evenly. When I hit play I can tell that the kick drum sometimes slightly speeds up and slows down. I cannot account for this behavior.

    If anyone has thoughts I would really appreciate it!!!
     
  2. JLF

    JLF

    Joined:
    Feb 25, 2013
    Posts:
    140
    Hi, the issue you're having is from trying to schedule audio in Update, or FixedUpdate, which is why you're getting time differences.

    It's fine for most scheduling but for exact musical time it's not accurate enough, and you need to use PlayScheduled instead, which takes a double time value and operates independent of frame rate.

    I've run into this problem before when learning how to make music systems for clients. So much so that I wrote a huge guide on PlayScheduled: https://gamedevbeginner.com/ultimate-guide-to-playscheduled-in-unity/ which might be helpful to you.

    Hope that helps,
    John.
     
  3. duojet

    duojet

    Joined:
    Jan 23, 2019
    Posts:
    6
    John thank you so much!!!!!! I am looking forward to thoroughly going through your guide. I may drop you an email as well.

    Best,
    Eric
     
    JLF likes this.
  4. JLF

    JLF

    Joined:
    Feb 25, 2013
    Posts:
    140
    You’re welcome glad I could help.

    and yeah of course, be sure to email me if you get stuck.