예제 #1
0
        void Update()
        {
            // Update the note state array.
            foreach (var cs in _channelArray)
            {
                for (var i = 0; i < 128; i++)
                {
                    var x = cs._noteArray[i];
                    if (x > 1)
                        cs._noteArray[i] = x - 1; // Key down -> Hold.
                    else if (x < 0)
                        cs._noteArray[i] = 0; // Key up -> Off.
                }
            }

            // Process the message queue.
            while (true)
            {
                // Pop from the queue.
                var data = DequeueIncomingData();
                if (data == 0) break;

                // Parse the message.
                var message = new MidiMessage(data);

                // Split the first byte.
                var statusCode = message.status >> 4;
                var channelNumber = message.status & 0xf;

                // Note on message?
                if (statusCode == 9)
                {
                    var velocity = 1.0f / 127 * message.data2 + 1;
                    _channelArray[channelNumber]._noteArray[message.data1] = velocity;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = velocity;
                    if (noteOnDelegate != null)
                        noteOnDelegate((MidiChannel)channelNumber, message.data1, velocity - 1);
                }

                // Note off message?
                if (statusCode == 8 || (statusCode == 9 && message.data2 == 0))
                {
                    _channelArray[channelNumber]._noteArray[message.data1] = -1;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = -1;
                    if (noteOffDelegate != null)
                        noteOffDelegate((MidiChannel)channelNumber, message.data1);
                }

                // CC message?
                if (statusCode == 0xb)
                {
                    // Normalize the value.
                    var level = 1.0f / 127 * message.data2;
                    // Update the channel if it already exists, or add a new channel.
                    _channelArray[channelNumber]._knobMap[message.data1] = level;
                    // Do again for All-ch.
                    _channelArray[(int)MidiChannel.All]._knobMap[message.data1] = level;
                    if (knobDelegate != null)
                        knobDelegate((MidiChannel)channelNumber, message.data1, level);
                }

                #if UNITY_EDITOR
                // Record the message.
                _totalMessageCount++;
                _messageHistory.Enqueue(message);
                #endif
            }

            #if UNITY_EDITOR
            // Truncate the history.
            while (_messageHistory.Count > 8)
                _messageHistory.Dequeue();
            #endif
        }
