devnotes 8-16-16 MultiVoice – Vamp – Ostinato

 


using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using System;

public class Argos_Note
{
    public int nIdx;
    public double startTime;
    public float phaseBase;
    public double phase;
    public double attack;
    public double decay;
    public double amplitude;
    public bool isPlaying = false;

    public Argos_Note(int nI, double sT, float pB, double aT, double dC, double amp)
    {
        nIdx = nI;
        startTime = sT;
        phaseBase = pB;
        attack = aT;
        decay = dC;
        amplitude = amp;

        phase = 0;
    }
}

[RequireComponent(typeof(AudioSource))]
public class Argos_Sound_Gen : MonoBehaviour
{
    AudioSource audioSource;

    public List<Argos_Note> noteList = new List<Argos_Note>();
    private int noteCount = 0;
    public Argos_Note[] voiceArray = new Argos_Note[10];

    public Text dbg_Text;

    public float estimatedLatency { get; protected set; }

    public int globalSampleRate;

    [Range(0, 5)]
    public double gain = 1;

    [Range(0.01f, 0.02f)]
    public double phase1base = 0.01;

    [Range(0.0f, 1f)]
    public double attack = 0.01;

    [Range(0.0f, 5f)]
    public double decay = 0.01;



    private double amp = 0.0F;
    private double phase = 0.0F;

    private int accent;
    private bool running = false;

    private bool seqOn = false;
    int noteIDX = 0;


    //private float[] _dtime = { 0.004124562f, 0.00389302f, 0.003674579f, 0.003468248f, 0.003273644f, 0.003089948f, 0.002916472f,
    //                            0.002752773f, 0.00259828f, 0.002452483f, 0.002314815f, 0.002184885f, 0.002062281f};

     private float[] _dtime = {

                                0.015571473f, //C2  0
                                0.014697237f, //Db2 1
                                0.013873474f, //D2  2
                                0.013094147f, //Eb2 3                                  
                                0.012359412f, //E2  4
                                0.011665889f, //F2  5
                                0.011010791f, //F#2 6
                                0.01039285f,  //G2  7
                                0.009809692f, //Ab2 8
                                0.009259259f, //A2  9
                                0.008739731f, //Bb2 10
                                0.008248783f, //B2  11
                                0.007786343f, //C3  12
                                0.007349159f, //Db3 13
                                0.006936737f, //D3  14
                                0.006547073f, //Eb3 15
                                0.006179706f, //E3  16
                                0.005832944f, //F3  17
                                0.005505698f, //F#3 18
                                0.005196695f, //G3  19
                                0.004904846f, //Ab3 20
                                0.00462963f,  //A3  21
                                0.004369865f, //Bb3 22
                                0.004124562f, //B3  23
                                0.00389302f,  //C4  24
                                0.003674579f, //Db4 25
                                0.003468248f, //D4  26
                                0.003273644f, //Eb4 27
                                0.003089948f, //E4  28
                                0.002916472f, //F4  29
                                0.002752773f, //F#4 30
                                0.00259828f,  //G4  31
                                0.002452483f, //Ab4 32
                                0.002314815f, //A4  33 --- A 432
                                0.002184885f, //Bb4 34
                                0.002062281f, //B4  35
                                0.00194651f,  //C4  36
                                0.001837256f,
                                0.001734154f,
                                0.001636822f,
                                0.00154495f,
                                0.001458236f,
                                0.001376406f,
                                0.00129914f,
                                0.001226227f,
                                0.001157407f,
                                0.001092442f,
                                0.00103113f,
                                0.000973264f,
                                0.000918636f,
                                0.000867077f,
                                0.000818411f,
                                0.000772475f,
                                0.000729123f,
                                0.000688198f,
                                0.000649574f,
                                0.000613117f,
                                0.000578704f,
                                0.000546224f,
                                0.000515568f,
                                0.00048663f,
                                0.000459318f,
                                0.000433539f,
                                0.000409205f,
                                0.000386239f,
                                0.00036456f,
                                0.000344099f,
                                0.000324786f,
                                0.000306558f,
                                0.000289352f,
                                0.000273112f,
                                0.000257783f,
                                0.000243315f,
                                0.000229659f,
                                0.000216769f,
                                0.000204603f,
                                0.000193119f,
                                0.00018228f,
                                0.00017205f,
                                0.000162393f,
                                0.000153279f,
                                0.000144676f,
                                0.000136556f,
                                0.000128892f };



