Esempio n. 1
0
        public void FindTimeOfNthNoteFrom_SkipsSplitChordCorrectly()
        {
            const int chordTime = 1800;

            var testArr = new InstrumentalArrangement();

            testArr.Levels.Add(new Level());
            testArr.Levels[0].Notes.Add(new Note
            {
                Time   = chordTime - 500,
                String = 1
            });
            testArr.Levels[0].Notes.Add(new Note
            {
                Time   = chordTime - 500,
                String = 2
            });
            testArr.Levels[0].Notes.Add(new Note
            {
                Time   = chordTime - 500,
                String = 3
            });
            testArr.Levels[0].Chords.Add(new Chord
            {
                Time = chordTime
            });

            int result = TimeParser.FindTimeOfNthNoteFrom(testArr.Levels[0], 0, 2);

            result.Should().Be(chordTime);
        }
Esempio n. 2
0
        public void FindTimeOfNthNoteFrom_FindsCorrectNote()
        {
            const int noteTime = 1200;

            var testArr = new InstrumentalArrangement();

            testArr.Levels.Add(new Level());
            testArr.Levels[0].Notes.Add(new Note
            {
                Time = noteTime
            });

            int result = TimeParser.FindTimeOfNthNoteFrom(testArr.Levels[0], 0, 1);

            result.Should().Be(noteTime);
        }
