Search
  • 1/4" Jack Of All Trades

MSc Final Project Weblog 6 : Solving The Metronome Problem


<21/09/21 - 03/10/21>


Solving The Metronome Problem



Tested and explored each proposed metronome method listed and outlined in previous post; the event eventual solution I found did not involve any of the previously outlined methods - after testing various different implementations I found that all were temporally unstable and therefore unsuitable for the requirements of this project. This included the attempts at using Unity's audioSource.playScheduled (see code segment).


public class PlayScheduled : MonoBehaviour
{       
    public float bpm = 140.0f;   
    private double nextEventTime;
    double beatLength;
    public double test;    
    private bool running = false;
    public int subdivision;
    double oldtime = 0.0d;
    double timeOffset = 0.02d;
    double startTime;
    bool isTriggered = false;
    PoolManager poolManager;

    void Start()
    {
        beatLength = (60.0d / bpm) / subdivision;
        nextEventTime = AudioSettings.dspTime + beatLength;
        Debug.Log(nextEventTime);
        running = true;
        poolManager = PoolManager.main;
        startTime = AudioSettings.dspTime;
    }

//tried in normal Update & OnAudioFilterRead
    void FixedUpdate()
    {
        if (!running)
        {
            return;
        }


        beatLength = (60.0d / bpm) / subdivision;
        double timeElapsed = AudioSettings.dspTime - startTime;
        double currentTime = AudioSettings.dspTime;

        if (currentTime > nextEventTime)
        {
            isTriggered = false;
        }
                
        timeOffset = beatLength / test;
        double remainder = timeElapsed % beatLength;
        
        if (currentTime + 1.0f> nextEventTime && !isTriggered)
        {                 
            GameObject go = poolManager.SpawnFromPool("Audio", this.transform.position, Quaternion.identity);                       
            nextEventTime = AudioSettings.dspTime + beatLength - remainder;
            go.GetComponent<PooledAudioSource>().SetStartTimeAndPlay(nextEventTime, beatLength);
            isTriggered = true;
        }
    }
}

I still have not been able to use DSP time to accurately create a sequencer.



In the end I have managed to adapt the sequencer code, found here, to fit with my existing Entity code; this approach uses the audio clip data and schedules a precise start time directly in the audio thread data buffer. The sequencer git repo also provides sequencer group functionality which ensures synchronicity between multiple sequencers. The sequencer code is already capable of outputting events for all sequencer steps as well as only active steps. Using this functionality I have started set up a complex network of event subscription that links different sequencers to different entity events. This sequencer code also requires the use of the Resonance Audio plugin in order to achieve 3D panning based on GameObject position vector.


The major tasks remaining are compiling a meaningful roster of biomes(themed AV assets - points clouds, audio clips etc) for the system to draw from and creating an optimal file structure and associated loading system.





Visual Aesthetic Considerations


Experimenting more with the Shapes library and coming to the conclusion that it should not have such a central role within the project; visually it is simplistic and such a minimal visual effect seems to strongly contradict the objectives of this project. I have begun to search for alternative options for making the visual interaction of the point clouds more interesting; and will begin experimenting with Unity's built-in particle system and it's mesh input options. If particle system experiments are successful, point clouds in their present, mostly static, form may be demoted to a more ambient decorative function within the project.



0 views0 comments