Example #1
0
        /**<summary>Redraws the control.</summary>*/
        protected override void OnRender(DrawingContext d)
        {
            // Set guidelines for pixel perfection
            GuidelineSet guidelines = new GuidelineSet();

            guidelines.GuidelinesX.Add(0.5);
            guidelines.GuidelinesX.Add(ActualHeight + 0.5);
            guidelines.GuidelinesY.Add(0.5);
            guidelines.GuidelinesY.Add(ActualWidth + 0.5);
            d.PushGuidelineSet(guidelines);

            // Highlight the midi's octave range
            if (!DesignerProperties.GetIsInDesignMode(this) && IsTrackLoaded)
            {
                int min = (AllTracksLoaded ? 0 : trackIndex);
                int max = (AllTracksLoaded ? Config.Midi.TrackCount : trackIndex + 1);
                for (int index = min; index < max; index++)
                {
                    if (!Config.Midi.GetTrackSettingsAt(index).Enabled&& AllTracksLoaded)
                    {
                        continue;
                    }
                    double high = GetSemitoneY((Config.Midi.GetTrackSettingsAt(index).OctaveOffset + 3) * 12);
                    double low  = GetSemitoneY((Config.Midi.GetTrackSettingsAt(index).OctaveOffset + 1) * 12);
                    d.DrawRectangle(Brushes.LightYellow, null, Floor(new Rect(
                                                                         GetProgressX(0), high, ActualWidthSpacing, low - high
                                                                         )));
                }
                for (int index = min; index < max; index++)
                {
                    if (!Config.Midi.GetTrackSettingsAt(index).Enabled&& AllTracksLoaded)
                    {
                        continue;
                    }
                    double high = GetSemitoneY((Config.Midi.GetTrackSettingsAt(index).OctaveOffset + 3) * 12);
                    double low  = GetSemitoneY((Config.Midi.GetTrackSettingsAt(index).OctaveOffset + 1) * 12);
                    d.DrawRectangle(null, new Pen(Brushes.Gold, 3), Floor(new Rect(
                                                                              GetProgressX(0), high, ActualWidthSpacing, low - high
                                                                              )));
                }
            }

            // Draw the octave lines and labels
            for (int i = 0; i <= OctaveRange; i++)
            {
                double y = TrackGraph.SpacingY + ActualHeightSpacing / OctaveRange * i;
                d.DrawLine(new Pen(Brushes.LightGray, 1),
                           Floor(new Point(SpacingLeft, y)),
                           Floor(new Point(ActualWidth - SpacingRight, y)));

                var formattedText = new FormattedText(
                    "C" + (highestOctave - i),
                    CultureInfo.GetCultureInfo("en-us"),
                    FlowDirection.LeftToRight,
                    new Typeface("Segoe UI"),
                    12,
                    Brushes.Black
                    );
                y -= formattedText.Height / 2;
                d.DrawText(formattedText, Floor(new Point(SpacingLabel, y)));
            }

            // Stop using the guidelines
            d.Pop();

            // The milliseconds of the next playable note
            int nextPlayable = 0;
            // The use time in milliseconds (Checked if not in designer)
            int useTime = 0;

            // Current milliseconds of the midi playback
            int currentMilliseconds = 0;

            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                useTime             = Config.UseTime * 1000 / 60;
                currentMilliseconds = Config.Sequencer.CurrentTime;
            }

            // Draw all notes
            for (int i = 0; i < notes.Count; i++)
            {
                TrackNote note = notes[i];
                note.Semitone += Config.Midi.NoteOffset;
                if (note.Semitone >= 0 && note.Semitone <= 132)
                {
                    double x = GetProgressX(note.Progress);
                    double y = GetSemitoneY(note.Semitone);

                    bool skipped        = note.Milliseconds < nextPlayable;
                    bool inRange        = IsNoteInsideRange(note);
                    bool recentlyPlayed =
                        note.Milliseconds <= currentMilliseconds &&
                        note.Milliseconds + RecentlyPlayedThreshold >= currentMilliseconds &&
                        Config.Midi.GetTrackSettingsAt(note.TrackIndex).Enabled;
                    SolidColorBrush brush;
                    if (skipped)
                    {
                        brush = SkippedNoteBrush;
                        if (!ShowSkippedNotes)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        nextPlayable = note.Milliseconds + useTime + 2;
                        if (!inRange)
                        {
                            brush = WrappedNoteBrush;
                            if (!ShowWrappedNotes)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            brush = ValidNoteBrush;
                            if (!ShowValidNotes)
                            {
                                continue;
                            }
                        }
                    }
                    if (recentlyPlayed && drawingPlayback && (!skipped || !Config.SkipPianoMode))
                    {
                        double scale = (double)(currentMilliseconds - note.Milliseconds) / RecentlyPlayedThreshold;
                        brush = Lerp(RecentlyPlayedNoteBrush, brush, scale);
                    }

                    // Don't floor the ellipse
                    d.DrawEllipse(brush, null, new Point(x, y), 2, 2);
                }
            }
        }
