Пример #1
0
        protected bool FillRhythmSegmentVoices(TablatureContext context, ILogger logger, RhythmSegmentBase rhythmSegment)
        {
            var duration = this.GetDuration();

            if (this.TrebleVoice != null)
            {
                this.TrebleVoice.ExpectedDuration = duration;

                RhythmSegmentVoice trebleVoice;
                if (!this.TrebleVoice.ToDocumentElement(context, logger, VoicePart.Treble, out trebleVoice))
                {
                    return(false);
                }

                rhythmSegment.TrebleVoice = trebleVoice;
            }

            if (this.BassVoice != null)
            {
                this.BassVoice.ExpectedDuration = duration;

                RhythmSegmentVoice bassVoice;
                if (!this.BassVoice.ToDocumentElement(context, logger, VoicePart.Bass, out bassVoice))
                {
                    return(false);
                }

                rhythmSegment.BassVoice = bassVoice;
            }

            return(true);
        }
Пример #2
0
        internal override bool Apply(TablatureContext context, ILogger logger)
        {
            Alternation alternation;

            if (!this.ToDocumentElement(context, logger, out alternation))
            {
                return(false);
            }

            if (context.DocumentState.AlternationTextExplicity != Explicity.NotSpecified &&
                alternation.Explicity != context.DocumentState.AlternationTextExplicity)
            {
                logger.Report(LogLevel.Warning, this.Range.To.AsRange(),
                              Messages.Warning_InconsistentAlternationTextExplicity);
            }

            using (var state = context.AlterDocumentState())
            {
                foreach (var index in alternation.Indices)
                {
                    state.DefinedAlternationIndices.Add(index);
                }

                state.CurrentAlternation       = alternation;
                state.AlternationTextType      = alternation.TextType;
                state.AlternationTextExplicity = alternation.Explicity;
            }

            return(true);
        }
Пример #3
0
        internal override bool Apply(TablatureContext context, ILogger logger)
        {
            Bar bar;

            if (!this.ToDocumentElement(context, logger, null, out bar))
            {
                return(false);
            }

            if (bar.Rhythm != null && bar.Lyrics != null)
            {
                var beats = bar.Rhythm.Segments.Sum(s => s.FirstVoice.Beats?.Count ?? 0);
                if (beats < bar.Lyrics.Segments.Count)
                {
                    logger.Report(LogLevel.Suggestion, bar.Lyrics.Range, Messages.Suggestion_LyricsTooLong);
                }
            }

            context.AddBar(bar);

            // check if this bar terminates an alternative ending, must be done AFTER adding this bar to context
            if ((bar.CloseLine == CloseBarLine.End || bar.CloseLine == CloseBarLine.EndRepeat) &&
                context.DocumentState.CurrentAlternation != null)
            {
                using (var state = context.AlterDocumentState())
                {
                    state.CurrentAlternation = null;
                }
            }

            return(true);
        }
Пример #4
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, VoicePart voicePart, out BeatNote element)
        {
            var documentState = context.DocumentState;

            if (this.Fret != null &&
                this.Fret.Value + documentState.MinimumCapoFret < (documentState.CapoFretOffsets?[this.String.Value - 1] ?? 0))
            {
                logger.Report(LogLevel.Warning, this.Fret.Range,
                              Messages.Warning_FretUnderCapo, this.String.Value,
                              this.Fret.Value);
            }

            element = new BeatNote
            {
                Range                    = this.Range,
                PreConnection            = this.PreConnection?.Value ?? PreNoteConnection.None,
                PostConnection           = this.PostConnection?.Value ?? PostNoteConnection.None,
                IsTied                   = this.Tie != null,
                TiePosition              = this.TiePosition?.Value,
                String                   = this.String.Value - 1,
                Fret                     = this.Fret?.Value ?? BeatNote.UnspecifiedFret,
                EffectTechnique          = this.EffectTechnique?.Value ?? NoteEffectTechnique.None,
                EffectTechniqueParameter = this.EffectTechniqueParameter?.Value,
                Accent                   = this.Accent?.Value ?? NoteAccent.Normal
            };

            if (!this.Validate(context, logger, voicePart, element))
            {
                return(false);
            }

            return(true);
        }
