#pragma once
#include "transcribe.h"
#include "weights.h"
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
struct ggml_context;
struct ggml_tensor;
struct ggml_cgraph;
namespace transcribe {
class MelFrontend;
}
namespace transcribe::granite5_ctc {
int encoder_frames_for(const Granite5CtcHParams & hp, int64_t n_samples);
transcribe_status compute_encoder_input(const transcribe::MelFrontend & mel,
const Granite5CtcHParams & hp,
const float * pcm,
int64_t n_samples,
int n_threads,
std::vector<float> & out_feats,
int & out_t_enc);
std::vector<int32_t> precompute_pos_rows(int context_size, int max_pos_emb);
std::vector<float> precompute_pad_mask(int context_size, int t_len, const std::vector<int> & real_lens);
std::vector<float> precompute_frame_mask(int t_len, const std::vector<int> & real_lens);
struct AttnStage {
int t_len = 0; int n_blocks = 0; ggml_tensor * pad_mask = nullptr; ggml_tensor * zero_pad = nullptr; ggml_tensor * frame_mask = nullptr;
};
struct EncoderBuild {
ggml_tensor * feats_in = nullptr; ggml_tensor * pos_rows = nullptr;
std::vector<AttnStage> stages; std::vector<int32_t> block_stage;
ggml_tensor * out = nullptr; ggml_tensor * ctc_logits = nullptr;
ggml_cgraph * graph = nullptr;
int t_out = 0;
int n_batch = 1;
std::vector<int> real_lens_out;
std::vector<std::pair<std::string, ggml_tensor *>> dump_list;
};
EncoderBuild build_encoder_graph(ggml_context * ctx,
const Granite5CtcWeights & weights,
const Granite5CtcHParams & hp,
int T_enc,
const std::vector<int> & real_lens = {});
}