Example #1
0
        private Dictionary <TimeTagInvalid, TimeTag[]> checkInvalidTimeTags(Lyric lyric)
        {
            var result = new Dictionary <TimeTagInvalid, TimeTag[]>();

            // todo : check out of range.
            var outOfRangeTags = TimeTagsUtils.FindOutOfRange(lyric.TimeTags, lyric.Text);

            if (outOfRangeTags?.Length > 0)
            {
                result.Add(TimeTagInvalid.OutOfRange, outOfRangeTags);
            }

            // Check overlapping.
            var groupCheck          = config.TimeTagTimeGroupCheck;
            var selfCheck           = config.TimeTagTimeSelfCheck;
            var overlappingTimeTags = TimeTagsUtils.FindOverlapping(lyric.TimeTags, groupCheck, selfCheck);

            if (overlappingTimeTags?.Length > 0)
            {
                result.Add(TimeTagInvalid.Overlapping, overlappingTimeTags);
            }

            // Check time-tag should have time.
            var noTimeTimeTags = TimeTagsUtils.FindNoneTime(lyric.TimeTags);

            if (noTimeTimeTags?.Length > 0)
            {
                result.Add(TimeTagInvalid.EmptyTime, noTimeTimeTags);
            }

            return(result);
        }
Example #2
0
        [TestCase("", new[] { "[0,start]:1000", "[0,end]:2000" }, false)]      // empty lyric should always count as missing.
        public void TestHasStartTimeTagInLyric(string text, string[] timeTagTexts, bool actual)
        {
            var timeTags = TestCaseTagHelper.ParseTimeTags(timeTagTexts);
            var missing  = TimeTagsUtils.HasStartTimeTagInLyric(timeTags, text);

            Assert.AreEqual(missing, actual);
        }
Example #3
0
        //[TestCase(new[] { "[0,start]:4000", "[0,end]:3000", "[1,start]:2000", "[1,end]:1000" }, new double[] { 4000, 4000, 4000, 4000 })]
        public void TestToDictionary(string[] timeTagTexts, double[] actualTimes)
        {
            var timeTags   = TestCaseTagHelper.ParseTimeTags(timeTagTexts);
            var dictionary = TimeTagsUtils.ToDictionary(timeTags);

            Assert.AreEqual(dictionary.Values.ToArray(), actualTimes);
        }
Example #4
0
        public void TestGetEndTime(string[] timeTagTexts, double?actualEndTime)
        {
            var timeTags = TestCaseTagHelper.ParseTimeTags(timeTagTexts);
            var endTime  = TimeTagsUtils.GetEndTime(timeTags);

            Assert.AreEqual(endTime, actualEndTime);
        }
Example #5
0
        public void TestSort(string[] timeTagTexts, string[] actualTimeTags)
        {
            var timeTags      = TestCaseTagHelper.ParseTimeTags(timeTagTexts);
            var sortedTimeTag = TimeTagsUtils.Sort(timeTags);

            TimeTagAssert.AreEqual(sortedTimeTag, TestCaseTagHelper.ParseTimeTags(actualTimeTags));
        }
Example #6
0
        public void TestFindOutOfRange(string text, string[] timeTagTexts, string[] invalidTimeTags)
        {
            var timeTags           = TestCaseTagHelper.ParseTimeTags(timeTagTexts);
            var outOfRangeTimeTags = TimeTagsUtils.FindOutOfRange(timeTags, text);

            TimeTagAssert.AreEqual(outOfRangeTimeTags, TestCaseTagHelper.ParseTimeTags(invalidTimeTags));
        }
Example #7
0
 private LyricLine encodeLyric(Objects.Lyric lyric) =>
 new LyricLine
 {
     Text = lyric.Text,
     // Note : save to lyric will lost some tags with no value.
     TimeTags = convertTimeTag(lyric.Text, TimeTagsUtils.ToDictionary(lyric.TimeTags)).ToArray(),
 };
