| 337 | core::ModuleBuildContext & ctx, |
| 338 | const core::TensorValue & input, |
| 339 | const MelBandWeights & weights, |
| 340 | const RoformerArchitectureConfig & config) { |
| 341 | std::vector<core::TensorValue> outputs; |
| 342 | outputs.reserve(weights.band_split.size()); |
| 343 | int64_t offset = 0; |
| 344 | for (size_t band = 0; band < weights.band_split.size(); ++band) { |
| 345 | const int64_t dim_in = config.band_input_dims[band]; |
| 346 | auto band_input = modules::SliceModule({2, offset, dim_in}).build(ctx, input); |
| 347 | band_input = build_reference_rms_norm(ctx, band_input, dim_in, weights.band_split[band].norm); |
| 348 | band_input = modules::LinearModule(binding::linear_config(dim_in, config.dim, true)) |
| 349 | .build(ctx, band_input, binding::linear_data(ctx, weights.band_split[band].proj.weight, weights.band_split[band].proj.bias)); |
| 350 | band_input = core::reshape_tensor( |
| 351 | ctx, |
| 352 | ensure_contiguous(ctx, band_input), |
| 353 | core::TensorShape::from_dims({input.shape.dims[0], input.shape.dims[1], 1, config.dim})); |
| 354 | outputs.push_back(band_input); |
| 355 | offset += dim_in; |
| 356 | } |
| 357 | |
| 358 | while (outputs.size() > 1) { |
| 359 | std::vector<core::TensorValue> next; |
| 360 | next.reserve((outputs.size() + 1) / 2); |
| 361 | for (size_t i = 0; i < outputs.size(); i += 2) { |
| 362 | if (i + 1 < outputs.size()) { |
| 363 | next.push_back(modules::ConcatModule({2}).build(ctx, outputs[i], outputs[i + 1])); |
| 364 | } else { |
| 365 | next.push_back(outputs[i]); |
| 366 | } |
| 367 | } |
| 368 | outputs = std::move(next); |
| 369 | } |
| 370 | return outputs.front(); |
| 371 | } |
| 372 | |
| 373 | core::TensorValue build_mask_output( |
| 374 | core::ModuleBuildContext & ctx, |
| 375 | const core::TensorValue & input, |
| 376 | const MelBandWeights & weights, |
| 377 | const RoformerArchitectureConfig & config) { |
no test coverage detected