    void Awake()
    {
        // Create an audio source.
        audioSource = gameObject.GetComponent<AudioSource>();
        audioSource.playOnAwake = false;
        audioSource.loop = true;
    }

    void Start()
    {
        globalSampleRate = AudioSettings.outputSampleRate;

        for(int i = 0; i<10; i++)
        {
            voiceArray[i] = null;
        }
    }

    void OnApplicationPause(bool paused)
    {

    }

    float accum = 0.0f;
    void Update()
    {
        //if (seqOn) test
        //{
        //    accum += Time.deltaTime;

        //    if(accum > 1.7f)
        //    {
        //        playNote(noteIDX, 0.8f);
        //        if (++noteIDX > _dtime.Length - 1)
        //        {
        //            seqOn = false;
        //            noteIDX = 0;
        //        }
        //        accum = 0f;
        //    }
        //}
    }




    public void playNote(int idx, float amp)
    {

            Argos_Note aN = new Argos_Note(idx, (double)AudioSettings.dspTime, _dtime[idx], attack, decay, amp);

            aN.isPlaying = true;

            if (noteList.Count < 500)
            {
                noteList.Add(aN);
            } 
            StartNewNote(aN);
    }

    public void StartNewNote(Argos_Note aN)
    {
        for(int i = 0; i<10; i++)
        {
            if(voiceArray[i] == null || !voiceArray[i].isPlaying)
            {
                voiceArray[i] = aN;
                return;
            }
        }

        //else replace oldest
        double minStartTime = double.MaxValue;
        int repIdx = 0;
        for(int j = 0; j < 10; j++)
        {
            if(voiceArray[j].startTime < minStartTime)
            {
                minStartTime = voiceArray[j].startTime;
                repIdx = j;
            }
        }
        voiceArray[repIdx] = aN;
    }


    double EnvelopShaper(Argos_Note aN, double sampTime)
    {
        amp = 0;

        if (sampTime - aN.startTime < aN.attack)
        {
            amp = CubicEaseIn(sampTime - aN.startTime, 0, 1, aN.attack);
        }
        else if (accumTime - aN.startTime < aN.attack + aN.decay)
        {
            amp = CubicEaseOut((sampTime - aN.startTime - aN.attack), 1, -1, aN.decay);
        }
        else
        {
            amp = 0;
            aN.isPlaying = false;
        }
        return amp;
    }

    float dTIME = 0f;
    double dt;
    int testCount = 0;
    double accumTime;

    void OnAudioFilterRead(float[] data, int channels)
    {

        //TESTER ACTIVE VOICE COUNT
        if (++testCount > 10)
        {
            int active = 0;
            for(int po = 0; po<10; po++)
            {
                if (voiceArray[po] != null)
                {
                    if (voiceArray[po].isPlaying) active++;
                }   
            }
            dbg_Text.text = "active Voices = " + active.ToString();
            testCount = 0;
        }

        accumTime = (double)AudioSettings.dspTime;

        double samples = AudioSettings.dspTime * globalSampleRate;
        int dataLen = data.Length / channels;
        double deltTime = (AudioSettings.dspTime / samples);//HIGHLY REDUNDANT - FIX
        int n = 0;

        double a;

        double sampTime = accumTime;

        //dt = deltTime / dTIME * 2f * Mathf.PI;

        while (n < dataLen)
        {
            sampTime += deltTime;
            //do 10 voices
            a = 0;
            for (int v = 0; v<10; v++)
            {
                if (voiceArray[v] != null)
                {
                    if (voiceArray[v].isPlaying)
                    {
                        a += voiceArray[v].amplitude * EnvelopShaper(voiceArray[v], sampTime) * Math.Sin(voiceArray[v].phase);
                    }
                }   
           }
 
           float x = (float)(a);
           int i = 0;

            while (i < channels)
            {
                data[n * channels + i] = x;
                i++;
            }

            for (int u = 0; u < 10; u++)
            {
                if (voiceArray[u] != null)
                {
                    if (voiceArray[u].isPlaying)
                    {
                        dt = deltTime / voiceArray[u].phaseBase * 2f * Mathf.PI;

                        voiceArray[u].phase += dt;
                        if (voiceArray[u].phase > Math.PI * 2f) voiceArray[u].phase = 0f;
                    }
                }
            }
            n++;
        }
    }
    /// </summary>
    /// <param name= t  "current">how long into the ease are we</param>
    /// <param name= b  "initialValue">starting value if current were 0</param>
    /// <param name= c  "totalChange">total change in the value (not the end value, but the end - start)</param>
    /// <param name= d  "duration">the total amount of time (when current == duration, the returned value will == initial + totalChange)</param>
    /// <returns></returns>

