Ejemplo n.º 1
0
        /****************
        * Constructors *
        ****************/

        #region Public Constructors

        /// <summary>Initializes a new instance of the MidiSysExEventDialog class.</summary>
        /// <param name="sysExEvent">
        /// MidiSysExEvent object representing the MIDI system exclusive
        /// (SysEx) message/event to edit, or null to create a new one.
        /// </param>
        public MidiSysExEventDialog(MidiSysExEvent sysExEvent)
            : base(sysExEvent)
        {
            int i = this.ControlCount;

            /* Initialize the "Escape" check box. */
            this.EscapeCheckBox = UI.CreateCheckBox(++i, MarginType.Standard, Properties.Resources.Escape, null);

            /* Initialize the "Data" controls. */
            this.DataLabel = UI.CreateLabel(MarginType.Standard, Properties.Resources.Data, true);
            DockPanel panel = MidiEventDialog.CreateDataPanel(ref this.DataHexTextBox, ref this.DataCommentTextBox, ++i);

            this.DataHexTextBox.TextChanged   += this.DataHexTextBox_TextChanged;
            this.DataCommentTextBox.IsReadOnly = true;
            this.DataLabel.Target = this.DataHexTextBox;

            /* Build out the window and its content. */
            this.AddUIElement(this.EscapeCheckBox);
            this.AddUIElement(this.DataLabel);
            this.AddUIElement(panel);
            this.BuildOut(UI.ClientWidth, MidiSysExEventDialog.TitleString);

            /* The OK button should start out disabled and stay that way until all required input is entered. */
            this.OkButton.IsEnabled = false;

            /* If a MidiSysExEvent object was supplied, use it to set initial values. */
            if (this.ForNewItem)
            {
                return;
            }
            this.DeltaTime = sysExEvent.DeltaTime;
            this.EscapeCheckBox.IsChecked = sysExEvent.Escape;
            this.DataHexTextBox.Text      = this.Hex = Midi.FormatHex(sysExEvent.Data, 0, sysExEvent.Data.Length);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Writes a variable-length quantity (VLQ) into this file's byte array, resizing the byte array if necessary.
        /// </summary>
        /// <param name="offset">Offset into the byte array at which the VLQ is written.</param>
        /// <param name="vlq">The VLQ to write.</param>
        /// <param name="length">Length of quantity that the VLQ is replacing (for resizing purposes).</param>
        public void WriteVLQ(int offset, int vlq, int length)
        {
            /* Resize the byte array (if necessary). */
            int i, n = Midi.SizeVLQ(vlq) - length;

            if (n != 0)
            {
                this.Resize(n, offset + length, 0);
            }

            /* For the simple (and common) case of a single-byte VLQ, take a shortcut. */
            if (vlq < 0x80)
            {
                this.Bytes[offset] = (byte)vlq; return;
            }

            /* The VLQ is stored as 7 bits per byte (most significant byte first).  All bytes except the last have the
             * Most Significant Bit (MSB) set, and the last byte has the MSB clear.  The easiest way to accomplish this
             * is to write the VLQ "backwards" (least significant byte first) to a temporary byte array, then reverse it.
             */
            for (n = 0, i = vlq; i > 0; i >>= 7)
            {
                this.Bytes[offset + n] = (byte)((i % 0x100) & 0x7F);
                if (n > 0)
                {
                    this.Bytes[offset + n] |= 0x80;
                }
                ++n;
            }
            Array.Reverse(this.Bytes, offset, n);
        }
Ejemplo n.º 3
0
        private static string DescribeNumber(int type, byte[] bytes)
        {
            int n = MidiMetaEvent.GetDataLength(type);

            if (bytes.Length < n)
            {
                return(null);
            }
            return(Midi.ReadNumber(bytes, 0, n).ToString());
        }
Ejemplo n.º 4
0
        /***********
        * Methods *
        ***********/

        #region Private Methods

        #region Event Handlers

        private void DataHexTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            byte[] bytes = Midi.ParseHex(this.DataHexTextBox.Text);
            if (bytes == null)
            {
                this.DataHexTextBox.Text = this.Hex; return;
            }
            this.Hex   = this.DataHexTextBox.Text;
            this._Data = bytes;
            this.DataCommentTextBox.Text = Midi.ReadText(this.Data, 0, this.Data.Length);
        }
Ejemplo n.º 5
0
        private static string DescribeTempo(byte[] bytes)
        {
            int n = MidiMetaEvent.GetDataLength(MidiMetaEvent.SetTempoType);

            if (bytes.Length < n)
            {
                return(null);
            }
            n = Midi.ReadNumber(bytes, 0, n);
            return(string.Format("{0} {1} ({2} {3})", n, Properties.Resources.MicrosecondsPerQuarterNote,
                                 (n == 0) ? double.PositiveInfinity : (60000000 / n), Properties.Resources.BeatsPerMinute));
        }
