Пример #1
0
        /// <summary>
        /// Update the data content of the message
        /// This is parsed into a <code>byte[]</code> that becomes the data of
        /// the MetaMessage.<br>
        /// Most events treat the string as a text value and just convert
        /// each character to a <code>byte</code> in the array but the
        /// following message types are handled specially
        /// <dl>
        /// <dt>Tempo</dt>
        /// <dd>an integer value with an optional "bpm" suffix. e.g. 120bpm</dd>
        /// <dt>SmpteOffset</dt>
        /// <dd>a string in the form <code>h:m:s:f:d</code> where<br>
        /// h=hours m=minutes s=seconds f=frames d=fields<br>
        /// If fewer than 5 values are given then the parser treats them as<br>
        /// 1. <b>s</b><br>
        /// 2. <b>m:s</b><br>
        /// 3. <b>h:m:s</b><br>
        /// 4. <b>h:m:s:f</b><br>
        /// 5. <b>h:m:s:f:d</b><br>
        /// and the unspecified values are set to zero.
        /// </dd>
        /// <dt>TimeSignature</dt>
        /// <dd>a time signature string in the format <code>n[/d]</code> where<br>
        /// n=numerator d=denominator<br>
        /// If only <code>n</code> is given then <code>d</code> defaults to 4</dd>
        /// <dt>KeySignature</dt>
        /// <dd>one of the following key signature strings<br>
        /// <b>Cb Gb Db Ab Eb Bb F C G D A E B F# C#</b/></dd>
        /// <dt>SequenceNumber and SequencerSpecificEvent</dt>
        /// <dd>a space-separated list of values that are parsed into
        /// a <code>byte[]</code> using <code>Convert.ToByte()</code><br>
        /// If any value cannot be parsed into a <code>byte</code>
        /// then it is treated as zero</dd>
        /// </dl
        /// </summary>
        /// <param name="mess">the message to update</param>
        /// <param name="value">a String that represents the data for the event.<br></param>
        /// <param name="ticksPerBeat">the tick resolution of the sequence</param>
        public static void SetMetaData(MetaMessage mess, string value, int ticksPerBeat)
        {
            byte[] data;
            int    type = mess.GetMetaMessageType();

            if (mess.IsText())
            {
                data = MidiHelper.GetBytes(value);
            }
            else if (type == (int)MidiHelper.MetaEventType.Tempo)
            {
                int bpm = ParseTempo(value);
                data = BpmToMicroSecs(bpm);
            }
            else if (type == (int)MidiHelper.MetaEventType.TimeSignature)
            {
                data = ParseTimeSignature(value, ticksPerBeat);
            }
            else if (type == (int)MidiHelper.MetaEventType.KeySignature)
            {
                data = MidiHelper.ConvertSBytes(KeySignatures.GetKeyValues(value));
            }
            else if (type == (int)MidiHelper.MetaEventType.SmpteOffset)
            {
                data = ParseSMPTEOffset(value);
            }
            else
            {
                // treat the string as a space separated list of
                // string representations of byte values
                // TODO: Should handle decimal, hexadecimal and octal representations
                // originally using the java.lang.Byte.decode() method
                data = MidiHelper.StringToByteArray(value, " ");
            }

            if (data != null)
            {
                mess.SetMessage(type, data, data.Length);
            }
        }