예제 #2
0
        void Update()
        {
            Refresh();

            // Update the note state array.
            foreach (var cs in _channelArray)
            {
                for (var i = 0; i < 128; i++)
                {
                    var x = cs._noteArray[i];
                    if (x > 1)
                    {
                        cs._noteArray[i] = x - 1; // Key down -> Hold.
                    }
                    else if (x < 0)
                    {
                        cs._noteArray[i] = 0; // Key up -> Off.
                    }
                }
            }

            MidiDriver.Refresh();

            // Process the message queue.
            while (true)
            {
                if (msgQueue.Count == 0)
                {
                    break;
                }

                // Pop from the queue.
                MidiMessage message = msgQueue.Dequeue();

                // Split the first byte.
                var statusCode    = message.status >> 4;
                var channelNumber = message.status & 0xf;

                // Note on message?
                if (statusCode == 9)
                {
                    var velocity = 1.0f / 127 * message.data2 + 1;
                    _channelArray[channelNumber]._noteArray[message.data1]        = velocity;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = velocity;
                    if (noteOnDelegate != null)
                    {
                        noteOnDelegate((MidiChannel)channelNumber, message.data1, velocity - 1);
                    }
                }

                // Note off message?
                if (statusCode == 8 || (statusCode == 9 && message.data2 == 0))
                {
                    _channelArray[channelNumber]._noteArray[message.data1]        = -1;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = -1;
                    if (noteOffDelegate != null)
                    {
                        noteOffDelegate((MidiChannel)channelNumber, message.data1);
                    }
                }

                // CC message?
                if (statusCode == 0xb)
                {
                    // Normalize the value.
                    var level = 1.0f / 127 * message.data2;
                    // Update the channel if it already exists, or add a new channel.
                    int knobNumber = message.data1;
                    if (_midiMap)
                    {
                        knobNumber = _midiMap.JackValue(knobNumber);
                    }
                    _channelArray[channelNumber]._knobMap[knobNumber] = level;
                    // Do again for All-ch.
                    _channelArray[(int)MidiChannel.All]._knobMap[knobNumber] = level;
                    if (knobDelegate != null)
                    {
                        knobDelegate((MidiChannel)channelNumber, knobNumber, level);
                    }
                }

                // System message?
                if (statusCode == 0xf)
                {
                    if (channelNumber == 0)
                    {
                        if (message.data1 >= _sysexMem.Length)
                        {
                            return;
                        }

                        _sysexMem[message.data1] = message.data2;

                        if (sysexDelegate != null)
                        {
                            sysexDelegate((MidiSysex)message.data1, message.data2);
                        }
                    }
                    else
                    {
                        if (message.status == (byte)MidiRealtime.Clock)
                        {
                            if (realtimeDelegate != null)
                            {
                                realtimeDelegate(MidiRealtime.Clock);
                            }
                        }

                        if (message.status == (byte)MidiRealtime.Start)
                        {
                            _isPlaying = true;

                            if (realtimeDelegate != null)
                            {
                                realtimeDelegate(MidiRealtime.Start);
                            }
                        }

                        if (message.status == (byte)MidiRealtime.Continue)
                        {
                            _isPlaying = true;

                            if (realtimeDelegate != null)
                            {
                                realtimeDelegate(MidiRealtime.Continue);
                            }
                        }

                        if (message.status == (byte)MidiRealtime.Stop)
                        {
                            _isPlaying = false;

                            if (realtimeDelegate != null)
                            {
                                realtimeDelegate(MidiRealtime.Stop);
                            }
                        }
                    }
                }
            }
        }
예제 #3
0
        void Update()
        {
            // Update the note state array.
            foreach (var cs in _channelArray)
            {
                for (var i = 0; i < 128; i++)
                {
                    var x = cs._noteArray[i];
                    if (x > 1)
                    {
                        cs._noteArray[i] = x - 1; // Key down -> Hold.
                    }
                    else if (x < 0)
                    {
                        cs._noteArray[i] = 0; // Key up -> Off.
                    }
                }
            }

            // Process the message queue.
            while (true)
            {
                // Pop from the queue.
                var data = DequeueIncomingData();
                if (data == 0)
                {
                    break;
                }

                // Parse the message.
                var message = new MidiMessage(data);

                // Split the first byte.
                var statusCode    = message.status >> 4;
                var channelNumber = message.status & 0xf;

                // Note on message?
                if (statusCode == 9)
                {
                    var velocity = 1.0f / 127 * message.data2 + 1;
                    _channelArray[channelNumber]._noteArray[message.data1]        = velocity;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = velocity;
                    if (noteOnDelegate != null)
                    {
                        noteOnDelegate((MidiChannel)channelNumber, message.data1, velocity - 1);
                    }
                    if (noteOnEvent != null)
                    {
                        noteOnEvent.Invoke((MidiChannel)channelNumber, message.data1, velocity - 1);
                    }
                }

                // Note off message?
                if (statusCode == 8 || (statusCode == 9 && message.data2 == 0))
                {
                    _channelArray[channelNumber]._noteArray[message.data1]        = -1;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = -1;
                    if (noteOffDelegate != null)
                    {
                        noteOffDelegate((MidiChannel)channelNumber, message.data1);
                    }
                    if (noteOffEvent != null)
                    {
                        noteOffEvent((MidiChannel)channelNumber, message.data1);
                    }
                }

                // CC message?
                if (statusCode == 0xb)
                {
                    // Normalize the value.
                    var level = 1.0f / 127 * message.data2;
                    // Update the channel if it already exists, or add a new channel.
                    _channelArray[channelNumber]._knobMap[message.data1] = level;
                    // Do again for All-ch.
                    _channelArray[(int)MidiChannel.All]._knobMap[message.data1] = level;
                    if (knobDelegate != null)
                    {
                        knobDelegate((MidiChannel)channelNumber, message.data1, level);
                    }
                    if (knobEvent != null)
                    {
                        knobEvent((MidiChannel)channelNumber, message.data1, level);
                    }
                }

                // Clock message ?
                if (message.status == 0xF8)
                {
                    var timestamp = GetTimestamp();
                    if (timestamp > 0)
                    {
                        _clockEventTimestamps.Enqueue(timestamp);
                    }
                    _clockEventCount++;

                    if (_clockEventCount >= 24)
                    {
                        if (_clockEventTimestamps.Count > 1)
                        {
                            float mean  = 0;
                            int   count = _clockEventTimestamps.Count - 1;
                            ulong time  = _clockEventTimestamps.Dequeue();

                            while (_clockEventTimestamps.Count > 0)
                            {
                                ulong temp = _clockEventTimestamps.Dequeue();
                                ulong diff = temp - time;
                                mean += ((diff) / (float)count);
                                time  = temp;
                            }

                            _lastBeatLength = (24.0f * mean / 1000.0f);
                            if (clockEvent != null)
                            {
                                clockEvent(24.0f * mean);
                            }
                        }
                        else
                        {
                            _clockEventTimestamps.Clear();
                        }

                        _clockEventCount = 0;
                    }
                }

                #if UNITY_EDITOR
                // Record the message.
                _totalMessageCount++;
                _messageHistory.Enqueue(message);
                #endif
            }

            #if UNITY_EDITOR
            // Truncate the history.
            while (_messageHistory.Count > 8)
            {
                _messageHistory.Dequeue();
            }
            #endif
        }
