Exemplo n.º 1
0
        void _MidiInProc(IntPtr handle, int msg, int instance, int lparam, int wparam)
        {
            switch (msg)
            {
            case MIM_OPEN:
                Opened?.Invoke(this, EventArgs.Empty);
                break;

            case MIM_CLOSE:
                Closed?.Invoke(this, EventArgs.Empty);
                break;

            case MIM_DATA:
                MidiMessage m;
                if (0 != _tempoSynchEnabled && 0xF8 == (0xFF & lparam))
                {
                    if (0 != _timingTimestamp)
                    {
                        var dif      = (_PreciseUtcNowTicks - _timingTimestamp) * 24;
                        var tpm      = TimeSpan.TicksPerMillisecond * 60000;
                        var newTempo = (tpm / (double)dif);
                        if (newTempo < _tempoSynchMininumTempo)
                        {
                            Interlocked.Exchange(ref _timingTimestamp, 0);
                        }
                        else
                        {
                            var timeNow = _PreciseUtcNowTicks;

                            if (0L == _tempoSyncTimestamp || 0L == _tempoSyncFrequency || (timeNow - _tempoSyncTimestamp > _tempoSyncFrequency))
                            {
                                var tmp = Tempo;
                                var ta  = (tmp + newTempo) / 2;
                                Tempo = ta;
                            }
                            Interlocked.Exchange(ref _timingTimestamp, timeNow);
                        }
                    }
                    else
                    {
                        var timeNow = _PreciseUtcNowTicks;
                        Interlocked.Exchange(ref _timingTimestamp, timeNow);
                    }
                }
                else
                {
                    m = MidiUtility.UnpackMessage(lparam);
                    _ProcessRecording(m);
                    Input?.Invoke(this, new MidiInputEventArgs(new TimeSpan(0, 0, 0, 0, wparam), m));
                }
                break;

            case MIM_ERROR:
                Error?.Invoke(this, new MidiInputEventArgs(new TimeSpan(0, 0, 0, 0, wparam), MidiUtility.UnpackMessage(lparam)));
                break;

            case MIM_LONGDATA:
            case MIM_LONGERROR:
                // TODO: Semi tested
                var hdr = (MIDIHDR)Marshal.PtrToStructure(new IntPtr(lparam), typeof(MIDIHDR));
                if (0 == hdr.dwBytesRecorded)
                {
                    return;                             // no message
                }
                // this code assumes it's a sysex message but I should probably check it.
                var status  = Marshal.ReadByte(hdr.lpData, 0);
                var payload = new byte[hdr.dwBytesRecorded - 1];
                Marshal.Copy(new IntPtr((int)hdr.lpData + 1), payload, 0, payload.Length);
                m = new MidiMessageSysex(payload);
                var sz = Marshal.SizeOf(typeof(MIDIHDR));
                _inHeader.dwBufferLength = _inHeader.dwBytesRecorded = 65536u;
                _inHeader.lpData         = _buffer;
                _CheckInResult(midiInPrepareHeader(_handle, ref _inHeader, sz));
                _CheckInResult(midiInAddBuffer(_handle, ref _inHeader, sz));
                _ProcessRecording(m);
                if (MIM_LONGDATA == msg)
                {
                    Input?.Invoke(this, new MidiInputEventArgs(new TimeSpan(0, 0, 0, 0, wparam), m));
                }
                else
                {
                    Error?.Invoke(this, new MidiInputEventArgs(new TimeSpan(0, 0, 0, 0, wparam), m));
                }
                break;

            case MIM_MOREDATA:
                break;

            default:
                break;
            }
        }