Example #8
0
        protected override void ParseStreamInto(LineBufferedReader stream, Beatmap output)
        {
            // Clear all hitobjects
            output.HitObjects.Clear();

            var lyricText = stream.ReadToEnd();
            var result    = new LrcParser().Decode(lyricText);

            // Convert line
            for (int i = 0; i < result.Lines.Length; i++)
            {
                // Empty line should not be imported
                var line = result.Lines[i];
                if (string.IsNullOrEmpty(line.Text))
                {
                    continue;
                }

                try
                {
                    // todo : check list ls sorted by time.
                    var lrcTimeTag = line.TimeTags;
                    var timeTags   = line.TimeTags.Where(x => x.Check).ToDictionary(k =>
                    {
                        var index = (int)Math.Ceiling((double)(Array.IndexOf(lrcTimeTag, k) - 1) / 2);
                        var state = (Array.IndexOf(lrcTimeTag, k) - 1) % 2 == 0 ? TextIndex.IndexState.Start : TextIndex.IndexState.End;
                        return(new TextIndex(index, state));
                    }, v => (double)v.Time);

                    var startTime = timeTags.FirstOrDefault(x => x.Value > 0).Value;
                    var duration  = timeTags.LastOrDefault(x => x.Value > 0).Value - startTime;

                    var lyric = new Lyric
                    {
                        Order = output.HitObjects.Count + 1, // should create default order.
                        Text  = line.Text,
                        // Start time and end time should be re-assigned
                        StartTime = startTime,
                        Duration  = duration,
                        TimeTags  = TimeTagsUtils.ToTimeTagList(timeTags),
                        RubyTags  = result.QueryRubies(line.Text).Select(ruby => new RubyTag
                        {
                            Text       = ruby.Ruby.Ruby,
                            StartIndex = ruby.StartIndex,
                            EndIndex   = ruby.EndIndex
                        }).ToArray()
                    };
                    lyric.InitialWorkingTime();
                    output.HitObjects.Add(lyric);
                }
                catch (Exception ex)
                {
                    var message = $"Parsing lyric '{line.Text}' got error in line:{i}" +
                                  "Please check time tag should be ordered and not duplicated." +
                                  "Then re-import again.";
                    throw new FormatException(message, ex);
                }
            }
        }
Example #9
0
        //[TestCase(new[] { "[0,start]:4000", "[0,end]:3000", "[1,start]:2000", "[1,end]:1000" }, GroupCheck.Asc, SelfCheck.BasedOnStart, new double[] { "[0,start]:4000", "[0,end]:4000", "[1,start]:4000", "[1,end]:4000" })]
        //[TestCase(new[] { "[0,start]:4000", "[0,end]:3000", "[1,start]:2000", "[1,end]:1000" }, GroupCheck.Asc, SelfCheck.BasedOnEnd, new double[] { "[0,start]:3000", "[0,end]:3000", "[1,start]:3000", "[1,end]:3000" })]
        //[TestCase(new[] { "[0,start]:4000", "[0,end]:3000", "[1,start]:2000", "[1,end]:1000" }, GroupCheck.Desc, SelfCheck.BasedOnStart, new double[] { "[0,start]:2000", "[0,end]:2000", "[1,start]:2000", "[1,end]:2000" })]
        //[TestCase(new[] { "[0,start]:4000", "[0,end]:3000", "[1,start]:2000", "[1,end]:1000" }, GroupCheck.Desc, SelfCheck.BasedOnEnd, new double[] { "[0,start]:1000", "[0,end]:1000", "[1,start]:1000", "[1,end]:1000" })]
        public void TestFixInvalid(string[] timeTagTexts, GroupCheck other, SelfCheck self, string[] actualTimeTagTexts)
        {
            // check which part is fixed, using list of time to check result.
            var timeTags     = TestCaseTagHelper.ParseTimeTags(timeTagTexts);
            var fixedTimeTag = TimeTagsUtils.FixInvalid(timeTags, other, self);

            TimeTagAssert.AreEqual(fixedTimeTag, TestCaseTagHelper.ParseTimeTags(actualTimeTagTexts));
        }
