#pragma once #include #include #include #include #include #include #include // Available languages for multilingual TTS extern const std::vector AVAILABLE_LANGS; /** * Configuration structure */ struct Config { struct AEConfig { int sample_rate; int base_chunk_size; } ae; struct TTLConfig { int chunk_compress_factor; int latent_dim; } ttl; }; /** * Unicode text processor */ class UnicodeProcessor { public: explicit UnicodeProcessor(const std::string& unicode_indexer_json_path); // Process text list to text IDs and mask void call( const std::vector& text_list, const std::vector& lang_list, std::vector>& text_ids, std::vector>>& text_mask ); private: std::vector indexer_; std::string preprocessText(const std::string& text, const std::string& lang); std::vector textToUnicodeValues(const std::string& text); std::vector>> getTextMask( const std::vector& text_ids_lengths ); }; /** * Style class */ class Style { public: Style(const std::vector& ttl_data, const std::vector& ttl_shape, const std::vector& dp_data, const std::vector& dp_shape); const std::vector& getTtlData() const { return ttl_data_; } const std::vector& getDpData() const { return dp_data_; } const std::vector& getTtlShape() const { return ttl_shape_; } const std::vector& getDpShape() const { return dp_shape_; } private: std::vector ttl_data_; std::vector dp_data_; std::vector ttl_shape_; std::vector dp_shape_; }; /** * TextToSpeech class */ class TextToSpeech { public: TextToSpeech( const Config& cfgs, UnicodeProcessor* text_processor, Ort::Session* dp_ort, Ort::Session* text_enc_ort, Ort::Session* vector_est_ort, Ort::Session* vocoder_ort ); struct SynthesisResult { std::vector wav; std::vector duration; }; SynthesisResult call( Ort::MemoryInfo& memory_info, const std::string& text, const std::string& lang, const Style& style, int total_step, float speed = 1.05f, float silence_duration = 0.3f ); SynthesisResult batch( Ort::MemoryInfo& memory_info, const std::vector& text_list, const std::vector& lang_list, const Style& style, int total_step, float speed = 1.05f ); int getSampleRate() const { return sample_rate_; } private: SynthesisResult _infer( Ort::MemoryInfo& memory_info, const std::vector& text_list, const std::vector& lang_list, const Style& style, int total_step, float speed = 1.05f ); Config cfgs_; UnicodeProcessor* text_processor_; Ort::Session* dp_ort_; Ort::Session* text_enc_ort_; Ort::Session* vector_est_ort_; Ort::Session* vocoder_ort_; int sample_rate_; int base_chunk_size_; int chunk_compress_factor_; int ldim_; void sampleNoisyLatent( const std::vector& duration, std::vector>>& noisy_latent, std::vector>>& latent_mask ); }; // Utility functions std::vector>> lengthToMask( const std::vector& lengths, int max_len = -1 ); std::vector>> getLatentMask( const std::vector& wav_lengths, int base_chunk_size, int chunk_compress_factor ); // ONNX model loading struct OnnxModels { std::unique_ptr dp; std::unique_ptr text_enc; std::unique_ptr vector_est; std::unique_ptr vocoder; }; std::unique_ptr loadOnnx( Ort::Env& env, const std::string& onnx_path, const Ort::SessionOptions& opts ); OnnxModels loadOnnxAll( Ort::Env& env, const std::string& onnx_dir, const Ort::SessionOptions& opts ); // Configuration and processor loading Config loadCfgs(const std::string& onnx_dir); std::unique_ptr loadTextProcessor(const std::string& onnx_dir); // Voice style loading Style loadVoiceStyle(const std::vector& voice_style_paths, bool verbose = false); // TextToSpeech loading std::unique_ptr loadTextToSpeech( Ort::Env& env, const std::string& onnx_dir, bool use_gpu = false ); // WAV file writing void writeWavFile( const std::string& filename, const std::vector& audio_data, int sample_rate ); // Tensor conversion utilities void clearTensorBuffers(); Ort::Value arrayToTensor( Ort::MemoryInfo& memory_info, const std::vector>>& array, const std::vector& dims ); Ort::Value intArrayToTensor( Ort::MemoryInfo& memory_info, const std::vector>& array, const std::vector& dims ); // JSON loading helpers std::vector loadJsonInt64(const std::string& file_path); // Timer utility template auto timer(const std::string& name, Func&& func) -> decltype(func()) { auto start = std::chrono::high_resolution_clock::now(); std::cout << name << "..." << std::endl; auto result = func(); auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed = end - start; std::cout << " -> " << name << " completed in " << std::fixed << std::setprecision(2) << elapsed.count() << " sec" << std::endl; return result; } // Sanitize filename std::string sanitizeFilename(const std::string& text, int max_len); // Chunk text into manageable segments std::vector chunkText(const std::string& text, int max_len = 300);