Esempio n. 3
0
        public void Apply(InstrumentalArrangement arrangement, Action <string> Log)
        {
            var events = arrangement.Events;

            var removeBeatsEvent = events.Find(ev => ev.Code.Equals("removebeats", StringComparison.OrdinalIgnoreCase));

            if (removeBeatsEvent is not null)
            {
                arrangement.Ebeats.RemoveAll(b => b.Time >= removeBeatsEvent.Time);

                Log($"removebeats event found: Removed beats from {removeBeatsEvent.Time.TimeToString()} onward.");

                events.Remove(removeBeatsEvent);
            }

            var slideoutEvents = events.Where(ev => ev.Code.StartsWith("so", StringComparison.OrdinalIgnoreCase)).ToList();

            foreach (var slideEvent in slideoutEvents)
            {
                int slideTime = slideEvent.Time;

                // Find the max level for the phrase the slide is in
                var phraseIter = arrangement.PhraseIterations.Last(pi => pi.Time <= slideTime);
                int diff       = arrangement.Phrases[phraseIter.PhraseId].MaxDifficulty;
                var level      = arrangement.Levels[diff];

                // If a number was given after the event code, get the time of the chord or note that is right of the event by that number
                if (slideEvent.Code.Length > 2 &&
                    int.TryParse(slideEvent.Code.Substring(2), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out int rightBy))
                {
                    slideTime = TimeParser.FindTimeOfNthNoteFrom(level, slideTime, rightBy);
                }

                int noteIndex  = level.Notes.FindIndexByTime(slideTime);
                int chordIndex = level.Chords.FindIndexByTime(slideTime);
                if (noteIndex == -1 && chordIndex == -1)
                {
                    string error = $"Could not find the notes or chord for SlideOut event at {slideEvent.Time.TimeToString()}";
                    _statusMessages.Add(new ImproverMessage(error, MessageType.Error, slideEvent.Time));
                    Log(error);
                    continue;
                }

                var           notes = new List <Note>();
                ChordTemplate originalChordTemplate;

                if (noteIndex != -1) // These are notes that follow a LinkNext chord
                {
                    do
                    {
                        var note = level.Notes[noteIndex];
                        if (note.IsUnpitchedSlide)
                        {
                            notes.Add(note);
                        }
                        noteIndex++;
                    } while (noteIndex < level.Notes.Count && level.Notes[noteIndex].Time == slideTime);

                    // Find the chord that is linked to the slide, its template and handshape
                    var linkNextChord   = level.Chords.Last(c => c.Time < slideTime);
                    var linkNextChordHs = level.HandShapes.Find(hs => hs.StartTime == linkNextChord.Time);
                    originalChordTemplate = arrangement.ChordTemplates[linkNextChord.ChordId];

                    // Shorten handshapes that EOF has set to include the slide out
                    // If chord notes is null here, there is an error in the XML file
                    if (linkNextChordHs is not null && linkNextChordHs.EndTime > linkNextChord.Time + linkNextChord.ChordNotes ![0].Sustain)
Esempio n. 4
0
        public void Apply(InstrumentalArrangement arrangement, Action <string> Log)
        {
            var phrasesToMove = arrangement.Phrases
                                .Where(p => p.Name.StartsWith("moveto", StringComparison.OrdinalIgnoreCase) ||
                                       p.Name.StartsWith("moveR", StringComparison.OrdinalIgnoreCase))
                                .ToList();

            if (phrasesToMove.Count > 0)
            {
                Log("Processing 'move' phrases:");
            }
            else
            {
                return;
            }

            foreach (var phraseToMove in phrasesToMove)
            {
                // Find phrase iterations by matching phrase index
                int phraseId = arrangement.Phrases.IndexOf(phraseToMove);
                foreach (var phraseIterationToMove in arrangement.PhraseIterations.Where(pi => pi.PhraseId == phraseId))
                {
                    int    phraseTime = phraseIterationToMove.Time;
                    int    movetoTime;
                    string phraseToMoveName = phraseToMove.Name;

                    // Relative phrase moving right
                    if (phraseToMoveName.StartsWith("moveR", StringComparison.OrdinalIgnoreCase))
                    {
                        if (int.TryParse(phraseToMoveName.Substring("moveR".Length), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out int moveRightBy))
                        {
                            var level = arrangement.Levels[phraseToMove.MaxDifficulty];
                            movetoTime = TimeParser.FindTimeOfNthNoteFrom(level, phraseTime, moveRightBy);
                        }
                        else
                        {
                            string errorMessage = $"Unable to read value for 'moveR' phrase at {phraseTime.TimeToString()}. (Usage example: moveR2)";
                            _statusMessages.Add(new ImproverMessage(errorMessage, MessageType.Warning));
                            Log(errorMessage);

                            continue;
                        }
                    }
                    else // Parse the absolute time to move to from the phrase name
                    {
                        int?parsedTime = TimeParser.Parse(phraseToMoveName);
                        if (parsedTime.HasValue)
                        {
                            movetoTime = parsedTime.Value;
                        }
                        else
                        {
                            MoveToParseFailure(phraseTime, Log);
                            continue;
                        }
                    }

                    // Check if anchor(s) should be moved
                    foreach (var level in arrangement.Levels)
                    {
                        if (level.Difficulty > phraseToMove.MaxDifficulty)
                        {
                            break;
                        }

                        var anchors             = level.Anchors;
                        int originalAnchorIndex = anchors.FindIndexByTime(phraseTime);
                        int movetoAnchorIndex   = anchors.FindIndexByTime(movetoTime);

                        // If there is an anchor at the original position, but not at the new position, move it
                        if (originalAnchorIndex != -1 && movetoAnchorIndex == -1)
                        {
                            var originalAnchor = anchors[originalAnchorIndex];
                            anchors.Insert(originalAnchorIndex + 1, new Anchor(originalAnchor.Fret, movetoTime, originalAnchor.Width));

                            // Remove anchor at original phrase position if no note or chord present
                            if (level.Notes.FindIndexByTime(phraseTime) == -1 &&
                                level.Chords.FindIndexByTime(phraseTime) == -1)
                            {
                                anchors.RemoveAt(originalAnchorIndex);
                                Log($"--Moved anchor from {phraseTime.TimeToString()} to {movetoTime.TimeToString()}");
                            }
                            else
                            {
                                Log($"--Added anchor at {movetoTime.TimeToString()}");
                            }
                        }
                    }

                    // Move phraseIteration
                    phraseIterationToMove.Time = movetoTime;

                    // Move section (if present)
                    var sectionToMove = arrangement.Sections.FindByTime(phraseTime);
                    if (sectionToMove is not null)
                    {
                        sectionToMove.Time = movetoTime;
                        Log($"--Moved phrase and section from {phraseTime.TimeToString()} to {movetoTime.TimeToString()}");
                    }
                    else
                    {
                        Log($"--Moved phrase from {phraseTime.TimeToString()} to {movetoTime.TimeToString()}");
                    }

                    // Add new temporary beat
                    var beatToAdd = new Ebeat(movetoTime, XMLProcessor.TempMeasureNumber);

                    var insertIndex = arrangement.Ebeats.FindIndex(b => b.Time > movetoTime);
                    arrangement.Ebeats.Insert(insertIndex, beatToAdd);

                    // Set the beat for later removal
                    _addedBeats.Add(beatToAdd);
                }
            }
        }