| 221 | mag * std::cos(phase), |
| 222 | mag * std::sin(phase), |
| 223 | }; |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | std::vector<float> framed(static_cast<size_t>(frames * config.n_fft), 0.0F); |
| 228 | engine::audio::real_fft_inverse( |
| 229 | {static_cast<size_t>(frames), static_cast<size_t>(config.n_fft)}, |
| 230 | { |
| 231 | static_cast<std::ptrdiff_t>(freq_bins * static_cast<int64_t>(sizeof(std::complex<float>))), |
| 232 | static_cast<std::ptrdiff_t>(sizeof(std::complex<float>)), |
| 233 | }, |
| 234 | { |
| 235 | static_cast<std::ptrdiff_t>(config.n_fft * static_cast<int64_t>(sizeof(float))), |
| 236 | static_cast<std::ptrdiff_t>(sizeof(float)), |
| 237 | }, |
| 238 | 1, |
| 239 | spectrum.data(), |
| 240 | framed.data(), |
| 241 | 1.0F / static_cast<float>(config.n_fft), |
| 242 | threads); |
| 243 | |
| 244 | const int64_t pad = (config.n_fft - config.hop_size) / 2; |
| 245 | const int64_t output_size = (frames - 1) * config.hop_size + config.n_fft; |
| 246 | std::vector<float> folded(static_cast<size_t>(output_size), 0.0F); |
| 247 | std::vector<float> envelope(static_cast<size_t>(output_size), 0.0F); |
| 248 | for (int64_t frame = 0; frame < frames; ++frame) { |
| 249 | const int64_t start = frame * config.hop_size; |
| 250 | const float * src = framed.data() + static_cast<size_t>(frame * config.n_fft); |
| 251 | for (int64_t i = 0; i < config.n_fft; ++i) { |
| 252 | const float w = window[static_cast<size_t>(i)]; |
| 253 | folded[static_cast<size_t>(start + i)] += src[i] * w; |
| 254 | envelope[static_cast<size_t>(start + i)] += w * w; |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | const int64_t samples = output_size - 2 * pad; |
| 259 | if (samples <= 0) { |
| 260 | throw std::runtime_error("Vevo2 vocoder ISTFT produced non-positive samples"); |
| 261 | } |
| 262 | std::vector<float> audio(static_cast<size_t>(samples), 0.0F); |
| 263 | for (int64_t i = 0; i < samples; ++i) { |
| 264 | const int64_t src = i + pad; |
| 265 | const float denom = envelope[static_cast<size_t>(src)]; |
| 266 | if (denom <= 1.0e-11F) { |
| 267 | throw std::runtime_error("Vevo2 vocoder ISTFT window envelope underflow"); |
| 268 | } |
| 269 | audio[static_cast<size_t>(i)] = folded[static_cast<size_t>(src)] / denom; |
| 270 | } |
| 271 | return audio; |
| 272 | } |
| 273 | |
| 274 | } // namespace |
| 275 | |
| 276 | struct Vevo2VocoderGraph { |
| 277 | Vevo2VocoderGraph( |
| 278 | ggml_backend_t backend, |
| 279 | engine::core::BackendType backend_type, |
| 280 | size_t graph_context_bytes, |
no test coverage detected