Exemplo n.º 2
0
        internal static MidiSequence ReadFrom(Stream stream)
        {
            MidiSequence result = new MidiSequence();
            var          rs     = (byte)0;
            var          delta  = _ReadVarlen(stream);

            if (BitConverter.IsLittleEndian)
            {
                delta = _Swap(delta);
            }
            var i = stream.ReadByte();

            while (-1 != i)
            {
                var hasStatus = false;
                var b         = (byte)i;
                if (0x7F < b)
                {
                    hasStatus = true;
                    rs        = b;
                    i         = stream.ReadByte();
                    if (-1 != i)
                    {
                        b = (byte)i;
                    }
                    else
                    {
                        b = 0;
                    }
                }
                var st = hasStatus ? rs : (byte)0;
                var m  = (MidiMessage)null;
                switch (rs & 0xF0)
                {
                case 0x80:
                    if (i == -1)
                    {
                        throw new EndOfStreamException();
                    }
                    m = new MidiMessageNoteOff(b, (byte)stream.ReadByte(), unchecked ((byte)(st & 0x0F)));
                    break;

                case 0x90:
                    if (i == -1)
                    {
                        throw new EndOfStreamException();
                    }
                    m = new MidiMessageNoteOn(b, (byte)stream.ReadByte(), unchecked ((byte)(st & 0x0F)));
                    break;

                case 0xA0:
                    if (i == -1)
                    {
                        throw new EndOfStreamException();
                    }
                    m = new MidiMessageKeyPressure(b, (byte)stream.ReadByte(), unchecked ((byte)(st & 0x0F)));
                    break;

                case 0xB0:
                    if (i == -1)
                    {
                        throw new EndOfStreamException();
                    }
                    m = new MidiMessageCC(b, (byte)stream.ReadByte(), unchecked ((byte)(st & 0x0F)));
                    break;

                case 0xC0:
                    if (i == -1)
                    {
                        throw new EndOfStreamException();
                    }
                    m = new MidiMessagePatchChange(b, unchecked ((byte)(st & 0x0F)));
                    break;

                case 0xD0:
                    if (i == -1)
                    {
                        throw new EndOfStreamException();
                    }
                    m = new MidiMessageChannelPressure(b, unchecked ((byte)(st & 0x0F)));
                    break;

                case 0xE0:
                    if (i == -1)
                    {
                        throw new EndOfStreamException();
                    }
                    m = new MidiMessageChannelPitch(b, (byte)stream.ReadByte(), unchecked ((byte)(st & 0x0F)));
                    break;

                case 0xF0:
                    switch (rs & 0xF)
                    {
                    case 0xF:
                        if (i == -1)
                        {
                            throw new EndOfStreamException();
                        }
                        var l = _ReadVarlen(stream);
                        //if (BitConverter.IsLittleEndian)
                        //	l = _Swap(l);
                        var ba = new byte[l];
                        if (l != stream.Read(ba, 0, ba.Length))
                        {
                            throw new EndOfStreamException();
                        }
                        m = new MidiMessageMeta(st, b, ba);
                        break;

                    case 0x0:
                    case 0x7:
                        if (i == -1)
                        {
                            throw new EndOfStreamException();
                        }
                        l = _ReadVarlen(b, stream);
                        //if (BitConverter.IsLittleEndian)
                        //	l = _Swap(l);
                        ba = new byte[l];
                        if (l != stream.Read(ba, 0, ba.Length))
                        {
                            throw new EndOfStreamException();
                        }
                        m = new MidiMessageSysex(st, ba);
                        break;

                    case 0x2:
                        if (i == -1)
                        {
                            throw new EndOfStreamException();
                        }
                        m = new MidiMessageWord(st, b, (byte)stream.ReadByte());
                        break;

                    case 0x3:
                        if (i == -1)
                        {
                            throw new EndOfStreamException();
                        }
                        m = new MidiMessageByte(st, b);
                        break;

                    case 0x6:

                    case 0x8:
                    case 0xA:
                    case 0xB:
                    case 0xC:
                        // status *was* specified if we got here
                        m = new MidiMessage(st);
                        break;

                    default:
                        throw new NotSupportedException("The MIDI message is not recognized.");
                    }
                    break;
                }

                result.Events.Add(new MidiEvent(delta, m));
                i = _ReadVarlen(stream);
                if (-1 == i)
                {
                    break;
                }
                delta = i;
                i     = stream.ReadByte();
            }
            return(result);
        }