public bool useDefaultInstruments; /** If true, don't change instruments */ #endregion Fields #region Constructors public MidiOptions(MidiFile midifile) { int numtracks = midifile.Tracks.Count; tracks = new bool[numtracks]; mute = new bool[numtracks]; instruments = new int[numtracks]; for (int i = 0; i < tracks.Length; i++) { tracks[i] = true; mute[i] = false; instruments[i] = midifile.Tracks[i].Instrument; if (midifile.Tracks[i].InstrumentName == "Percussion") { tracks[i] = false; } } useDefaultInstruments = true; scrollVert = true; largeNoteSize = false; if (tracks.Length == 1) { twoStaffs = true; } else { twoStaffs = false; } showNoteLetters = NoteNameNone; showLyrics = true; showMeasures = false; shifttime = 0; transpose = 0; key = -1; time = midifile.Time; colors = null; shadeColor = Color.FromArgb(210, 205, 220); shade2Color = Color.FromArgb(80, 100, 250); combineInterval = 40; tempo = midifile.Time.Tempo; pauseTime = 0; playMeasuresInLoop = false; playMeasuresInLoopStart = 0; playMeasuresInLoopEnd = midifile.EndTime() / midifile.Time.Measure; }
public void TestChangeSoundTrack() { const byte notenum = 60; MidiFile midifile = CreateTestChangeSoundMidiFile(); MidiOptions options = new MidiOptions(midifile); options.useDefaultInstruments = false; options.tracks[0] = false; options.tracks[1] = true; options.tracks[2] = false; options.instruments[0] = 40; options.instruments[1] = 41; options.instruments[2] = 42; bool ret = midifile.ChangeSound(testfile, options); Assert.AreEqual(ret, true); MidiFile newmidi = new MidiFile(testfile); Assert.AreEqual(newmidi.Tracks.Count, 1); Assert.AreEqual(newmidi.Tracks[0].Instrument, 41); for (int i = 0; i < 3; i++) { MidiNote note = newmidi.Tracks[0].Notes[i]; Assert.AreEqual(note.Number, notenum + 10 + i); } File.Delete(testfile); }
public void TestChangeSoundTempo() { MidiFile midifile = CreateTestChangeSoundMidiFile(); MidiOptions options = new MidiOptions(midifile); options.tempo = 0x405060; bool ret = midifile.ChangeSound(testfile, options); Assert.AreEqual(ret, true); MidiFile newmidi = new MidiFile(testfile); Assert.AreEqual(newmidi.Tracks.Count, 3); Assert.AreEqual(newmidi.Time.Tempo, 0x405060); File.Delete(testfile); }
public void TestChangeSoundPerChannelTranspose() { const byte notenum = 60; MidiFile midifile = CreateTestChangeSoundPerChannelMidiFile(); MidiOptions options = new MidiOptions(midifile); options.transpose = 10; bool ret = midifile.ChangeSound(testfile, options); Assert.AreEqual(ret, true); MidiFile newmidi = new MidiFile(testfile); Assert.AreEqual(newmidi.Tracks.Count, 3); for (int tracknum = 0; tracknum < 3; tracknum++) { MidiTrack track = newmidi.Tracks[tracknum]; for (int i = 0; i < 3; i++) { MidiNote note = track.Notes[i]; Assert.AreEqual(note.Number, notenum + tracknum*10 + i + 10); } } File.Delete(testfile); }
/** Set the MidiFile to use. * Save the list of midi notes. Each midi note includes the note Number * and StartTime (in pulses), so we know which notes to shade given the * current pulse time. */ public void SetMidiFile(MidiFile midifile, MidiOptions options) { if (midifile == null) { notes = null; useTwoColors = false; return; } List<MidiTrack> tracks = midifile.ChangeMidiNotes(options); MidiTrack track = MidiFile.CombineToSingleTrack(tracks); notes = track.Notes; maxShadeDuration = midifile.Time.Quarter * 2; /* We want to know which track the note came from. * Use the 'channel' field to store the track. */ for (int tracknum = 0; tracknum < tracks.Count; tracknum++) { foreach (MidiNote note in tracks[tracknum].Notes) { note.Channel = tracknum; } } /* When we have exactly two tracks, we assume this is a piano song, * and we use different colors for highlighting the left hand and * right hand notes. */ useTwoColors = false; if (tracks.Count == 2) { useTwoColors = true; } showNoteLetters = options.showNoteLetters; this.Invalidate(); }
public void TestTruncatedFile() { const byte notenum = 60; const byte quarternote = 240; const byte numtracks = 1; const byte velocity = 80; byte[] data = new byte[] { 77, 84, 104, 100, /* MThd ascii header */ 0, 0, 0, 6, /* length of header in bytes */ 0, 1, /* one or more simultaneous tracks */ 0, numtracks, 0, quarternote, 77, 84, 114, 107, /* MTrk ascii header */ 0, 0, 0, 30, /* Length of track, in bytes. Should be 24. */ /* time_interval, NoteEvent, note number, velocity */ 0, EventNoteOn, notenum, velocity, 60, EventNoteOff, notenum, 0, 0, EventNoteOn, notenum+1, velocity, 30, EventNoteOff, notenum+1, 0, 0, EventNoteOn, notenum+2, velocity, 90, EventNoteOff, notenum+2, 0 }; WriteTestFile(data); bool got_exception = false; try { MidiFile midifile = new MidiFile(testfile); } catch (MidiFileException e) { got_exception = true; } File.Delete(testfile); Assert.AreEqual(got_exception, false); }
/* Create the MidiFile for the TestChangeSoundPerChannel tests. * It has only one track, but multiple channels. */ MidiFile CreateTestChangeSoundPerChannelMidiFile() { const byte notenum = 60; const byte quarternote = 240; const byte numtracks = 1; const byte velocity = 80; byte[] data = new byte[] { 77, 84, 104, 100, /* MThd ascii header */ 0, 0, 0, 6, /* length of header in bytes */ 0, 1, /* one or more simultaneous tracks */ 0, numtracks, 0, quarternote, 77, 84, 114, 107, /* MTrk ascii header */ 0, 0, 0, 81, /* Length of track, in bytes */ /* Instruments are * channel 0 = 0 (Acoustic Piano) * channel 1 = 4 (Electric Piano 1) * channel 2 = 5 (Electric Piano 2) */ 0, EventProgramChange, 0, 0, EventProgramChange+1, 4, 0, EventProgramChange+2, 5, /* time_interval, NoteEvent, note number, velocity */ 0, EventNoteOn, notenum, velocity, 0, EventNoteOn+1, notenum+10, velocity, 0, EventNoteOn+2, notenum+20, velocity, 30, EventNoteOff, notenum, 0, 0, EventNoteOff+1, notenum+10, 0, 0, EventNoteOff+2, notenum+20, 0, 30, EventNoteOn, notenum+1, velocity, 0, EventNoteOn+1, notenum+11, velocity, 0, EventNoteOn+2, notenum+21, velocity, 30, EventNoteOff, notenum+1, 0, 0, EventNoteOff+1, notenum+11, 0, 0, EventNoteOff+2, notenum+21, 0, 30, EventNoteOn, notenum+2, velocity, 0, EventNoteOn+1, notenum+12, velocity, 0, EventNoteOn+2, notenum+22, velocity, 30, EventNoteOff, notenum+2, 0, 0, EventNoteOff+1, notenum+12, 0, 0, EventNoteOff+2, notenum+22, 0, }; /* Verify that the original midi has 3 tracks, one per channel */ WriteTestFile(data); MidiFile midifile = new MidiFile(testfile); Assert.AreEqual(midifile.Tracks.Count, 3); Assert.AreEqual(midifile.Tracks[0].Instrument, 0); Assert.AreEqual(midifile.Tracks[1].Instrument, 4); Assert.AreEqual(midifile.Tracks[2].Instrument, 5); for (int tracknum = 0; tracknum < 3; tracknum++) { MidiTrack track = midifile.Tracks[tracknum]; Assert.AreEqual(track.Notes.Count, 3); for (int n = 0; n < track.Notes.Count; n++) { MidiNote m = track.Notes[n]; Assert.AreEqual(m.Number, notenum + 10*tracknum + n); } } return midifile; }
/** Create a new SheetMusic control. * MidiFile is the parsed midi file to display. * SheetMusic Options are the menu options that were selected. * * - Apply all the Menu Options to the MidiFile tracks. * - Calculate the key signature * - For each track, create a list of MusicSymbols (notes, rests, bars, etc) * - Vertically align the music symbols in all the tracks * - Partition the music notes into horizontal staffs */ public void init(MidiFile file, MidiOptions options) { if (options == null) { options = new MidiOptions(file); } zoom = 1.0f; filename = file.FileName; SetColors(options.colors, options.shadeColor, options.shade2Color); pen = new Pen(Color.Black, 1); List<MidiTrack> tracks = file.ChangeMidiNotes(options); SetNoteSize(options.largeNoteSize); scrollVert = options.scrollVert; showNoteLetters= options.showNoteLetters; TimeSignature time = file.Time; if (options.time != null) { time = options.time; } if (options.key == -1) { mainkey = GetKeySignature(tracks); } else { mainkey = new KeySignature(options.key); } numtracks = tracks.Count; int lastStart = file.EndTime() + options.shifttime; /* Create all the music symbols (notes, rests, vertical bars, and * clef changes). The symbols variable contains a list of music * symbols for each track. The list does not include the left-side * Clef and key signature symbols. Those can only be calculated * when we create the staffs. */ List<MusicSymbol>[] symbols = new List<MusicSymbol> [ numtracks ]; for (int tracknum = 0; tracknum < numtracks; tracknum++) { MidiTrack track = tracks[tracknum]; ClefMeasures clefs = new ClefMeasures(track.Notes, time.Measure); List<ChordSymbol> chords = CreateChords(track.Notes, mainkey, time, clefs); symbols[tracknum] = CreateSymbols(chords, clefs, time, lastStart); } List<LyricSymbol>[] lyrics = null; if (options.showLyrics) { lyrics = GetLyrics(tracks); } /* Vertically align the music symbols */ SymbolWidths widths = new SymbolWidths(symbols, lyrics); // SymbolWidths widths = new SymbolWidths(symbols); AlignSymbols(symbols, widths); staffs = CreateStaffs(symbols, mainkey, options, time.Measure); CreateAllBeamedChords(symbols, time); if (lyrics != null) { AddLyricsToStaffs(staffs, lyrics); } /* After making chord pairs, the stem directions can change, * which affects the staff height. Re-calculate the staff height. */ foreach (Staff staff in staffs) { staff.CalculateHeight(); } BackColor = Color.White; SetZoom(1.0f); }
/** Create a new SheetMusic control, using the given parsed MidiFile. * The options can be null. */ public SheetMusic(MidiFile file, MidiOptions options) { init(file, options); }
/** Create a new SheetMusic control, using the given midi filename. * The options can be null. */ public SheetMusic(string filename, MidiOptions options) { MidiFile file = new MidiFile(filename); init(file, options); }
/** Create a new SheetMusic control, using the given raw midi byte[] data. * The options can be null. */ public SheetMusic(byte[] data, string title, MidiOptions options) { MidiFile file = new MidiFile(data, title); init(file, options); }
private Image volumeImage; /** The volume image */ #endregion Fields #region Constructors /** Create a new MidiPlayer, displaying the play/stop buttons, the * speed bar, and volume bar. The midifile and sheetmusic are initially null. */ public MidiPlayer() { this.Font = new Font("Arial", 10, FontStyle.Bold); loadButtonImages(); int buttonheight = this.Font.Height * 2; this.midifile = null; this.options = null; this.sheet = null; playstate = stopped; startTime = DateTime.Now.TimeOfDay; startPulseTime = 0; currentPulseTime = 0; prevPulseTime = -10; errormsg = new StringBuilder(256); ToolTip tip; /* Create the rewind button */ rewindButton = new Button(); rewindButton.Parent = this; rewindButton.Image = rewindImage; rewindButton.ImageAlign = ContentAlignment.MiddleCenter; rewindButton.Size = new Size(buttonheight, buttonheight); rewindButton.Location = new Point(buttonheight/2, buttonheight/2); rewindButton.Click += new EventHandler(Rewind); tip = new ToolTip(); tip.SetToolTip(rewindButton, "Rewind"); /* Create the play button */ playButton = new Button(); playButton.Parent = this; playButton.Image = playImage; playButton.ImageAlign = ContentAlignment.MiddleCenter; playButton.Size = new Size(buttonheight, buttonheight); playButton.Location = new Point(buttonheight/2, buttonheight/2); playButton.Location = new Point(rewindButton.Location.X + rewindButton.Width + buttonheight/2, rewindButton.Location.Y); playButton.Click += new EventHandler(PlayPause); playTip = new ToolTip(); playTip.SetToolTip(playButton, "Play"); /* Create the stop button */ stopButton = new Button(); stopButton.Parent = this; stopButton.Image = stopImage; stopButton.ImageAlign = ContentAlignment.MiddleCenter; stopButton.Size = new Size(buttonheight, buttonheight); stopButton.Location = new Point(playButton.Location.X + playButton.Width + buttonheight/2, playButton.Location.Y); stopButton.Click += new EventHandler(Stop); tip = new ToolTip(); tip.SetToolTip(stopButton, "Stop"); /* Create the fastFwd button */ fastFwdButton = new Button(); fastFwdButton.Parent = this; fastFwdButton.Image = fastFwdImage; fastFwdButton.ImageAlign = ContentAlignment.MiddleCenter; fastFwdButton.Size = new Size(buttonheight, buttonheight); fastFwdButton.Location = new Point(stopButton.Location.X + stopButton.Width + buttonheight/2, stopButton.Location.Y); fastFwdButton.Click += new EventHandler(FastForward); tip = new ToolTip(); tip.SetToolTip(fastFwdButton, "Fast Forward"); /* Create the Speed bar */ Label speedLabel = new Label(); speedLabel.Parent = this; speedLabel.Text = "Speed: "; speedLabel.TextAlign = ContentAlignment.MiddleRight; speedLabel.Height = buttonheight; speedLabel.Width = buttonheight*2; speedLabel.Location = new Point(fastFwdButton.Location.X + fastFwdButton.Width + buttonheight/2, fastFwdButton.Location.Y); speedBar = new TrackBar(); speedBar.Parent = this; speedBar.Minimum = 1; speedBar.Maximum = 100; speedBar.TickFrequency = 10; speedBar.TickStyle = TickStyle.BottomRight; speedBar.LargeChange = 10; speedBar.Value = 100; speedBar.Width = buttonheight * 5; speedBar.Location = new Point(speedLabel.Location.X + speedLabel.Width + 2, speedLabel.Location.Y); tip = new ToolTip(); tip.SetToolTip(speedBar, "Adjust the speed"); /* Create the Volume bar */ Label volumeLabel = new Label(); volumeLabel.Parent = this; volumeLabel.Image = volumeImage; volumeLabel.ImageAlign = ContentAlignment.MiddleRight; volumeLabel.Height = buttonheight; volumeLabel.Width = buttonheight*2; volumeLabel.Location = new Point(speedBar.Location.X + speedBar.Width + buttonheight/2, speedBar.Location.Y); volumeBar = new TrackBar(); volumeBar.Parent = this; volumeBar.Minimum = 1; volumeBar.Maximum = 100; volumeBar.TickFrequency = 10; volumeBar.TickStyle = TickStyle.BottomRight; volumeBar.LargeChange = 10; volumeBar.Value = 100; volumeBar.Width = buttonheight * 5; volumeBar.Location = new Point(volumeLabel.Location.X + volumeLabel.Width + 2, volumeLabel.Location.Y); volumeBar.Scroll += new EventHandler(ChangeVolume); tip = new ToolTip(); tip.SetToolTip(volumeBar, "Adjust the volume"); Height = buttonheight*2; /* Initialize the timer used for playback, but don't start * the timer yet (enabled = false). */ timer = new Timer(); timer.Enabled = false; timer.Interval = 100; /* 100 millisec */ timer.Tick += new EventHandler(TimerCallback); tempSoundFile = ""; }
/** The MidiFile and/or SheetMusic has changed. Stop any playback sound, * and store the current midifile and sheet music. */ public void SetMidiFile(MidiFile file, MidiOptions opt, SheetMusic s) { /* If we're paused, and using the same midi file, redraw the * highlighted notes. */ if ((file == midifile && midifile != null && playstate == paused)) { options = opt; sheet = s; sheet.ShadeNotes((int)currentPulseTime, (int)-10, false); /* We have to wait some time (200 msec) for the sheet music * to scroll and redraw, before we can re-shade. */ Timer redrawTimer = new Timer(); redrawTimer.Interval = 200; redrawTimer.Tick += new EventHandler(ReShade); redrawTimer.Enabled = true; redrawTimer.Start(); } else { this.Stop(null, null); midifile = file; options = opt; sheet = s; } this.DeleteSoundFile(); }
private ComboBox[] instrumentChoices; /** The instruments to use per track */ #endregion Fields #region Constructors /** Create a new InstrumentDialog. Call the ShowDialog() method * to display the dialog. */ public InstrumentDialog(MidiFile midifile) { /* Create the dialog box */ dialog = new Form(); Font font = dialog.Font; dialog.Font = new Font(font.FontFamily, font.Size * 1.4f); int unit = dialog.Font.Height; int xstart = unit * 2; int ystart = unit * 2; int labelheight = unit * 2; int maxwidth = 0; dialog.Text = "Choose Instruments For Each Track"; dialog.MaximizeBox = false; dialog.MinimizeBox = false; dialog.ShowInTaskbar = false; dialog.Icon = new Icon(GetType(), "NotePair.ico"); dialog.AutoScroll = true; List<MidiTrack> tracks = midifile.Tracks; instrumentChoices = new ComboBox[tracks.Count]; /* For each midi track, create a label with the track number * ("Track 2"), and a ComboBox containing all the possible * midi instruments. Add the text "(default)" to the instrument * specified in the midi file. */ for (int i = 0; i < tracks.Count; i++) { int num = i+1; Label label = new Label(); label.Parent = dialog; label.Text = "Track " + num; label.TextAlign = ContentAlignment.MiddleRight; label.Location = new Point(xstart, ystart + i*labelheight); label.AutoSize = true; maxwidth = Math.Max(maxwidth, label.Width); } for (int i = 0; i < tracks.Count; i++) { instrumentChoices[i] = new ComboBox(); instrumentChoices[i].DropDownStyle = ComboBoxStyle.DropDownList; instrumentChoices[i].Parent = dialog; instrumentChoices[i].Location = new Point(xstart + maxwidth * 3/2, ystart + i*labelheight); instrumentChoices[i].Size = new Size(labelheight * 8, labelheight); for (int instr = 0; instr < MidiFile.Instruments.Length; instr++) { string name = MidiFile.Instruments[instr]; if (tracks[i].Instrument == instr) { name += " (default)"; } instrumentChoices[i].Items.Add(name); } instrumentChoices[i].SelectedIndex = tracks[i].Instrument; } /* Create the "Set All To Piano" button */ Button allPiano = new Button(); allPiano.Parent = dialog; allPiano.Text = "Set All To Piano"; allPiano.Location = new Point(xstart + maxwidth * 3/2, ystart + tracks.Count * labelheight); allPiano.Click += new EventHandler(SetAllPiano); allPiano.Size = new Size(labelheight * 5, labelheight); /* Create the OK and Cancel buttons */ int ypos = ystart + (tracks.Count + 3) * labelheight; Button ok = new Button(); ok.Parent = dialog; ok.Text = "OK"; ok.Location = new Point(xstart, ypos); ok.DialogResult = DialogResult.OK; Button cancel = new Button(); cancel.Parent = dialog; cancel.Text = "Cancel"; cancel.Location = new Point(ok.Location.X + ok.Width + labelheight/2, ypos); cancel.DialogResult = DialogResult.Cancel; dialog.Size = new Size(instrumentChoices[0].Location.X + instrumentChoices[0].Width + 50, cancel.Location.Y + cancel.Size.Height + 50); }
public void TestChangeSoundTranspose() { const byte notenum = 60; MidiFile midifile = CreateTestChangeSoundMidiFile(); MidiOptions options = new MidiOptions(midifile); options.transpose = 10; bool ret = midifile.ChangeSound(testfile, options); Assert.AreEqual(ret, true); MidiFile newmidi = new MidiFile(testfile); Assert.AreEqual(newmidi.Tracks.Count, 3); for (int tracknum = 0; tracknum < 3; tracknum++) { MidiTrack track = newmidi.Tracks[tracknum]; List<MidiNote> notes = track.Notes; Assert.AreEqual(notes.Count, 3); Assert.AreEqual(notes[0].StartTime, 0); Assert.AreEqual(notes[0].Number, notenum + 10*tracknum + 10); Assert.AreEqual(notes[0].Duration, 60); Assert.AreEqual(notes[1].StartTime, 60); Assert.AreEqual(notes[1].Number, notenum + 10*tracknum + 11); Assert.AreEqual(notes[1].Duration, 30); Assert.AreEqual(notes[2].StartTime, 90); Assert.AreEqual(notes[2].Number, notenum + 10*tracknum + 12); Assert.AreEqual(notes[2].Duration, 90); } File.Delete(testfile); }
/* Create the midi file used by the TestChangeSound() methods */ public MidiFile CreateTestChangeSoundMidiFile() { const byte notenum = 60; const byte quarternote = 240; const byte numtracks = 3; const byte velocity = 80; byte[] data = new byte[] { 77, 84, 104, 100, /* MThd ascii header */ 0, 0, 0, 6, /* length of header in bytes */ 0, 1, /* one or more simultaneous tracks */ 0, numtracks, 0, quarternote, 77, 84, 114, 107, /* MTrk ascii header */ 0, 0, 0, 34, /* Length of track, in bytes */ /* tempo event, len=3, tempo = 0x0032ff */ 0, MetaEvent, MetaEventTempo, 3, 0x0, 0x32, 0xff, /* instrument = 4 (Electric Piano 1) */ 0, EventProgramChange, 4, /* time_interval, NoteEvent, note number, velocity */ 0, EventNoteOn, notenum, velocity, 60, EventNoteOff, notenum, 0, 0, EventNoteOn, notenum+1, velocity, 30, EventNoteOff, notenum+1, 0, 0, EventNoteOn, notenum+2, velocity, 90, EventNoteOff, notenum+2, 0, 77, 84, 114, 107, /* MTrk ascii header */ 0, 0, 0, 34, /* Length of track, in bytes */ /* tempo event, len=3, tempo = 0xa0b0cc */ 0, MetaEvent, MetaEventTempo, 3, 0xa0, 0xb0, 0xcc, /* instrument = 5 (Electric Piano 2) */ 0, EventProgramChange, 5, /* time_interval, NoteEvent, note number, velocity */ 0, EventNoteOn, notenum+10, velocity, 60, EventNoteOff, notenum+10, 0, 0, EventNoteOn, notenum+11, velocity, 30, EventNoteOff, notenum+11, 0, 0, EventNoteOn, notenum+12, velocity, 90, EventNoteOff, notenum+12, 0, 77, 84, 114, 107, /* MTrk ascii header */ 0, 0, 0, 34, /* Length of track, in bytes */ /* tempo event, len=3, tempo = 0x121244 */ 0, MetaEvent, MetaEventTempo, 3, 0x12, 0x12, 0x44, /* instrument = 0 (Acoustic Grand Piano) */ 0, EventProgramChange, 0, /* time_interval, NoteEvent, note number, velocity */ 0, EventNoteOn, notenum+20, velocity, 60, EventNoteOff, notenum+20, 0, 0, EventNoteOn, notenum+21, velocity, 30, EventNoteOff, notenum+21, 0, 0, EventNoteOn, notenum+22, velocity, 90, EventNoteOff, notenum+22, 0, }; WriteTestFile(data); /* Verify the original Midi File */ MidiFile midifile = new MidiFile(testfile); Assert.AreEqual(midifile.Tracks.Count, 3); Assert.AreEqual(midifile.Tracks[0].Instrument, 4); Assert.AreEqual(midifile.Tracks[1].Instrument, 5); Assert.AreEqual(midifile.Tracks[2].Instrument, 0); for (int tracknum = 0; tracknum < 3; tracknum++) { MidiTrack track = midifile.Tracks[tracknum]; List<MidiNote> notes = track.Notes; Assert.AreEqual(notes.Count, 3); Assert.AreEqual(notes[0].StartTime, 0); Assert.AreEqual(notes[0].Number, notenum + 10*tracknum); Assert.AreEqual(notes[0].Duration, 60); Assert.AreEqual(notes[1].StartTime, 60); Assert.AreEqual(notes[1].Number, notenum + 10*tracknum + 1); Assert.AreEqual(notes[1].Duration, 30); Assert.AreEqual(notes[2].StartTime, 90); Assert.AreEqual(notes[2].Number, notenum + 10*tracknum + 2); Assert.AreEqual(notes[2].Duration, 90); } return midifile; }
public void TestMultipleTracks() { const byte notenum = 60; const byte quarternote = 240; const byte numtracks = 3; const byte velocity = 80; byte[] data = new byte[] { 77, 84, 104, 100, /* MThd ascii header */ 0, 0, 0, 6, /* length of header in bytes */ 0, 1, /* one or more simultaneous tracks */ 0, numtracks, 0, quarternote, 77, 84, 114, 107, /* MTrk ascii header */ 0, 0, 0, 24, /* Length of track, in bytes */ /* time_interval, NoteEvent, note number, velocity */ 0, EventNoteOn, notenum, velocity, 60, EventNoteOff, notenum, 0, 0, EventNoteOn, notenum+1, velocity, 30, EventNoteOff, notenum+1, 0, 0, EventNoteOn, notenum+2, velocity, 90, EventNoteOff, notenum+2, 0, 77, 84, 114, 107, /* MTrk ascii header */ 0, 0, 0, 24, /* Length of track, in bytes */ /* time_interval, NoteEvent, note number, velocity */ 0, EventNoteOn, notenum+1, velocity, 60, EventNoteOff, notenum+1, 0, 0, EventNoteOn, notenum+2, velocity, 30, EventNoteOff, notenum+2, 0, 0, EventNoteOn, notenum+3, velocity, 90, EventNoteOff, notenum+3, 0, 77, 84, 114, 107, /* MTrk ascii header */ 0, 0, 0, 24, /* Length of track, in bytes */ /* time_interval, NoteEvent, note number, velocity */ 0, EventNoteOn, notenum+2, velocity, 60, EventNoteOff, notenum+2, 0, 0, EventNoteOn, notenum+3, velocity, 30, EventNoteOff, notenum+3, 0, 0, EventNoteOn, notenum+4, velocity, 90, EventNoteOff, notenum+4, 0, }; WriteTestFile(data); MidiFile midifile = new MidiFile(testfile); File.Delete(testfile); Assert.AreEqual(midifile.Tracks.Count, numtracks); Assert.AreEqual(midifile.Time.Numerator, 4); Assert.AreEqual(midifile.Time.Denominator, 4); Assert.AreEqual(midifile.Time.Quarter, quarternote); Assert.AreEqual(midifile.Time.Measure, quarternote * 4); for (int tracknum = 0; tracknum < numtracks; tracknum++) { MidiTrack track = midifile.Tracks[tracknum]; List<MidiNote> notes = track.Notes; Assert.AreEqual(notes.Count, 3); Assert.AreEqual(notes[0].StartTime, 0); Assert.AreEqual(notes[0].Number, notenum + tracknum); Assert.AreEqual(notes[0].Duration, 60); Assert.AreEqual(notes[1].StartTime, 60); Assert.AreEqual(notes[1].Number, notenum + tracknum + 1); Assert.AreEqual(notes[1].Duration, 30); Assert.AreEqual(notes[2].StartTime, 90); Assert.AreEqual(notes[2].Number, notenum + tracknum + 2); Assert.AreEqual(notes[2].Duration, 90); } }
public void TestChangeSoundPerChannelInstruments() { MidiFile midifile = CreateTestChangeSoundPerChannelMidiFile(); MidiOptions options = new MidiOptions(midifile); options.useDefaultInstruments = false; for (int tracknum = 0; tracknum < 3; tracknum++) { options.instruments[tracknum] = 40 + tracknum; } bool ret = midifile.ChangeSound(testfile, options); Assert.AreEqual(ret, true); MidiFile newmidi = new MidiFile(testfile); Assert.AreEqual(newmidi.Tracks.Count, 3); Assert.AreEqual(newmidi.Tracks[0].Instrument, 40); Assert.AreEqual(newmidi.Tracks[1].Instrument, 41); Assert.AreEqual(newmidi.Tracks[2].Instrument, 42); File.Delete(testfile); }
public void TestVariousEvents() { const byte notenum = 60; const byte quarternote = 240; const byte numtracks = 1; const byte velocity = 80; byte[] data = new byte[] { 77, 84, 104, 100, /* MThd ascii header */ 0, 0, 0, 6, /* length of header in bytes */ 0, 1, /* one or more simultaneous tracks */ 0, numtracks, 0, quarternote, 77, 84, 114, 107, /* MTrk ascii header */ 0, 0, 0, 39, /* Length of track, in bytes */ /* time_interval, NoteEvent, note number, velocity */ 0, EventNoteOn, notenum, velocity, 60, EventNoteOff, notenum, 0, 0, EventKeyPressure, notenum, 10, 0, EventControlChange, 10, 10, 0, EventNoteOn, notenum+1, velocity, 30, EventNoteOff, notenum+1, 0, 0, EventProgramChange, 10, 0, EventPitchBend, 0, 0, 0, EventNoteOn, notenum+2, velocity, 90, EventNoteOff, notenum+2, 0 }; WriteTestFile(data); MidiFile midifile = new MidiFile(testfile); File.Delete(testfile); Assert.AreEqual(midifile.Tracks.Count, 1); Assert.AreEqual(midifile.Time.Numerator, 4); Assert.AreEqual(midifile.Time.Denominator, 4); Assert.AreEqual(midifile.Time.Quarter, quarternote); Assert.AreEqual(midifile.Time.Measure, quarternote * 4); MidiTrack track = midifile.Tracks[0]; List<MidiNote> notes = track.Notes; Assert.AreEqual(notes.Count, 3); Assert.AreEqual(notes[0].StartTime, 0); Assert.AreEqual(notes[0].Number, notenum); Assert.AreEqual(notes[0].Duration, 60); Assert.AreEqual(notes[1].StartTime, 60); Assert.AreEqual(notes[1].Number, notenum+1); Assert.AreEqual(notes[1].Duration, 30); Assert.AreEqual(notes[2].StartTime, 90); Assert.AreEqual(notes[2].Number, notenum+2); Assert.AreEqual(notes[2].Duration, 90); }
public void TestChangeSoundPerChannelPauseTime() { const byte notenum = 60; MidiFile midifile = CreateTestChangeSoundPerChannelMidiFile(); MidiOptions options = new MidiOptions(midifile); options.pauseTime = 50; bool ret = midifile.ChangeSound(testfile, options); Assert.AreEqual(ret, true); MidiFile newmidi = new MidiFile(testfile); Assert.AreEqual(newmidi.Tracks.Count, 3); for (int tracknum = 0; tracknum < 3; tracknum++) { MidiTrack track = newmidi.Tracks[tracknum]; Assert.AreEqual(track.Notes.Count, 2); for (int i = 0; i < 2; i++) { MidiNote note = track.Notes[i]; Assert.AreEqual(note.Number, notenum + 10*tracknum + 1 + i); Assert.AreEqual(note.StartTime, 60 * (i+1) - 50); } } File.Delete(testfile); }
/* Command-line program to print out a parsed Midi file. Used for debugging. * To run: * - Change Main2 to Main * - csc MidiNote.cs MidiEvent.cs MidiTrack.cs MidiFileReader.cs MidiOptions.cs * MidiFile.cs MidiException.cs TimeSignature.cs * - MidiFile.exe file.mid * */ public static void Main2(string[] arg) { if (arg.Length == 0) { Console.WriteLine("Usage: MidiFile <filename>"); return; } MidiFile f = new MidiFile(arg[0]); Console.Write(f.ToString()); }
public void TestChangeSoundPerChannelTracks() { const byte notenum = 60; MidiFile midifile = CreateTestChangeSoundPerChannelMidiFile(); MidiOptions options = new MidiOptions(midifile); options.tracks[0] = false; options.tracks[1] = true; options.tracks[2] = false; bool ret = midifile.ChangeSound(testfile, options); Assert.AreEqual(ret, true); MidiFile newmidi = new MidiFile(testfile); Assert.AreEqual(newmidi.Tracks.Count, 1); MidiTrack track = newmidi.Tracks[0]; Assert.AreEqual(track.Notes.Count, 3); for (int i = 0; i < track.Notes.Count; i++) { MidiNote note = track.Notes[i]; Assert.AreEqual(note.Number, notenum + 10 + i); } File.Delete(testfile); }
private NumericUpDown startMeasure; /** The starting measure */ #endregion Fields #region Constructors /** Create a new PlayMeasuresDialog. Call the ShowDialog() method * to display the dialog. */ public PlayMeasuresDialog(MidiFile midifile) { int lastStart = midifile.EndTime(); int lastMeasure = 1 + lastStart / midifile.Time.Measure; /* Create the dialog box */ dialog = new Form(); dialog.Text = "Play Selected Measures in a Loop"; dialog.MaximizeBox = false; dialog.MinimizeBox = false; dialog.ShowInTaskbar = false; dialog.Icon = new Icon(GetType(), "NotePair.ico"); dialog.AutoScroll = true; Font font = dialog.Font; dialog.Font = new Font(font.FontFamily, font.Size * 1.4f); int labelheight = dialog.Font.Height * 2; int xpos = labelheight/2; int ypos = labelheight/2; enable = new CheckBox(); enable.Parent = dialog; enable.Text = "Play Selected Measures in a Loop"; enable.Checked = false; enable.Location = new Point(xpos, ypos); enable.Size = new Size(labelheight*9, labelheight); ypos += labelheight * 3/2; Label label = new Label(); label.Parent = dialog; label.Text = "Start Measure"; label.Location = new Point(xpos, ypos); label.Size = new Size(labelheight * 3, labelheight); xpos += labelheight * 4; startMeasure = new NumericUpDown(); startMeasure.Parent = dialog; startMeasure.Minimum = 1; startMeasure.Maximum = lastMeasure; startMeasure.Value = 1; startMeasure.Location = new Point(xpos, ypos); startMeasure.Size = new Size(labelheight*2, labelheight); xpos = labelheight/2; ypos += labelheight * 3/2; label = new Label(); label.Parent = dialog; label.Text = "End Measure"; label.Location = new Point(xpos, ypos); label.Size = new Size(labelheight * 3, labelheight); xpos += labelheight * 4; endMeasure = new NumericUpDown(); endMeasure.Parent = dialog; endMeasure.Minimum = 1; endMeasure.Maximum = lastMeasure; endMeasure.Value = lastMeasure; endMeasure.Location = new Point(xpos, ypos); endMeasure.Size = new Size(labelheight*2, labelheight); /* Create the OK and Cancel buttons */ xpos = labelheight/2; ypos += labelheight * 3/2; Button ok = new Button(); ok.Parent = dialog; ok.Text = "OK"; ok.Location = new Point(xpos, ypos); ok.DialogResult = DialogResult.OK; dialog.Size = new Size(labelheight * 10, labelheight * 8); }
/** * Read the midi file into a MidiFile instance. * Create a SheetMusic control based on the MidiFile. * Add the sheetmusic control to this form. * Enable all the menu items. * * If any error occurs while reading the midi file, * display a MessageBox with the error message. */ public void OpenMidiFile(string filename) { try { midifile = new MidiFile(filename); DisableMenus(); EnableMenus(); string displayName = Path.GetFileName(filename); displayName = displayName.Replace("__", ": "); displayName = displayName.Replace("_", " "); Text = displayName + " - Midi Sheet Music"; instrumentDialog = new InstrumentDialog(midifile); playMeasuresDialog = new PlayMeasuresDialog(midifile); RedrawSheetMusic(); } catch (MidiFileException e) { filename = Path.GetFileName(filename); string message = ""; message += "MidiSheetMusic was unable to open the file " + filename; message += "\nIt does not appear to be a valid midi file.\n" + e.Message; MessageBox.Show(message, "Error Opening File", MessageBoxButtons.OK, MessageBoxIcon.Error); midifile = null; DisableMenus(); } catch (System.IO.IOException e) { filename = Path.GetFileName(filename); string message = ""; message += "MidiSheetMusic was unable to open the file " + filename; message += "because:\n" + e.Message + "\n"; MessageBox.Show(message, "Error Opening File", MessageBoxButtons.OK, MessageBoxIcon.Error); midifile = null; DisableMenus(); } }