/* Create a new MIDI file (represented by this instance), including the header chunk and appropriate * number of track chunks (with End of Track events). This does not set delta-time division. */ private MidiHeader Create(int format, int numberOfTracks) { /* Make sure we start with a clean slate. */ this.Clear(); int n = MidiChunkInfo.SizeItem(); this.Bytes = new byte[n + MidiHeader.SizeItem()]; /* Start the header chunk. */ MidiChunkInfo chunkInfo = this.CreateChunkInfo(0, MidiChunkInfo.HeaderType); this.Items.Add(chunkInfo); /* Finish the header chunk. (Don't set NumberOfTracks here; AddTrack will set it.) */ MidiHeader header = new MidiHeader(this, n); header.Format = format; this.Items.Add(header); /* Add each track chunk (with an End of Track meta-event). */ for (int i = 0; i < numberOfTracks; ++i) { this.AddTrack(); this.AddMetaEvent(0, MidiMetaEvent.EndOfTrackType, null); } /* Delta-time division still needs to be set. */ return(header); }
private MidiChunkInfo CreateChunkInfo(int offset, string type) { MidiChunkInfo chunkInfo = new MidiChunkInfo(this, offset); chunkInfo.Type = type; chunkInfo.Length = (type == MidiChunkInfo.HeaderType) ? MidiHeader.SizeItem() : 0; if (type == MidiChunkInfo.TrackType) { ++this.Header.NumberOfTracks; } return(chunkInfo); }
/// <summary>Loads an existing MIDI file from disk (into this instance).</summary> /// <param name="path">The path of the MIDI file to load.</param> public void Load(string path) { int n, i, j = 0; MidiChunkInfo chunkInfo; MidiHeader header = null; /* Make sure we start with a clean slate. */ this.Clear(); this.Bytes = File.ReadAllBytes(path); /* Process each MidiItem object from the byte array. */ for (i = 0; i < this.Bytes.Length; i += chunkInfo.Length) { /* A chunk should begin here. */ chunkInfo = new MidiChunkInfo(this, i); this.Items.Add(chunkInfo); i += MidiChunkInfo.SizeItem(); /* What comes next depends on the chunk type. */ switch (chunkInfo.Type) { case MidiChunkInfo.HeaderType: if (header == null) { header = new MidiHeader(this, i); this.Items.Add(header); } else { this.AddErrorText(Properties.Resources.MultipleHeaders, 0); } break; case MidiChunkInfo.TrackType: this.ParseEvents(i, chunkInfo.Length, ++j); break; } } /* Check for track number mismatch. */ n = (header == null) ? 0 : header.NumberOfTracks; if (n != j) { string s = UI.ParseLabel(Properties.Resources.Track).ToLower(); s = string.Format(Properties.Resources.MismatchFormat, s, n, j); this.AddErrorText(s, 0); } }
/// <summary>Initializes a new instance of the MidiHeaderDialog class.</summary> /// <param name="header"> /// MidiHeader object representing the MIDI header (MThd) chunk to edit, or null to create a new one. /// </param> public MidiHeaderDialog(MidiHeader header) : base(header) { Label label; int i = 0, j; MarginType marginType; /* If a new (file) header is being created, prompt for a file name. */ if (this.ForNewItem) { /* Initialize the "File name" label. */ label = UI.CreateLabel(MarginType.Top, Properties.Resources.FileName, true); this.AddUIElement(label); /* Initialize the "File name" text box. */ this.FileNameTextBox = new TextBox(); this.FileNameTextBox.TabIndex = ++i; this.FileNameTextBox.Margin = new Thickness(0, 0, UI.HalfSpace, 0); this.FileNameTextBox.GotFocus += UI.TextBox_GotFocus; this.FileNameTextBox.TextChanged += this.FileNameTextBox_TextChanged; label.Target = this.FileNameTextBox; this.InitialElement = this.FileNameTextBox; /* Initialize the browse button. */ Button button = new Button(); button.TabIndex = ++i; button.Margin = new Thickness(UI.HalfSpace, 0, 0, 0); button.Content = " ... "; button.Click += this.BrowseButton_Click; /* Build out a dock panel to contain the file name text box and browse button. */ DockPanel.SetDock(button, Dock.Right); DockPanel dockPanel = new DockPanel(); dockPanel.Children.Add(button); dockPanel.Children.Add(this.FileNameTextBox); dockPanel.Margin = new Thickness(UI.TripleSpace, UI.HalfSpace, UI.TripleSpace, UI.UnitSpace); this.AddUIElement(dockPanel); /* Set the margin type for the next label. */ marginType = MarginType.Standard; } else { marginType = MarginType.Top; } /* Initialize the "Format" label. */ label = UI.CreateLabel(marginType, Properties.Resources.Format, true); /* Initialize the "Format" combo box. */ this.FormatComboBox = new ComboBox(); this.FormatComboBox.TabIndex = ++i; this.FormatComboBox.Margin = new Thickness(UI.TripleSpace, UI.HalfSpace, UI.TripleSpace, UI.UnitSpace); this.FormatComboBox.Items.Add(Properties.Resources.Format0); this.FormatComboBox.Items.Add(Properties.Resources.Format1); this.FormatComboBox.Items.Add(Properties.Resources.Format2); this.FormatComboBox.SelectionChanged += this.FormatComboBox_SelectionChanged; label.Target = this.FormatComboBox; /* Initialize the "Number of tracks" label. */ this.NumberOfTracksLabel = UI.CreateLabel(MarginType.Standard, Properties.Resources.NumberOfTracks, true); /* Initialize the "Number of tracks" text box. */ this.NumberOfTracksTextBox = new TextBox(); this.NumberOfTracksTextBox.TabIndex = ++i; this.NumberOfTracksTextBox.Margin = new Thickness(UI.TripleSpace, UI.HalfSpace, UI.TripleSpace, UI.UnitSpace); this.NumberOfTracksTextBox.TextAlignment = TextAlignment.Right; this.NumberOfTracksTextBox.GotFocus += UI.TextBox_GotFocus; this.NumberOfTracksTextBox.TextChanged += this.NumberOfTracksTextBox_TextChanged; this.NumberOfTracksLabel.Target = this.NumberOfTracksTextBox; /* Initialize the "Metrical time" radio button. */ this.MetricalTimeRadioButton = new RadioButton(); this.MetricalTimeRadioButton.TabIndex = ++i; this.MetricalTimeRadioButton.Margin = new Thickness(UI.TripleSpace, UI.TripleSpace, UI.TripleSpace, UI.UnitSpace); this.MetricalTimeRadioButton.Content = Properties.Resources.MetricalTime; this.MetricalTimeRadioButton.Checked += this.MetricalTimeRadioButton_Checked; /* Initialize the "Ticks per quarter note" label. */ this.TicksPerQuarterNoteLabel = UI.CreateLabel(MarginType.Indent, Properties.Resources.TicksPerQuarterNote, true); this.TicksPerQuarterNoteLabel.IsEnabled = false; /* Initialize the "Ticks per quarter note" text box. */ this.TicksPerQuarterNoteTextBox = new TextBox(); this.TicksPerQuarterNoteTextBox.TabIndex = ++i; this.TicksPerQuarterNoteTextBox.Margin = new Thickness(UI.IndentSpace, UI.HalfSpace, UI.TripleSpace, UI.UnitSpace); this.TicksPerQuarterNoteTextBox.TextAlignment = TextAlignment.Right; this.TicksPerQuarterNoteTextBox.IsEnabled = false; this.TicksPerQuarterNoteTextBox.GotFocus += UI.TextBox_GotFocus; this.TicksPerQuarterNoteTextBox.TextChanged += this.TicksPerQuarterNoteTextBox_TextChanged; this.TicksPerQuarterNoteLabel.Target = this.TicksPerQuarterNoteTextBox; /* Initialize the "Time-code-based time" radio button. */ this.TimeCodeBasedTimeRadioButton = new RadioButton(); this.TimeCodeBasedTimeRadioButton.TabIndex = ++i; this.TimeCodeBasedTimeRadioButton.Margin = new Thickness(UI.TripleSpace, UI.DoubleSpace, UI.TripleSpace, UI.UnitSpace); this.TimeCodeBasedTimeRadioButton.Content = Properties.Resources.TimeCodeBasedTime; this.TimeCodeBasedTimeRadioButton.Checked += this.TimeCodeBasedTimeRadioButton_Checked; /* Initialize the "Frames per second" label. */ this.FramesPerSecondLabel = UI.CreateLabel(MarginType.Indent, Properties.Resources.FramesPerSecond, true); this.FramesPerSecondLabel.IsEnabled = false; /* Initialize the "Frames per second" combo box. */ this.FramesPerSecondComboBox = new ComboBox(); this.FramesPerSecondComboBox.TabIndex = ++i; this.FramesPerSecondComboBox.Margin = new Thickness(UI.IndentSpace, UI.HalfSpace, UI.TripleSpace, UI.UnitSpace); for (j = 0; j < MidiHeaderDialog.FramesPerSecondCount; ++j) { this.FramesPerSecondComboBox.Items.Add(MidiHeaderDialog.FramesPerSecondStrings[j]); } this.FramesPerSecondComboBox.IsEnabled = false; this.FramesPerSecondComboBox.SelectionChanged += this.FramesPerSecondComboBox_SelectionChanged; this.FramesPerSecondLabel.Target = this.FramesPerSecondComboBox; /* Initialize the "Ticks per frame" label. */ this.TicksPerFrameLabel = UI.CreateLabel(MarginType.Indent, Properties.Resources.TicksPerFrame, true); this.TicksPerFrameLabel.IsEnabled = false; /* Initialize the "Ticks per frame" text box. */ this.TicksPerFrameTextBox = new TextBox(); this.TicksPerFrameTextBox.TabIndex = ++i; this.TicksPerFrameTextBox.Margin = new Thickness(UI.IndentSpace, UI.HalfSpace, UI.TripleSpace, UI.TripleSpace); this.TicksPerFrameTextBox.TextAlignment = TextAlignment.Right; this.TicksPerFrameTextBox.IsEnabled = false; this.TicksPerFrameTextBox.GotFocus += UI.TextBox_GotFocus; this.TicksPerFrameTextBox.TextChanged += this.TicksPerFrameTextBox_TextChanged; this.TicksPerFrameLabel.Target = this.TicksPerFrameTextBox; /* Build out the stack panel, which will serve as the content for the "Delta-time division" group box. */ StackPanel stackPanel = new StackPanel(); stackPanel.Children.Add(this.MetricalTimeRadioButton); stackPanel.Children.Add(this.TicksPerQuarterNoteLabel); stackPanel.Children.Add(this.TicksPerQuarterNoteTextBox); stackPanel.Children.Add(this.TimeCodeBasedTimeRadioButton); stackPanel.Children.Add(this.FramesPerSecondLabel); stackPanel.Children.Add(this.FramesPerSecondComboBox); stackPanel.Children.Add(this.TicksPerFrameLabel); stackPanel.Children.Add(this.TicksPerFrameTextBox); /* Build out the "Delta-time division" group box. */ GroupBox groupBox = new GroupBox(); groupBox.Header = Properties.Resources.DeltaTimeDivision; groupBox.Content = stackPanel; groupBox.Margin = new Thickness(UI.TripleSpace, UI.UnitSpace, UI.TripleSpace, UI.UnitSpace); /* Build out the window and its content. */ this.AddUIElement(label); this.AddUIElement(this.FormatComboBox); this.AddUIElement(this.NumberOfTracksLabel); this.AddUIElement(this.NumberOfTracksTextBox); this.AddUIElement(groupBox); this.BuildOut(UI.ClientWidth, MidiHeaderDialog.TitleString); /* The OK button should start out disabled and stay that way until all required input is entered. */ this.OkButton.IsEnabled = false; /* If a MidiHeader object was supplied, use it to set initial values. */ if (this.ForNewItem) { return; } this.InitialElement = this.FormatComboBox; this.NumberOfTracksTextBox.IsEnabled = false; this.NumberOfTracksLabel.IsEnabled = false; this.NumberOfTracksTextBox.Text = header.NumberOfTracks.ToString(); this.FormatComboBox.SelectedIndex = header.Format; if (header.TicksPerQuarterNote < 0) { this.TimeCodeBasedTimeRadioButton.IsChecked = true; for (j = 0; j < MidiHeaderDialog.FramesPerSecondCount; ++j) { if (MidiHeaderDialog.FramesPerSecondValues[j] == header.FramesPerSecond) { this.FramesPerSecondComboBox.SelectedIndex = j; break; } } this.TicksPerFrameTextBox.Text = header.TicksPerFrame.ToString(); } else { this.MetricalTimeRadioButton.IsChecked = true; this.TicksPerQuarterNoteTextBox.Text = header.TicksPerQuarterNote.ToString(); } }