예제 #4
0
        void Update()
        {
            // Update the note state array.
            foreach (var cs in _channelArray)
            {
                for (var i = 0; i < 128; i++)
                {
                    var x = cs._noteArray[i];
                    if (x > 1)
                    {
                        cs._noteArray[i] = x - 1; // Key down -> Hold.
                    }
                    else if (x < 0)
                    {
                        cs._noteArray[i] = 0; // Key up -> Off.
                    }
                }
            }

            // Process the message queue.
            while (true)
            {
                // MIDI IN message pop from the queue.
                var data = DequeueIncomingData();
                if (data == 0)
                {
                    break;
                }

                // Parse the message.
                var message = new MidiMessage(data);

                // Split the first byte.
                var statusCode    = message.status >> 4;
                var channelNumber = message.status & 0xf;

                // Note on message?
                if (statusCode == 9)
                {
                    var velocity = 1.0f / 127 * message.data2 + 1;
                    _channelArray[channelNumber]._noteArray[message.data1]        = velocity;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = velocity;
                    if (noteOnDelegate != null)
                    {
                        noteOnDelegate((MidiChannel)channelNumber, message.data1, velocity - 1);
                    }
                }

                // Note off message?
                if (statusCode == 8 || (statusCode == 9 && message.data2 == 0))
                {
                    _channelArray[channelNumber]._noteArray[message.data1]        = -1;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = -1;
                    if (noteOffDelegate != null)
                    {
                        noteOffDelegate((MidiChannel)channelNumber, message.data1);
                    }
                }

                // CC message?
                if (statusCode == 0xb)
                {
                    // Normalize the value.
                    var level = 1.0f / 127 * message.data2;
                    // Update the channel if it already exists, or add a new channel.
                    _channelArray[channelNumber]._knobMap[message.data1] = level;
                    // Do again for All-ch.
                    _channelArray[(int)MidiChannel.All]._knobMap[message.data1] = level;
                    if (knobDelegate != null)
                    {
                        knobDelegate((MidiChannel)channelNumber, message.data1, level);
                    }
                }

                #if UNITY_EDITOR
                // Record the message.
                _totalMessageCount++;
                _messageHistory.Enqueue(message);
                #endif
            }

            while (true)
            {
                // dequeue MIDI OUT message
                var data = DequeueSendData();
                if (data == 0)
                {
                    break;
                }
            }

            #if UNITY_EDITOR
            // Truncate the history.
            while (_messageHistory.Count > 8)
            {
                _messageHistory.Dequeue();
            }
            #endif
        }