Example #2
0
 /**<summary>Gets if the note is within the midi's octave range.</summary>*/
 private bool IsNoteInsideRange(TrackNote note)
 {
     return(note.Semitone - (Config.Midi.GetTrackSettingsAt(note.TrackIndex).OctaveOffset + 1) * 12 >= 0 &&
            note.Semitone - (Config.Midi.GetTrackSettingsAt(note.TrackIndex).OctaveOffset + 1) * 12 <= 24);
 }
Example #3
0
        /**<summary>Updates changes made to the track.</summary>*/
        public void Update()
        {
            lowestOctave  = 10;
            highestOctave = -1;

            int min = (AllTracksLoaded ? 0 : trackIndex);
            int max = (AllTracksLoaded ? Config.Midi.TrackCount : trackIndex + 1);

            for (int index = min; index < max; index++)
            {
                if (!Config.Midi.GetTrackSettingsAt(index).Enabled&& AllTracksLoaded)
                {
                    continue;
                }
                lowestOctave = Math.Min(lowestOctave, Math.Max(-1, Math.Min(
                                                                   Config.Midi.GetTrackSettingsAt(index).OctaveOffset - 1,
                                                                   (Config.Midi.GetTrackAt(index).LowestNote + Config.Midi.NoteOffset) / 12 - 1
                                                                   )));
                highestOctave = Math.Max(highestOctave, Math.Min(10, Math.Max(
                                                                     Config.Midi.GetTrackSettingsAt(index).OctaveOffset + 3,
                                                                     (Config.Midi.GetTrackAt(index).HighestNote + Config.Midi.NoteOffset - 1) / 12
                                                                     )));
            }
            if (lowestOctave >= highestOctave)
            {
                lowestOctave  = -1;
                highestOctave = 10;
            }

            // The milliseconds of the next playable note
            int nextPlayable = 0;
            // The use time in milliseconds (Checked if not in designer)
            int useTime = 0;

            ValidNotes   = 0;
            WrappedNotes = 0;
            SkippedNotes = 0;

            // Count note categories
            for (int i = 0; i < notes.Count; i++)
            {
                TrackNote note = notes[i];
                note.Semitone += Config.Midi.NoteOffset;
                if (note.Semitone >= 0 && note.Semitone <= 132)
                {
                    bool skipped = note.Milliseconds < nextPlayable;
                    bool inRange = IsNoteInsideRange(note);
                    if (skipped)
                    {
                        SkippedNotes++;
                    }
                    else
                    {
                        nextPlayable = note.Milliseconds + useTime + 2;
                        if (!inRange)
                        {
                            WrappedNotes++;
                        }
                        else
                        {
                            ValidNotes++;
                        }
                    }
                }
                else
                {
                    SkippedNotes++;
                }
            }

            InvalidateVisual();
        }