예제 #1
0
        public void Write_Compression_DeleteDefaultKeySignature_Obsolete()
        {
            var nonDefaultKeySignatureEvent = new KeySignatureEvent(-5, 1);

            var midiFile = new MidiFile(
                new TrackChunk(
                    new NoteOnEvent((SevenBitNumber)100, (SevenBitNumber)50),
                    new NoteOffEvent((SevenBitNumber)100, (SevenBitNumber)50),
                    new UnknownMetaEvent(254),
                    new KeySignatureEvent(),
                    nonDefaultKeySignatureEvent));

            Write_Compression_Obsolete(
                midiFile,
                CompressionPolicy.DeleteDefaultKeySignature,
                (fileInfo1, fileInfo2) =>
            {
                var originalMidiFile = MidiFile.Read(fileInfo1.FullName);
                Assert.AreEqual(
                    2,
                    originalMidiFile.GetTrackChunks().SelectMany(c => c.Events).OfType <KeySignatureEvent>().Count(),
                    "Invalid count of Key Signature events in original file.");

                var newMidiFile        = MidiFile.Read(fileInfo2.FullName);
                var keySignatureEvents = newMidiFile.GetTrackChunks().SelectMany(c => c.Events).OfType <KeySignatureEvent>().ToArray();
                Assert.AreEqual(
                    1,
                    keySignatureEvents.Length,
                    "Invalid count of Key Signature events in new file.");

                MidiAsserts.AreEventsEqual(keySignatureEvents[0], nonDefaultKeySignatureEvent, false, "Invalid Key Signature event.");
            });
        }
예제 #2
0
        public void Write_DeleteDefaultKeySignature_DeleteDefaultSetTempo()
        {
            var nonDefaultKeySignatureEvent = new KeySignatureEvent(-5, 1);
            var nonDefaultSetTempoEvent     = new SetTempoEvent(100000);

            var midiFile = new MidiFile(
                new TrackChunk(
                    new NoteOnEvent((SevenBitNumber)100, (SevenBitNumber)50),
                    new NoteOffEvent((SevenBitNumber)100, (SevenBitNumber)50),
                    new UnknownMetaEvent(254),
                    new KeySignatureEvent(),
                    nonDefaultKeySignatureEvent,
                    new SetTempoEvent(),
                    nonDefaultSetTempoEvent));

            Write(
                midiFile,
                settings =>
            {
                settings.DeleteDefaultKeySignature = true;
                settings.DeleteDefaultSetTempo     = true;
            },
                (fileInfo1, fileInfo2) =>
            {
                var originalMidiFile = MidiFile.Read(fileInfo1.FullName);
                var newMidiFile      = MidiFile.Read(fileInfo2.FullName);

                //

                Assert.AreEqual(
                    2,
                    originalMidiFile.GetTrackChunks().SelectMany(c => c.Events).OfType <KeySignatureEvent>().Count(),
                    "Invalid count of Key Signature events in original file.");

                var keySignatureEvents = newMidiFile.GetTrackChunks().SelectMany(c => c.Events).OfType <KeySignatureEvent>().ToArray();
                Assert.AreEqual(
                    1,
                    keySignatureEvents.Length,
                    "Invalid count of Key Signature events in new file.");

                MidiAsserts.AreEventsEqual(keySignatureEvents[0], nonDefaultKeySignatureEvent, false, "Invalid Key Signature event.");

                //

                Assert.AreEqual(
                    2,
                    originalMidiFile.GetTrackChunks().SelectMany(c => c.Events).OfType <SetTempoEvent>().Count(),
                    "Invalid count of Set Tempo events in original file.");

                var setTempoEvents = newMidiFile.GetTrackChunks().SelectMany(c => c.Events).OfType <SetTempoEvent>().ToArray();
                Assert.AreEqual(
                    1,
                    setTempoEvents.Length,
                    "Invalid count of Set Tempo events in new file.");

                MidiAsserts.AreEventsEqual(setTempoEvents[0], nonDefaultSetTempoEvent, false, "Invalid Set Tempo event.");
            });
        }