예제 #5
0
        public void Update()
        {
            // Update the note state array.
            foreach (var cs in _channelArray)
            {
                for (var i = 0; i < 128; i++)
                {
                    var x = cs._noteArray[i];
                    if (x > 1)
                    {
                        cs._noteArray[i] = x - 1; // Key down -> Hold.
                    }
                    else if (x < 0)
                    {
                        cs._noteArray[i] = 0; // Key up -> Off.
                    }
                }
            }

            // Process the message queue.
            while (true)
            {
                // Pop from the queue.
                var data = DequeueIncomingData();
                if (data == 0)
                {
                    break;
                }

                // Parse the message.
                var message = new MidiMessage(data);

                // Split the first byte.
                var statusCode    = (StatusCode)(message.status >> 4);
                var channelNumber = message.status & 0xf;

                if (statusCode == StatusCode.NoteOn)
                {
                    var velocity = 1.0f / 127 * message.data2 + 1;
                    _channelArray[channelNumber]._noteArray[message.data1]        = velocity;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = velocity;
                    if (noteOnDelegate != null)
                    {
                        noteOnDelegate((MidiChannel)channelNumber, message.data1, velocity - 1);
                    }
                }

                else if (statusCode == StatusCode.NoteOff || (statusCode == StatusCode.NoteOn && message.data2 == 0))
                {
                    _channelArray[channelNumber]._noteArray[message.data1]        = -1;
                    _channelArray[(int)MidiChannel.All]._noteArray[message.data1] = -1;
                    if (noteOffDelegate != null)
                    {
                        noteOffDelegate((MidiChannel)channelNumber, message.data1);
                    }
                }

                else if (statusCode == StatusCode.ControlChange)
                {
                    // Normalize the value.
                    var level = 1.0f / 127 * message.data2;
                    // Update the channel if it already exists, or add a new channel.
                    _channelArray[channelNumber]._knobMap[message.data1] = level;
                    // Do again for All-ch.
                    _channelArray[(int)MidiChannel.All]._knobMap[message.data1] = level;
                    if (knobDelegate != null)
                    {
                        knobDelegate((MidiChannel)channelNumber, message.data1, level);
                    }
                }

                else if (statusCode == StatusCode.Clock)
                {
                    // Add the current time to the clock history queue
                    _midiClockHistory.Enqueue(Time.time);
                    // Keep 96 messages in the queue (a bar worth)
                    while (_midiClockHistory.Count > 96)
                    {
                        _midiClockHistory.Dequeue();
                        // Calculate the tempo by averaging the difference between each time recorded
                        var times = _midiClockHistory.ToArray();
                        var sum   = 0f;
                        for (int i = 1; i < times.Length; i++)
                        {
                            sum += times[i] - times[i - 1];
                        }
                        SecondsPerBeat = sum / 96;
                        BeatsPerMinute = 60 / (SecondsPerBeat * 24);
                    }
                }

#if UNITY_EDITOR
                // If it's not a clock, record the message.
                if (statusCode != StatusCode.Clock)
                {
                    _totalMessageCount++;
                    _messageHistory.Enqueue(message);
                }
#endif
            }

#if UNITY_EDITOR
            // Truncate the history.
            while (_messageHistory.Count > 8)
            {
                _messageHistory.Dequeue();
            }
#endif
        }