From 11b028419843f9efd7bd76598a42c64ee4d3f776 Mon Sep 17 00:00:00 2001 From: Fangjun Kuang Date: Thu, 11 Dec 2025 18:23:05 +0800 Subject: [PATCH 1/2] Remove cppinyin --- CMakeLists.txt | 2 - build-ios.sh | 4 +- build-swift-macos.sh | 1 - c-api-examples/Makefile | 2 +- cmake/cppinyin.cmake | 82 ---- cmake/cppinyin.patch | 81 ---- cmake/sherpa-onnx-static.pc.in | 2 +- .../sherpa-onnx-deps.props | 1 - .../sherpa-onnx-deps.props | 1 - .../sherpa-onnx-deps.props | 1 - sherpa-onnx/csrc/CMakeLists.txt | 2 - sherpa-onnx/csrc/matcha-tts-lexicon.cc | 33 +- sherpa-onnx/csrc/matcha-tts-lexicon.h | 5 +- sherpa-onnx/csrc/offline-tts-matcha-impl.h | 4 +- .../offline-tts-zipvoice-frontend-test.cc | 81 ---- .../csrc/offline-tts-zipvoice-frontend.cc | 386 ------------------ .../csrc/offline-tts-zipvoice-frontend.h | 62 --- sherpa-onnx/csrc/offline-tts-zipvoice-impl.h | 39 +- .../csrc/offline-tts-zipvoice-model-config.cc | 11 +- .../csrc/offline-tts-zipvoice-model-config.h | 12 +- .../csrc/offline-tts-zipvoice-model.cc | 7 +- sherpa-onnx/pascal-api/sherpa_onnx.pas | 1 - 22 files changed, 60 insertions(+), 760 deletions(-) delete mode 100644 cmake/cppinyin.cmake delete mode 100644 cmake/cppinyin.patch delete mode 100644 sherpa-onnx/csrc/offline-tts-zipvoice-frontend-test.cc delete mode 100644 sherpa-onnx/csrc/offline-tts-zipvoice-frontend.cc delete mode 100644 sherpa-onnx/csrc/offline-tts-zipvoice-frontend.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 84be55eaf0..57cb8e7fde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -496,8 +496,6 @@ if(SHERPA_ONNX_ENABLE_WEBSOCKET) endif() if(SHERPA_ONNX_ENABLE_TTS) - include(cppinyin) - include(espeak-ng-for-piper) set(ESPEAK_NG_DIR ${espeak_ng_SOURCE_DIR}) message(STATUS "ESPEAK_NG_DIR: ${ESPEAK_NG_DIR}") diff --git a/build-ios.sh b/build-ios.sh index c2bba8195f..6e23ea0ce0 100755 --- a/build-ios.sh +++ b/build-ios.sh @@ -127,7 +127,7 @@ cmake --build build/os64 --target install echo "Generate xcframework" mkdir -p "build/simulator/lib" -for f in libcppinyin_core.a libkaldi-native-fbank-core.a libkissfft-float.a libsherpa-onnx-c-api.a libsherpa-onnx-core.a \ +for f in libkaldi-native-fbank-core.a libkissfft-float.a libsherpa-onnx-c-api.a libsherpa-onnx-core.a \ libsherpa-onnx-fstfar.a libssentencepiece_core.a \ libsherpa-onnx-fst.a libsherpa-onnx-kaldifst-core.a libkaldi-decoder-core.a \ libucd.a libpiper_phonemize.a libespeak-ng.a; do @@ -139,7 +139,6 @@ done # Merge archive first, because the following xcodebuild create xcframework # cannot accept multi archive with the same architecture. libtool -static -o build/simulator/libsherpa-onnx.a \ - build/simulator/lib/libcppinyin_core.a \ build/simulator/lib/libkaldi-native-fbank-core.a \ build/simulator/lib/libkissfft-float.a \ build/simulator/lib/libsherpa-onnx-c-api.a \ @@ -154,7 +153,6 @@ libtool -static -o build/simulator/libsherpa-onnx.a \ build/simulator/lib/libssentencepiece_core.a libtool -static -o build/os64/libsherpa-onnx.a \ - build/os64/lib/libcppinyin_core.a \ build/os64/lib/libkaldi-native-fbank-core.a \ build/os64/lib/libkissfft-float.a \ build/os64/lib/libsherpa-onnx-c-api.a \ diff --git a/build-swift-macos.sh b/build-swift-macos.sh index 8fef5da7e7..1e1e8e9c07 100755 --- a/build-swift-macos.sh +++ b/build-swift-macos.sh @@ -27,7 +27,6 @@ make install rm -fv ./install/include/cargs.h libtool -static -o ./install/lib/libsherpa-onnx.a \ - ./install/lib/libcppinyin_core.a \ ./install/lib/libsherpa-onnx-c-api.a \ ./install/lib/libsherpa-onnx-core.a \ ./install/lib/libkaldi-native-fbank-core.a \ diff --git a/c-api-examples/Makefile b/c-api-examples/Makefile index 6480e9851b..cbaaf63c05 100644 --- a/c-api-examples/Makefile +++ b/c-api-examples/Makefile @@ -4,7 +4,7 @@ CUR_DIR :=$(shell pwd) CFLAGS := -I ../ -I ../build/_deps/cargs-src/include/ LDFLAGS := -L ../build/lib LDFLAGS += -L ../build/_deps/onnxruntime-src/lib -LDFLAGS += -lsherpa-onnx-c-api -lsherpa-onnx-core -lkaldi-decoder-core -lsherpa-onnx-kaldifst-core -lsherpa-onnx-fstfar -lsherpa-onnx-fst -lkaldi-native-fbank-core -lkissfft-float -lpiper_phonemize -lespeak-ng -lucd -lcargs -lonnxruntime -lcppinyin_core +LDFLAGS += -lsherpa-onnx-c-api -lsherpa-onnx-core -lkaldi-decoder-core -lsherpa-onnx-kaldifst-core -lsherpa-onnx-fstfar -lsherpa-onnx-fst -lkaldi-native-fbank-core -lkissfft-float -lpiper_phonemize -lespeak-ng -lucd -lcargs -lonnxruntime LDFLAGS += -framework Foundation LDFLAGS += -lc++ LDFLAGS += -Wl,-rpath,${CUR_DIR}/../build/lib diff --git a/cmake/cppinyin.cmake b/cmake/cppinyin.cmake deleted file mode 100644 index 9e2c92b5cb..0000000000 --- a/cmake/cppinyin.cmake +++ /dev/null @@ -1,82 +0,0 @@ -function(download_cppinyin) - include(FetchContent) - - set(cppinyin_URL "https://github.com/pkufool/cppinyin/archive/refs/tags/v0.10.tar.gz") - set(cppinyin_URL2 "https://gh-proxy.com/https://github.com/pkufool/cppinyin/archive/refs/tags/v0.10.tar.gz") - set(cppinyin_HASH "SHA256=abe6584d7ee56829e8f4b5fbda3b50ecdf49a13be8e413a78d1b0d5d5c019982") - - # If you don't have access to the Internet, - # please pre-download cppinyin - set(possible_file_locations - $ENV{HOME}/Downloads/cppinyin-0.10.tar.gz - ${CMAKE_SOURCE_DIR}/cppinyin-0.10.tar.gz - ${CMAKE_BINARY_DIR}/cppinyin-0.10.tar.gz - /tmp/cppinyin-0.10.tar.gz - /star-fj/fangjun/download/github/cppinyin-0.10.tar.gz - ) - - foreach(f IN LISTS possible_file_locations) - if(EXISTS ${f}) - set(cppinyin_URL "${f}") - file(TO_CMAKE_PATH "${cppinyin_URL}" cppinyin_URL) - message(STATUS "Found local downloaded cppinyin: ${cppinyin_URL}") - set(cppinyin_URL2) - break() - endif() - endforeach() - - set(CPPINYIN_ENABLE_TESTS OFF CACHE BOOL "" FORCE) - set(CPPINYIN_BUILD_PYTHON OFF CACHE BOOL "" FORCE) - - FetchContent_Declare(cppinyin - URL - ${cppinyin_URL} - ${cppinyin_URL2} - URL_HASH - ${cppinyin_HASH} - ) - - FetchContent_GetProperties(cppinyin) - if(NOT cppinyin_POPULATED) - message(STATUS "Downloading cppinyin ${cppinyin_URL}") - FetchContent_Populate(cppinyin) - - file(REMOVE ${cppinyin_SOURCE_DIR}/CMakeLists.txt) - configure_file( - ${CMAKE_CURRENT_LIST_DIR}/cppinyin.patch - ${cppinyin_SOURCE_DIR}/CMakeLists.txt - COPYONLY - ) - endif() - - message(STATUS "cppinyin is downloaded to ${cppinyin_SOURCE_DIR}") - - if(BUILD_SHARED_LIBS) - set(_build_shared_libs_bak ${BUILD_SHARED_LIBS}) - set(BUILD_SHARED_LIBS OFF) - endif() - - add_subdirectory(${cppinyin_SOURCE_DIR} ${cppinyin_BINARY_DIR} EXCLUDE_FROM_ALL) - - if(_build_shared_libs_bak) - set_target_properties(cppinyin_core - PROPERTIES - POSITION_INDEPENDENT_CODE ON - C_VISIBILITY_PRESET hidden - CXX_VISIBILITY_PRESET hidden - ) - set(BUILD_SHARED_LIBS ON) - endif() - - target_include_directories(cppinyin_core - PUBLIC - ${cppinyin_SOURCE_DIR}/ - ) - - if(NOT BUILD_SHARED_LIBS) - install(TARGETS cppinyin_core DESTINATION lib) - endif() - -endfunction() - -download_cppinyin() diff --git a/cmake/cppinyin.patch b/cmake/cppinyin.patch deleted file mode 100644 index ec146874a1..0000000000 --- a/cmake/cppinyin.patch +++ /dev/null @@ -1,81 +0,0 @@ -cmake_minimum_required(VERSION 3.12 FATAL_ERROR) - -project(cppinyin) - -set(CPPINYIN_VERSION "0.10") - -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") - -set(CMAKE_SKIP_BUILD_RPATH FALSE) -set(BUILD_RPATH_USE_ORIGIN TRUE) -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) - -if(NOT APPLE) - set(CPPINYIN_RPATH_ORIGIN "$ORIGIN") -else() - set(CPPINYIN_RPATH_ORIGIN "@loader_path") -endif() - -set(CMAKE_INSTALL_RPATH ${CPPINYIN_RPATH_ORIGIN}) -set(CMAKE_BUILD_RPATH ${CPPINYIN_RPATH_ORIGIN}) - -option(CPPINYIN_ENABLE_TESTS "Whether to build tests" OFF) -option(CPPINYIN_BUILD_PYTHON "Whether to build Python" OFF) -option(BUILD_SHARED_LIBS "Whether to build shared libraries" ON) - -if(NOT CMAKE_BUILD_TYPE) - message(STATUS "No CMAKE_BUILD_TYPE given, default to Release") - set(CMAKE_BUILD_TYPE Release) -endif() - -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) - -include(CheckCXXCompilerFlag) -if(NOT WIN32) - check_cxx_compiler_flag("-std=c++14" CPPINYIN_COMPILER_SUPPORTS_CXX14) -else() - # windows x86 or x86_64 - check_cxx_compiler_flag("/std:c++14" CPPINYIN_COMPILER_SUPPORTS_CXX14) -endif() -if(NOT CPPINYIN_COMPILER_SUPPORTS_CXX14) - message(FATAL_ERROR " - cppinyin requires a compiler supporting at least C++14. - If you are using GCC, please upgrade it to at least version 7.0. - If you are using Clang, please upgrade it to at least version 3.4.") -endif() - -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14 CACHE STRING "The C++ version to be used.") -endif() -set(CMAKE_CXX_EXTENSIONS OFF) -message(STATUS "C++ Standard version: ${CMAKE_CXX_STANDARD}") - -if(CPPINYIN_BUILD_PYTHON) - include(pybind11) -endif() - -include_directories(${CMAKE_SOURCE_DIR}) - -if(WIN32) - # disable various warnings for MSVC - # 4244: 'initializing': conversion from 'float' to 'int32_t', - # 4267: 'argument': conversion from 'size_t' to 'uint32_t', possible loss of data - set(disabled_warnings - /wd4244 - /wd4267 - ) - message(STATUS "Disabled warnings: ${disabled_warnings}") - foreach(w IN LISTS disabled_warnings) - string(APPEND CMAKE_CXX_FLAGS " ${w} ") - endforeach() -endif() - -if(CPPINYIN_ENABLE_TESTS) - include(googletest) - enable_testing() -endif() - -add_subdirectory(cppinyin) diff --git a/cmake/sherpa-onnx-static.pc.in b/cmake/sherpa-onnx-static.pc.in index 061905fce6..42beb084ab 100644 --- a/cmake/sherpa-onnx-static.pc.in +++ b/cmake/sherpa-onnx-static.pc.in @@ -22,4 +22,4 @@ Cflags: -I"${includedir}" # Note: -lcargs is required only for the following file # https://github.com/k2-fsa/sherpa-onnx/blob/master/c-api-examples/decode-file-c-api.c # We add it here so that users don't need to specify -lcargs when compiling decode-file-c-api.c -Libs: -L"${libdir}" -lsherpa-onnx-c-api -lsherpa-onnx-core -lkaldi-decoder-core -lsherpa-onnx-kaldifst-core -lsherpa-onnx-fstfar -lsherpa-onnx-fst -lkaldi-native-fbank-core -lkissfft-float -lpiper_phonemize -lespeak-ng -lucd -lonnxruntime -lssentencepiece_core -lcppinyin_core -Wl,-rpath,${libdir} @SHERPA_ONNX_PKG_WITH_CARGS@ @SHERPA_ONNX_PKG_CONFIG_EXTRA_LIBS@ +Libs: -L"${libdir}" -lsherpa-onnx-c-api -lsherpa-onnx-core -lkaldi-decoder-core -lsherpa-onnx-kaldifst-core -lsherpa-onnx-fstfar -lsherpa-onnx-fst -lkaldi-native-fbank-core -lkissfft-float -lpiper_phonemize -lespeak-ng -lucd -lonnxruntime -lssentencepiece_core -Wl,-rpath,${libdir} @SHERPA_ONNX_PKG_WITH_CARGS@ @SHERPA_ONNX_PKG_CONFIG_EXTRA_LIBS@ diff --git a/mfc-examples/NonStreamingSpeechRecognition/sherpa-onnx-deps.props b/mfc-examples/NonStreamingSpeechRecognition/sherpa-onnx-deps.props index cc0aa01423..9b35d475df 100644 --- a/mfc-examples/NonStreamingSpeechRecognition/sherpa-onnx-deps.props +++ b/mfc-examples/NonStreamingSpeechRecognition/sherpa-onnx-deps.props @@ -15,7 +15,6 @@ sherpa-onnx-fst.lib; kaldi-native-fbank-core.lib; kissfft-float.lib; - cppinyin_core.lib; onnxruntime.lib; piper_phonemize.lib; espeak-ng.lib; diff --git a/mfc-examples/NonStreamingTextToSpeech/sherpa-onnx-deps.props b/mfc-examples/NonStreamingTextToSpeech/sherpa-onnx-deps.props index cc0aa01423..9b35d475df 100644 --- a/mfc-examples/NonStreamingTextToSpeech/sherpa-onnx-deps.props +++ b/mfc-examples/NonStreamingTextToSpeech/sherpa-onnx-deps.props @@ -15,7 +15,6 @@ sherpa-onnx-fst.lib; kaldi-native-fbank-core.lib; kissfft-float.lib; - cppinyin_core.lib; onnxruntime.lib; piper_phonemize.lib; espeak-ng.lib; diff --git a/mfc-examples/StreamingSpeechRecognition/sherpa-onnx-deps.props b/mfc-examples/StreamingSpeechRecognition/sherpa-onnx-deps.props index cc0aa01423..9b35d475df 100644 --- a/mfc-examples/StreamingSpeechRecognition/sherpa-onnx-deps.props +++ b/mfc-examples/StreamingSpeechRecognition/sherpa-onnx-deps.props @@ -15,7 +15,6 @@ sherpa-onnx-fst.lib; kaldi-native-fbank-core.lib; kissfft-float.lib; - cppinyin_core.lib; onnxruntime.lib; piper_phonemize.lib; espeak-ng.lib; diff --git a/sherpa-onnx/csrc/CMakeLists.txt b/sherpa-onnx/csrc/CMakeLists.txt index 2a7e7433ec..d03dd75d29 100755 --- a/sherpa-onnx/csrc/CMakeLists.txt +++ b/sherpa-onnx/csrc/CMakeLists.txt @@ -261,7 +261,6 @@ if(SHERPA_ONNX_ENABLE_TTS) offline-tts-model-config.cc offline-tts-vits-model-config.cc offline-tts-vits-model.cc - offline-tts-zipvoice-frontend.cc offline-tts-zipvoice-model-config.cc offline-tts-zipvoice-model.cc offline-tts.cc @@ -417,7 +416,6 @@ target_link_libraries(sherpa-onnx-core fstfar fst) if(SHERPA_ONNX_ENABLE_TTS) target_link_libraries(sherpa-onnx-core - cppinyin_core piper_phonemize) endif() diff --git a/sherpa-onnx/csrc/matcha-tts-lexicon.cc b/sherpa-onnx/csrc/matcha-tts-lexicon.cc index 873918d0a5..77d47f3974 100644 --- a/sherpa-onnx/csrc/matcha-tts-lexicon.cc +++ b/sherpa-onnx/csrc/matcha-tts-lexicon.cc @@ -123,8 +123,12 @@ std::vector SplitTokensUTF8(const std::string &s) { } std::vector ProcessPhonemes( - const std::vector> &phonemes) { + const std::vector> &phonemes, bool skip_replacement) { auto tokens = ConvertPhonemesToUTF8(phonemes); + if (skip_replacement) { + return tokens; + } + std::string joined = Join(tokens); std::string replaced = ApplyReplacements(joined); return SplitTokensUTF8(replaced); @@ -139,8 +143,8 @@ void CallPhonemizeEspeak(const std::string &text, class MatchaTtsLexicon::Impl { public: Impl(const std::string &lexicon, const std::string &tokens, - const std::string &data_dir, bool debug) - : debug_(debug) { + const std::string &data_dir, bool debug, bool skip_replacement) + : debug_(debug), skip_replacement_(skip_replacement) { if (lexicon.empty()) { SHERPA_ONNX_LOGE("Please provide lexicon.txt for this model"); SHERPA_ONNX_EXIT(-1); @@ -163,8 +167,8 @@ class MatchaTtsLexicon::Impl { template Impl(Manager *mgr, const std::string &lexicon, const std::string &tokens, - const std::string &data_dir, bool debug) - : debug_(debug) { + const std::string &data_dir, bool debug, bool skip_replacement) + : debug_(debug), skip_replacement_(skip_replacement) { if (lexicon.empty()) { SHERPA_ONNX_LOGE("Please provide lexicon.txt for this model"); SHERPA_ONNX_EXIT(-1); @@ -360,7 +364,7 @@ class MatchaTtsLexicon::Impl { std::vector> phonemes; CallPhonemizeEspeak(w, config, &phonemes); - auto pp = ProcessPhonemes(phonemes); + auto pp = ProcessPhonemes(phonemes, skip_replacement_); for (const auto &p : pp) { if (token2id_.count(p)) { @@ -477,20 +481,25 @@ class MatchaTtsLexicon::Impl { std::unordered_map id2token_; bool debug_ = false; + bool skip_replacement_ = false; }; // namespace sherpa_onnx MatchaTtsLexicon::~MatchaTtsLexicon() = default; MatchaTtsLexicon::MatchaTtsLexicon(const std::string &lexicon, const std::string &tokens, - const std::string &data_dir, bool debug) - : impl_(std::make_unique(lexicon, tokens, data_dir, debug)) {} + const std::string &data_dir, bool debug, + bool skip_replacement) + : impl_(std::make_unique(lexicon, tokens, data_dir, debug, + skip_replacement)) {} template MatchaTtsLexicon::MatchaTtsLexicon(Manager *mgr, const std::string &lexicon, const std::string &tokens, - const std::string &data_dir, bool debug) - : impl_(std::make_unique(mgr, lexicon, tokens, data_dir, debug)) {} + const std::string &data_dir, bool debug, + bool skip_replacement) + : impl_(std::make_unique(mgr, lexicon, tokens, data_dir, debug, + skip_replacement)) {} std::vector MatchaTtsLexicon::ConvertTextToTokenIds( const std::string &text, const std::string & /*unused_voice = ""*/) const { @@ -502,7 +511,7 @@ template MatchaTtsLexicon::MatchaTtsLexicon(AAssetManager *mgr, const std::string &lexicon, const std::string &tokens, const std::string &data_dir, - bool debug); + bool debug, bool skip_replacement); #endif #if __OHOS__ @@ -510,7 +519,7 @@ template MatchaTtsLexicon::MatchaTtsLexicon(NativeResourceManager *mgr, const std::string &lexicon, const std::string &tokens, const std::string &data_dir, - bool debug); + bool debug, bool skip_replacement); #endif } // namespace sherpa_onnx diff --git a/sherpa-onnx/csrc/matcha-tts-lexicon.h b/sherpa-onnx/csrc/matcha-tts-lexicon.h index f9da31a631..f23df4392b 100644 --- a/sherpa-onnx/csrc/matcha-tts-lexicon.h +++ b/sherpa-onnx/csrc/matcha-tts-lexicon.h @@ -20,12 +20,13 @@ class MatchaTtsLexicon : public OfflineTtsFrontend { ~MatchaTtsLexicon() override; MatchaTtsLexicon(const std::string &lexicon, const std::string &tokens, - const std::string &data_dir, bool debug); + const std::string &data_dir, bool debug, + bool skip_replacement); template MatchaTtsLexicon(Manager *mgr, const std::string &lexicon, const std::string &tokens, const std::string &data_dir, - bool debug); + bool debug, bool skip_replacement); std::vector ConvertTextToTokenIds( const std::string &text, diff --git a/sherpa-onnx/csrc/offline-tts-matcha-impl.h b/sherpa-onnx/csrc/offline-tts-matcha-impl.h index 92d7efff3d..9440e25a04 100644 --- a/sherpa-onnx/csrc/offline-tts-matcha-impl.h +++ b/sherpa-onnx/csrc/offline-tts-matcha-impl.h @@ -386,7 +386,7 @@ class OfflineTtsMatchaImpl : public OfflineTtsImpl { if (meta_data.is_zh_en) { frontend_ = std::make_unique( mgr, config_.model.matcha.lexicon, config_.model.matcha.tokens, - config_.model.matcha.data_dir, config_.model.debug); + config_.model.matcha.data_dir, config_.model.debug, false); } else if (meta_data.jieba) { frontend_ = std::make_unique( mgr, config_.model.matcha.lexicon, config_.model.matcha.tokens, @@ -407,7 +407,7 @@ class OfflineTtsMatchaImpl : public OfflineTtsImpl { if (meta_data.is_zh_en) { frontend_ = std::make_unique( config_.model.matcha.lexicon, config_.model.matcha.tokens, - config_.model.matcha.data_dir, config_.model.debug); + config_.model.matcha.data_dir, config_.model.debug, false); } else if (meta_data.jieba) { frontend_ = std::make_unique( config_.model.matcha.lexicon, config_.model.matcha.tokens, diff --git a/sherpa-onnx/csrc/offline-tts-zipvoice-frontend-test.cc b/sherpa-onnx/csrc/offline-tts-zipvoice-frontend-test.cc deleted file mode 100644 index 0cf582c79d..0000000000 --- a/sherpa-onnx/csrc/offline-tts-zipvoice-frontend-test.cc +++ /dev/null @@ -1,81 +0,0 @@ -// sherpa-onnx/csrc/offline-tts-zipvoice-frontend-test.cc -// -// Copyright (c) 2025 Xiaomi Corporation - -#include "sherpa-onnx/csrc/offline-tts-zipvoice-frontend.h" - -#include -#include - -#include "espeak-ng/speak_lib.h" -#include "gtest/gtest.h" -#include "phoneme_ids.hpp" // NOLINT -#include "phonemize.hpp" // NOLINT -#include "sherpa-onnx/csrc/file-utils.h" -#include "sherpa-onnx/csrc/macros.h" - -namespace sherpa_onnx { - -TEST(ZipVoiceFrontend, Case1) { - std::string data_dir = "../zipvoice/espeak-ng-data"; - if (!FileExists(data_dir + "/en_dict")) { - SHERPA_ONNX_LOGE("%s/en_dict does not exist. Skipping test", - data_dir.c_str()); - return; - } - - if (!FileExists(data_dir + "/phontab")) { - SHERPA_ONNX_LOGE("%s/phontab does not exist. Skipping test", - data_dir.c_str()); - return; - } - - if (!FileExists(data_dir + "/phonindex")) { - SHERPA_ONNX_LOGE("%s/phonindex does not exist. Skipping test", - data_dir.c_str()); - return; - } - - if (!FileExists(data_dir + "/phondata")) { - SHERPA_ONNX_LOGE("%s/phondata does not exist. Skipping test", - data_dir.c_str()); - return; - } - - if (!FileExists(data_dir + "/intonations")) { - SHERPA_ONNX_LOGE("%s/intonations does not exist. Skipping test", - data_dir.c_str()); - return; - } - - std::string pinyin_dict = data_dir + "/../pinyin.dict"; - if (!FileExists(pinyin_dict)) { - SHERPA_ONNX_LOGE("%s does not exist. Skipping test", pinyin_dict.c_str()); - return; - } - - std::string tokens_file = data_dir + "/../tokens.txt"; - if (!FileExists(tokens_file)) { - SHERPA_ONNX_LOGE("%s does not exist. Skipping test", tokens_file.c_str()); - return; - } - - auto frontend = OfflineTtsZipvoiceFrontend( - tokens_file, data_dir, pinyin_dict, - OfflineTtsZipvoiceModelMetaData{.use_espeak = true, .use_pinyin = true}, - true); - - std::string text = "how are you doing?"; - std::vector ans = - frontend.ConvertTextToTokenIds(text, "en-us"); - - text = "这是第一句。这是第二句。"; - ans = frontend.ConvertTextToTokenIds(text, "en-us"); - - text = - "这是第一句。这是第二句。测试 [S1]and hello " - "world[S2]这是第三句。"; - ans = frontend.ConvertTextToTokenIds(text, "en-us"); -} - -} // namespace sherpa_onnx diff --git a/sherpa-onnx/csrc/offline-tts-zipvoice-frontend.cc b/sherpa-onnx/csrc/offline-tts-zipvoice-frontend.cc deleted file mode 100644 index 26ca18f49b..0000000000 --- a/sherpa-onnx/csrc/offline-tts-zipvoice-frontend.cc +++ /dev/null @@ -1,386 +0,0 @@ -// sherpa-onnx/csrc/offline-tts-zipvoice-frontend.cc -// -// Copyright (c) 2025 Xiaomi Corporation - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __ANDROID_API__ >= 9 -#include "android/asset_manager.h" -#include "android/asset_manager_jni.h" -#endif - -#if __OHOS__ -#include "rawfile/raw_file_manager.h" -#endif - -#include "cppinyin/csrc/cppinyin.h" -#include "espeak-ng/speak_lib.h" -#include "phoneme_ids.hpp" // NOLINT -#include "phonemize.hpp" // NOLINT -#include "sherpa-onnx/csrc/file-utils.h" -#include "sherpa-onnx/csrc/macros.h" -#include "sherpa-onnx/csrc/offline-tts-zipvoice-frontend.h" -#include "sherpa-onnx/csrc/text-utils.h" - -namespace sherpa_onnx { - -void CallPhonemizeEspeak(const std::string &text, - piper::eSpeakPhonemeConfig &config, // NOLINT - std::vector> *phonemes); - -static std::unordered_map ReadTokens(std::istream &is) { - std::unordered_map token2id; - - std::string line; - std::string sym; - int32_t id = 0; - while (std::getline(is, line)) { - std::istringstream iss(line); - iss >> sym; - if (iss.eof()) { - id = atoi(sym.c_str()); - sym = " "; - } else { - iss >> id; - } - // eat the trailing \r\n on windows - iss >> std::ws; - if (!iss.eof()) { - SHERPA_ONNX_LOGE("Error when reading tokens: %s", line.c_str()); - exit(-1); - } - - if (token2id.count(sym)) { - SHERPA_ONNX_LOGE("Duplicated token %s. Line %s. Existing ID: %d", - sym.c_str(), line.c_str(), token2id.at(sym)); - exit(-1); - } - token2id.insert({sym, id}); - } - return token2id; -} - -static std::string MapPunctuations( - const std::string &text, - const std::unordered_map &punct_map) { - std::string result = text; - for (const auto &kv : punct_map) { - // Replace all occurrences of kv.first with kv.second - size_t pos = 0; - while ((pos = result.find(kv.first, pos)) != std::string::npos) { - result.replace(pos, kv.first.length(), kv.second); - pos += kv.second.length(); - } - } - return result; -} - -static void ProcessPinyin( - const std::string &pinyin, const cppinyin::PinyinEncoder *pinyin_encoder, - const std::unordered_map &token2id, - std::vector *tokens_ids, std::vector *tokens) { - auto initial = pinyin_encoder->ToInitial(pinyin); - if (!initial.empty()) { - // append '0' to fix the conflict with espeak token - initial = initial + "0"; - if (token2id.count(initial)) { - tokens_ids->push_back(token2id.at(initial)); - tokens->push_back(initial); - } else { - SHERPA_ONNX_LOGE("Skip unknown initial %s", initial.c_str()); - } - } - auto final_t = pinyin_encoder->ToFinal(pinyin); - if (!final_t.empty()) { - if (!std::isdigit(final_t.back())) { - final_t = final_t + "5"; // use 5 for neutral tone - } - if (token2id.count(final_t)) { - tokens_ids->push_back(token2id.at(final_t)); - tokens->push_back(final_t); - } else { - SHERPA_ONNX_LOGE("Skip unknown final %s", final_t.c_str()); - } - } -} - -static void TokenizeZh(const std::string &words, - const cppinyin::PinyinEncoder *pinyin_encoder, - const std::unordered_map &token2id, - std::vector *token_ids, - std::vector *tokens) { - std::vector pinyins; - pinyin_encoder->Encode(words, &pinyins, "number" /*tone*/, false /*partial*/); - for (const auto &pinyin : pinyins) { - if (pinyin_encoder->ValidPinyin(pinyin, "number" /*tone*/)) { - ProcessPinyin(pinyin, pinyin_encoder, token2id, token_ids, tokens); - } else { - auto wstext = ToWideString(pinyin); - for (auto &wc : wstext) { - auto c = ToString(std::wstring(1, wc)); - if (token2id.count(c)) { - token_ids->push_back(token2id.at(c)); - tokens->push_back(c); - } else { - SHERPA_ONNX_LOGE("Skip unknown character %s", c.c_str()); - } - } - } - } -} - -static void TokenizeEn(const std::string &words, - const std::unordered_map &token2id, - const std::string &voice, - std::vector *token_ids, - std::vector *tokens) { - piper::eSpeakPhonemeConfig config; - // ./bin/espeak-ng-bin --path ./install/share/espeak-ng-data/ --voices - // to list available voices - config.voice = voice; // e.g., voice is en-us - - std::vector> phonemes; - - CallPhonemizeEspeak(words, config, &phonemes); - - for (const auto &p : phonemes) { - for (const auto &ph : p) { - auto token = Utf32ToUtf8(std::u32string(1, ph)); - if (token2id.count(token)) { - token_ids->push_back(token2id.at(token)); - tokens->push_back(token); - } else { - SHERPA_ONNX_LOGE("Skip unknown phoneme %s", token.c_str()); - } - } - } -} - -static void TokenizeTag( - const std::string &words, - const std::unordered_map &token2id, - std::vector *tokens_ids, std::vector *tokens) { - // in zipvoice tags are all in upper case - std::string tag = ToUpperAscii(words); - if (token2id.count(tag)) { - tokens_ids->push_back(token2id.at(tag)); - tokens->push_back(tag); - } else { - SHERPA_ONNX_LOGE("Skip unknown tag %s", tag.c_str()); - } -} - -static void TokenizePinyin( - const std::string &words, const cppinyin::PinyinEncoder *pinyin_encoder, - const std::unordered_map &token2id, - std::vector *tokens_ids, std::vector *tokens) { - // words are in the form of , - std::string pinyin = words.substr(1, words.size() - 2); - if (!pinyin.empty()) { - if (pinyin[pinyin.size() - 1] == '5') { - pinyin = pinyin.substr(0, pinyin.size() - 1); // remove the tone - } - if (pinyin_encoder->ValidPinyin(pinyin, "number" /*tone*/)) { - ProcessPinyin(pinyin, pinyin_encoder, token2id, tokens_ids, tokens); - } else { - SHERPA_ONNX_LOGE("Invalid pinyin %s", pinyin.c_str()); - } - } -} - -OfflineTtsZipvoiceFrontend::OfflineTtsZipvoiceFrontend( - const std::string &tokens, const std::string &data_dir, - const std::string &pinyin_dict, - const OfflineTtsZipvoiceModelMetaData &meta_data, bool debug /*= false*/) - : debug_(debug), meta_data_(meta_data) { - std::ifstream is(tokens); - token2id_ = ReadTokens(is); - if (meta_data_.use_pinyin) { - pinyin_encoder_ = std::make_unique(pinyin_dict); - } else { - pinyin_encoder_ = nullptr; - } - if (meta_data_.use_espeak) { - // We should copy the directory of espeak-ng-data from the asset to - // some internal or external storage and then pass the directory to - // data_dir. - InitEspeak(data_dir); - } -} - -template -OfflineTtsZipvoiceFrontend::OfflineTtsZipvoiceFrontend( - Manager *mgr, const std::string &tokens, const std::string &data_dir, - const std::string &pinyin_dict, - const OfflineTtsZipvoiceModelMetaData &meta_data, bool debug) - : debug_(debug), meta_data_(meta_data) { - auto buf = ReadFile(mgr, tokens); - std::istrstream is(buf.data(), buf.size()); - token2id_ = ReadTokens(is); - if (meta_data_.use_pinyin) { - auto buf = ReadFile(mgr, pinyin_dict); - std::istringstream iss(std::string(buf.begin(), buf.end())); - pinyin_encoder_ = std::make_unique(iss); - } else { - pinyin_encoder_ = nullptr; - } - if (meta_data_.use_espeak) { - // We should copy the directory of espeak-ng-data from the asset to - // some internal or external storage and then pass the directory to - // data_dir. - InitEspeak(data_dir); - } -} - -std::vector OfflineTtsZipvoiceFrontend::ConvertTextToTokenIds( - const std::string &_text, const std::string &voice) const { - std::string text = _text; - if (meta_data_.use_espeak) { - text = ToLowerAscii(_text); - } - - text = MapPunctuations(text, punct_map_); - - auto wstext = ToWideString(text); - - std::vector parts; - // Match <...>, [...], or single character - std::wregex part_pattern(LR"([<\[].*?[>\]]|.)"); - auto words_begin = - std::wsregex_iterator(wstext.begin(), wstext.end(), part_pattern); - auto words_end = std::wsregex_iterator(); - for (std::wsregex_iterator i = words_begin; i != words_end; ++i) { - parts.push_back(ToString(i->str())); - } - - // types are en, zh, tag, pinyin, other - // tag is [...] - // pinyin is <...> - // other is any other text that does not match the above, normally numbers and - // punctuations - std::vector types; - for (auto &word : parts) { - if (word.size() == 1 && std::isalpha(word[0])) { - // single character, e.g., 'a', 'b', 'c' - types.push_back("en"); - } else if (word.size() > 1 && word[0] == '<' && word.back() == '>') { - // e.g., , - types.push_back("pinyin"); - } else if (word.size() > 1 && word[0] == '[' && word.back() == ']') { - types.push_back("tag"); - } else if (ContainsCJK(word)) { // word contains one CJK characters - types.push_back("zh"); - } else { - types.push_back("other"); - } - } - - std::vector> parts_with_types; - std::ostringstream oss; - std::string t_lang; - oss.str(""); - std::ostringstream debug_oss; - if (debug_) { - debug_oss << "Text : " << _text << ", Parts with types: \n"; - } - for (int32_t i = 0; i < types.size(); ++i) { - if (i == 0) { - oss << parts[i]; - t_lang = types[i]; - } else { - if (t_lang == "other" && (types[i] != "tag" && types[i] != "pinyin")) { - // combine into current type if the previous part is "other" - // do not combine with "tag" or "pinyin" - oss << parts[i]; - t_lang = types[i]; - } else { - if ((t_lang == types[i] || types[i] == "other") && t_lang != "pinyin" && - t_lang != "tag") { - // same language or other, continue - // do not combine other into "pinyin" or "tag" - oss << parts[i]; - } else { - // different language, start a new sentence - std::string part = oss.str(); - oss.str(""); - parts_with_types.emplace_back(part, t_lang); - if (debug_) { - debug_oss << "(" << part << ", " << t_lang << "),"; - } - oss << parts[i]; - t_lang = types[i]; - } - } - } - } - - std::string part = oss.str(); - oss.str(""); - parts_with_types.emplace_back(part, t_lang); - if (debug_) { - debug_oss << "(" << part << ", " << t_lang << ")\n"; - SHERPA_ONNX_LOGE("%s", debug_oss.str().c_str()); - debug_oss.str(""); - } - - std::vector token_ids; - std::vector tokens; // for debugging - for (const auto &pt : parts_with_types) { - if (pt.second == "zh") { - TokenizeZh(pt.first, pinyin_encoder_.get(), token2id_, &token_ids, - &tokens); - } else if (pt.second == "en") { - TokenizeEn(pt.first, token2id_, "en-us", &token_ids, &tokens); - } else if (pt.second == "pinyin") { - TokenizePinyin(pt.first, pinyin_encoder_.get(), token2id_, &token_ids, - &tokens); - } else if (pt.second == "tag") { - TokenizeTag(pt.first, token2id_, &token_ids, &tokens); - } else { - SHERPA_ONNX_LOGE("Unexpected type: %s", pt.second.c_str()); - exit(-1); - } - } - if (debug_) { - debug_oss << "Tokens and IDs: \n"; - for (int32_t i = 0; i < tokens.size(); i++) { - debug_oss << "(" << tokens[i] << ", " << token_ids[i] << "),"; - } - debug_oss << "\n"; - SHERPA_ONNX_LOGE("%s", debug_oss.str().c_str()); - } - - std::vector ans; - ans.push_back(TokenIDs(std::move(token_ids))); - return ans; -} - -#if __ANDROID_API__ >= 9 -template OfflineTtsZipvoiceFrontend::OfflineTtsZipvoiceFrontend( - AAssetManager *mgr, const std::string &tokens, const std::string &data_dir, - const std::string &pinyin_dict, - const OfflineTtsZipvoiceModelMetaData &meta_data, bool debug = false); - -#endif - -#if __OHOS__ -template OfflineTtsZipvoiceFrontend::OfflineTtsZipvoiceFrontend( - NativeResourceManager *mgr, const std::string &tokens, - const std::string &data_dir, const std::string &pinyin_dict, - const OfflineTtsZipvoiceModelMetaData &meta_data, bool debug = false); - -#endif - -} // namespace sherpa_onnx diff --git a/sherpa-onnx/csrc/offline-tts-zipvoice-frontend.h b/sherpa-onnx/csrc/offline-tts-zipvoice-frontend.h deleted file mode 100644 index 1e47103a4f..0000000000 --- a/sherpa-onnx/csrc/offline-tts-zipvoice-frontend.h +++ /dev/null @@ -1,62 +0,0 @@ -// sherpa-onnx/csrc/offline-tts-zipvoice-frontend.h -// -// Copyright (c) 2025 Xiaomi Corporation - -#ifndef SHERPA_ONNX_CSRC_OFFLINE_TTS_ZIPVOICE_FRONTEND_H_ -#define SHERPA_ONNX_CSRC_OFFLINE_TTS_ZIPVOICE_FRONTEND_H_ -#include -#include -#include -#include -#include - -#include "cppinyin/csrc/cppinyin.h" -#include "sherpa-onnx/csrc/offline-tts-frontend.h" -#include "sherpa-onnx/csrc/offline-tts-zipvoice-model-meta-data.h" - -namespace sherpa_onnx { - -class OfflineTtsZipvoiceFrontend : public OfflineTtsFrontend { - public: - OfflineTtsZipvoiceFrontend(const std::string &tokens, - const std::string &data_dir, - const std::string &pinyin_dict, - const OfflineTtsZipvoiceModelMetaData &meta_data, - bool debug = false); - - template - OfflineTtsZipvoiceFrontend(Manager *mgr, const std::string &tokens, - const std::string &data_dir, - const std::string &pinyin_dict, - const OfflineTtsZipvoiceModelMetaData &meta_data, - bool debug = false); - - /** Convert a string to token IDs. - * - * @param text The input text. - * Example 1: "This is the first sample sentence; this is the - * second one." Example 2: "这是第一句。这是第二句。" - * @param voice Optional. It is for espeak-ng. - * - * @return Return a vector-of-vector of token IDs. Each subvector contains - * a sentence that can be processed independently. - * If a frontend does not support splitting the text into - * sentences, the resulting vector contains only one subvector. - */ - std::vector ConvertTextToTokenIds( - const std::string &text, const std::string &voice = "") const override; - - private: - bool debug_ = false; - std::unordered_map token2id_; - const std::unordered_map punct_map_ = { - {",", ","}, {"。", "."}, {"!", "!"}, {"?", "?"}, {";", ";"}, - {":", ":"}, {"、", ","}, {"‘", "'"}, {"“", "\""}, {"”", "\""}, - {"’", "'"}, {"⋯", "…"}, {"···", "…"}, {"・・・", "…"}, {"...", "…"}}; - OfflineTtsZipvoiceModelMetaData meta_data_; - std::unique_ptr pinyin_encoder_; -}; - -} // namespace sherpa_onnx - -#endif // SHERPA_ONNX_CSRC_OFFLINE_TTS_ZIPVOICE_FRONTEND_H_ diff --git a/sherpa-onnx/csrc/offline-tts-zipvoice-impl.h b/sherpa-onnx/csrc/offline-tts-zipvoice-impl.h index ff16bf604e..8e9861f5d0 100644 --- a/sherpa-onnx/csrc/offline-tts-zipvoice-impl.h +++ b/sherpa-onnx/csrc/offline-tts-zipvoice-impl.h @@ -15,9 +15,9 @@ #include "kaldi-native-fbank/csrc/mel-computations.h" #include "kaldi-native-fbank/csrc/stft.h" #include "sherpa-onnx/csrc/macros.h" +#include "sherpa-onnx/csrc/matcha-tts-lexicon.h" #include "sherpa-onnx/csrc/offline-tts-frontend.h" #include "sherpa-onnx/csrc/offline-tts-impl.h" -#include "sherpa-onnx/csrc/offline-tts-zipvoice-frontend.h" #include "sherpa-onnx/csrc/offline-tts-zipvoice-model-config.h" #include "sherpa-onnx/csrc/offline-tts-zipvoice-model.h" #include "sherpa-onnx/csrc/onnx-utils.h" @@ -83,8 +83,16 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl { } // we assume batch size is 1 - std::vector tokens = text_token_ids[0].tokens; - std::vector prompt_tokens = prompt_token_ids[0].tokens; + std::vector tokens; + for (const auto &t : text_token_ids) { + tokens.insert(tokens.end(), t.tokens.begin(), t.tokens.end()); + } + + std::vector prompt_tokens; + for (const auto &t : prompt_token_ids) { + prompt_tokens.insert(prompt_tokens.end(), t.tokens.begin(), + t.tokens.end()); + } return Process(tokens, prompt_tokens, prompt_samples, sample_rate, speed, num_steps); @@ -93,28 +101,15 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl { private: template void InitFrontend(Manager *mgr) { - const auto &meta_data = model_->GetMetaData(); - frontend_ = std::make_unique( - mgr, config_.model.zipvoice.tokens, config_.model.zipvoice.data_dir, - config_.model.zipvoice.pinyin_dict, meta_data, config_.model.debug); + frontend_ = std::make_unique( + mgr, config_.model.zipvoice.lexicon, config_.model.zipvoice.tokens, + config_.model.zipvoice.data_dir, config_.model.debug, true); } void InitFrontend() { - const auto &meta_data = model_->GetMetaData(); - - if (meta_data.use_pinyin && config_.model.zipvoice.pinyin_dict.empty()) { - SHERPA_ONNX_LOGE( - "Please provide --zipvoice-pinyin-dict for converting Chinese into " - "pinyin."); - exit(-1); - } - if (meta_data.use_espeak && config_.model.zipvoice.data_dir.empty()) { - SHERPA_ONNX_LOGE("Please provide --zipvoice-data-dir for espeak-ng."); - exit(-1); - } - frontend_ = std::make_unique( - config_.model.zipvoice.tokens, config_.model.zipvoice.data_dir, - config_.model.zipvoice.pinyin_dict, meta_data, config_.model.debug); + frontend_ = std::make_unique( + config_.model.zipvoice.lexicon, config_.model.zipvoice.tokens, + config_.model.zipvoice.data_dir, config_.model.debug, true); } std::vector ComputeMelSpectrogram( diff --git a/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.cc b/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.cc index 453bd6f6c2..b8179a9e67 100644 --- a/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.cc +++ b/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.cc @@ -17,13 +17,14 @@ void OfflineTtsZipvoiceModelConfig::Register(ParseOptions *po) { "Path to tokens.txt for ZipVoice models"); po->Register("zipvoice-data-dir", &data_dir, "Path to the directory containing dict for espeak-ng."); + po->Register("zipvoice-lexicon", &lexicon, "Plah to lexicon.txt for Chinese"); po->Register("zipvoice-pinyin-dict", &pinyin_dict, "Path to the pinyin dictionary for cppinyin (i.e converting " "Chinese into phones)."); po->Register("zipvoice-text-model", &text_model, "Path to zipvoice text model"); po->Register("zipvoice-flow-matching-model", &flow_matching_model, - "Path to zipvoice flow-matching model"); + "Path to zipvoice flow-matching model, i.e., the decoder model"); po->Register("zipvoice-vocoder", &vocoder, "Path to zipvoice vocoder"); po->Register("zipvoice-feat-scale", &feat_scale, "Feature scale for ZipVoice (default: 0.1)"); @@ -96,12 +97,6 @@ bool OfflineTtsZipvoiceModelConfig::Validate() const { } } - if (!pinyin_dict.empty() && !FileExists(pinyin_dict)) { - SHERPA_ONNX_LOGE("--zipvoice-pinyin-dict: '%s' does not exist", - pinyin_dict.c_str()); - return false; - } - if (feat_scale <= 0) { SHERPA_ONNX_LOGE("--zipvoice-feat-scale must be positive. Given: %f", feat_scale); @@ -138,7 +133,7 @@ std::string OfflineTtsZipvoiceModelConfig::ToString() const { os << "flow_matching_model=\"" << flow_matching_model << "\", "; os << "vocoder=\"" << vocoder << "\", "; os << "data_dir=\"" << data_dir << "\", "; - os << "pinyin_dict=\"" << pinyin_dict << "\", "; + os << "lexicon=\"" << lexicon << "\", "; os << "feat_scale=" << feat_scale << ", "; os << "t_shift=" << t_shift << ", "; os << "target_rms=" << target_rms << ", "; diff --git a/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.h b/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.h index ef43bf4123..5b5d0c24b7 100644 --- a/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.h +++ b/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.h @@ -15,12 +15,11 @@ namespace sherpa_onnx { struct OfflineTtsZipvoiceModelConfig { std::string tokens; std::string text_model; - std::string flow_matching_model; + std::string flow_matching_model; // decoder std::string vocoder; - // If data_dir is given, lexicon is ignored - // data_dir is for piper-phonemize, which uses espeak-ng std::string data_dir; + std::string lexicon; // Used for converting Chinese characters to pinyin std::string pinyin_dict; @@ -35,14 +34,15 @@ struct OfflineTtsZipvoiceModelConfig { OfflineTtsZipvoiceModelConfig( const std::string &tokens, const std::string &text_model, const std::string &flow_matching_model, const std::string &vocoder, - const std::string &data_dir, const std::string &pinyin_dict, - float feat_scale = 0.1, float t_shift = 0.5, float target_rms = 0.1, - float guidance_scale = 1.0) + const std::string &data_dir, const std::string &lexicon, + const std::string &pinyin_dict, float feat_scale = 0.1, + float t_shift = 0.5, float target_rms = 0.1, float guidance_scale = 1.0) : tokens(tokens), text_model(text_model), flow_matching_model(flow_matching_model), vocoder(vocoder), data_dir(data_dir), + lexicon(lexicon), pinyin_dict(pinyin_dict), feat_scale(feat_scale), t_shift(t_shift), diff --git a/sherpa-onnx/csrc/offline-tts-zipvoice-model.cc b/sherpa-onnx/csrc/offline-tts-zipvoice-model.cc index 05f324c97f..8b4d321bac 100644 --- a/sherpa-onnx/csrc/offline-tts-zipvoice-model.cc +++ b/sherpa-onnx/csrc/offline-tts-zipvoice-model.cc @@ -68,7 +68,7 @@ class OfflineTtsZipvoiceModel::Impl { if (batch_size != 1) { SHERPA_ONNX_LOGE("Support only batch_size == 1. Given: %d", static_cast(batch_size)); - exit(-1); + SHERPA_ONNX_EXIT(-1); } std::vector prompt_feat_shape = @@ -108,7 +108,10 @@ class OfflineTtsZipvoiceModel::Impl { std::random_device rd; std::default_random_engine rng(rd()); std::normal_distribution norm(0, 1); - for (auto &v : x_data) v = norm(rng); + for (auto &v : x_data) { + v = norm(rng); + } + std::vector x_shape = {batch_size, num_frames, feat_dim}; Ort::Value x = Ort::Value::CreateTensor( memory_info, x_data.data(), x_data.size(), x_shape.data(), diff --git a/sherpa-onnx/pascal-api/sherpa_onnx.pas b/sherpa-onnx/pascal-api/sherpa_onnx.pas index 2357724d3b..5d86b3c959 100644 --- a/sherpa-onnx/pascal-api/sherpa_onnx.pas +++ b/sherpa-onnx/pascal-api/sherpa_onnx.pas @@ -698,7 +698,6 @@ implementation {$linklib sherpa-onnx-kaldifst-core} {$linklib sherpa-onnx-fstfar} {$linklib sherpa-onnx-fst} - {$linklib cppinyin_core} {$linklib kissfft-float} {$linklib kaldi-native-fbank-core} {$linklib piper_phonemize} From 6d63ab108d0348c6972001854d583c33162180cc Mon Sep 17 00:00:00 2001 From: Fangjun Kuang Date: Thu, 11 Dec 2025 18:47:30 +0800 Subject: [PATCH 2/2] Fix typos --- sherpa-onnx/csrc/offline-tts-zipvoice-model-config.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.cc b/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.cc index b8179a9e67..1226adf858 100644 --- a/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.cc +++ b/sherpa-onnx/csrc/offline-tts-zipvoice-model-config.cc @@ -17,7 +17,7 @@ void OfflineTtsZipvoiceModelConfig::Register(ParseOptions *po) { "Path to tokens.txt for ZipVoice models"); po->Register("zipvoice-data-dir", &data_dir, "Path to the directory containing dict for espeak-ng."); - po->Register("zipvoice-lexicon", &lexicon, "Plah to lexicon.txt for Chinese"); + po->Register("zipvoice-lexicon", &lexicon, "Path to lexicon.txt for Chinese"); po->Register("zipvoice-pinyin-dict", &pinyin_dict, "Path to the pinyin dictionary for cppinyin (i.e converting " "Chinese into phones).");