Пример #5
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, out ChordDefinition element)
        {
            if (context.DocumentState.DefinedChords.Any(
                    c => c.Name.Equals(this.Name.Value,
                                       StringComparison.InvariantCulture)))
            {
                logger.Report(LogLevel.Warning, this.Range, Messages.Warning_ChordAlreadyDefined);
                element = null;
                return(false);
            }

            ChordFingering chordFingering;

            if (!this.Fingering.ToDocumentElement(context, logger, out chordFingering))
            {
                element = null;
                return(false);
            }

            element = new ChordDefinition
            {
                Range       = this.Range,
                DisplayName = this.GetDisplayName(),
                Name        = this.Name.Value,
                Fingering   = chordFingering
            };

            return(true);
        }
Пример #6
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, out Rhythm rhythm)
        {
            rhythm = new Rhythm
            {
                Range = this.Range
            };

            var duration = PreciseDuration.Zero;

            foreach (var segment in this.Segments)
            {
                RhythmSegment rhythmSegment;
                if (!segment.ToDocumentElement(context, logger, out rhythmSegment))
                {
                    return(false);
                }

                rhythm.Segments.Add(rhythmSegment);
                duration += segment.GetDuration();
            }

            // duration could be 0 if rhythm is not defined (only chord defined), rhythm will be determined by the rhythm instruction
            if (duration > 0 && duration == context.DocumentState.TimeSignature.Time.GetDuration())
            {
                logger.Report(LogLevel.Warning, this.Range, Messages.Warning_BeatsNotMatchingTimeSignature);
                rhythm.NotMatchingTime = true;
            }

            return(true);
        }
Пример #7
0
        public override bool CheckIntegrity(TablatureContext context, ILogger logger)
        {
            if (context.Bars.Count > 0)
            {
                var firstBar = context.Bars[0];
                if (firstBar.OpenLine == null)
                {
                    logger.Report(LogLevel.Hint, firstBar.Range.Value.From.AsRange(), Messages.Hint_FirstOpenBarLineMissing);
                }

                for (var i = 1; i < context.Bars.Count - 1; ++i)
                {
                    if (context.Bars[i].CloseLine == null && context.Bars[i + 1].OpenLine == null)
                    {
                        logger.Report(LogLevel.Warning, context.Bars[i].Range.Value.To.AsRange(), Messages.Warning_BarLineMissing);
                    }
                }

                var lastBar = context.Bars[context.Bars.Count - 1];
                if (lastBar.CloseLine == null)
                {
                    logger.Report(LogLevel.Hint, lastBar.Range.Value.To.AsRange(), Messages.Hint_LastCloseBarLineMissing);
                }
            }

            return(true);
        }
        public override bool CheckIntegrity(TablatureContext context, ILogger logger)
        {
            var lastIndex      = 0;
            var missingIndices = new List <int>();

            foreach (var index in context.DocumentState.DefinedAlternationIndices.OrderBy(i => i))
            {
                if (index != lastIndex + 1)
                {
                    missingIndices.Add(index);
                }

                lastIndex = index;
            }

            if (missingIndices.Count == 0)
            {
                return(true);
            }


            var alternationTextType = context.DocumentState.AlternationTextType ?? AlternationTextType.Arabic;

            logger.Report(LogLevel.Error, null, Messages.Error_MissingAlternationTexts,
                          string.Join(", ",
                                      missingIndices.Select(i => AlternationText.GetAlternationText(alternationTextType, i))));
            return(false);
        }
Пример #9
0
        internal override bool Apply(TablatureContext context, ILogger logger)
        {
            if (context.DocumentState.BarAppeared)
            {
                logger.Report(LogLevel.Error, this.Range, Messages.Error_TuningInstructionAfterBarAppeared);
                return(false);
            }

            if (context.DocumentState.TuningSignature != null)
            {
                logger.Report(LogLevel.Warning, this.Range, Messages.Warning_RedefiningTuningInstruction);
                return(false);
            }

            TuningSignature tuning;

            if (!this.ToDocumentElement(context, logger, out tuning))
            {
                return(false);
            }

            using (var state = context.AlterDocumentState())
            {
                state.TuningSignature = tuning;
            }

            return(true);
        }
