Exemplo n.º 1
0
    public Sequencer()
    {
        dispatcher.MetaMessageDispatched += delegate(object sender, MetaMessageEventArgs e)
        {
            if (e.Message.MetaType == MetaType.EndOfTrack)
            {
                tracksPlayingCount--;

                if (tracksPlayingCount == 0)
                {
                    Stop();

                    OnPlayingCompleted(EventArgs.Empty);
                }
            }
            else
            {
                clock.Process(e.Message);
            }
        };

        dispatcher.ChannelMessageDispatched += delegate(object sender, ChannelMessageEventArgs e)
        {
            stopper.Process(e.Message);
        };

        clock.Tick += delegate(object sender, EventArgs e)
        {
            lock (lockObject)
            {
                if (!playing)
                {
                    return;
                }

                foreach (IEnumerator <int> enumerator in enumerators)
                {
                    enumerator.MoveNext();
                }
            }
        };
    }
Exemplo n.º 2
0
    public SequencerWP()
    {
        dispatcher.MetaMessageDispatched += delegate(object sender, MetaMessageEventArgs e)
        {
            if (e.Message.MetaType == MetaType.EndOfTrack)
            {
                tracksPlayingCount--;
                UnityEngine.Debug.LogFormat("end. t:{0}", tracksPlayingCount);
                if (tracksPlayingCount == 0)
                {
                    Stop(true);
                    // playing completed handles initialization if looping is enabled.
                    OnPlayingCompleted(EventArgs.Empty);
                }
            }
            else
            {
                clock.Process(e.Message);
            }
        };

        dispatcher.ChannelMessageDispatched += delegate(object sender, ChannelMessageEventArgs e)
        {
            stopper.Process(e.Message);
        };

        clock.Tick += delegate(object sender, EventArgs e)
        {
            lock (lockObject)
            {
                if (!playing)
                {
                    return;
                }

                if (Position == LoopEnd)
                {
                    Stop(true);
                    // playing completed handles initialization if looping is enabled.
                    OnPlayingCompleted(EventArgs.Empty);
                    return;
                }

                // only go through tick iterator if we are out of start offset
                if (Position >= LoopStart)
                {
                    foreach (IEnumerator <int> enumerator in enumerators)
                    {
                        enumerator.MoveNext();
                    }
                }
            }
        };

        sequence = GlobalReference.sequence;

        if (Sequence == null)
        {
            throw new Exception("Sequence should not be null.");
        }
        // Process each track and produce the queue of notes to played. This queue is the player paced sheet music.
        Dictionary <int, NoteWithDuration> noteToTicksTable = new Dictionary <int, NoteWithDuration>();

        foreach (Track t in Sequence)
        {
            if (t.TrackId == -1)
            {
                throw new Exception("Track ID is 0. Track is not loaded correctly.");
            }

            // not part of user select track to play
            if (t.TrackId != GlobalReference.leftHandTrackIndex && t.TrackId != GlobalReference.rightHandTrackIndex)
            {
                continue;
            }

            noteToTicksTable.Clear();
            notesList.Add(new NotesList());
            int trackIndex = notesList.Count - 1;

            IEnumerator <MidiEvent> enumerator = t.Iterator().GetEnumerator();
            while (enumerator.MoveNext())
            {
                if (enumerator.Current.MidiMessage.MessageType != MidiMessageType.Channel)
                {
                    continue;
                }

                ChannelMessage channelMsg = (ChannelMessage)enumerator.Current.MidiMessage;

                // Store absolute ticks of NoteOn message in hash table
                if (channelMsg.Command == ChannelCommand.NoteOn)
                {
                    if (channelMsg.Data2 == 0) // Note on message with velocity of 0 is equivalent of Note Off Message
                    {
                        NoteWithDuration noteOff;
                        if (noteToTicksTable.TryGetValue(channelMsg.Data1, out noteOff))
                        {
                            //UnityEngine.Debug.LogFormat("OFF, {0}", channelMsg.Data1);
                            noteOff.Duration = enumerator.Current.AbsoluteTicks - noteOff.AbsoluteTicks; // TODO: Test if this works
                            noteToTicksTable.Remove(channelMsg.Data1);
                        }
                    }
                    else
                    {
                        //UnityEngine.Debug.LogFormat("ON, {0} Ticks:{1}", channelMsg.Data1, enumerator.Current.AbsoluteTicks);
                        if (!noteToTicksTable.ContainsKey(channelMsg.Data1))
                        {
                            NoteWithDuration note = new NoteWithDuration(enumerator.Current.AbsoluteTicks, channelMsg.Data1, -1, channelMsg.MidiTrack);
                            notesList[trackIndex].Add(ref note);
                            noteToTicksTable.Add(channelMsg.Data1, note);
                        }
                        else
                        {
                            UnityEngine.Debug.LogFormat("Multiple Note On Msgs. Ignored ID: {0}", channelMsg.Data1);
                        }
                    }
                }
                // When encounter NoteOff message, Find corresponding NoteOn message in hash table
                // and calculate duration. Update the duration of that note.
                else if (channelMsg.Command == ChannelCommand.NoteOff)
                {
                    NoteWithDuration noteOff;
                    if (noteToTicksTable.TryGetValue(channelMsg.Data1, out noteOff))
                    {
                        //UnityEngine.Debug.LogFormat("OFF, {0}", channelMsg.Data1);
                        noteOff.Duration = enumerator.Current.AbsoluteTicks - noteOff.AbsoluteTicks; // TODO: Test if this works
                        noteToTicksTable.Remove(channelMsg.Data1);
                    }
                }
            }
        }

        // Find first tick of NoteOn message among the tracks
        for (int i = 0; i < notesList.Count; i++)
        {
            firstTick = (firstTick == -1 || notesList[i].FirstTick < firstTick) ? notesList[i].FirstTick : firstTick;
        }

        // Find last tick of NoteOn message among the tracks
        for (int i = 0; i < Sequence.Count; i++)
        {
            UnityEngine.Debug.LogFormat("Sequence track length: {0}", Sequence[i].Length);
            lastTick = (lastTick == -1 || Sequence[i].Length > lastTick) ? Sequence[i].Length : lastTick;
        }
    }