/** 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(); }
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 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 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 parsed MidiFile. * The options can be null. */ public SheetMusic(MidiFile file, MidiOptions options) { init(file, options); }
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); }
/** 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 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); }
/** 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 = ""; }