kaldi(3) SimpleDecoder:ProcessEmitting

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_++;
}
 

 

posted @ 2021-09-11 13:31  智人心  阅读(139)  评论(0)    收藏  举报