    public static double CubicEaseOut(double t, double b, double c, double d)
    {
        if (t < d)
        {
            return c * ((t = t / d - 1) * t * t + 1) + b;
        }
        else
        {
            return b + c;
        }
    }

    public static double CubicEaseIn(double t, double b, double c, double d)
    {
        if (t < d)
        {
            return c * (t /= d) * t * t + b;
        }
        else
        {
            return b + c;
        }
    }
}

voices


using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;

[RequireComponent(typeof(AudioSource))]
public class Argos_Sound_Gen : MonoBehaviour
{
    AudioSource audioSource;

    public Text dbg_Text;

    public float estimatedLatency { get; protected set; }

    public int globalSampleRate;

    [Range(0, 5)]
    public double gain = 1;

    [Range(0.01f, 0.02f)]
    public double phase1base = 0.01;

    [Range(0.0f, 1f)]
    public double attack1 = 0.01;

    [Range(0.0f, 1f)]
    public double decay1 = 0.01;

    double phase1;

    double amp1;

    private double amp = 0.0F;
    private double phase = 0.0F;

    private int accent;
    private bool running = false;


    private bool seqOn = false;
    int noteIDX = 0;


    //private float[] _dtime = { 0.004124562f, 0.00389302f, 0.003674579f, 0.003468248f, 0.003273644f, 0.003089948f, 0.002916472f,
    //                            0.002752773f, 0.00259828f, 0.002452483f, 0.002314815f, 0.002184885f, 0.002062281f};

     private float[] _dtime = {

                                0.015571473f,
                                0.014697237f,
                                0.013873474f,
                                0.013094147f,
                                0.012359412f,
                                0.011665889f,
                                0.011010791f,
                                0.01039285f,
                                0.009809692f,
                                0.009259259f,
                                0.008739731f,
                                0.008248783f,
                                0.007786343f,
                                0.007349159f,
                                0.006936737f,
                                0.006547073f,
                                0.006179706f,
                                0.005832944f,
                                0.005505698f,
                                0.005196695f,
                                0.004904846f,
                                0.00462963f,
                                0.004369865f,
                                0.004124562f,
                                0.00389302f,
                                0.003674579f,
                                0.003468248f,
                                0.003273644f,
                                0.003089948f,
                                0.002916472f,
                                0.002752773f,
                                0.00259828f,
                                0.002452483f,
                                0.002314815f,//A 432
                                0.002184885f,
                                0.002062281f,
                                0.00194651f,
                                0.001837256f,
                                0.001734154f,
                                0.001636822f,
                                0.00154495f,
                                0.001458236f,
                                0.001376406f,
                                0.00129914f,
                                0.001226227f,
                                0.001157407f,
                                0.001092442f,
                                0.00103113f,
                                0.000973264f,
                                0.000918636f,
                                0.000867077f,
                                0.000818411f,
                                0.000772475f,
                                0.000729123f,
                                0.000688198f,
                                0.000649574f,
                                0.000613117f,
                                0.000578704f,
                                0.000546224f,
                                0.000515568f,
                                0.00048663f,
                                0.000459318f,
                                0.000433539f,
                                0.000409205f,
                                0.000386239f,
                                0.00036456f,
                                0.000344099f,
                                0.000324786f,
                                0.000306558f,
                                0.000289352f,
                                0.000273112f,
                                0.000257783f,
                                0.000243315f,
                                0.000229659f,
                                0.000216769f,
                                0.000204603f,
                                0.000193119f,
                                0.00018228f,
                                0.00017205f,
                                0.000162393f,
                                0.000153279f,
                                0.000144676f,
                                0.000136556f,
                                0.000128892f };