예제 #3
0
        private bool HasKeySignature(string midiFileName)
        {
            MidiFile midiFile          = new MidiFile(midiFileName);
            bool     foundKeySignature = false;

            for (int track = 0; track < midiFile.Tracks; track++)
            {
                foreach (MidiEvent midiEvent in midiFile.Events[track])
                {
                    KeySignatureEvent kse = midiEvent as KeySignatureEvent;
                    if (kse != null)
                    {
                        foundKeySignature = true;
                    }
                }
            }
            return(foundKeySignature);
        }
예제 #4
0
        public int getKey()
        {
            // Assume C
            int key = 0;

            // For each track in the file
            for (int track = 0; track < m_data.Tracks; track++)
            {
                // For each MidiEvent in the track
                foreach (MidiEvent e in m_data[track])
                {
                    // If this is a MetaEvent
                    if (e.CommandCode == MidiCommandCode.MetaEvent)
                    {
                        // Check if the type of event is KeySignatureEvent
                        if (e is KeySignatureEvent)
                        {
                            // Good. We have a key! Cast it.
                            KeySignatureEvent n = (KeySignatureEvent)e;

                            // Representation is:
                            // -: # of flats (to -7)
                            // 0: C
                            // +: # of sharps (to +7)

                            // Directly read in the value
                            key = n.SharpsFlats;

                            // HACKHACK: The documentation for NAUDIO
                            // is incorrect. Flat keys are stored as 255
                            // minus a key adjustment amount. This corrects
                            // it down to the -7 to 0 range expected.
                            if (key > 7)
                            {
                                key = -1 * (255 - key + 1);
                            }
                        }
                    }
                }
            }

            // Return it
            return(key);
        }
예제 #5
0
        public IMessage getMessage(MetaEvent metaEvent)
        {
            switch (metaEvent.MetaEventType)
            {
            case SetTempo:
                TempoEvent       tempoEvent = (TempoEvent)metaEvent;
                TempoMetaMessage message    = TempoMetaMessage(tempoEvent.Tempo, tempoEvent.AbsoluteTime);
                return(message);

            case TimeSignature:
                TimeSignatureEvent       timeSignatureEvent = (TimeSignatureEvent)metaEvent;
                TimeSignatureMetaMessage message            = TimeSignatureMetaMessage(timeSignatureEvent.Numerator, timeSignatureEvent.Numerator, timeSignatureEvent.AbsoluteTime);
                return(message);

            case KeySignature:
                KeySignatureEvent        keySignatureEvent = (KeySignatureEvent)metaEvent;
                TimeSignatureMetaMessage message           = TimeSignatureMetaMessage((sbyte)keySignatureEvent.SharpsFlats, (byte)keySignatureEvent.MajorMinor, timeSignatureEvent.AbsoluteTime);
                return(message);

            default:
                return(null);    // TODO remaining MetaMessage types
            }
        }
