/// <summary>
    /// Passed a note/chord for lead, and note for melody. This chooses a sampler
    /// on which to play the note, sets the pitch accordingly, and then plays the single note
    /// or in the case of a lead chord, it plays all notes of the chord
    ///
    /// scale is the 12th root of 2, or 1 semitone step, the basis assumes its at C (first note) of
    /// the scale. It is precomputed, and reset each time a note tries to play to prevent weird offsets
    ///
    /// FUTURE WORK: Precompute all scale^notevals and use that instead of Math.Pow()
    /// </summary>
    public void Play(IMusicalValue leadValue, IMusicalValue melodyValue)
    {
        float scale = 1.059463f;// Mathf.Pow(2f, 1.0f / 12f);

        // Play the sound on the next voice (And pass envelope modifications)

        //Base chords and individual notes for lead
        if (leadValue is Chord)
        {
            Chord leadChord = leadValue as Chord;
            //Debug.Log("Chord Cast");
            foreach (Tone note in leadChord.Notes)
            {
                _samplerVoices[_nextVoiceIndex].Pitch = Mathf.Pow(scale, (float)note - 1);
                _samplerVoices[_nextVoiceIndex].Play(LeadInstrument, _attackLead, _sustainLead, _releaseLead);
                ++_nextVoiceIndex;
                _nextVoiceIndex = (_nextVoiceIndex + 1) % _samplerVoices.Length;
            }
        }
        else if (leadValue is Note)
        {
            //Playing a single note

            Note leadNote = leadValue as Note;
            _samplerVoices[_nextVoiceIndex].Pitch = Mathf.Pow(scale, (float)leadNote.Value - 1);
            if (leadNote.Value == Tone.Rest)
            {
                _samplerVoices[_nextVoiceIndex].Play(RestSpacer, _attackLead, _sustainLead, _releaseLead);
            }
            else
            {
                //Debug.Log("Note Cast and played");
                _samplerVoices[_nextVoiceIndex].Play(LeadInstrument, _attackLead, _sustainLead, _releaseLead);
            }
            ++_nextVoiceIndex;
            _nextVoiceIndex = (_nextVoiceIndex + 1) % _samplerVoices.Length;
        }

        if (melodyValue is Note)
        {
            //Playing a single note
            Note melodyNote = melodyValue as Note;
            _samplerVoices[_nextVoiceIndex].Pitch = Mathf.Pow(scale, (float)melodyNote.Value - 1);
            //Debug.Log("playing melody note" + melodyNote.Value);
            if (melodyNote.Value == Tone.Rest)
            {
                _samplerVoices[_nextVoiceIndex].Play(RestSpacer, _attackMelody, _sustainMelody, _releaseMelody);
            }
            else
            {
                _samplerVoices[_nextVoiceIndex].Play(MelodyInstrument, _attackMelody, _sustainMelody, _releaseMelody);
            }
            ++_nextVoiceIndex;
            _nextVoiceIndex = (_nextVoiceIndex + 1) % _samplerVoices.Length;
        }
        //wrap nextvoice around if it exceeds max
    }
        /// <summary>
        /// Generates a Melody using the notes in this bar (lead) and a melody pattern
        /// </summary>
        private List <IMusicalValue> GetMelodyBar(List <IMusicalValue> bar, List <int?> pattern)
        {
            IMusicalValue barChord    = bar[(int)Beat.One];
            Note          rootBarNote = CurrentMood.TonicNote;

            if (barChord is Chord)
            {
                rootBarNote = Theory.GetNote(((Chord)barChord).Notes[0]);
            }
            else if (barChord is Note)
            {
                rootBarNote = (Note)barChord;
                if (rootBarNote.Value == Tone.Rest)
                {
                    rootBarNote = CurrentMood.TonicNote;
                }
            }
            else
            {
                Debug.Log("Cannot determine the root note or chord for this bar. Shouldnt happen.");
            }
            List <IMusicalValue> newMelodyBar = new List <IMusicalValue>();

            for (int n = 0; n < pattern.Count; n++)
            {
                if (pattern[n] != null)
                {
                    newMelodyBar.Add(Theory.GetNextNoteByInterval(rootBarNote, (int)pattern[n]));
                }
                else
                {
                    newMelodyBar.Add(Theory.Rest);
                }
            }
            return(newMelodyBar);
        }
Example #3
0
        /// <summary>
        /// Step each track forward one position and pass the notevalues to the sampler
        /// at that position
        /// </summary>
        public void Step()
        {
            IMusicalValue leadValue   = LeadTrack.Dequeue();
            IMusicalValue melodyValue = MelodyTrack.Dequeue();

            Sampler.Play(leadValue, melodyValue);
            if (LeadTrack.Count < 2)
            {
                //Changing mood at some point within this
                MusicGenerator MusicGen = MusicGenerator.GetInstance();
                Metronome      metro    = FindObjectOfType <Metronome>();
                MusicGen.GetMood();
                if (MusicGen.CurrentMood != currentMood)
                {
                    Debug.Log("CHANGING MOOD");
                    MusicGen.Generate();
                    currentMood = MusicGen.CurrentMood;
                    var emptyBar = MusicGen.GetBar();
                    foreach (IMusicalValue note in emptyBar)
                    {
                        LeadTrack.Enqueue(note);
                        MelodyTrack.Enqueue(note);
                    }
                    metro.bpm = currentMood.Tempo;
                    Sampler.LeadInstrument   = currentMood.LeadInstrumentSample;
                    Sampler.MelodyInstrument = currentMood.MelodyInstrumentSample;
                    Sampler.SetASR(currentMood.ASRSettings);
                }
                //else
                //{
                //    //slow down as we fade out
                //    metro.bpm /= 2;
                //}
                GetNextTracks();
            }
        }