| 42 | } // namespace |
| 43 | |
| 44 | int main(int argc, char ** argv) { |
| 45 | if (argc < 2) { |
| 46 | std::cerr << "usage: ace_step_memory_validate <model_dir> [cpu|cuda|vulkan|best] [threads] " |
| 47 | "[--decode-latents-file path --output-wav path]\n"; |
| 48 | return 2; |
| 49 | } |
| 50 | |
| 51 | const std::filesystem::path model_dir = argv[1]; |
| 52 | const std::string backend_name = argc >= 3 ? argv[2] : "cuda"; |
| 53 | const int threads = argc >= 4 ? std::max(1, std::atoi(argv[3])) : 1; |
| 54 | const std::string decode_latents_file = arg_value(argc, argv, "--decode-latents-file"); |
| 55 | const std::string output_wav = arg_value(argc, argv, "--output-wav"); |
| 56 | |
| 57 | engine::core::BackendType backend_type = engine::core::BackendType::Cuda; |
| 58 | if (backend_name == "cpu") { |
| 59 | backend_type = engine::core::BackendType::Cpu; |
| 60 | } else if (backend_name == "vulkan") { |
| 61 | backend_type = engine::core::BackendType::Vulkan; |
| 62 | } else if (backend_name == "best") { |
| 63 | backend_type = engine::core::BackendType::BestAvailable; |
| 64 | } else if (backend_name != "cuda") { |
| 65 | throw std::runtime_error("backend must be cpu, cuda, vulkan, or best"); |
| 66 | } |
| 67 | |
| 68 | if (!decode_latents_file.empty()) { |
| 69 | if (output_wav.empty()) { |
| 70 | throw std::runtime_error("--output-wav is required with --decode-latents-file"); |
| 71 | } |
| 72 | auto assets = engine::models::ace_step::load_ace_step_assets(model_dir); |
| 73 | engine::core::BackendConfig backend_config; |
| 74 | backend_config.type = backend_type; |
| 75 | backend_config.threads = threads; |
| 76 | engine::core::ExecutionContext execution(backend_config); |
| 77 | engine::models::ace_step::AceStepVAEDecoderRuntime vae( |
| 78 | assets, |
| 79 | execution, |
| 80 | engine::assets::TensorStorageType::F32); |
| 81 | const auto values = engine::io::read_f32_file(decode_latents_file); |
| 82 | const int64_t channels = assets->config.vae.decoder_input_channels; |
| 83 | if (channels <= 0 || values.size() % static_cast<size_t>(channels) != 0) { |
| 84 | throw std::runtime_error("invalid ACE-Step latent file shape for VAE decode"); |
| 85 | } |
| 86 | engine::models::ace_step::AceStepLatents latents; |
| 87 | latents.channels = channels; |
| 88 | latents.frames = static_cast<int64_t>(values.size() / static_cast<size_t>(channels)); |
| 89 | latents.values = values; |
| 90 | const auto audio = vae.decode(latents); |
| 91 | engine::audio::write_pcm16_wav(output_wav, audio.sample_rate, audio.channels, audio.samples); |
| 92 | std::cout << "decode.samples=" << audio.samples.size() << "\n"; |
| 93 | return 0; |
| 94 | } |
| 95 | |
| 96 | engine::runtime::TaskSpec task{engine::runtime::VoiceTaskKind::Tts, engine::runtime::RunMode::Offline}; |
| 97 | auto registry = engine::runtime::make_default_registry(); |
| 98 | engine::runtime::ModelLoadRequest load_request; |
| 99 | load_request.model_path = model_dir; |
| 100 | load_request.family_hint = "ace_step"; |
| 101 | auto model = registry.load(load_request); |
nothing calls this directly
no test coverage detected