예제 #1
0
        /// <summary>
        /// Dump the Midi content as a human readable text file
        /// </summary>
        /// <param name="sequence">The sequence to be dumped.</param>
        /// <param name="outputFilePath">text file to store dump to</param>
        public static void DumpMidi(this Sequence sequence, string outputFilePath)
        {
            int trackno = 1;

            using (var outfile = new StreamWriter(outputFilePath, false)) {
                // write header
                string midiTypeName = MidiHelper.GetMidiFormatString(sequence.MidiFileType);
                outfile.WriteLine("Midi Type: {0} = {1}", sequence.MidiFileType, midiTypeName);

                float  divisionType       = sequence.DivisionType;
                string divisionTypeString = "";
                if (divisionType == Sequence.PPQ)
                {
                    divisionTypeString = "PPQ";
                }
                else if (divisionType == Sequence.SMPTE_24)
                {
                    divisionTypeString = "SMPTE_24";
                }
                else if (divisionType == Sequence.SMPTE_25)
                {
                    divisionTypeString = "SMPTE_25";
                }
                else if (divisionType == Sequence.SMPTE_30)
                {
                    divisionTypeString = "SMPTE_30";
                }
                else if (divisionType == Sequence.SMPTE_30DROP)
                {
                    divisionTypeString = "SMPTE_30DROP";
                }
                outfile.WriteLine("Division Type: {0} = {1}", divisionTypeString, divisionType);
                outfile.WriteLine("Resolution: {0}", sequence.Resolution);
                outfile.WriteLine("Tracks: {0}", sequence.Tracks.Count);
                outfile.WriteLine("Time: {0} ticks", sequence.GetTickLength());
                outfile.WriteLine();

                foreach (var track in sequence.Tracks)
                {
                    outfile.WriteLine("Track {0}", trackno);
                    foreach (var ev in track.Events)
                    {
                        long tick          = ev.Tick;
                        int  beat          = (int)tick / sequence.Resolution;
                        int  tickRemainder = (int)tick % sequence.Resolution;

                        MidiMessage msg = ev.Message;
                        outfile.WriteLine("{0:0000}:{1:000} {2}", beat, tickRemainder, msg);
                    }
                    trackno++;
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Return the string representation of this object
        /// </summary>
        /// <returns>the string representation of this object</returns>
        public override string ToString()
        {
            // GetMetaStrings: { type name, length, value string }
            object[] meta        = this.GetMetaStrings();
            string   metaStrings = string.Format("{0,-22} '{2}' ({1} bytes)", meta[0], meta[1], meta[2]);

            int    messageType = GetMetaMessageType();
            string typeName    = MidiHelper.GetMetaString(messageType);

            byte[] messageData = GetMetaMessageData();
            string hex         = MidiHelper.ByteArrayToString(messageData, ",");

            //return string.Format("{0} [{1}:{2}: {3}]", metaStrings, messageType, typeName, hex);
            return(string.Format("{0}", metaStrings));
        }
예제 #3
0
        /// <summary>
        /// Return the string representation of this object
        /// </summary>
        /// <returns>the string representation of this object</returns>
        public override string ToString()
        {
            // Event, Note, Value, Patch, Text, Channel
            object[] meta        = this.GetShortStrings(false);
            string   metaStrings = string.Format("{0,-22} {1,-8} {2,-8} {3,-22} {4,-8} {5,-8}", meta[0], meta[1], meta[2], meta[3], meta[4], meta[5]);

            int    command     = GetCommand();
            string commandName = MidiHelper.GetEventTypeString((MidiHelper.MidiEventType)command);

            int channel = GetChannel();

            byte[] messageData = GetMessage();
            string hex         = MidiHelper.ByteArrayToString(messageData, ",");

            //return string.Format("{0} [{1}:{2}: {3}]", metaStrings, command, commandName, hex);
            return(string.Format("{0}", metaStrings));
        }
예제 #4
0
        /// <summary>
        /// Return the string representation of this object
        /// </summary>
        /// <returns>the string representation of this object</returns>
        public override string ToString()
        {
            string hex = MidiHelper.ByteArrayToString(data, ",");

            return(string.Format("Sysex: [{0}]", hex));
        }
예제 #5
0
        /// <summary>Converts the MIDI sequence into a new one with the desired format.</summary>
        /// <param name="sequence">The sequence to be converted.</param>
        /// <param name="format">The format to which we want to convert the sequence.</param>
        /// <param name="options">Options used when doing the conversion.</param>
        /// <param name="newResolution">the new resolution (disable using 0 or -1)</param>
        /// <returns>The new, converted sequence.</returns>
        /// <remarks>This is based on the excellent MidiSharp package by Stephen Toub.</remarks>
        public static Sequence Convert(this Sequence sequence, int format, FormatConversionOption options, int newResolution, string trackName)
        {
            if (sequence.MidiFileType == format)
            {
                // If the desired format is the same as the original, just return a copy.
                // No transformation is necessary.
                sequence = new Sequence(sequence);
            }
            else if (format != 0 || sequence.Tracks.Count == 1)
            {
                // If the desired format is is not 0 or there's only one track, just copy the sequence with a different format number.
                // If it's not zero, then multiple tracks are acceptable, so no transformation is necessary.
                // Or if there's only one track, then there's no possible transformation to be done.
                var newSequence = new Sequence(sequence.DivisionType, sequence.Resolution, 0, format);
                foreach (Track t in sequence.Tracks)
                {
                    newSequence.Tracks.Add(new Track(t));
                }
                sequence = newSequence;
            }
            else
            {
                // Now the harder cases, converting to format 0.  We need to combine all tracks into 1,
                // as format 0 requires that there only be a single track with all of the events for the song.
                int originalResolution = sequence.Resolution;
                if (newResolution <= 0)
                {
                    newResolution = originalResolution;
                }

                sequence = new Sequence(sequence);
                sequence.MidiFileType = (int)MidiHelper.MidiFormat.SingleTrack;

                // Add all events to new track (except for end of track markers and SequenceOrTrackName events)
                int trackNumber = 0;
                var newTrack    = new Track();

                foreach (Track track in sequence.Tracks)
                {
                    foreach (MidiEvent midiEvent in track.Events)
                    {
                        bool doAddEvent = true;

                        var msg = midiEvent.Message;

                        // check if this is a meta message
                        var mm = msg as MetaMessage;
                        if (mm != null)
                        {
                            // we have a meta message
                            // add all meta messages except the end of track markers (we'll add our own)
                            int type = mm.GetMetaMessageType();

                            if (type == (int)MidiHelper.MetaEventType.EndOfTrack)
                            {
                                doAddEvent = false;
                            }
                            else if (type == (int)MidiHelper.MetaEventType.SequenceOrTrackName)
                            {
                                doAddEvent = false;

                                // store track name, will be used later
                                if (string.IsNullOrEmpty(trackName))
                                {
                                    byte[] data = mm.GetMetaMessageData();
                                    string text = MidiHelper.GetString(data);
                                    trackName = MidiHelper.TextString(text);
                                }
                            }
                        }

                        // check if this is a short message
                        var sm = msg as ShortMessage;
                        if (sm != null)
                        {
                            // get the data
                            var channel = sm.GetChannel();
                            var cmd     = sm.GetCommand();
                            var data1   = sm.GetData1();
                            var data2   = sm.GetData2();

                            // If this event has a channel, and if we're storing tracks as channels, copy to it
                            if ((options & FormatConversionOption.CopyTrackToChannel) > 0 &&
                                trackNumber >= MidiHelper.MIN_CHANNEL && trackNumber <= MidiHelper.MAX_CHANNEL)
                            {
                                if (sm.IsChannelMessage())
                                {
                                    // store the track number as the channel
                                    sm.SetMessage(cmd, trackNumber, data1, data2);
                                }
                            }

                            if ((options & FormatConversionOption.NoteOffZero2NoteOnZero) > 0)
                            {
                                // If the event is a NoteOff with Volume 0
                                if (cmd == (int)MidiHelper.MidiEventType.NoteOff && data2 == 0)
                                {
                                    // convert to a NoteOn instead
                                    sm.SetMessage((int)MidiHelper.MidiEventType.NoteOn, channel, data1, data2);
                                }
                            }
                        }

                        // convert ticks if resolution has changed
                        if (originalResolution != newResolution)
                        {
                            if (midiEvent.Tick != 0)
                            {
                                double fraction = (double)midiEvent.Tick / (double)originalResolution;
                                int    tick     = (int)(fraction * newResolution);
                                midiEvent.Tick = tick;
                            }
                        }

                        // Add all events, except for end of track markers (we'll add our own)
                        if (doAddEvent)
                        {
                            //newTrack.Events.Add(midiEvent); // add to end of list
                            newTrack.Add(midiEvent);                             // add in the right position based on the tick
                        }
                    }
                    trackNumber++;
                }

                if (originalResolution != newResolution)
                {
                    sequence.Resolution = newResolution;
                }

                // Sort the events by total time
                // newTrack.Events.Sort((x, y) => x.Tick.CompareTo(y.Tick));
                // Note! using newTrack.Add instead of newTrack.Events.Add, already ensures a correct sort order

                // Top things off with an end-of-track marker.
                newTrack.Add(MetaEvent.CreateMetaEvent("EndOfTrack", "", newTrack.Ticks(), 0));

                // add a new track name as the very first event
                newTrack.Events.Insert(0, MetaEvent.CreateMetaEvent((int)MidiHelper.MetaEventType.SequenceOrTrackName, trackName, 0, 0));

                // We now have all of the combined events in newTrack.  Clear out the sequence, replacing all the tracks
                // with this new one.
                sequence.Tracks.Clear();
                sequence.Tracks.Add(newTrack);
            }

            return(sequence);
        }
예제 #6
0
        /// <summary>
        /// Creates C# code from a MIDI sequence.
        /// </summary>
        /// <param name="sequence">The sequence to be generated as C# code and saved.</param>
        /// <param name="outputFilePath">path to text file to store generated code to</param>
        public static void SaveGenerateMidiCode(this Sequence sequence, string outputFilePath)
        {
            // generate code
            int trackno = 1;

            using (var outfile = new StreamWriter(outputFilePath, false)) {
                string   midiTypeName = MidiHelper.GetMidiFormatString(sequence.MidiFileType);
                DateTime now          = DateTime.Now;

                outfile.WriteLine("/*");
                outfile.WriteLine("* Generated by GnuMidi");
                outfile.WriteLine("* Author: [email protected]");
                outfile.WriteLine("* Date: {0}", now.ToString("yyyy-MM-dd"));
                outfile.WriteLine("* Time: {0}", now.ToString("HH:mm"));
                outfile.WriteLine("*/");
                outfile.WriteLine("using System;");
                outfile.WriteLine("using System.IO;");
                outfile.WriteLine("using gnu.sound.midi;");
                outfile.WriteLine("using gnu.sound.midi.file;");
                outfile.WriteLine("using gnu.sound.midi.info;");
                outfile.WriteLine();
                outfile.WriteLine("namespace MidiGeneration");
                outfile.WriteLine("{");
                outfile.WriteLine("	public static class GenerateMidi");
                outfile.WriteLine("	{");
                outfile.WriteLine("		public static void Main(string[] args)");
                outfile.WriteLine("		{");
                outfile.WriteLine("			// Generate Midi");
                outfile.WriteLine("			var sequence = GenerateSequence();");
                outfile.WriteLine("			sequence.DumpMidi(\"generated_dump.txt\");");
                outfile.WriteLine("			new MidiFileWriter().Write(sequence, sequence.MidiFileType, new FileInfo(\"generated.mid\"));");
                outfile.WriteLine("		}");
                outfile.WriteLine();

                outfile.WriteLine("		public static Sequence GenerateSequence() {");
                outfile.WriteLine();
                outfile.WriteLine("			// Generate midi file");
                outfile.WriteLine("			var sequence = new Sequence({0}, {1}, 0, (int) MidiHelper.MidiFormat.{2});", sequence.DivisionType, sequence.Resolution, midiTypeName);

                foreach (var track in sequence.Tracks)
                {
                    outfile.WriteLine();
                    outfile.WriteLine("			var track{0} = sequence.CreateTrack();", trackno);
                    foreach (var ev in track.Events)
                    {
                        long tick          = ev.Tick;
                        int  beat          = (int)tick / sequence.Resolution;
                        int  tickRemainder = (int)tick % sequence.Resolution;

                        MidiMessage msg = ev.Message;

                        // check if this is a meta message
                        var mm = msg as MetaMessage;
                        if (mm != null)
                        {
                            string metaCodeString = mm.CreateMetaEventGeneratedCode(tick, sequence.Resolution);
                            outfile.WriteLine("			track{0}.Add({1});", trackno, metaCodeString);
                        }

                        // check if this is a short message
                        var sm = msg as ShortMessage;
                        if (sm != null)
                        {
                            string shortCodeString = sm.CreateShortEventGeneratedCode(true, tick);
                            outfile.WriteLine("			track{0}.Add({1}", trackno, shortCodeString);
                        }

                        // check if this is a sysex message
                        var ss = msg as SysexMessage;
                        if (ss != null)
                        {
                            var    data        = ss.GetMessage();
                            string sysexString = MidiHelper.ByteArrayToString(data, ",");
                            outfile.WriteLine("			track{0}.Add(SysexEvent.CreateSysexEvent(\"{1}\", {2}));", trackno, sysexString, tick);
                        }
                    }
                    trackno++;
                }

                outfile.WriteLine();
                outfile.WriteLine("			return sequence;");
                outfile.WriteLine("		}");

                outfile.WriteLine("	}");
                outfile.WriteLine("}");
            }
        }