Example #10
0
        public void TestFindOverlapping(string[] timeTagTexts, GroupCheck other, SelfCheck self, int[] errorIndex)
        {
            // run all and find overlapping indexes.
            var timeTags                  = TestCaseTagHelper.ParseTimeTags(timeTagTexts);
            var overlappingTimeTags       = TimeTagsUtils.FindOverlapping(timeTags, other, self);
            var overlappingTimeTagIndexed = overlappingTimeTags.Select(v => timeTags.IndexOf(v)).ToArray();

            Assert.AreEqual(overlappingTimeTagIndexed, errorIndex);
        }
Example #11
0
        public void TestFindInvalid(string[] timeTagTexts, GroupCheck other, SelfCheck self, int[] errorIndex)
        {
            // run all and find invalid indexes.
            var timeTags       = TestCaseTagHelper.ParseTimeTags(timeTagTexts);
            var invalidTimeTag = TimeTagsUtils.FindInvalid(timeTags, other, self);
            var invalidIndexes = invalidTimeTag.Select(v => timeTags.IndexOf(v)).ToArray();

            Assert.AreEqual(invalidIndexes, errorIndex);
        }
Example #12
0
        private Lyric createDefaultLyricLine()
        {
            var          startTime = Time.Current;
            const double duration  = 1000000;

            return(new Lyric
            {
                StartTime = startTime,
                Duration = duration,
                Text = "カラオケ!",
                TimeTags = TimeTagsUtils.ToTimeTagList(new Dictionary <TextIndex, double>
                {
                    { new TextIndex(0), startTime + 500 },
                    { new TextIndex(1), startTime + 600 },
                    { new TextIndex(2), startTime + 1000 },
                    { new TextIndex(3), startTime + 1500 },
                    { new TextIndex(4), startTime + 2000 },
                }),
                RubyTags = new[]
                {
                    new RubyTag
                    {
                        StartIndex = 0,
                        EndIndex = 1,
                        Text = "か"
                    },
                    new RubyTag
                    {
                        StartIndex = 2,
                        EndIndex = 3,
                        Text = "お"
                    }
                },
                RomajiTags = new[]
                {
                    new RomajiTag
                    {
                        StartIndex = 1,
                        EndIndex = 2,
                        Text = "ra"
                    },
                    new RomajiTag
                    {
                        StartIndex = 3,
                        EndIndex = 4,
                        Text = "ke"
                    }
                }
            });
        }
Example #13
0
        private Lyric createDefaultLyric(string text, string[] ruby, string[] romaji, string translate)
        {
            var          startTime = Time.Current;
            const double duration  = 1000000;

            using (var stream = new MemoryStream())
                using (var writer = new StreamWriter(stream))
                    using (var reader = new LineBufferedReader(stream))
                    {
                        writer.WriteLine("karaoke file format v1");
                        writer.WriteLine("[HitObjects]");

                        writer.WriteLine(text);
                        ruby?.ForEach(x => writer.WriteLine(x));
                        romaji?.ForEach(x => writer.WriteLine(x));

                        writer.WriteLine("end");
                        writer.Flush();
                        stream.Position = 0;

                        var lyric = new KaraokeLegacyBeatmapDecoder().Decode(reader).HitObjects.OfType <Lyric>().FirstOrDefault();

                        // Check is not null
                        if (lyric == null)
                        {
                            throw new ArgumentNullException();
                        }

                        // Apply property
                        lyric.StartTime = startTime;
                        lyric.Duration  = duration;

                        // todo : implementation
                        var defaultLanguage = new CultureInfo("en-US");
                        lyric.Translates.Add(defaultLanguage, translate);

                        lyric.TimeTags = TimeTagsUtils.ToTimeTagList(new Dictionary <TextIndex, double>
                        {
                            { new TextIndex(0), startTime },
                            { new TextIndex(4), startTime + duration },
                        });

                        return(lyric);
                    }
        }
