void SimpleDecoder::ProcessEmitting(DecodableInterface *decodable) {
int32 frame = num_frames_decoded_;
// Processes emitting arcs for one frame. Propagates from
// prev_toks_ to cur_toks_.
// 处理一帧。从prev_toks_传递到cur_toks_
// 在调用本函数之前,cur_toks_.swap(prev_toks_)已完成了prev_toks_的填充
// 设置一个界限,用于剪掉分数过低的令牌
double cutoff = std::numeric_limits<BaseFloat>::infinity();
// 对prev_toks_即上一帧的全部带令牌的状态进行遍历
for (unordered_map<StateId, Token*>::iterator iter = prev_toks_.begin();
iter != prev_toks_.end();
++iter) {
StateId state = iter->first;
Token *tok = iter->second; //获取当前状态的令牌
KALDI_ASSERT(state == tok->arc_.nextstate);
// 遍历从当前状态出发的每一个跳转
for (fst::ArcIterator<fst::Fst<StdArc> > aiter(fst_, state);
!aiter.Done();
aiter.Next()){
const StdArc &arc = aiter.Value();
if (arc.ilabel != 0) { // propagate..只处理输出标签不为<eps>的情况
// 调用Decoderable的LogLikelihood()函数计算声学分
BaseFloat acoustic_cost = -decodable->LogLikelihood(frame, arc.ilabel);
// 代价=历史代价+图权重-声学分
double total_cost = tok->cost_ + arc.weight.Value() + acoustic_cost;
// 如果代价过大,则剪掉该路径
if (total_cost >= cutoff) continue;
// 更新界限值,使剪枝阈值在一个合理的范围内
if (total_cost + beam_ < cutoff)
cutoff = total_cost + beam_;
// 基于当前令牌,建立新令牌
Token *new_tok = new Token(arc, acoustic_cost, tok);
unordered_map<StateId, Token*>::iterator find_iter
= cur_toks_.find(arc.nextstate);
if (find_iter == cur_toks_.end()) {
// 下一个状态如果还没有令牌,那么将此令牌放到下一个状态上
cur_toks_[arc.nextstate] = new_tok;
} else {
if ( *(find_iter->second) < *new_tok ) {
// 如果下一个状态令牌不如新令牌代价小,则用新令牌替换下一个状态的令牌
Token::TokenDelete(find_iter->second);
find_iter->second = new_tok;
}
else {
// 如果下一个状态的令牌比新令牌代价小,则删除新令牌
Token::TokenDelete(new_tok);
}
}
}
}
}
num_frames_decoded_++;
}