diff --git a/backend/cpp/audio-cpp/generation_request.cpp b/backend/cpp/audio-cpp/generation_request.cpp index f09d14284..515cd691a 100644 --- a/backend/cpp/audio-cpp/generation_request.cpp +++ b/backend/cpp/audio-cpp/generation_request.cpp @@ -232,9 +232,12 @@ build_sound_generation_request(const backend::SoundGenerationRequest &request, task.options["think"] = bool_option(request.think()); } if (request.has_caption()) { - // Read only by irodori_tts, which advertises Tts/VoiceCloning/VoiceDesign - // and not AudioGeneration, so it is unreachable from this RPC: DEAD here. task.options["caption"] = request.caption(); + // YuE2 calls the musical caption "style". Preserve explicit options, + // including an empty style, while accepting Studio's caption field. + if (!request.caption().empty()) { + task.options.emplace("style", request.caption()); + } } if (request.has_lyrics()) { // Read by ace_step and heartmula. diff --git a/backend/cpp/audio-cpp/generation_request_ctest.cpp b/backend/cpp/audio-cpp/generation_request_ctest.cpp index 32c905090..3f342209e 100644 --- a/backend/cpp/audio-cpp/generation_request_ctest.cpp +++ b/backend/cpp/audio-cpp/generation_request_ctest.cpp @@ -426,6 +426,42 @@ static void test_sound_generation_minimal() { check(!task.voice.has_value(), "sound: no voice condition"); } +static void test_sound_generation_caption_style() { + backend::SoundGenerationRequest request; + request.set_caption("slow acoustic folk"); + request.set_lyrics("first line\nsecond line"); + + auto task = build_sound_generation_request(request, std::nullopt); + check(option_or(task.options, "style", "") == "slow acoustic folk", + "sound: caption supplies the default YuE2 style"); + check(option_or(task.options, "caption", "") == "slow acoustic folk", + "sound: caption remains available under its own name"); + check(option_or(task.options, "lyrics", "") == "first line\nsecond line", + "sound: style fallback preserves lyrics"); + check(request.params().empty(), "sound: style fallback does not mutate params"); + + (*request.mutable_params())["style"] = "fast jazz"; + task = build_sound_generation_request(request, std::nullopt); + check(option_or(task.options, "style", "") == "fast jazz", + "sound: explicit style overrides caption"); + + (*request.mutable_params())["style"] = ""; + task = build_sound_generation_request(request, std::nullopt); + check(has_key(task.options, "style") && task.options.at("style").empty(), + "sound: explicit empty style overrides caption"); + + request.mutable_params()->clear(); + request.set_caption(""); + task = build_sound_generation_request(request, std::nullopt); + check(!has_key(task.options, "style"), "sound: empty caption supplies no style"); + + request.clear_caption(); + (*request.mutable_params())["style"] = "instrumental jazz"; + task = build_sound_generation_request(request, std::nullopt); + check(option_or(task.options, "style", "") == "instrumental jazz", + "sound: explicit style works without a caption"); +} + static void test_sound_generation_full() { backend::SoundGenerationRequest request; request.set_text("a slow blues in E"); @@ -616,6 +652,7 @@ int main() { test_tts_language_and_params(); test_tts_reference_transcript(); test_sound_generation_minimal(); + test_sound_generation_caption_style(); test_sound_generation_full(); test_transform_text_absent(); test_transform_text_canonical_key(); diff --git a/docs/content/features/text-to-audio.md b/docs/content/features/text-to-audio.md index c8109ba57..4b7140600 100644 --- a/docs/content/features/text-to-audio.md +++ b/docs/content/features/text-to-audio.md @@ -421,6 +421,11 @@ Use `params` to pass backend-specific string options that do not have fixed requ fields. Every value in `params` must be a string. Existing fixed fields remain authoritative when a fixed field and `params` contain the same option. +The `audio-cpp` backend uses a nonempty `caption` as the default `style` option. +An explicit `params.style` takes precedence, including an empty string. In +Studio → Sound, select Advanced mode and enter the musical style in Caption +and the song text in Lyrics to use YuE2. + Install the YuE2 gallery model and generate a song: ```bash