/** 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); sheet.MouseClick += new MouseEventHandler(MoveToClicked); /* 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; if (sheet != null) { sheet.MouseClick += new MouseEventHandler(MoveToClicked); } } this.DeleteSoundFile(); }
/** 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); } List <MidiTrack> tracks = file.ChangeMidiNotes(options); init(file, options, tracks); }
/* Merge in the saved options to this MidiOptions.*/ public void Merge(MidiOptions saved) { if (saved.tracks != null && saved.tracks.Length == tracks.Length) { for (int i = 0; i < tracks.Length; i++) { tracks[i] = saved.tracks[i]; } } if (saved.mute != null && saved.mute.Length == mute.Length) { for (int i = 0; i < mute.Length; i++) { mute[i] = saved.mute[i]; } } if (saved.instruments != null && saved.instruments.Length == instruments.Length) { for (int i = 0; i < instruments.Length; i++) { instruments[i] = saved.instruments[i]; } } if (saved.time != null) { time = new TimeSignature(saved.time.Numerator, saved.time.Denominator, saved.time.Quarter, saved.time.Tempo); } useDefaultInstruments = saved.useDefaultInstruments; scrollVert = saved.scrollVert; smoothScroll = saved.smoothScroll; largeNoteSize = saved.largeNoteSize; showLyrics = saved.showLyrics; twoStaffs = saved.twoStaffs; showNoteLetters = saved.showNoteLetters; transpose = saved.transpose; key = saved.key; combineInterval = saved.combineInterval; if (saved.shadeColor != Color.White) { shadeColor = saved.shadeColor; } if (saved.shade2Color != Color.White) { shade2Color = saved.shade2Color; } if (saved.colors != null) { colors = saved.colors; } showMeasures = saved.showMeasures; playMeasuresInLoop = saved.playMeasuresInLoop; playMeasuresInLoopStart = saved.playMeasuresInLoopStart; playMeasuresInLoopEnd = saved.playMeasuresInLoopEnd; }
CreateStaffs(List <MusicSymbol>[] allsymbols, KeySignature key, MidiOptions options, int measurelen) { List <Staff>[] trackstaffs = new List <Staff> [allsymbols.Length]; int totaltracks = trackstaffs.Length; for (int track = 0; track < totaltracks; track++) { List <MusicSymbol> symbols = allsymbols[track]; trackstaffs[track] = CreateStaffsForTrack(symbols, measurelen, key, options, track, totaltracks); } /* Update the EndTime of each Staff. EndTime is used for playback */ foreach (List <Staff> list in trackstaffs) { for (int i = 0; i < list.Count - 1; i++) { list[i].EndTime = list[i + 1].StartTime; } } /* Interleave the staffs of each track into the result array. */ int maxstaffs = 0; for (int i = 0; i < trackstaffs.Length; i++) { if (maxstaffs < trackstaffs[i].Count) { maxstaffs = trackstaffs[i].Count; } } List <Staff> result = new List <Staff>(maxstaffs * trackstaffs.Length); for (int i = 0; i < maxstaffs; i++) { foreach (List <Staff> list in trackstaffs) { if (i < list.Count) { result.Add(list[i]); } } } return(result); }
private int ytop; /** The y pixel of the top of the staff */ #endregion Fields #region Constructors /** Create a new staff with the given list of music symbols, * and the given key signature. The clef is determined by * the clef of the first chord symbol. The track number is used * to determine whether to join this left/right vertical sides * with the staffs above and below. The SheetMusicOptions are used * to check whether to display measure numbers or not. */ public Staff(List<MusicSymbol> symbols, KeySignature key, MidiOptions options, int tracknum, int totaltracks) { keysigWidth = SheetMusic.KeySignatureWidth(key); this.tracknum = tracknum; this.totaltracks = totaltracks; showMeasures = (options.showMeasures && tracknum == 0); measureLength = options.time.Measure; Clef clef = FindClef(symbols); clefsym = new ClefSymbol(clef, 0, false); keys = key.GetSymbols(clef); this.symbols = symbols; CalculateWidth(options.scrollVert); CalculateHeight(); CalculateStartEndTime(); FullJustify(); }
private int measureLength; /** The time (in pulses) of a measure */ /** Create a new staff with the given list of music symbols, * and the given key signature. The clef is determined by * the clef of the first chord symbol. The track number is used * to determine whether to join this left/right vertical sides * with the staffs above and below. The SheetMusicOptions are used * to check whether to display measure numbers or not. */ public Staff(List <MusicSymbol> symbols, KeySignature key, MidiOptions options, int tracknum, int totaltracks) { keysigWidth = SheetMusic.KeySignatureWidth(key); this.tracknum = tracknum; this.totaltracks = totaltracks; showMeasures = (options.showMeasures && tracknum == 0); measureLength = options.time.Measure; Clef clef = FindClef(symbols); clefsym = new ClefSymbol(clef, 0, false); keys = key.GetSymbols(clef); this.symbols = symbols; CalculateWidth(options.scrollVert); CalculateHeight(); CalculateStartEndTime(); FullJustify(); }
/** 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(); }
/** 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; scoreFollowingState = stopped; startTime = DateTime.Now.TimeOfDay; startPulseTime = 0; currentPulseTime = 0; currentPulseTimeScoreFollowing = 0; prevPulseTime = -10; prevPulseTimeScoreFollowing = -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, Strings.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, Strings.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, Strings.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, Strings.fastForward); /* Create the score follower button */ scoreFollowingButton = new Button(); scoreFollowingButton.Parent = this; scoreFollowingButton.Image = playImage; scoreFollowingButton.ImageAlign = ContentAlignment.MiddleCenter; scoreFollowingButton.Size = new Size(buttonheight, buttonheight); scoreFollowingButton.Location = new Point(fastFwdButton.Location.X + fastFwdButton.Width + buttonheight / 2, fastFwdButton.Location.Y); scoreFollowingButton.Click += new EventHandler(StartStopScoreFollowing); tip = new ToolTip(); tip.SetToolTip(scoreFollowingButton, "Start score following"); /* Create the Speed bar */ speedLabel = new Label(); speedLabel.Parent = this; speedLabel.Text = Strings.speed + " : 100%"; speedLabel.TextAlign = ContentAlignment.MiddleLeft; speedLabel.Height = buttonheight; speedLabel.Width = buttonheight * 3; speedLabel.Location = new Point(scoreFollowingButton.Location.X + scoreFollowingButton.Width + buttonheight / 2, scoreFollowingButton.Location.Y); speedBar = new TrackBar(); speedBar.Parent = this; speedBar.Minimum = 1; speedBar.Maximum = 150; speedBar.TickFrequency = 10; speedBar.TickStyle = TickStyle.BottomRight; speedBar.LargeChange = 10; speedBar.Value = 100; speedBar.Width = buttonheight * 6; speedBar.Location = new Point(speedLabel.Location.X + speedLabel.Width + 2, speedLabel.Location.Y); speedBar.Scroll += new EventHandler(SpeedBarChanged); tip = new ToolTip(); tip.SetToolTip(speedBar, Strings.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 * 6; volumeBar.Location = new Point(volumeLabel.Location.X + volumeLabel.Width + 2, volumeLabel.Location.Y); volumeBar.Scroll += new EventHandler(ChangeVolume); tip = new ToolTip(); tip.SetToolTip(volumeBar, Strings.volume); Height = buttonheight * 2; textBox = new TextBox(); textBox.Parent = this; textBox.Height = buttonheight * 3; textBox.Width = buttonheight * 20; textBox.Location = new Point(volumeBar.Location.X + volumeBar.Width + 2, volumeBar.Location.Y); /* 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 = ""; /////////////////////////////////////////////////////////////////// /* Initialize the timer used for score following */ timerScoreFollowing = new Timer(); timerScoreFollowing.Enabled = false; // Need to run at a higher frquency than the backend (otherwise, // we may not capute teh instructions). timerScoreFollowing.Interval = 50; timerScoreFollowing.Tick += new EventHandler(TimerCallbackScoreFollowing); // Create the ZQM sockets, open the TCP ports context = new ZContext(); subscriber = new ZSocket(context, ZSocketType.SUB); subscriber.Subscribe(""); subscriber.Conflate = true; // Keep only the last message subscriber.Connect("tcp://127.0.0.1:5555"); publisher = new ZSocket(context, ZSocketType.PUB); publisher.Bind("tcp://127.0.0.1:5556"); /////////////////////////////////////////////////////////////////// }
/** 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); }
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 = ""; }
/** 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); }
/** 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(); }
void AlignSymbols(List <MusicSymbol>[] allsymbols, SymbolWidths widths, MidiOptions options) { // If we show measure numbers, increase bar symbol width if (options.showMeasures) { for (int track = 0; track < allsymbols.Length; track++) { List <MusicSymbol> symbols = allsymbols[track]; foreach (MusicSymbol sym in symbols) { if (sym is BarSymbol) { sym.Width += SheetMusic.NoteWidth; } } } } for (int track = 0; track < allsymbols.Length; track++) { List <MusicSymbol> symbols = allsymbols[track]; List <MusicSymbol> result = new List <MusicSymbol>(); int i = 0; /* If a track doesn't have a symbol for a starttime, * add a blank symbol. */ foreach (int start in widths.StartTimes) { /* BarSymbols are not included in the SymbolWidths calculations */ while (i < symbols.Count && (symbols[i] is BarSymbol) && symbols[i].StartTime <= start) { result.Add(symbols[i]); i++; } if (i < symbols.Count && symbols[i].StartTime == start) { while (i < symbols.Count && symbols[i].StartTime == start) { result.Add(symbols[i]); i++; } } else { result.Add(new BlankSymbol(start, 0)); } } /* For each starttime, increase the symbol width by * SymbolWidths.GetExtraWidth(). */ i = 0; while (i < result.Count) { if (result[i] is BarSymbol) { i++; continue; } int start = result[i].StartTime; int extra = widths.GetExtraWidth(track, start); result[i].Width += extra; /* Skip all remaining symbols with the same starttime. */ while (i < result.Count && result[i].StartTime == start) { i++; } } allsymbols[track] = result; } }
public bool Write(string destfile, MidiOptions options) { try { FileStream stream; stream = new FileStream(destfile, FileMode.Create); bool result = Write(stream, options); stream.Close(); return result; } catch (IOException e) { return false; } }
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); }
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); }
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); }
/** Create a new SheetMusic control, using the given parsed MidiFile. * The options can be null. */ public SheetMusic(MidiFile file, MidiOptions options) { init(file, options); }
/** Given MusicSymbols for a track, create the staffs for that track. * Each Staff has a maxmimum width of PageWidth (800 pixels). * Also, measures should not span multiple Staffs. */ private List<Staff> CreateStaffsForTrack(List<MusicSymbol> symbols, int measurelen, KeySignature key, MidiOptions options, int track, int totaltracks) { int keysigWidth = KeySignatureWidth(key); int startindex = 0; List<Staff> thestaffs = new List<Staff>(symbols.Count / 50); while (startindex < symbols.Count) { /* startindex is the index of the first symbol in the staff. * endindex is the index of the last symbol in the staff. */ int endindex = startindex; int width = keysigWidth; int maxwidth; /* If we're scrolling vertically, the maximum width is PageWidth. */ if (scrollVert) { maxwidth = SheetMusic.PageWidth; } else { maxwidth = 2000000; } while (endindex < symbols.Count && width + symbols[endindex].Width < maxwidth) { width += symbols[endindex].Width; endindex++; } endindex--; /* There's 3 possibilities at this point: * 1. We have all the symbols in the track. * The endindex stays the same. * * 2. We have symbols for less than one measure. * The endindex stays the same. * * 3. We have symbols for 1 or more measures. * Since measures cannot span multiple staffs, we must * make sure endindex does not occur in the middle of a * measure. We count backwards until we come to the end * of a measure. */ if (endindex == symbols.Count - 1) { /* endindex stays the same */ } else if (symbols[startindex].StartTime / measurelen == symbols[endindex].StartTime / measurelen) { /* endindex stays the same */ } else { int endmeasure = symbols[endindex+1].StartTime/measurelen; while (symbols[endindex].StartTime / measurelen == endmeasure) { endindex--; } } int range = endindex + 1 - startindex; if (scrollVert) { width = SheetMusic.PageWidth; } Staff staff = new Staff(symbols.GetRange(startindex, range), key, options, track, totaltracks); thestaffs.Add(staff); startindex = endindex + 1; } return thestaffs; }
/** Given all the MusicSymbols for every track, create the staffs * for the sheet music. There are two parts to this: * * - Get the list of staffs for each track. * The staffs will be stored in trackstaffs as: * * trackstaffs[0] = { Staff0, Staff1, Staff2, ... } for track 0 * trackstaffs[1] = { Staff0, Staff1, Staff2, ... } for track 1 * trackstaffs[2] = { Staff0, Staff1, Staff2, ... } for track 2 * * - Store the Staffs in the staffs list, but interleave the * tracks as follows: * * staffs = { Staff0 for track 0, Staff0 for track1, Staff0 for track2, * Staff1 for track 0, Staff1 for track1, Staff1 for track2, * Staff2 for track 0, Staff2 for track1, Staff2 for track2, * ... } */ private List<Staff> CreateStaffs(List<MusicSymbol>[] allsymbols, KeySignature key, MidiOptions options, int measurelen) { List<Staff>[] trackstaffs = new List<Staff>[ allsymbols.Length ]; int totaltracks = trackstaffs.Length; for (int track = 0; track < totaltracks; track++) { List<MusicSymbol> symbols = allsymbols[ track ]; trackstaffs[track] = CreateStaffsForTrack(symbols, measurelen, key, options, track, totaltracks); } /* Update the EndTime of each Staff. EndTime is used for playback */ foreach (List<Staff> list in trackstaffs) { for (int i = 0; i < list.Count-1; i++) { list[i].EndTime = list[i+1].StartTime; } } /* Interleave the staffs of each track into the result array. */ int maxstaffs = 0; for (int i = 0; i < trackstaffs.Length; i++) { if (maxstaffs < trackstaffs[i].Count) { maxstaffs = trackstaffs[i].Count; } } List<Staff> result = new List<Staff>(maxstaffs * trackstaffs.Length); for (int i = 0; i < maxstaffs; i++) { foreach (List<Staff> list in trackstaffs) { if (i < list.Count) { result.Add(list[i]); } } } return result; }
/** 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(); }
/** 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); }
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); }
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 SheetMusic(MidiFile file, MidiOptions options, List <MidiTrack> tracks) { init(file, options, tracks); }
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); }
/** 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); }
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); }
CreateStaffsForTrack(List <MusicSymbol> symbols, int measurelen, KeySignature key, MidiOptions options, int track, int totaltracks) { int keysigWidth = KeySignatureWidth(key); int startindex = 0; List <Staff> thestaffs = new List <Staff>(symbols.Count / 50); while (startindex < symbols.Count) { /* startindex is the index of the first symbol in the staff. * endindex is the index of the last symbol in the staff. */ int endindex = startindex; int width = keysigWidth; int maxwidth; /* If we're scrolling vertically, the maximum width is PageWidth. */ if (scrollVert) { maxwidth = SheetMusic.PageWidth; } else { maxwidth = 2000000; } while (endindex < symbols.Count && width + symbols[endindex].Width < maxwidth) { width += symbols[endindex].Width; endindex++; } endindex--; /* There's 3 possibilities at this point: * 1. We have all the symbols in the track. * The endindex stays the same. * * 2. We have symbols for less than one measure. * The endindex stays the same. * * 3. We have symbols for 1 or more measures. * Since measures cannot span multiple staffs, we must * make sure endindex does not occur in the middle of a * measure. We count backwards until we come to the end * of a measure. */ if (endindex == symbols.Count - 1) { /* endindex stays the same */ } else if (symbols[startindex].StartTime / measurelen == symbols[endindex].StartTime / measurelen) { /* endindex stays the same */ } else { int endmeasure = symbols[endindex + 1].StartTime / measurelen; while (symbols[endindex].StartTime / measurelen == endmeasure) { endindex--; } } int range = endindex + 1 - startindex; if (scrollVert) { width = SheetMusic.PageWidth; } Staff staff = new Staff(symbols.GetRange(startindex, range), key, options, track, totaltracks); thestaffs.Add(staff); startindex = endindex + 1; } return(thestaffs); }
/** Write this Midi file to the given stream. * If options is not null, apply those options to the midi events * before performing the write. * Return true if the file was saved successfully, else false. */ public bool Write(Stream stream, MidiOptions options) { List<MidiEvent>[] newevents = events; if (options != null) { newevents = ApplyOptionsToEvents(options); } return WriteEvents(stream, newevents, trackmode, quarternote); }
/** Create the MidiOptions based on the menus */ MidiOptions GetMidiOptions() { MidiOptions options = new MidiOptions(midifile); /* Get the list of selected tracks from the Tracks menu */ for (int track = 0; track < midifile.Tracks.Count; track++) { options.tracks[track] = trackDisplayMenu.MenuItems[track+2].Checked; options.mute[track] = trackMuteMenu.MenuItems[track+2].Checked; } options.scrollVert = scrollVertMenu.Checked; options.largeNoteSize = largeNotesMenu.Checked; options.twoStaffs = twoStaffMenu.Checked; options.showNoteLetters = MidiOptions.NoteNameNone; for (int i = 0; i < 6; i++) { if (showLettersMenu.MenuItems[i].Checked) { options.showNoteLetters = (int)showLettersMenu.MenuItems[i].Tag; } } if (showLyricsMenu != null) { options.showLyrics = showLyricsMenu.Checked; } options.showMeasures = showMeasuresMenu.Checked; options.shifttime = 0; options.transpose = 0; options.key = -1; options.time = midifile.Time; /* Get the time signature to use */ foreach (MenuItem menu in timeSigMenu.MenuItems) { int quarter = options.time.Quarter; int tempo = options.time.Tempo; if (menu.Checked && !menu.Text.Contains("default")) { if (menu.Text == "3/4") { options.time = new TimeSignature(3, 4, quarter, tempo); } else if (menu.Text == "4/4") { options.time = new TimeSignature(4, 4, quarter, tempo); } } } /* Get the measure length to use */ foreach (MenuItem menu in measureMenu.MenuItems) { if (menu.Checked) { int num = options.time.Numerator; int denom = options.time.Denominator; int measure = (int)menu.Tag; int tempo = options.time.Tempo; int quarter = measure * options.time.Quarter / options.time.Measure; options.time = new TimeSignature(num, denom, quarter, tempo); } } /* Get the amount to shift the notes left/right */ foreach (MenuItem menu in shiftNotesMenu.MenuItems) { if (menu.Checked) { int shift = (int)menu.Tag; if (shift >= 0) options.shifttime = midifile.Time.Quarter/2 * (shift); else options.shifttime = shift; } } /* Get the key signature to use */ foreach (MenuItem menu in changeKeyMenu.MenuItems) { if (menu.Checked && !menu.Text.Contains("Default")) { int tag = (int)menu.Tag; /* If the tag is positive, it has the number of sharps. * If the tag is negative, it has the number of flats. */ int num_flats = 0; int num_sharps = 0; if (tag < 0) num_flats = -tag; else num_sharps = tag; options.key = new KeySignature(num_sharps, num_flats).Notescale(); } } /* Get the amount to transpose the key up/down */ foreach (MenuItem menu in transposeMenu.MenuItems) { if (menu.Checked) { options.transpose = (int)menu.Tag; } } /* Get the time interval for combining notes into the same chord. */ foreach (MenuItem menu in combineNotesMenu.MenuItems) { if (menu.Checked) { options.combineInterval = (int)menu.Tag; } } /* Get the list of instruments from the Instrument dialog */ options.instruments = instrumentDialog.Instruments; options.useDefaultInstruments = instrumentDialog.isDefault(); /* Get the speed/tempo to use */ options.tempo = midifile.Time.Tempo; /* Get whether to play measures in a loop */ options.playMeasuresInLoop = playMeasuresDialog.IsEnabled(); if (options.playMeasuresInLoop) { options.playMeasuresInLoopStart = playMeasuresDialog.GetStartMeasure(); options.playMeasuresInLoopEnd = playMeasuresDialog.GetEndMeasure(); if (options.playMeasuresInLoopStart > options.playMeasuresInLoopEnd) { options.playMeasuresInLoopEnd = options.playMeasuresInLoopStart; } } /* Get the note colors to use */ options.shadeColor = colordialog.ShadeColor; options.shade2Color = colordialog.Shade2Color; if (useColorMenu.Checked) { options.colors = colordialog.Colors; } else { options.colors = null; } return options; }
/* Apply the following sound options to the midi events: * - The tempo (the microseconds per pulse) * - The instruments per track * - The note number (transpose value) * - The tracks to include * Return the modified list of midi events. */ private List<MidiEvent>[] ApplyOptionsToEvents(MidiOptions options) { int i; if (trackPerChannel) { return ApplyOptionsPerChannel(options); } /* A midifile can contain tracks with notes and tracks without notes. * The options.tracks and options.instruments are for tracks with notes. * So the track numbers in 'options' may not match correctly if the * midi file has tracks without notes. Re-compute the instruments, and * tracks to keep. */ int num_tracks = events.Length; int[] instruments = new int[num_tracks]; bool[] keeptracks = new bool[num_tracks]; for (i = 0; i < num_tracks; i++) { instruments[i] = 0; keeptracks[i] = true; } for (int tracknum = 0; tracknum < tracks.Count; tracknum++) { MidiTrack track = tracks[tracknum]; int realtrack = track.Number; instruments[realtrack] = options.instruments[tracknum]; if (options.tracks[tracknum] == false || options.mute[tracknum] == true) { keeptracks[realtrack] = false; } } List<MidiEvent>[] newevents = CloneMidiEvents(events); /* Set the tempo at the beginning of each track */ for (int tracknum = 0; tracknum < newevents.Length; tracknum++) { MidiEvent mevent = CreateTempoEvent(options.tempo); newevents[tracknum].Insert(0, mevent); } /* Change the note number (transpose), instrument, and tempo */ for (int tracknum = 0; tracknum < newevents.Length; tracknum++) { foreach (MidiEvent mevent in newevents[tracknum]) { int num = mevent.Notenumber + options.transpose; if (num < 0) num = 0; if (num > 127) num = 127; mevent.Notenumber = (byte)num; if (!options.useDefaultInstruments) { mevent.Instrument = (byte)instruments[tracknum]; } mevent.Tempo = options.tempo; } } if (options.pauseTime != 0) { newevents = StartAtPauseTime(newevents, options.pauseTime); } /* Change the tracks to include */ int count = 0; for (int tracknum = 0; tracknum < keeptracks.Length; tracknum++) { if (keeptracks[tracknum]) { count++; } } List<MidiEvent>[] result = new List<MidiEvent>[count]; i = 0; for (int tracknum = 0; tracknum < keeptracks.Length; tracknum++) { if (keeptracks[tracknum]) { result[i] = newevents[tracknum]; i++; } } return result; }
/** Apply the given sheet music options to the MidiNotes. * Return the midi tracks with the changes applied. */ public List<MidiTrack> ChangeMidiNotes(MidiOptions options) { List<MidiTrack> newtracks = new List<MidiTrack>(); for (int track = 0; track < tracks.Count; track++) { if (options.tracks[track]) { newtracks.Add(tracks[track].Clone() ); } } /* To make the sheet music look nicer, we round the start times * so that notes close together appear as a single chord. We * also extend the note durations, so that we have longer notes * and fewer rest symbols. */ TimeSignature time = timesig; if (options.time != null) { time = options.time; } MidiFile.RoundStartTimes(newtracks, options.combineInterval, timesig); MidiFile.RoundDurations(newtracks, time.Quarter); if (options.twoStaffs) { newtracks = MidiFile.CombineToTwoTracks(newtracks, timesig.Measure); } if (options.shifttime != 0) { MidiFile.ShiftTime(newtracks, options.shifttime); } if (options.transpose != 0) { MidiFile.Transpose(newtracks, options.transpose); } return newtracks; }
/** 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, Resources.Localization.Strings.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, Resources.Localization.Strings.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, Resources.Localization.Strings.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, Resources.Localization.Strings.fastForward); /* Create the Speed bar */ speedLabel = new Label(); speedLabel.Parent = this; speedLabel.Text = Resources.Localization.Strings.speed + " : 100%"; speedLabel.TextAlign = ContentAlignment.MiddleLeft; speedLabel.Height = buttonheight; speedLabel.Width = buttonheight * 3; 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 = 150; speedBar.TickFrequency = 10; speedBar.TickStyle = TickStyle.BottomRight; speedBar.LargeChange = 10; speedBar.Value = 100; speedBar.Width = buttonheight * 6; speedBar.Location = new Point(speedLabel.Location.X + speedLabel.Width + 2, speedLabel.Location.Y); speedBar.Scroll += new EventHandler(SpeedBarChanged); tip = new ToolTip(); tip.SetToolTip(speedBar, Resources.Localization.Strings.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 * 6; volumeBar.Location = new Point(volumeLabel.Location.X + volumeLabel.Width + 2, volumeLabel.Location.Y); volumeBar.Scroll += new EventHandler(ChangeVolume); tip = new ToolTip(); tip.SetToolTip(volumeBar, Resources.Localization.Strings.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 = ""; }
/** Write this Midi file to the given filename. * If options is not null, apply those options to the midi events * before performing the write. * Return true if the file was saved successfully, else false. */ public bool ChangeSound(string destfile, MidiOptions options) { return Write(destfile, options); }
/* Apply the following sound options to the midi events: * - The tempo (the microseconds per pulse) * - The instruments per track * - The note number (transpose value) * - The tracks to include * Return the modified list of midi events. * * This Midi file only has one actual track, but we've split that * into multiple fake tracks, one per channel, and displayed that * to the end-user. So changing the instrument, and tracks to * include, is implemented differently than ApplyOptionsToEvents(). * * - We change the instrument based on the channel, not the track. * - We include/exclude channels, not tracks. * - We exclude a channel by setting the note volume/velocity to 0. */ private List<MidiEvent>[] ApplyOptionsPerChannel(MidiOptions options) { /* Determine which channels to include/exclude. * Also, determine the instruments for each channel. */ int[] instruments = new int[16]; bool[] keepchannel = new bool[16]; for (int i = 0; i < 16; i++) { instruments[i] = 0; keepchannel[i] = true; } for (int tracknum = 0; tracknum < tracks.Count; tracknum++) { MidiTrack track = tracks[tracknum]; int channel = track.Notes[0].Channel; instruments[channel] = options.instruments[tracknum]; if (options.tracks[tracknum] == false || options.mute[tracknum] == true) { keepchannel[channel] = false; } } List<MidiEvent>[] newevents = CloneMidiEvents(events); /* Set the tempo at the beginning of each track */ for (int tracknum = 0; tracknum < newevents.Length; tracknum++) { MidiEvent mevent = CreateTempoEvent(options.tempo); newevents[tracknum].Insert(0, mevent); } /* Change the note number (transpose), instrument, and tempo */ for (int tracknum = 0; tracknum < newevents.Length; tracknum++) { foreach (MidiEvent mevent in newevents[tracknum]) { int num = mevent.Notenumber + options.transpose; if (num < 0) num = 0; if (num > 127) num = 127; mevent.Notenumber = (byte)num; if (!keepchannel[mevent.Channel]) { mevent.Velocity = 0; } if (!options.useDefaultInstruments) { mevent.Instrument = (byte)instruments[mevent.Channel]; } mevent.Tempo = options.tempo; } } if (options.pauseTime != 0) { newevents = StartAtPauseTime(newevents, options.pauseTime); } return newevents; }