Ejemplo n.º 6
0
        /// <summary>Adds a new MIDI channel message/event to the end of this file.</summary>
        /// <param name="deltaTime">The amount of time (in ticks) between the previous event in the track and this one.</param>
        /// <param name="status">The status byte of the event, or -1 for running status.</param>
        /// <param name="data1">The first data byte of the event.</param>
        /// <param name="data2">The second data byte of the event (if applicable).</param>
        /// <returns>The new MidiChannelEvent object that is added.</returns>
        public MidiChannelEvent AddChannelEvent(int deltaTime, int status, int data1, int data2)
        {
            int             offset = this.Bytes.Length, n = (status < 0) ? this.GetRunningStatus(offset) : status;
            MidiMessageType messageType = (MidiMessageType)Midi.GetHighNibble(n);

            n = MidiChannelEvent.SizeItem(0, (status < 0), messageType);
            this.Resize(n, offset, this.ItemCount);
            MidiChannelEvent channelEvent = this.CreateChannelEvent(offset, deltaTime, status, data1, data2);

            this.Items.Add(channelEvent);
            this.SetTotalTime(this.ItemCount - 1);
            return(channelEvent);
        }
Ejemplo n.º 7
0
        /// <summary>Inserts a new MIDI channel message/event into this file at the specified index.</summary>
        /// <param name="index">The index in this file's list at which the event should be inserted.</param>
        /// <param name="deltaTime">The amount of time (in ticks) between the previous event in the track and this one.</param>
        /// <param name="status">The status byte of the event, or -1 for running status.</param>
        /// <param name="data1">The first data byte of the event.</param>
        /// <param name="data2">The second data byte of the event (if applicable).</param>
        /// <returns>The new MidiChannelEvent object that is inserted.</returns>
        public MidiChannelEvent InsertChannelEvent(int index, int deltaTime, int status, int data1, int data2)
        {
            int             offset = this.Items[index].Offset, n = (status < 0) ? this.GetRunningStatus(offset) : status;
            MidiMessageType messageType = (MidiMessageType)Midi.GetHighNibble(n);

            n = MidiChannelEvent.SizeItem(0, (status < 0), messageType);
            this.Resize(n, offset, index);
            MidiChannelEvent channelEvent = this.CreateChannelEvent(offset, deltaTime, status, data1, data2);

            this.Items.Insert(index, channelEvent);
            this.SetTotalTime(index);
            return(channelEvent);
        }
Ejemplo n.º 8
0
 /// <summary>Reads text as a string of ASCII characters from a byte array.</summary>
 /// <param name="bytes">Array of bytes containing the text.</param>
 /// <param name="offset">Offset into the byte array at which the text is stored.</param>
 /// <param name="length">The number of bytes (ASCII characters) to read.</param>
 /// <returns>The text that is read.</returns>
 public static string ReadText(byte[] bytes, int offset, int length)
 {
     char[] chars = new char[length];
     for (int i = 0; i < length; ++i)
     {
         chars[i] = (char)bytes[offset + i];
         if (!Midi.IsPrintable(chars[i]))
         {
             chars[i] = '.';
         }
     }
     return(new string(chars));
 }
Ejemplo n.º 9
0
        private void DataHexTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            /* If the hex input is not valid, revert to previous hex. */
            byte[] bytes = Midi.ParseHex(this.DataHexTextBox.Text);
            if (bytes == null)
            {
                this.NoValidation        = true;
                this.DataHexTextBox.Text = this.Hex;
                this.NoValidation        = false;
                return;
            }

            /* The hex input is valid. */
            this.Hex   = this.DataHexTextBox.Text;
            this._Data = bytes;
            this.UpdateDataComment();
        }
Ejemplo n.º 10
0
        private void DataCommentTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            /* Prevent unnecessary recursion. */
            if (this.NoValidation)
            {
                return;
            }
            this.NoValidation = true;

            /* Populate hex box based on text/character/string input. */
            int i, n = this.DataCommentTextBox.Text.Length;

            byte[] bytes = new byte[n];
            for (i = 0; i < n; ++i)
            {
                bytes[i] = (byte)this.DataCommentTextBox.Text[i];
            }
            this.DataHexTextBox.Text = Midi.FormatHex(bytes, 0, n);
            this.NoValidation        = false;
        }