Пример #10
0
        private bool ValidatePostConnection(TablatureContext context, ILogger logger, VoicePart voicePart, BeatNote element)
        {
            if (this.PostConnection == null || this.PostConnection.Value == PostNoteConnection.None)
            {
                return(true);
            }

            if (this.PostConnection.Value == PostNoteConnection.SlideOutToHigher ||
                this.PostConnection.Value == PostNoteConnection.SlideOutToLower)
            {
                if (this.Fret == null)
                {
                    logger.Report(LogLevel.Error, this.PreConnection.Range,
                                  Messages.Error_FretMissingForSlideOutNote);
                    return(false);
                }

                if (this.PostConnection.Value == PostNoteConnection.SlideOutToLower &&
                    this.Fret.Value <= context.DocumentState.GetCapoFretOffset(this.String.Value - 1))
                {
                    logger.Report(LogLevel.Warning, this.Fret.Range,
                                  Messages.Warning_FretTooLowForSlideOutNote);
                    element.PostConnection = PostNoteConnection.None;
                }
            }

            return(true);
        }
        public bool ToDocumentElement(TablatureContext context, ILogger logger, out TimeSignature element)
        {
            if ((context.DocumentState.RhythmTemplate != null || context.DocumentState.BarAppeared) &&
                context.DocumentState.TimeSignature == null)
            {
                logger.Report(LogLevel.Error, this.Range, Messages.Error_TimeInstructionAfterBarAppearedOrRhythmInstruction);
                element = null;
                return(false);
            }

            if (context.DocumentState.TimeSignature != null && this.ValueEquals(context.DocumentState.TimeSignature))
            {
                logger.Report(LogLevel.Suggestion, this.Range, Messages.Suggestion_UselessTimeInstruction);
                element = null;
                return(false);
            }

            element = new TimeSignature
            {
                Range = this.Range,
                Time  = new Time(this.Beats.Value, this.NoteValue.Value)
            };

            return(true);
        }
Пример #12
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, out RhythmTemplateSegment rhythmSegment)
        {
            rhythmSegment = new RhythmTemplateSegment
            {
                Range = this.Range
            };

            return(this.FillRhythmSegmentVoices(context, logger, rhythmSegment));
        }
Пример #13
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, out LyricsSegment lyricsSegment)
        {
            lyricsSegment = new LyricsSegment
            {
                Text  = this.Text.Value,
                Range = this.Range
            };

            return(true);
        }
Пример #14
0
 public BarArranger(TablatureContext context, DocumentBar bar)
 {
     _context       = context;
     _bar           = bar;
     _previousBeats = new Dictionary <VoicePart, Beat>
     {
         { VoicePart.Bass, null },
         { VoicePart.Treble, null }
     };
 }
Пример #15
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, out TuningSignature element)
        {
            element = new TuningSignature
            {
                Range  = this.Range,
                Tuning =
                    new Tuning(this.Name?.Value, this.StringTunings.Select(t => t.ToPitch()).ToArray())
            };

            return(true);
        }
Пример #16
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, VoicePart voicePart, out RhythmSegmentVoice voice)
        {
            voice = new RhythmSegmentVoice(voicePart)
            {
                Range = this.Range
            };

            context.CurrentVoice = voice;

            foreach (var beat in this.Beats)
            {
                Beat documentBeat;
                if (!beat.ToDocumentElement(context, logger, voice, out documentBeat))
                {
                    return(false);
                }

                voice.Beats.Add(documentBeat);
            }

            // try to fill voice with rests if insufficient notes fed
            var duration = this.GetDuration();

            if (duration < this.ExpectedDuration)
            {
                BaseNoteValue[] factors;
                if (!BaseNoteValues.TryFactorize(this.ExpectedDuration - duration, out factors))
                {
                    logger.Report(LogLevel.Error, this.Range,
                                  Messages.Error_InconsistentVoiceDurationCannotBeFilledWithRest);
                    return(false);
                }

                logger.Report(LogLevel.Suggestion, this.Range, Messages.Suggestion_InconsistentVoiceDuration);

                foreach (var factor in factors)
                {
                    var beat = new Beat()
                    {
                        NoteValue = new NoteValue(factor),
                        IsRest    = true,
                        Notes     = new BeatNote[0]
                    };

                    context.CurrentVoice.IsTerminatedWithRest = true;

                    voice.Beats.Add(beat);
                }
            }

            return(true);
        }
