Skip to content

Commit

Permalink
Merge pull request #287 from andy840119/import/implement-language-cal…
Browse files Browse the repository at this point in the history
…culation

Implement auto-generate in import screen.
  • Loading branch information
andy840119 authored Dec 6, 2020
2 parents 9c94a8f + 4268585 commit 6e56476
Show file tree
Hide file tree
Showing 23 changed files with 306 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private void load()
[Test]
public void TestGoToStep() => Schedule(() =>
{
var temp = TestResources.GetTestLrcForImport("default");
var temp = TestResources.GetTestLrcForImport("light");
Child = screen = new TestImportLyricScreen(new FileInfo(temp));

var steps = (ImportLyricStep[])Enum.GetValues(typeof(ImportLyricStep));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class TestSceneManageLanguagesDialog : OsuManualInputManagerTestScene
protected override Container<Drawable> Content { get; } = new Container { RelativeSizeAxes = Axes.Both };

private DialogOverlay dialogOverlay;
private LanguageManager manager;
private TranslateManager manager;

private ManageLanguagesDialog dialog;

Expand All @@ -35,7 +35,7 @@ private void load()

base.Content.AddRange(new Drawable[]
{
manager = new LanguageManager(),
manager = new TranslateManager(),
Content,
dialogOverlay = new DialogOverlay()
});
Expand Down
34 changes: 34 additions & 0 deletions osu.Game.Rulesets.Karaoke.Tests/Resources/Testing/Lrc/light.lrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
枯れた世界に輝く 名もない永遠の華
強く生きていけるよう 私を変えていく

あぁ、わかっていたの 本当は
光なんて求めちゃいけないってこと

あぁ、それでもきっと人は
輝く未来なんてものを求めてさまよう

女神なんて 信じてるわけじゃない
未来をこの 手で切り開く勇気が 強さがほしい
あなたを守りたい

枯れた世界に輝く 名もない永遠の華
強く生きていけるよう 私を変えていく

あぁ、例えこの世が暗く
絶望に飲み込まれても 私は大丈夫

あなたがいればそこは
灰色(いろ)(いろ)の景色(いろ)(いろ)さえ色づき始める

華もきっと 咲き誇るときを終え
いつかきっと また蕾をつけるだろう 
終わることない
生命(いのち)が続くまでは

あなたの手を離さない 瞳に誓う 永遠の恋
強く儚い思いを 守り続けていたい

枯れた世界に輝く 名もない永遠の華
強く生き抜きけるように 私を変えていく
あなたの手を離さない 瞳に誓う 永遠の恋
強く儚い思いを 守り続けていたい
3 changes: 0 additions & 3 deletions osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ private LyricLine encodeLyric(Objects.Lyric lyric) =>

private IEnumerable<TimeTag> convertTimeTag(string text, IReadOnlyDictionary<TimeTagIndex, double> tags)
{
if (tags == null || !tags.Any())
throw new ArgumentNullException($"{nameof(tags)} cannot be null.");

var totalTags = text.Length * 2 + 2;

for (int i = 0; i < totalTags; i++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ protected override void TimeTagLogic(Lyric lyric, List<Tuple<TimeTagIndex, doubl
}
}
}

return timeTags;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public ZhTimeTagGenerator(ZhTimeTagGeneratorConfig config)
protected override void TimeTagLogic(Lyric lyric, List<Tuple<TimeTagIndex, double?>> timeTags)
{
var text = lyric.Text;

for (var i = 1; i < text.Length; i++)
{
if (CharUtils.IsChinese(text[i]))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ public class AssignLanguageSubScreen : ImportLyricSubScreenWithTopNavigation

public override IconUsage Icon => FontAwesome.Solid.Globe;

[Cached]
protected readonly LyricManager LyricManager;

public AssignLanguageSubScreen()
{
AddInternal(LyricManager = new LyricManager());
}

protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
Expand Down Expand Up @@ -56,7 +64,8 @@ protected void AskForAutoAssignLanguage()
{
DialogOverlay.Push(new UseLanguageDetectorPopupDialog(ok =>
{
// todo : call manager to do that.
if (ok)
LyricManager.AutoDetectLyricLanguage();
}));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Karaoke.Edit.RubyRomaji;
Expand All @@ -17,6 +18,14 @@ public class GenerateRubySubScreen : ImportLyricSubScreenWithTopNavigation

public override IconUsage Icon => FontAwesome.Solid.Gem;

[Cached]
protected readonly RubyRomajiManager RubyRomajiManager;

public GenerateRubySubScreen()
{
AddInternal(RubyRomajiManager = new RubyRomajiManager());
}

protected override TopNavigation CreateNavigation()
=> new GenerateRubyNavigation(this);

Expand All @@ -42,7 +51,8 @@ protected void AskForAutoGenerateRuby()
{
DialogOverlay.Push(new UseAutoGenerateRubyPopupDialog(ok =>
{
// todo : call manager to do that.
if (ok)
RubyRomajiManager.AutoGenerateRubyTags();
}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ public class GenerateTimeTagSubScreen : ImportLyricSubScreenWithTopNavigation

public override IconUsage Icon => FontAwesome.Solid.Tag;

[Cached]
protected readonly TimeTagManager TimeTagManager;

public GenerateTimeTagSubScreen()
{
AddInternal(TimeTagManager = new TimeTagManager());
}

protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
Expand Down Expand Up @@ -56,7 +64,8 @@ protected void AskForAutoGenerateTimeTag()
{
DialogOverlay.Push(new UseAutoGenerateTimeTagPopupDialog(ok =>
{
// todo : call manager to do that.
if (ok)
TimeTagManager.AutoGenerateTimeTags();
}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Karaoke.Beatmaps.Formats;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Screens.Edit;

namespace osu.Game.Rulesets.Karaoke.Edit.ImportLyric
Expand Down Expand Up @@ -52,10 +53,12 @@ public void ImportLrcFile(FileInfo info)
var decoder = new LrcDecoder();
var lrcBeatmap = decoder.Decode(reader);

// todo : remove all notes and lyric
// or just clear all beatmap because not really sure is singer should be removed also?
// remove all hit objects (note and lyric) from beatmap
editorBeatmap.Clear();

// then re-add the lyric.
var lyrics = lrcBeatmap.HitObjects.OfType<Lyric>();
editorBeatmap.AddRange(lyrics);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ public LanguageInfoBadge(Lyric lyric)
{
var language = value.NewValue;

if (language == null)
BadgeText = "None";
else
BadgeText = language.DisplayName;
BadgeText = language == null ? "None" : language.DisplayName;
}, true);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ protected override void ApplyFont(KaraokeFont font)
return;

// todo : need to delay until karaoke text has been calculated.
ScheduleAfterChildren(() => UpdateTimeTags());
ScheduleAfterChildren(UpdateTimeTags);
}

protected override void ApplyLayout(KaraokeLayout layout)
Expand Down Expand Up @@ -101,7 +101,11 @@ public override double LifetimeEnd
protected void UpdateTimeTags()
{
timeTagContainer.Clear();
foreach (var timeTag in TimeTagsBindable.Value)
var timeTags = TimeTagsBindable.Value;
if (timeTags == null)
return;

foreach (var timeTag in timeTags)
{
var index = Math.Min(timeTag.Item1.Index, HitObject.Text.Length - 1);
var percentage = timeTag.Item1.State == TimeTagIndex.IndexState.Start ? 0 : 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ protected override Drawable CreateContent()
// in larger size should use real icon.
new LanguageInfoBadge(Model)
{
Margin = new MarginPadding{ Right = 5 }
Margin = new MarginPadding { Right = 5 }
}
}
},
Expand Down
45 changes: 45 additions & 0 deletions osu.Game.Rulesets.Karaoke/Edit/Lyrics/LyricManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Karaoke.Edit.Generator.Languages;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Screens.Edit;
using System.Linq;

namespace osu.Game.Rulesets.Karaoke.Edit.Lyrics
{
public class LyricManager : Component
{
[Resolved]
private EditorBeatmap beatmap { get; set; }

[Resolved(CanBeNull = true)]
private IEditorChangeHandler changeHandler { get; set; }

/// <summary>
/// Will auto-detect each <see cref="Lyric"/> 's <see cref="Lyric.Language"/> and apply on them.
/// </summary>
public void AutoDetectLyricLanguage()
{
var lyrics = beatmap.HitObjects.OfType<Lyric>().ToList();
if (!lyrics.Any())
return;

// todo : should get the config from setting.
var config = new LanguageDetectorConfig();
var detector = new LanguageDetector(config);

changeHandler?.BeginChange();

foreach (var lyric in lyrics)
{
var detectedLanguage = detector.DetectLanguage(lyric);
lyric.Language = detectedLanguage;
}

changeHandler?.EndChange();
}
}
}
85 changes: 85 additions & 0 deletions osu.Game.Rulesets.Karaoke/Edit/Lyrics/TimeTagManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Rulesets.Karaoke.Edit.Generator.TimeTags.Ja;
using osu.Game.Rulesets.Karaoke.Edit.Generator.TimeTags.Zh;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Screens.Edit;
using System;
using System.Linq;

namespace osu.Game.Rulesets.Karaoke.Edit.Lyrics
{
public class TimeTagManager : Component
{
[Resolved]
private EditorBeatmap beatmap { get; set; }

[Resolved(CanBeNull = true)]
private IEditorChangeHandler changeHandler { get; set; }

/// <summary>
/// Will auto-detect each <see cref="Lyric"/> 's <see cref="Lyric.TimeTags"/> and apply on them.
/// </summary>
public void AutoGenerateTimeTags()
{
var lyrics = beatmap.HitObjects.OfType<Lyric>().ToList();
if (!lyrics.Any())
return;

changeHandler?.BeginChange();

var selector = new TimeTagGeneratorSelector();

foreach (var lyric in lyrics)
{
var timeTags = selector.GenerateTimeTags(lyric);
lyric.TimeTags = timeTags;
}

changeHandler?.EndChange();
}

public class TimeTagGeneratorSelector
{
private readonly Lazy<JaTimeTagGenerator> jaTimeTagGenerator;
private readonly Lazy<ZhTimeTagGenerator> zhTimeTagGenerator;

public TimeTagGeneratorSelector()
{
jaTimeTagGenerator = new Lazy<JaTimeTagGenerator>(() =>
{
// todo : get config from setting.
var config = new JaTimeTagGeneratorConfig();
return new JaTimeTagGenerator(config);
});
zhTimeTagGenerator = new Lazy<ZhTimeTagGenerator>(() =>
{
// todo : get config from setting.
var config = new ZhTimeTagGeneratorConfig();
return new ZhTimeTagGenerator(config);
});
}

public Tuple<TimeTagIndex, double?>[] GenerateTimeTags(Lyric lyric)
{
// lazy to generate language detector and apply it's setting
switch (lyric.Language.LCID)
{
case 17:
case 1041:
return jaTimeTagGenerator.Value.CreateTimeTags(lyric);

case 1028:
return zhTimeTagGenerator.Value.CreateTimeTags(lyric);

default:
return null;
}
}
}
}
}
Loading

0 comments on commit 6e56476

Please sign in to comment.