Ejemplo n.º 11
0
        /****************
        * Constructors *
        ****************/

        #region Public Constructors

        /// <summary>Initializes a new instance of the MidiMetaEventDialog class.</summary>
        /// <param name="metaEvent">
        /// MidiMetaEvent object representing the MIDI meta-event to edit, or null to create a new one.
        /// </param>
        public MidiMetaEventDialog(MidiMetaEvent metaEvent)
            : base(metaEvent)
        {
            int       i = this.ControlCount;
            DockPanel typePanel, dataPanel;

            /* Initialize the "Type" controls. */
            this.TypeLabel = UI.CreateLabel(MarginType.Standard, Properties.Resources.Type, true);
            typePanel      = MidiEventDialog.CreateDataBytePanel(ref this.TypeTextBox, ref this.TypeTextBlock, ++i);
            this.TypeTextBox.TextChanged += this.TypeTextBox_TextChanged;
            this.TypeLabel.Target         = this.TypeTextBox;

            /* Initialize the "Data" controls. */
            Label label = UI.CreateLabel(MarginType.Standard, Properties.Resources.Data, true);

            dataPanel = MidiEventDialog.CreateDataPanel(ref this.DataHexTextBox, ref this.DataCommentTextBox, ++i);
            this.DataHexTextBox.TextChanged     += this.DataHexTextBox_TextChanged;
            this.DataCommentTextBox.TextChanged += this.DataCommentTextBox_TextChanged;
            label.Target = this.DataHexTextBox;

            /* Build out the window and its content. */
            this.AddUIElement(this.TypeLabel);
            this.AddUIElement(typePanel);
            this.AddUIElement(label);
            this.AddUIElement(dataPanel);
            this.BuildOut(UI.ClientWidth, MidiMetaEventDialog.TitleString);

            /* The OK button should start out disabled and stay that way until all required input is entered. */
            this.OkButton.IsEnabled = false;

            /* If a MidiMetaEvent object was supplied, use it to set initial values. */
            if (this.ForNewItem)
            {
                return;
            }
            this.DeltaTime           = metaEvent.DeltaTime;
            this.TypeTextBox.Text    = metaEvent.Type.ToString();
            this.NoValidation        = true;
            this.DataHexTextBox.Text = this.Hex = Midi.FormatHex(metaEvent.Data, 0, metaEvent.Data.Length);
            this.NoValidation        = false;
        }
Ejemplo n.º 12
0
        /***********
        * Methods *
        ***********/

        #region Public Methods

        /// <summary>Returns the number of bytes required to store an item of this type.</summary>
        public static int SizeItem(int deltaTime, int dataLength)
        {
            return(Midi.SizeVLQ(deltaTime) + 2 + Midi.SizeVLQ(dataLength) + dataLength);
        }
Ejemplo n.º 13
0
 /// <summary>Represents a portion of this file's byte array in hexadecimal format.</summary>
 /// <param name="offset">Offset into the byte array at which to start reading.</param>
 /// <param name="length">The number of bytes to read.</param>
 /// <returns>Representation of the specified portion of the byte array in hexadecimal format.</returns>
 public string FormatHex(int offset, int length)
 {
     return(Midi.FormatHex(this.Bytes, offset, length));
 }
Ejemplo n.º 14
0
 /// <summary>Returns a comment for the data bytes of a meta-event.</summary>
 /// <param name="type">Meta-event type (always less than 128).</param>
 /// <param name="bytes">The data bytes of the event.</param>
 /// <returns>A comment for the data bytes.</returns>
 public static string GetDataComment(int type, byte[] bytes)
 {
     return((MidiMetaEvent.TypeMap.ContainsKey(type) && MidiMetaEvent.TypeMap[type].DescribeData != null)
         ? MidiMetaEvent.TypeMap[type].DescribeData(bytes) : Midi.ReadText(bytes, 0, bytes.Length));
 }
Ejemplo n.º 15
0
        /// <summary>Attempts to convert the data bytes of a meta-event to a MidiKeySignature value.</summary>
        /// <param name="bytes">The data bytes of the event.</param>
        /// <returns>
        /// The data bytes converted to a MidiKeySignature value, or MidiKeySignature.NA if the data could not be converted.
        /// </returns>
        public static MidiKeySignature DataToKeySignature(byte[] bytes)
        {
            int n = Midi.ReadNumber(bytes, 0, bytes.Length);

            return(Enum.IsDefined(typeof(MidiKeySignature), n) ? (MidiKeySignature)n : MidiKeySignature.NA);
        }
Ejemplo n.º 16
0
        /***********
        * Methods *
        ***********/

        #region Public Methods

        /// <summary>Returns the number of bytes required to store an item of this type.</summary>
        public static int SizeItem(int deltaTime, bool runningStatus, MidiMessageType messageType)
        {
            return(Midi.SizeVLQ(deltaTime) + (runningStatus ? 0 : 1) + (MidiChannelEvent.HasData2(messageType) ? 2 : 1));
        }
Ejemplo n.º 17
0
 /// <summary>Reads text as a string of ASCII characters from this file's byte array.</summary>
 /// <param name="offset">Offset into the byte array at which the text is stored.</param>
 /// <param name="length">The number of bytes (ASCII characters) to read.</param>
 /// <returns>The text that is read.</returns>
 public string ReadText(int offset, int length)
 {
     return(Midi.ReadText(this.Bytes, offset, length));
 }
Ejemplo n.º 18
0
 /// <summary>Reads a number as an integer (in network byte order) from this file's byte array.</summary>
 /// <param name="offset">
 /// Offset into the byte array at which the number is stored (most significant byte first).
 /// </param>
 /// <param name="length">The number of bytes to read (should not be greater than 4).</param>
 /// <returns>The number that is read.</returns>
 public int ReadNumber(int offset, int length)
 {
     return(Midi.ReadNumber(this.Bytes, offset, length));
 }