Пример #17
0
        internal override bool Apply(TablatureContext context, ILogger logger)
        {
            var templateBarNodes = this.TemplateBars.Bars;
            var instanceBarNodes = this.InstanceBars.Bars;

            if (instanceBarNodes.Count < templateBarNodes.Count)
            {
                logger.Report(LogLevel.Warning, this.InstanceBars.Range,
                              Messages.Warning_PatternInstanceBarsLessThanTemplateBars);
            }

            var templateBars = new List <Bar>();

            foreach (var barNode in templateBarNodes)
            {
                if (barNode.Lyrics != null)
                {
                    logger.Report(LogLevel.Warning, barNode.Lyrics.Range,
                                  Messages.Warning_TemplateBarCannotContainLyrics);
                }

                Bar bar;
                if (!barNode.ToDocumentElement(context, logger, null, out bar))
                {
                    return(false);
                }

                templateBars.Add(bar);
            }

            var templateIndex = 0;

            foreach (var barNode in instanceBarNodes)
            {
                var templateBar = templateBars[templateIndex];

                Bar instanceBar;
                if (this.ApplyTemplateBar(templateBar, barNode, out instanceBar, context, logger))
                {
                    context.AddBar(instanceBar);
                }

                ++templateIndex;
                if (templateIndex == templateBarNodes.Count)
                {
                    templateIndex = 0;
                }
            }

            return(true);
        }
Пример #18
0
        internal override bool Apply(TablatureContext context, ILogger logger)
        {
            KeySignature key;

            if (!this.ToDocumentElement(context, logger, out key))
            {
                return(false);
            }

            using (var state = context.AlterDocumentState())
                state.KeySignature = key;

            return(true);
        }
Пример #19
0
        internal override bool Apply(TablatureContext context, ILogger logger)
        {
            Capo capo;
            if (!this.ToDocumentElement(context, logger, out capo))
                return false;

            using (var state = context.AlterDocumentState())
            {
                state.Capos.Add(capo);
                state.CapoFretOffsets = capo.OffsetFrets(state.CapoFretOffsets);
            }

            return true;
        }
Пример #20
0
        public override bool CheckIntegrity(TablatureContext context, ILogger logger)
        {
            foreach (var capo in
                     context.DocumentState
                     .Capos
                     .Where(capo => capo.CapoInfo.AffectedStrings
                            .All(n => capo.CapoInfo.Position < context.DocumentState.CapoFretOffsets[n - 1]))
                     )
            {
                logger.Report(LogLevel.Suggestion, capo.Range, Messages.Suggestion_UselessCapoInstruction);
            }

            return(true);
        }
Пример #21
0
        public bool ValidateColumn(TablatureContext context, ILogger logger, BarColumn column)
        {
            if (column.VoiceBeats.Count == 2 && column.VoiceBeats.All(b => b.StrumTechnique != StrumTechnique.None))
            {
                if (column.VoiceBeats[0].StrumTechnique != column.VoiceBeats[1].StrumTechnique)
                {
                    logger.Report(LogLevel.Warning, column.VoiceBeats[1].Range, Messages.Warning_ConflictedStrumTechniques);

                    column.VoiceBeats[1].StrumTechnique = StrumTechnique.None;
                }
            }

            return(true);
        }
Пример #22
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, RhythmSegmentVoice ownerVoice, out Beat beat)
        {
            beat = new Beat()
            {
                Range                    = this.Range,
                StrumTechnique           = this.StrumTechnique?.Value ?? (StrumTechniqueEnum?)this.ChordStrumTechnique?.Value ?? StrumTechniqueEnum.None,
                Accent                   = this.Accent?.Value ?? Core.MusicTheory.BeatAccent.Normal,
                HoldAndPause             = this.HoldAndPause?.Value ?? Core.MusicTheory.HoldAndPause.None,
                Ornament                 = this.Ornament?.Value ?? Core.MusicTheory.Ornament.None,
                NoteRepetition           = this.NoteRepetition?.Value ?? Core.MusicTheory.NoteRepetition.None,
                EffectTechniqueParameter = this.OrnamentParameter?.Value ?? default(double),
                IsRest                   = this.Rest != null,
                IsTied                   = this.Tie != null,
                TiePosition              = this.TiePosition?.Value,
                PreConnection            = this.PreConnection?.Value ?? PreBeatConnection.None,
                PostConnection           = this.PostConnection?.Value ?? PostBeatConnection.None,
                NoteValue                = this.NoteValue.ToNoteValue(),
                VoicePart                = ownerVoice.Part,
                IsForceBeamStart         = this.ForceBeamStart != null,
                IsForceBeamEnd           = this.ForceBeamEnd != null
            };

            if (!this.Validate(context, logger, beat))
            {
                return(false);
            }

            var notes = new List <BeatNote>();

            foreach (var note in this.Notes)
            {
                BeatNote documentNote;
                if (!note.ToDocumentElement(context, logger, ownerVoice.Part, out documentNote))
                {
                    return(false);
                }
                documentNote.OwnerBeat = beat;

                notes.Add(documentNote);

                ownerVoice.LastNoteOnStrings[documentNote.String] = documentNote;
            }

            beat.Notes = notes.ToArray();

            ownerVoice.IsTerminatedWithRest = beat.IsRest;

            return(true);
        }