예제 #6
0
        private static Tuple <Option <MidiEvent>, int, byte> NextEvent(List <byte> trackData, int startIndex, byte lastMidiChannel)
        {
            var i = startIndex - 1;

            MidiEvent midiEvent = null;

            {
                int deltaTime;
                {
                    var lengthTemp = new List <byte>();
                    do
                    {
                        i += 1;
                        lengthTemp.Add(trackData.ElementAt(i));
                    } while (trackData.ElementAt(i) > 0x7F);

                    deltaTime = VariableLengthUtil.decode_to_int(lengthTemp);
                }

                i += 1;

                var eventTypeValue = trackData.ElementAt(i);

                // MIDI Channel Events
                if ((eventTypeValue & 0xF0) < 0xF0)
                {
                    var midiChannelEventType = (byte)(eventTypeValue & 0xF0);
                    var midiChannel          = (byte)(eventTypeValue & 0x0F);
                    i += 1;
                    var  parameter1 = trackData.ElementAt(i);
                    byte parameter2;

                    // One or two parameter type
                    switch (midiChannelEventType)
                    {
                    // One parameter types
                    case 0xC0:
                        midiEvent       = new ProgramChangeEvent(deltaTime, midiChannel, parameter1);
                        lastMidiChannel = midiChannel;
                        break;

                    case 0xD0:
                        midiEvent       = new ChannelAftertouchEvent(deltaTime, midiChannel, parameter1);
                        lastMidiChannel = midiChannel;
                        break;

                    // Two parameter types
                    case 0x80:
                        i              += 1;
                        parameter2      = trackData.ElementAt(i);
                        midiEvent       = new NoteOffEvent(deltaTime, midiChannel, parameter1, parameter2);
                        lastMidiChannel = midiChannel;
                        break;

                    case 0x90:
                        i              += 1;
                        parameter2      = trackData.ElementAt(i);
                        midiEvent       = new NoteOnEvent(deltaTime, midiChannel, parameter1, parameter2);
                        lastMidiChannel = midiChannel;
                        break;

                    case 0xA0:
                        i              += 1;
                        parameter2      = trackData.ElementAt(i);
                        midiEvent       = new NoteAftertouchEvent(deltaTime, midiChannel, parameter1, parameter2);
                        lastMidiChannel = midiChannel;
                        break;

                    case 0xB0:
                        i              += 1;
                        parameter2      = trackData.ElementAt(i);
                        midiEvent       = new ControllerEvent(deltaTime, midiChannel, parameter1, parameter2);
                        lastMidiChannel = midiChannel;
                        break;

                    case 0xE0:
                        i              += 1;
                        parameter2      = trackData.ElementAt(i);
                        midiEvent       = new PitchBendEvent(deltaTime, midiChannel, parameter1, parameter2);
                        lastMidiChannel = midiChannel;
                        break;

                    // Might be a Control Change Messages LSB
                    default:
                        midiEvent = new ControllerEvent(deltaTime, lastMidiChannel, eventTypeValue, parameter1);
                        break;
                    }

                    i += 1;
                }
                // Meta Events
                else if (eventTypeValue == 0xFF)
                {
                    i += 1;
                    var metaEventType = trackData.ElementAt(i);
                    i += 1;
                    var metaEventLength = trackData.ElementAt(i);
                    i += 1;
                    var metaEventData = Enumerable.Range(i, metaEventLength).Select(trackData.ElementAt).ToArray();

                    switch (metaEventType)
                    {
                    case 0x00:
                        midiEvent = new SequenceNumberEvent(BitConverter.ToUInt16(metaEventData.Reverse().ToArray(), 0));
                        break;

                    case 0x01:
                        midiEvent = new TextEvent(deltaTime, StringEncoder.GetString(metaEventData));
                        break;

                    case 0x02:
                        midiEvent = new CopyrightNoticeEvent(StringEncoder.GetString(metaEventData));
                        break;

                    case 0x03:
                        midiEvent = new SequenceOrTrackNameEvent(StringEncoder.GetString(metaEventData));
                        break;

                    case 0x04:
                        midiEvent = new InstrumentNameEvent(deltaTime, StringEncoder.GetString(metaEventData));
                        break;

                    case 0x05:
                        midiEvent = new LyricsEvent(deltaTime, StringEncoder.GetString(metaEventData));
                        break;

                    case 0x06:
                        midiEvent = new MarkerEvent(deltaTime, StringEncoder.GetString(metaEventData));
                        break;

                    case 0x07:
                        midiEvent = new CuePointEvent(deltaTime, StringEncoder.GetString(metaEventData));
                        break;

                    case 0x20:
                        midiEvent = new MIDIChannelPrefixEvent(deltaTime, metaEventData[0]);
                        break;

                    case 0x2F:
                        midiEvent = new EndOfTrackEvent(deltaTime);
                        break;

                    case 0x51:
                        var tempo =
                            (metaEventData[2] & 0x0F) +
                            ((metaEventData[2] & 0xF0) * 16) +
                            ((metaEventData[1] & 0x0F) * 256) +
                            ((metaEventData[1] & 0xF0) * 4096) +
                            ((metaEventData[0] & 0x0F) * 65536) +
                            ((metaEventData[0] & 0xF0) * 1048576);
                        midiEvent = new SetTempoEvent(deltaTime, tempo);
                        break;

                    case 0x54:
                        midiEvent = new SMPTEOffsetEvent(deltaTime, metaEventData[0], metaEventData[1], metaEventData[2], metaEventData[3], metaEventData[4]);
                        break;

                    case 0x58:
                        midiEvent = new TimeSignatureEvent(deltaTime, metaEventData[0], metaEventData[1], metaEventData[2], metaEventData[3]);
                        break;

                    case 0x59:
                        midiEvent = new KeySignatureEvent(deltaTime, metaEventData[0], metaEventData[1]);
                        break;

                    case 0x7F:
                        midiEvent = new SequencerSpecificEvent(deltaTime, metaEventData);
                        break;
                    }

                    i += metaEventLength;
                }
                // System Exclusive Events
                else if (eventTypeValue == 0xF0 || eventTypeValue == 0xF7)
                {
                    var lengthTemp = new List <byte>();
                    do
                    {
                        i += 1;
                        lengthTemp.Add(trackData.ElementAt(i));
                    } while (trackData.ElementAt(i) > 0x7F);

                    var eventLength = VariableLengthUtil.decode_to_int(lengthTemp);

                    i += 1;

                    var eventData = Enumerable.Range(i, eventLength).Select(trackData.ElementAt);

                    midiEvent = new SysexEvent(deltaTime, eventTypeValue, eventData);

                    i += eventLength;
                }
            }

            return(midiEvent != null
                ? new Tuple <Option <MidiEvent>, int, byte>(new Some <MidiEvent>(midiEvent), i - startIndex, lastMidiChannel)
                : new Tuple <Option <MidiEvent>, int, byte>(new None <MidiEvent>(), i - startIndex, lastMidiChannel));
        }
