| 1368 | } |
| 1369 | |
| 1370 | RnnoiseSequenceOutput RnnoiseModel::infer_features( |
| 1371 | const std::vector<float> & features, |
| 1372 | int64_t frames, |
| 1373 | int64_t feature_size) const { |
| 1374 | if (frames <= 0 || feature_size != config().feature_size || |
| 1375 | static_cast<int64_t>(features.size()) != frames * feature_size) { |
| 1376 | throw std::runtime_error("RNNoise feature sequence shape mismatch"); |
| 1377 | } |
| 1378 | |
| 1379 | const int64_t required_capacity = std::min<int64_t>(frames, kRnnoiseSequenceChunkFrames); |
| 1380 | if (!weights_->sequence_graph || !weights_->sequence_graph->supports(required_capacity)) { |
| 1381 | weights_->sequence_graph.reset(); |
| 1382 | weights_->sequence_graph = std::make_unique<RnnoiseSequenceGraph>(*weights_, required_capacity); |
| 1383 | } |
| 1384 | |
| 1385 | RnnoiseSequenceState state(config()); |
| 1386 | RnnoiseSequenceOutput output; |
| 1387 | output.frames = frames; |
| 1388 | output.gain_bands = config().gain_bands; |
| 1389 | output.gains.reserve(static_cast<size_t>(frames * config().gain_bands)); |
| 1390 | output.vad.reserve(static_cast<size_t>(frames)); |
| 1391 | int64_t offset = 0; |
| 1392 | while (offset < frames) { |
| 1393 | const int64_t chunk_frames = std::min<int64_t>(frames - offset, weights_->sequence_graph->capacity_frames()); |
| 1394 | const auto chunk = weights_->sequence_graph->run( |
| 1395 | features.data() + static_cast<std::ptrdiff_t>(offset * feature_size), |
| 1396 | chunk_frames, |
| 1397 | state); |
| 1398 | output.gains.insert(output.gains.end(), chunk.gains.begin(), chunk.gains.end()); |
| 1399 | output.vad.insert(output.vad.end(), chunk.vad.begin(), chunk.vad.end()); |
| 1400 | offset += chunk_frames; |
| 1401 | } |
| 1402 | return output; |
| 1403 | } |
| 1404 | |
| 1405 | RnnoiseWaveformOutput RnnoiseModel::process_mono_48k(const std::vector<float> & waveform) const { |
| 1406 | if (waveform.empty()) { |