Пример #23
0
        private bool RetrievePreConnectedNote(TablatureContext context, ILogger logger, BeatNote element)
        {
            var lastNote = context.GetLastNoteOnString(this.String.Value - 1);

            if (lastNote == null)
            {
                logger.Report(LogLevel.Error, this.PreConnection.Range,
                              Messages.Error_ConnectionPredecessorNotExisted);
                return(false);
            }

            element.PreConnectedNote = lastNote;

            return(true);
        }
Пример #24
0
        internal override bool Apply(TablatureContext context, ILogger logger)
        {
            TempoSignature tempo;

            if (!this.ToDocumentElement(context, logger, out tempo))
            {
                return(false);
            }

            using (var state = context.AlterDocumentState())
            {
                state.TempoSignature = tempo;
            }

            return(true);
        }
Пример #25
0
        internal override bool Apply(TablatureContext context, ILogger logger)
        {
            ChordDefinition definition;

            if (!this.ToDocumentElement(context, logger, out definition))
            {
                return(false);
            }

            using (var state = context.AlterDocumentState())
            {
                state.DefinedChords.Add(definition);
            }

            return(true);
        }
Пример #26
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, out TempoSignature element)
        {
            if (this.ValueEquals(context.DocumentState.TempoSignature))
            {
                logger.Report(LogLevel.Suggestion, this.Range, Messages.Suggestion_UselessTempoInstruction);
                element = null;
                return(false);
            }

            element = new TempoSignature
            {
                Range = this.Range,
                Tempo = new Tempo(this.Beats.Value, this.NoteValue?.Value ?? BaseNoteValue.Quater)
            };

            return(true);
        }
Пример #27
0
        internal override bool Apply(TablatureContext context, ILogger logger)
        {
            Section section;

            if (!this.ToDocumentElement(context, logger, out section))
            {
                return(false);
            }

            using (var state = context.AlterDocumentState())
            {
                state.DefinedSections.Add(section);
                state.CurrentSection = section;
            }

            return(true);
        }
Пример #28
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, out Section element)
        {
            if (context.DocumentState.DefinedSections.Any(this.ValueEquals))
            {
                logger.Report(LogLevel.Warning, this.Range, Messages.Warning_DuplicatedSectionName,
                              this.SectionName.Value);
                element = null;
                return(false);
            }

            element = new Section
            {
                Name  = this.SectionName.Value,
                Range = this.Range
            };

            return(true);
        }
Пример #29
0
        private bool Validate(TablatureContext context, ILogger logger, VoicePart voicePart, BeatNote element)
        {
            if (!this.ValidateTie(context, logger, element))
            {
                return(false);
            }

            if (!this.ValidatePreConnection(context, logger, voicePart, element))
            {
                return(false);
            }

            if (!this.ValidatePostConnection(context, logger, voicePart, element))
            {
                return(false);
            }
            return(true);
        }
Пример #30
0
        public bool ToDocumentElement(TablatureContext context, ILogger logger, out KeySignature element)
        {
            var noteName = this.Key.ToNoteName();

            if (context.DocumentState.KeySignature != null && context.DocumentState.KeySignature.Key == noteName)
            {
                logger.Report(LogLevel.Suggestion, this.Range, Messages.Suggestion_RedundantKeySignature);
                element = null;
                return(false);
            }

            element = new KeySignature
            {
                Range = this.Range,
                Key   = noteName
            };

            return(true);
        }