@@ -409,15 +409,12 @@ namespace srt::svs {
409409 std::string (param.tag .name ()) +
410410 " resample failed" , {}, " acoustic" );
411411 }
412- // Create f0 tensor for acoustic model
413- auto expForAcoustic = ds::infer::inferutil::TensorHelper<float >::createFor1DArray (targetLength);
414- if (!expForAcoustic) {
415- Log.srtCritical (" %1 start: failed to create f0 tensor: %2" ,
416- kLogPrefix , expForAcoustic.error ().message ());
417- return expForAcoustic.takeError ();
418- }
419- auto &acousticHelper = expForAcoustic.value ();
420-
412+ // tone_shift (音区偏移) applies to the f0 that drives the acoustic
413+ // model only. The original (un-shifted) f0 is returned through
414+ // AcousticResult::f0 so callers can drive the vocoder / variance
415+ // stage with a pitch independent from the register-shifted one;
416+ // reusing the shifted f0 there double-transposes the output.
417+ auto acousticSamples = samples;
421418 if (pToneShiftParam) {
422419 const auto &toneShift = *pToneShiftParam;
423420 if (!toneShift.values .empty ()) {
@@ -430,35 +427,60 @@ namespace srt::svs {
430427 }
431428 if (convertToF0) {
432429 for (size_t i = 0 ; i < targetLength; ++i) {
433- samples [i] += toneShiftSamples[i] / 100.0 ;
430+ acousticSamples [i] += toneShiftSamples[i] / 100.0 ;
434431 }
435432 } else {
436433 for (size_t i = 0 ; i < targetLength; ++i) {
437- samples [i] *= std::exp2 (toneShiftSamples[i] / 1200.0 );
434+ acousticSamples [i] *= std::exp2 (toneShiftSamples[i] / 1200.0 );
438435 }
439436 }
440437 }
441438 }
442- if (convertToF0) {
443- // Convert midi note to hz
444- for (const auto midi_note : std::as_const (samples)) {
445- constexpr double a4_freq_hz = 440.0 ;
446- constexpr double midi_a4_note = 69.0 ;
447- const auto f0Acoustic =
448- a4_freq_hz * std::exp2 ((midi_note - midi_a4_note) / 12.0 );
449- // Buffer guaranteed not to overflow,
450- // given (resampled.size() == targetLength), which has been checked before
451- acousticHelper.writeUnchecked (static_cast <float >(f0Acoustic));
452- }
453- } else {
454- for (const auto sample : std::as_const (samples)) {
455- // Buffer guaranteed not to overflow,
456- // given (resampled.size() == targetLength), which has been checked before
457- acousticHelper.writeUnchecked (static_cast <float >(sample));
439+
440+ // Convert midi note to hz
441+ const auto toHz = [](double note) -> float {
442+ constexpr double a4_freq_hz = 440.0 ;
443+ constexpr double midi_a4_note = 69.0 ;
444+ return static_cast <float >(a4_freq_hz * std::exp2 ((note - midi_a4_note) / 12.0 ));
445+ };
446+ const auto fillF0 = [&](ds::infer::inferutil::TensorHelper<float > &helper,
447+ const std::vector<double > &value) {
448+ if (convertToF0) {
449+ for (const auto item : std::as_const (value)) {
450+ // Buffer guaranteed not to overflow,
451+ // given samples.size() == targetLength, checked above
452+ helper.writeUnchecked (toHz (item));
453+ }
454+ } else {
455+ for (const auto item : std::as_const (value)) {
456+ // Buffer guaranteed not to overflow,
457+ // given samples.size() == targetLength, checked above
458+ helper.writeUnchecked (static_cast <float >(item));
459+ }
458460 }
461+ };
462+
463+ // f0 tensor for the acoustic model (tone-shifted)
464+ auto expForAcoustic = ds::infer::inferutil::TensorHelper<float >::createFor1DArray (targetLength);
465+ if (!expForAcoustic) {
466+ Log.srtCritical (" %1 start: failed to create f0 tensor: %2" ,
467+ kLogPrefix , expForAcoustic.error ().message ());
468+ return expForAcoustic.takeError ();
459469 }
460- f0TensorForVocoder = acousticHelper.take ();
461- sessionInput->inputs [" f0" ] = f0TensorForVocoder; // ref count +1
470+ auto &acousticHelper = expForAcoustic.value ();
471+ fillF0 (acousticHelper, acousticSamples);
472+ sessionInput->inputs [" f0" ] = acousticHelper.take (); // ref count +1
473+
474+ // f0 tensor for the vocoder (original, un-shifted)
475+ auto expForVocoder = ds::infer::inferutil::TensorHelper<float >::createFor1DArray (targetLength);
476+ if (!expForVocoder) {
477+ Log.srtCritical (" %1 start: failed to create vocoder f0 tensor: %2" ,
478+ kLogPrefix , expForVocoder.error ().message ());
479+ return expForVocoder.takeError ();
480+ }
481+ auto &vocoderHelper = expForVocoder.value ();
482+ fillF0 (vocoderHelper, samples);
483+ f0TensorForVocoder = vocoderHelper.take ();
462484 return srt::core::Expected<void >();
463485 };
464486
0 commit comments