diff --git a/.github/scripts/test-dot-net.sh b/.github/scripts/test-dot-net.sh index f120653c6..aa41ad985 100755 --- a/.github/scripts/test-dot-net.sh +++ b/.github/scripts/test-dot-net.sh @@ -3,7 +3,7 @@ cd dotnet-examples/ cd ./kokoro-tts -./run-kokoro-en.sh +./run-kokoro.sh ls -lh cd ../offline-tts diff --git a/dotnet-examples/kokoro-tts/Program.cs b/dotnet-examples/kokoro-tts/Program.cs index 61792683a..b72f98fcb 100644 --- a/dotnet-examples/kokoro-tts/Program.cs +++ b/dotnet-examples/kokoro-tts/Program.cs @@ -13,6 +13,63 @@ class OfflineTtsDemo { static void Main(string[] args) + { + + TestZhEn(); + TestEn(); + } + + static void TestZhEn() + { + var config = new OfflineTtsConfig(); + config.Model.Kokoro.Model = "./kokoro-multi-lang-v1_0/model.onnx"; + config.Model.Kokoro.Voices = "./kokoro-multi-lang-v1_0/voices.bin"; + config.Model.Kokoro.Tokens = "./kokoro-multi-lang-v1_0/tokens.txt"; + config.Model.Kokoro.DataDir = "./kokoro-multi-lang-v1_0/espeak-ng-data"; + config.Model.Kokoro.DictDir = "./kokoro-multi-lang-v1_0/dict"; + config.Model.Kokoro.Lexicon = "./kokoro-multi-lang-v1_0/lexicon-us-en.txt,./kokoro-multi-lang-v1_0/lexicon-zh.txt"; + + config.Model.NumThreads = 2; + config.Model.Debug = 1; + config.Model.Provider = "cpu"; + + var tts = new OfflineTts(config); + var speed = 1.0f; + var text = "中英文语音合成测试。This is generated by next generation Kaldi using Kokoro without Misaki. 你觉得中英文说的如何呢?"; + + var sid = 50; + + var MyCallback = (IntPtr samples, int n, float progress) => + { + float[] data = new float[n]; + Marshal.Copy(samples, data, 0, n); + // You can process samples here, e.g., play them. + // See ../kokoro-tts-playback for how to play them + Console.WriteLine($"Progress {progress*100}%"); + + // 1 means to keep generating + // 0 means to stop generating + return 1; + }; + + var callback = new OfflineTtsCallbackProgress(MyCallback); + + var audio = tts.GenerateWithCallbackProgress(text, speed, sid, callback); + + var outputFilename = "./generated-kokoro-zh-en.wav"; + var ok = audio.SaveToWaveFile(outputFilename); + + if (ok) + { + Console.WriteLine($"Wrote to {outputFilename} succeeded!"); + } + else + { + Console.WriteLine($"Failed to write {outputFilename}"); + } + } + + static void TestEn() { var config = new OfflineTtsConfig(); config.Model.Kokoro.Model = "./kokoro-en-v0_19/model.onnx"; @@ -54,7 +111,7 @@ static void Main(string[] args) var audio = tts.GenerateWithCallbackProgress(text, speed, sid, callback); - var outputFilename = "./generated-kokoro-0.wav"; + var outputFilename = "./generated-kokoro-en.wav"; var ok = audio.SaveToWaveFile(outputFilename); if (ok) diff --git a/dotnet-examples/kokoro-tts/run-kokoro-en.sh b/dotnet-examples/kokoro-tts/run-kokoro.sh similarity index 51% rename from dotnet-examples/kokoro-tts/run-kokoro-en.sh rename to dotnet-examples/kokoro-tts/run-kokoro.sh index 08bdc693a..117a2fc1b 100755 --- a/dotnet-examples/kokoro-tts/run-kokoro-en.sh +++ b/dotnet-examples/kokoro-tts/run-kokoro.sh @@ -1,6 +1,12 @@ #!/usr/bin/env bash set -ex +if [ ! -f ./kokoro-multi-lang-v1_0/model.onnx ]; then + curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/kokoro-multi-lang-v1_0.tar.bz2 + tar xf kokoro-multi-lang-v1_0.tar.bz2 + rm kokoro-multi-lang-v1_0.tar.bz2 +fi + if [ ! -f ./kokoro-en-v0_19/model.onnx ]; then curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/kokoro-en-v0_19.tar.bz2 tar xf kokoro-en-v0_19.tar.bz2 diff --git a/scripts/dotnet/OfflineTtsKokoroModelConfig.cs b/scripts/dotnet/OfflineTtsKokoroModelConfig.cs index 18fd60daa..2ac402426 100644 --- a/scripts/dotnet/OfflineTtsKokoroModelConfig.cs +++ b/scripts/dotnet/OfflineTtsKokoroModelConfig.cs @@ -15,6 +15,9 @@ public OfflineTtsKokoroModelConfig() DataDir = ""; LengthScale = 1.0F; + + DictDir = ""; + Lexicon = ""; } [MarshalAs(UnmanagedType.LPStr)] public string Model; @@ -29,5 +32,11 @@ public OfflineTtsKokoroModelConfig() public string DataDir; public float LengthScale; + + [MarshalAs(UnmanagedType.LPStr)] + public string DictDir; + + [MarshalAs(UnmanagedType.LPStr)] + public string Lexicon; } }