    void Awake()
    {
        // Create an audio source.
        audioSource = gameObject.GetComponent<AudioSource>();
        audioSource.playOnAwake = false;
        audioSource.loop = true;
    }

    void Start()
    {
        globalSampleRate = AudioSettings.outputSampleRate;
    }

    void OnApplicationPause(bool paused)
    {

    }

    float accum = 0.0f;
    void Update()
    {
        if (seqOn)
        {
            accum += Time.deltaTime;

            if(accum > 1.7f)
            {
                playNote(noteIDX, 0.8f);
                if (++noteIDX > _dtime.Length - 1)
                {
                    seqOn = false;
                    noteIDX = 0;
                }
                accum = 0f;
            }
        }
    }


    public void playNote(int idx, float vol)
    {
        seqOn = true;

        time1 = accumTime;//Attack
        phasemult1 = idx;
        gain = vol;
        dTIME = _dtime[(int)phasemult1];

        dbg_Text.text = idx.ToString();

    }


    public void playNote(int idx)
    {
        time1 = accumTime;//Attack
        phasemult1 = idx;
        dTIME = _dtime[(int)phasemult1];
    }
    int count1 = 0;

    double phasemult1 = 3.0f;

    bool switch1 = true;

    double time1;

    double accumTime;

    bool aOn = true;

    double ampSamp(int voice, double sampTime)
    {
        amp = 0;

        if (voice == 1)
        {
            if (sampTime - time1 < attack1)
            {
                amp = CubicEaseIn(sampTime - time1, 0, 1, attack1);
            }
            else if (accumTime - time1 < attack1 + decay1)
            {
                amp = CubicEaseOut((sampTime - time1 - attack1), 1, -1, decay1);
            }
            else
            {
                amp = 0;
            }
        }
        return amp;
    }


    float dTIME = 0f;
    double dt;
    void OnAudioFilterRead(float[] data, int channels)
    {
        accumTime = (double)AudioSettings.dspTime;

        double samples = AudioSettings.dspTime * globalSampleRate;
        int dataLen = data.Length / channels;
        double deltTime = (AudioSettings.dspTime / samples);
        int n = 0;

        double a;

        double sampTime = accumTime;

        dt = deltTime / dTIME * 2f * Mathf.PI;

        while (n < dataLen)
        {
            sampTime += deltTime;

            a =  gain * ampSamp(1, sampTime)* Math.Sin(phase1);
 
           float x = (float)(a);
           int i = 0;

            while (i < channels)
            {
                data[n * channels + i] = x;
                i++;
            }

            phase1 += dt;
            if (phase1 > Math.PI * 2f) phase1 = 0f;

            n++;
        }
    }
    /// </summary>
    /// <param name= t  "current">how long into the ease are we</param>
    /// <param name= b  "initialValue">starting value if current were 0</param>
    /// <param name= c  "totalChange">total change in the value (not the end value, but the end - start)</param>
    /// <param name= d  "duration">the total amount of time (when current == duration, the returned value will == initial + totalChange)</param>
    /// <returns></returns>

    public static double CubicEaseOut(double t, double b, double c, double d)
    {
        if (t < d)
        {
            return c * ((t = t / d - 1) * t * t + 1) + b;
        }
        else
        {
            return b + c;
        }
    }

    public static double CubicEaseIn(double t, double b, double c, double d)
    {
        if (t < d)
        {
            return c * (t /= d) * t * t + b;
        }
        else
        {
            return b + c;
        }
    }
}

42