Пример #2
0
        // A good MIDI Files Specification: http://www.somascape.org/midi/tech/mfile.html

        #region MetaMessage Extension Methods

        /// <summary>
        /// Get the values that represent the given META event.
        /// The returned array consists of <ol>
        /// <li>the event name as a String</li>
        /// <li>the length of the event data as an Integer</li>
        /// <li>the event data as a String</li>
        /// </ol>
        /// </summary>
        /// <param name="mess">the META message to format</param>
        /// <returns>the representation of the message</returns>
        public static object[] GetMetaStrings(this MetaMessage mess)
        {
            // Some data is String some is a series of bytes others are neither
            bool dumpText  = false;
            bool dumpBytes = false;

            int type = mess.GetMetaMessageType();

            byte[] data = mess.GetMetaMessageData();

            // The returned Object array
            // { type name, length, value string }
            object[] result = { "M:", null, "" };
            result[1] = data.Length;

            switch (type)
            {
            case (int)MidiHelper.MetaEventType.SequenceNumber:
                result[0] = "M:SequenceNumber";
                dumpBytes = true;
                break;

            case (int)MidiHelper.MetaEventType.TextEvent:
                result[0] = "M:TextEvent";
                dumpText  = true;
                break;

            case (int)MidiHelper.MetaEventType.CopyrightNotice:
                result[0] = "M:CopyrightNotice";
                dumpText  = true;
                break;

            case (int)MidiHelper.MetaEventType.SequenceOrTrackName:
                result[0] = "M:SequenceOrTrackName";
                dumpText  = true;
                break;

            case (int)MidiHelper.MetaEventType.InstrumentName:
                result[0] = "M:InstrumentName";
                dumpText  = true;
                break;

            case (int)MidiHelper.MetaEventType.LyricText:
                result[0] = "M:LyricText";
                dumpText  = true;
                break;

            case (int)MidiHelper.MetaEventType.MarkerText:
                result[0] = "M:MarkerText";
                dumpText  = true;
                break;

            case (int)MidiHelper.MetaEventType.CuePoint:
                result[0] = "M:CuePoint";
                dumpText  = true;
                break;

            case (int)MidiHelper.MetaEventType.ProgramName:
                result[0] = "M:ProgramName";
                dumpText  = true;
                break;

            case (int)MidiHelper.MetaEventType.DeviceName:
                result[0] = "M:DeviceName";
                dumpText  = true;
                break;

            case (int)MidiHelper.MetaEventType.SmpteOffset:
                result[0] = "M:SmpteOffset";
                // Hour, Minute, Second, Frame, Field
                // hr mn se fr ff
                result[2] = string.Format("{0:00}:{1:00}:{2:00}:{3:00}:{4:00}",
                                          data[0] & 0x00FF,
                                          data[1] & 0x00FF,
                                          data[2] & 0x00FF,
                                          data[3] & 0x00FF,
                                          data[4] & 0x00FF);
                break;

            case (int)MidiHelper.MetaEventType.TimeSignature:
                result[0] = "M:TimeSignature";
                int nn = (data[0] & 0x00FF);                         // numerator
                int dd = (int)(Math.Pow(2, (data[1] & 0x00FF)));     // denominator
                int cc = (data[2] & 0x00FF);                         // midiClocksPerMetronomeClick
                int bb = (data[3] & 0x00FF);                         // notated 32nd-notes in a MIDI quarter-note
                result[2] = nn + "/" + dd + ", "
                            + cc + " clicks per metronome, "
                            + bb + " 32nd notes per quarter-note";
                break;

            case (int)MidiHelper.MetaEventType.KeySignature:
                result[0] = "M:KeySignature";
                result[2] = KeySignatures.GetKeyName(data);
                break;

            case (int)MidiHelper.MetaEventType.Tempo:
                result[0] = "M:Tempo";
                int bpm = MicroSecsToBpm(data);
                result[2] = string.Format("{0}", bpm);
                break;

            case (int)MidiHelper.MetaEventType.EndOfTrack:
                result[0] = "M:EndOfTrack";
                break;

            case (int)MidiHelper.MetaEventType.SequencerSpecificEvent:
                result[0] = "M:SequencerSpecificEvent";
                dumpBytes = true;
                break;

            default:
                result[0] = "M:" + type;
                dumpBytes = true;
                break;
            }

            if (dumpText)
            {
                result[2] = MidiHelper.GetStringWithoutNewlines(data);
            }

            if (dumpBytes)
            {
                result[2] = MidiHelper.ByteArrayToHexString(data, ",");
            }
            return(result);
        }
Пример #3
0
        /// <summary>
        /// Create a C# code line for this meta event
        /// </summary>
        /// <param name="mess">the META message to process</param>
        /// <param name="tick">the position of the event in the sequence</param>
        /// <param name="ticksPerBeat">the tick resolution of the sequence</param>
        /// <returns>a C# code line</returns>
        public static string CreateMetaEventGeneratedCode(this MetaMessage mess, long tick, int ticksPerBeat)
        {
            int    type     = mess.GetMetaMessageType();
            string typeName = MidiHelper.GetMetaString(type);

            byte[] data       = mess.GetMetaMessageData();
            int    dataLength = data.Length;

            string value = "";

            switch (type)
            {
            // First handle the text based events (0x01 - 0x09)
            case (int)MidiHelper.MetaEventType.TextEvent:
            case (int)MidiHelper.MetaEventType.CopyrightNotice:
            case (int)MidiHelper.MetaEventType.SequenceOrTrackName:
            case (int)MidiHelper.MetaEventType.InstrumentName:
            case (int)MidiHelper.MetaEventType.LyricText:
            case (int)MidiHelper.MetaEventType.MarkerText:
            case (int)MidiHelper.MetaEventType.CuePoint:
            case (int)MidiHelper.MetaEventType.ProgramName:
            case (int)MidiHelper.MetaEventType.DeviceName:
                string text = MidiHelper.GetString(data);
                value = MidiHelper.TextString(text);
                break;

            // And then the special events
            case (int)MidiHelper.MetaEventType.SmpteOffset:
                // Hour, Minute, Second, Frame, Field
                // hr mn se fr ff
                value = string.Format("{0:00}:{1:00}:{2:00}:{3:00}:{4:00}",
                                      data[0] & 0x00FF,
                                      data[1] & 0x00FF,
                                      data[2] & 0x00FF,
                                      data[3] & 0x00FF,
                                      data[4] & 0x00FF);
                break;

            case (int)MidiHelper.MetaEventType.TimeSignature:
                int nn = (data[0] & 0x00FF);                         // numerator
                int dd = (int)(Math.Pow(2, (data[1] & 0x00FF)));     // denominator
                int cc = (data[2] & 0x00FF);                         // midiClocksPerMetronomeClick
                int bb = (data[3] & 0x00FF);                         // notated 32nd-notes in a MIDI quarter-note
                value = nn + "/" + dd;
                break;

            case (int)MidiHelper.MetaEventType.KeySignature:
                value = KeySignatures.GetKeyName(data);
                break;

            case (int)MidiHelper.MetaEventType.Tempo:
                int bpm = MicroSecsToBpm(data);
                value = string.Format("{0}", bpm);
                break;

            case (int)MidiHelper.MetaEventType.EndOfTrack:
                break;

            default:
                value = MidiHelper.ByteArrayToString(data, " ");
                break;
            }

            return(string.Format("MetaEvent.CreateMetaEvent((int) MidiHelper.MetaEventType.{0}, \"{1}\", {2}, {3})", typeName, value, tick, ticksPerBeat));
        }