@@ -33,6 +33,8 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
3333 model_(std::make_unique<OfflineTtsZipvoiceModel>(config.model)),
3434 vocoder_(Vocoder::Create(config.model)) {
3535 InitFrontend ();
36+
37+ PostInit ();
3638 }
3739
3840 template <typename Manager>
@@ -41,6 +43,8 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
4143 model_ (std::make_unique<OfflineTtsZipvoiceModel>(mgr, config.model)),
4244 vocoder_(Vocoder::Create(mgr, config.model)) {
4345 InitFrontend (mgr);
46+
47+ PostInit ();
4448 }
4549
4650 int32_t SampleRate () const override {
@@ -99,6 +103,33 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
99103 }
100104
101105 private:
106+ void PostInit () { InitMelBanks (); }
107+
108+ void InitMelBanks () {
109+ const auto &meta = model_->GetMetaData ();
110+ int32_t sample_rate = meta.sample_rate ;
111+ int32_t n_fft = meta.n_fft ;
112+ int32_t hop_length = meta.hop_length ;
113+ int32_t win_length = meta.window_length ;
114+ int32_t num_mels = meta.num_mels ;
115+
116+ knf::FrameExtractionOptions frame_opts;
117+ frame_opts.samp_freq = sample_rate;
118+ frame_opts.frame_length_ms = win_length * 1000 / sample_rate;
119+ frame_opts.frame_shift_ms = hop_length * 1000 / sample_rate;
120+ frame_opts.window_type = " hanning" ;
121+
122+ knf::MelBanksOptions mel_opts;
123+ mel_opts.num_bins = num_mels;
124+ mel_opts.low_freq = 0 ;
125+ mel_opts.high_freq = sample_rate / 2 ;
126+ mel_opts.is_librosa = true ;
127+ mel_opts.use_slaney_mel_scale = false ;
128+ mel_opts.norm = " " ;
129+
130+ mel_banks_ = std::make_unique<knf::MelBanks>(mel_opts, frame_opts, 1 .0f );
131+ }
132+
102133 template <typename Manager>
103134 void InitFrontend (Manager *mgr) {
104135 frontend_ = std::make_unique<MatchaTtsLexicon>(
@@ -112,9 +143,9 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
112143 config_.model .zipvoice .data_dir , config_.model .debug , true );
113144 }
114145
115- std::vector<int32_t > ComputeMelSpectrogram (
116- const std::vector< float > &_samples, int32_t sample_rate,
117- std::vector<float > *prompt_features) const {
146+ void ComputeMelSpectrogram ( const std::vector<float > &_samples,
147+ int32_t sample_rate, float feat_scale ,
148+ std::vector<float > *prompt_features) const {
118149 const auto &meta = model_->GetMetaData ();
119150 if (sample_rate != meta.sample_rate ) {
120151 SHERPA_ONNX_LOGE (
@@ -131,19 +162,18 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
131162 sample_rate, meta.sample_rate , lowpass_cutoff, lowpass_filter_width);
132163 std::vector<float > samples;
133164 resampler->Resample (_samples.data (), _samples.size (), true , &samples);
134- return ComputeMelSpectrogram (samples, prompt_features);
135- } else {
136- // Use the original samples if the sample rate matches
137- return ComputeMelSpectrogram (_samples, prompt_features);
165+ ComputeMelSpectrogram (samples, feat_scale, prompt_features);
166+ return ;
138167 }
168+
169+ ComputeMelSpectrogram (_samples, feat_scale, prompt_features);
139170 }
140171
141- std::vector<int32_t > ComputeMelSpectrogram (
142- const std::vector< float > &samples ,
143- std::vector<float > *prompt_features) const {
172+ void ComputeMelSpectrogram ( const std::vector<float > &samples,
173+ float feat_scale ,
174+ std::vector<float > *prompt_features) const {
144175 const auto &meta = model_->GetMetaData ();
145176
146- int32_t sample_rate = meta.sample_rate ;
147177 int32_t n_fft = meta.n_fft ;
148178 int32_t hop_length = meta.hop_length ;
149179 int32_t win_length = meta.window_length ;
@@ -161,46 +191,23 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
161191 int32_t num_frames = stft_result.num_frames ;
162192 int32_t fft_bins = n_fft / 2 + 1 ;
163193
164- knf::FrameExtractionOptions frame_opts;
165- frame_opts.samp_freq = sample_rate;
166- frame_opts.frame_length_ms = win_length * 1000 / sample_rate;
167- frame_opts.frame_shift_ms = hop_length * 1000 / sample_rate;
168- frame_opts.window_type = " hanning" ;
169-
170- knf::MelBanksOptions mel_opts;
171- mel_opts.num_bins = num_mels;
172- mel_opts.low_freq = 0 ;
173- mel_opts.high_freq = sample_rate / 2 ;
174- mel_opts.is_librosa = true ;
175- mel_opts.use_slaney_mel_scale = false ;
176- mel_opts.norm = " " ;
177-
178- knf::MelBanks mel_banks (mel_opts, frame_opts, 1 .0f );
194+ prompt_features->resize (num_frames * num_mels);
195+ float *p = prompt_features->data ();
179196
180- prompt_features->clear ();
181- prompt_features->reserve (num_frames * num_mels);
197+ std::vector<float > magnitude_spectrum (fft_bins);
182198
183- for (int32_t i = 0 ; i < num_frames; ++i) {
184- std::vector<float > magnitude_spectrum (fft_bins);
199+ for (int32_t i = 0 ; i < num_frames; ++i, p += num_mels) {
185200 for (int32_t k = 0 ; k < fft_bins; ++k) {
186201 float real = stft_result.real [i * fft_bins + k];
187202 float imag = stft_result.imag [i * fft_bins + k];
188203 magnitude_spectrum[k] = std::sqrt (real * real + imag * imag);
189204 }
190- std::vector<float > mel_features (num_mels, 0 .0f );
191- mel_banks.Compute (magnitude_spectrum.data (), mel_features.data ());
192- for (auto &v : mel_features) {
193- v = std::log (v + 1e-10f );
205+
206+ mel_banks_->Compute (magnitude_spectrum.data (), p);
207+
208+ for (int32_t j = 0 ; j < num_mels; ++j) {
209+ p[j] = std::log (p[j] + 1e-10f ) * feat_scale;
194210 }
195- // Instead of push_back a vector, push elements individually
196- prompt_features->insert (prompt_features->end (), mel_features.begin (),
197- mel_features.end ());
198- }
199- if (num_frames == 0 ) {
200- SHERPA_ONNX_LOGE (" No frames extracted from the prompt audio" );
201- return {0 , 0 };
202- } else {
203- return {num_frames, num_mels};
204211 }
205212 }
206213
@@ -214,12 +221,14 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
214221
215222 std::array<int64_t , 2 > tokens_shape = {1 ,
216223 static_cast <int64_t >(tokens.size ())};
224+
217225 Ort::Value tokens_tensor = Ort::Value::CreateTensor (
218226 memory_info, const_cast <int64_t *>(tokens.data ()), tokens.size (),
219227 tokens_shape.data (), tokens_shape.size ());
220228
221229 std::array<int64_t , 2 > prompt_tokens_shape = {
222230 1 , static_cast <int64_t >(prompt_tokens.size ())};
231+
223232 Ort::Value prompt_tokens_tensor = Ort::Value::CreateTensor (
224233 memory_info, const_cast <int64_t *>(prompt_tokens.data ()),
225234 prompt_tokens.size (), prompt_tokens_shape.data (),
@@ -230,31 +239,32 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
230239
231240 // Scale prompt_samples
232241 std::vector<float > prompt_samples_scaled = prompt_samples;
233- float prompt_rms = 0 .0f ;
242+ double prompt_rms = 0.0 ;
234243 double sum_sq = 0.0 ;
235244 // Compute RMS of prompt_samples
236245 for (float s : prompt_samples_scaled) {
237246 sum_sq += s * s;
238247 }
239248 prompt_rms = std::sqrt (sum_sq / prompt_samples_scaled.size ());
240249 if (prompt_rms < target_rms && prompt_rms > 0 .0f ) {
241- float scale = target_rms / static_cast < float >( prompt_rms) ;
250+ float scale = target_rms / prompt_rms;
242251 for (auto &s : prompt_samples_scaled) {
243252 s *= scale;
244253 }
245254 }
246255
247256 std::vector<float > prompt_features;
248- auto res_shape = ComputeMelSpectrogram (prompt_samples_scaled, sample_rate,
249- &prompt_features);
250257
251- int32_t num_frames = res_shape[0 ];
252- int32_t mel_dim = res_shape[1 ];
258+ int32_t mel_dim = model_->GetMetaData ().num_mels ;
253259
254- if (feat_scale != 1 .0f ) {
255- for (auto &item : prompt_features) {
256- item *= feat_scale;
257- }
260+ ComputeMelSpectrogram (prompt_samples_scaled, sample_rate, feat_scale,
261+ &prompt_features);
262+
263+ int32_t num_frames = prompt_features.size () / mel_dim;
264+
265+ if (num_frames == 0 ) {
266+ SHERPA_ONNX_LOGE (" No frames extracted from the prompt audio" );
267+ return {};
258268 }
259269
260270 std::array<int64_t , 3 > shape = {1 , num_frames, mel_dim};
@@ -268,16 +278,19 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
268278
269279 // Assume mel_shape = {1, T, C}
270280 std::vector<int64_t > mel_shape = mel.GetTensorTypeAndShapeInfo ().GetShape ();
271- int64_t T = mel_shape[1 ], C = mel_shape[2 ];
281+ int64_t T = mel_shape[1 ];
282+ int64_t C = mel_shape[2 ];
272283
273- float *mel_data = mel.GetTensorMutableData <float >();
284+ const float *mel_data = mel.GetTensorData <float >();
274285 std::vector<float > mel_permuted (C * T);
275286
287+ float inv_feat_scale = 1 / feat_scale;
288+
276289 for (int64_t c = 0 ; c < C; ++c) {
277290 for (int64_t t = 0 ; t < T; ++t) {
278291 int64_t src_idx = t * C + c; // src: [T, C] (row major)
279292 int64_t dst_idx = c * T + t; // dst: [C, T] (row major)
280- mel_permuted[dst_idx] = mel_data[src_idx] / feat_scale ;
293+ mel_permuted[dst_idx] = mel_data[src_idx] * inv_feat_scale ;
281294 }
282295 }
283296
@@ -304,6 +317,8 @@ class OfflineTtsZipvoiceImpl : public OfflineTtsImpl {
304317 std::unique_ptr<OfflineTtsZipvoiceModel> model_;
305318 std::unique_ptr<Vocoder> vocoder_;
306319 std::unique_ptr<OfflineTtsFrontend> frontend_;
320+
321+ std::unique_ptr<knf::MelBanks> mel_banks_;
307322};
308323
309324} // namespace sherpa_onnx
0 commit comments