예제 #7
0
        private void CreateTrackZeroEvents(List<MidiEvent> trackZeroEvents, MidiFile midiFile, long startAbsoluteTime, long endAbsoluteTime, bool includeAllTrackEvents)
        {
            MetaEvent tempoEvent = null;
            MetaEvent keySignatureEvent = null;
            MetaEvent timeSignatureEvent = null;
            bool gotAStartTempo = false;
            bool gotAStartKeySig = false;
            bool gotAStartTimeSig = false;

            for (int track = 0; track < ((includeAllTrackEvents) ? midiFile.Tracks : 1); track++)
            {
                foreach (MidiEvent midiEvent in midiFile.Events[track])
                {
                    if ((midiEvent.AbsoluteTime >= startAbsoluteTime) && (midiEvent.AbsoluteTime < endAbsoluteTime))
                    {
                        bool exclude = false;
                        MetaEvent metaEvent = midiEvent as MetaEvent;
                        if (metaEvent != null)
                        {
                            if (metaEvent.MetaEventType == MetaEventType.EndTrack)
                            {
                                // we'll add our own
                                exclude = true;
                            }
                            if (metaEvent.AbsoluteTime == startAbsoluteTime)
                            {
                                switch (metaEvent.MetaEventType)
                                {
                                    case MetaEventType.SetTempo:
                                        gotAStartTempo = true;
                                        break;
                                    case MetaEventType.KeySignature:
                                        gotAStartKeySig = true;
                                        break;
                                    case MetaEventType.TimeSignature:
                                        gotAStartTimeSig = true;
                                        break;
                                    case MetaEventType.Marker:
                                        // already done this elsewhere
                                        exclude = true;
                                        break;
                                    case MetaEventType.TextEvent:
                                        // exclude if text events as markers is on
                                        exclude = settings.TextEventMarkers;
                                        break;
                                }
                            }
                        }
                        else
                        {
                            exclude = !includeAllTrackEvents;
                        }
                        if (!exclude)
                        {
                            AddMidiEvent(midiEvent, trackZeroEvents, endAbsoluteTime);
                        }

                    }
                    else if (midiEvent.AbsoluteTime < startAbsoluteTime)
                    {
                        // TODO: perhaps look out for a patch change too
                        MetaEvent metaEvent = midiEvent as MetaEvent;
                        if (metaEvent != null)
                        {
                            switch (metaEvent.MetaEventType)
                            {
                                case MetaEventType.TextEvent:
                                case MetaEventType.Copyright:
                                case MetaEventType.SequenceTrackName:
                                    //TextEvent te = (TextEvent)metaEvent;
                                    //trackZeroEvents.Add(new TextEvent(te.Text, metaEvent.MetaEventType, startAbsoluteTime));
                                    break;
                                case MetaEventType.KeySignature:
                                    KeySignatureEvent kse = (KeySignatureEvent)metaEvent;
                                    keySignatureEvent = new KeySignatureEvent(kse.SharpsFlats, kse.MajorMinor, startAbsoluteTime);
                                    break;
                                case MetaEventType.SetTempo:
                                    tempoEvent = new TempoEvent(((TempoEvent)metaEvent).MicrosecondsPerQuarterNote, startAbsoluteTime); ;
                                    break;
                                case MetaEventType.TimeSignature:
                                    TimeSignatureEvent tse = (TimeSignatureEvent)metaEvent;
                                    timeSignatureEvent = new TimeSignatureEvent(tse.Numerator, tse.Denominator, tse.TicksInMetronomeClick, tse.No32ndNotesInQuarterNote, startAbsoluteTime);
                                    break;
                                case MetaEventType.TrackSequenceNumber:
                                    // TODO: needed?
                                    break;
                                case MetaEventType.TrackInstrumentName:
                                case MetaEventType.Lyric:
                                case MetaEventType.CuePoint:
                                case MetaEventType.Marker:
                                case MetaEventType.SequencerSpecific:
                                case MetaEventType.DeviceName:
                                case MetaEventType.ProgramName:
                                case MetaEventType.SmpteOffset:
                                case MetaEventType.EndTrack:
                                    // ignore these
                                    break;
                                default:
                                    //System.Diagnostics.Debug.Assert(false, String.Format("Unexpected meta event type {0}", metaEvent));
                                    break;
                            }
                        }
                    }
                }
            }
            if ((tempoEvent != null) && (!gotAStartTempo))
                trackZeroEvents.Add(tempoEvent);
            if ((keySignatureEvent != null) && (!gotAStartKeySig))
                trackZeroEvents.Add(keySignatureEvent);
            if ((timeSignatureEvent != null) && (!gotAStartTimeSig))
                trackZeroEvents.Add(timeSignatureEvent);

            // add an end track marker
            trackZeroEvents.Sort(new MidiEventComparer());
            trackZeroEvents.Add(new MetaEvent(MetaEventType.EndTrack,0,trackZeroEvents[trackZeroEvents.Count-1].AbsoluteTime));
        }
예제 #8
0
        public static Key GetKeyFromKeySignature(KeySignatureEvent keySignature)
        {
            // major = 0 ~ 11 / minor = 21 ~ 23, 12 ~ 20
            int k = 0;

            switch (keySignature.SharpsFlats)
            {
            case 0:         // C
                break;

            case -5:        // Db = C#
            case 7:
                k += 1;
                break;

            case 2:         // D
                k += 2;
                break;

            case -3:        // Eb
                k += 3;
                break;

            case 4:         // E
                k += 4;
                break;

            case -1:        // F
                k += 5;
                break;

            case -6:        // Gb = F#
            case 6:
                k += 6;
                break;

            case 1:         // G
                k += 7;
                break;

            case -4:        // Ab
                k += 8;
                break;

            case 3:         // A
                k += 9;
                break;

            case -2:        // Bb
                k += 10;
                break;

            case 5:         // B = Cb
            case -7:
                k += 11;
                break;
            }
            if (keySignature.MajorMinor == 0)
            {
                // major
                return((Key)k);
            }
            else
            {
                // minor
                return((Key)(((k + 9) % 12) + 12));
            }
        }