Example #14
0
        [TestCase(null, null, 2, null)]                         // should not be null.
        public void GenerateTimeTag(string startTag, string endTag, int index, string result)
        {
            try
            {
                var generatedTimeTag = TimeTagsUtils.GenerateCenterTimeTag(
                    TestCaseTagHelper.ParseTimeTag(startTag),
                    TestCaseTagHelper.ParseTimeTag(endTag),
                    index);

                var actualTimeTag = TestCaseTagHelper.ParseTimeTag(result);
                Assert.AreEqual(generatedTimeTag.Index, actualTimeTag.Index);
                Assert.AreEqual(generatedTimeTag.Time, actualTimeTag.Time);
            }
            catch
            {
                Assert.IsNull(result);
            }
        }
Example #15
0
        public Note[] CreateNotes(Lyric lyric)
        {
            var timeTags = TimeTagsUtils.ToDictionary(lyric.TimeTags);
            var notes    = new List <Note>();

            foreach (var timeTag in timeTags)
            {
                var(key, endTime) = timeTags.GetNext(timeTag);

                if (key.Index <= 0)
                {
                    continue;
                }

                var startTime = timeTag.Value;

                int startIndex = timeTag.Key.Index;
                int endIndex   = TextIndexUtils.ToStringIndex(key);

                var text = lyric.Text[startIndex..endIndex];
Example #16
0
        private void load()
        {
            Scale        = new Vector2(2f);
            AutoSizeAxes = Axes.Both;

            AddInternal(KaraokeText   = new KaraokeSpriteText());
            AddInternal(translateText = new OsuSpriteText
            {
                Anchor = Anchor.BottomLeft,
                Origin = Anchor.TopLeft,
            });

            TextBindable.BindValueChanged(text => { KaraokeText.Text = text.NewValue; });
            TimeTagsBindable.BindValueChanged(timeTags => { KaraokeText.TimeTags = TimeTagsUtils.ToDictionary(timeTags.NewValue); });
            RubyTagsBindable.BindValueChanged(rubyTags => { ApplyRuby(); });
            RomajiTagsBindable.BindValueChanged(romajiTags => { ApplyRomaji(); });
            SingersBindable.BindValueChanged(index => { ApplySkin(CurrentSkin, false); });
            LayoutIndexBindable.BindValueChanged(index => { ApplySkin(CurrentSkin, false); });
            TranslateTextBindable.BindCollectionChanged((_, args) => { ApplyTranslate(); });
        }
Example #17
0
        public void TestDecodeLyric()
        {
            const string lyric_text = "[00:01.00]か[00:02.00]ら[00:03.00]お[00:04.00]け[00:05.00]";
            var          beatmap    = decodeLrcLine(lyric_text);

            // Get first beatmap
            var lyric = beatmap.HitObjects.OfType <Lyric>().FirstOrDefault();

            // Check lyric
            Assert.AreEqual(lyric?.Text, "からおけ");
            Assert.AreEqual(lyric?.StartTime, 1000);
            Assert.AreEqual(lyric?.EndTime, 5000);

            // Check time tag
            var tags        = TimeTagsUtils.ToDictionary(lyric?.TimeTags);
            var checkedTags = tags.ToArray();

            Assert.AreEqual(tags.Count, 5);
            Assert.AreEqual(checkedTags.Length, 5);
            Assert.AreEqual(string.Join(',', tags.Select(x => x.Key.Index)), "0,1,2,3,4");
            Assert.AreEqual(string.Join(',', tags.Select(x => x.Value)), "1000,2000,3000,4000,5000");
        }
Example #18
0
        public Dictionary <TimeTagInvalid, TimeTag[]> CheckInvalidTimeTags(Lyric lyric)
        {
            var result = new Dictionary <TimeTagInvalid, TimeTag[]>();

            // todo : check out of range.
            var outOfRangeTags = TimeTagsUtils.FindOutOfRange(lyric.TimeTags, lyric.Text);

            if (outOfRangeTags?.Length > 0)
            {
                result.Add(TimeTagInvalid.OutOfRange, outOfRangeTags);
            }

            // Check overlapping.
            var groupCheck      = config.TimeTagTimeGroupCheck;
            var selfCheck       = config.TimeTagTimeSelfCheck;
            var invalidTimeTags = TimeTagsUtils.FindInvalid(lyric.TimeTags, groupCheck, selfCheck);

            if (invalidTimeTags?.Length > 0)
            {
                result.Add(TimeTagInvalid.Overlapping, invalidTimeTags);
            }

            return(result);
        }
Example #19
0
 private void sortingTimeTag(Lyric lyric)
 => lyric.TimeTags = TimeTagsUtils.Sort(lyric.TimeTags);
Example #20
0
        public void TestEncodeBeatmapLyric()
        {
            // Because encoder is not fully implemented, so just test not crash during encoding.
            const int start_time = 1000;
            const int duration   = 2500;

            var beatmap = new Beatmap
            {
                HitObjects = new List <HitObject>
                {
                    new Lyric
                    {
                        StartTime = start_time,
                        Duration  = duration,
                        Text      = "カラオケ!",
                        TimeTags  = TimeTagsUtils.ToTimeTagList(new Dictionary <TextIndex, double>
                        {
                            { new TextIndex(0), start_time + 500 },
                            { new TextIndex(1), start_time + 600 },
                            { new TextIndex(2), start_time + 1000 },
                            { new TextIndex(3), start_time + 1500 },
                            { new TextIndex(4), start_time + 2000 },
                        }),
                        RubyTags = new[]
                        {
                            new RubyTag
                            {
                                StartIndex = 0,
                                EndIndex   = 1,
                                Text       = "か"
                            },
                            new RubyTag
                            {
                                StartIndex = 2,
                                EndIndex   = 3,
                                Text       = "お"
                            }
                        },
                        RomajiTags = new[]
                        {
                            new RomajiTag
                            {
                                StartIndex = 1,
                                EndIndex   = 2,
                                Text       = "ra"
                            },
                            new RomajiTag
                            {
                                StartIndex = 3,
                                EndIndex   = 4,
                                Text       = "ke"
                            }
                        },
                    }
                }
            };

            using (var ms = new MemoryStream())
                using (var sw = new StreamWriter(ms))
                {
                    var encoder      = new KaraokeLegacyBeatmapEncoder();
                    var encodeResult = encoder.Encode(beatmap);
                    sw.WriteLine(encodeResult);
                }
        }
Example #21
0
 private bool checkMissingEndTimeTag(Lyric lyric)
 => !TimeTagsUtils.HasEndTimeTagInLyric(lyric.TimeTags, lyric.Text);
Example #22
0
        private Drawable testSingle(bool auto = false, double timeOffset = 0)
        {
            var          startTime = Time.Current + 1000 + timeOffset;
            const double duration  = 2500;

            var lyric = new Lyric
            {
                StartTime = startTime,
                Duration  = duration,
                Text      = "カラオケ!",
                TimeTags  = TimeTagsUtils.ToTimeTagList(new Dictionary <TextIndex, double>
                {
                    { new TextIndex(0), startTime + 500 },
                    { new TextIndex(1), startTime + 600 },
                    { new TextIndex(2), startTime + 1000 },
                    { new TextIndex(3), startTime + 1500 },
                    { new TextIndex(4), startTime + 2000 },
                }),
                RubyTags = new[]
                {
                    new RubyTag
                    {
                        StartIndex = 0,
                        EndIndex   = 1,
                        Text       = "か"
                    },
                    new RubyTag
                    {
                        StartIndex = 2,
                        EndIndex   = 3,
                        Text       = "お"
                    }
                },
                RomajiTags = new[]
                {
                    new RomajiTag
                    {
                        StartIndex = 1,
                        EndIndex   = 2,
                        Text       = "ra"
                    },
                    new RomajiTag
                    {
                        StartIndex = 3,
                        EndIndex   = 4,
                        Text       = "ke"
                    }
                },
            };

            var defaultLanguage = new CultureInfo("en-US");

            lyric.Translates.Add(defaultLanguage, "karaoke");

            lyric.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());

            var drawable = CreateDrawableLyric(lyric, auto);

            drawable.DisplayTranslateLanguage = defaultLanguage;

            foreach (var mod in SelectedMods.Value.OfType <IApplicableToDrawableHitObjects>())
            {
                mod.ApplyToDrawableHitObjects(new[] { drawable });
            }

            return(drawable);
        }