@@ -83,6 +83,88 @@ class DecodableMatrixScaledMapped: public DecodableInterface {
8383 KALDI_DISALLOW_COPY_AND_ASSIGN (DecodableMatrixScaledMapped);
8484};
8585
86+ /* *
87+ This decodable class returns log-likes stored in a matrix; it supports
88+ repeatedly writing to the matrix and setting a time-offset representing the
89+ frame-index of the first row of the matrix. It's intended for use in
90+ multi-threaded decoding; mutex and semaphores are not included. External
91+ code will call SetLoglikes() each time more log-likelihods are available.
92+ If you try to access a log-likelihood that's no longer available because
93+ the frame index is less than the current offset, it is of course an error.
94+ */
95+ class DecodableMatrixMappedOffset : public DecodableInterface {
96+ public:
97+ DecodableMatrixMappedOffset (const TransitionModel &tm):
98+ trans_model_ (tm), frame_offset_(0 ), input_is_finished_(false ) { }
99+
100+
101+
102+ virtual int32 NumFramesReady () { return frame_offset_ + loglikes_.NumRows (); }
103+
104+ // this is not part of the generic Decodable interface.
105+ int32 FirstAvailableFrame () { return frame_offset_; }
106+
107+ // This function is destructive of the input "loglikes" because it may
108+ // under some circumstances do a shallow copy using Swap(). This function
109+ // appends loglikes to any existing likelihoods you've previously supplied.
110+ // frames_to_discard, if nonzero, will discard that number of previously
111+ // available frames, from the left, advancing FirstAvailableFrame() by
112+ // a number equal to frames_to_discard. You should only set frames_to_discard
113+ // to nonzero if you know your decoder won't want to access the loglikes
114+ // for older frames.
115+ void AcceptLoglikes (Matrix<BaseFloat> *loglikes,
116+ int32 frames_to_discard) {
117+ if (loglikes->NumRows () == 0 ) return ;
118+ KALDI_ASSERT (loglikes->NumCols () == trans_model_.NumPdfs ());
119+ KALDI_ASSERT (frames_to_discard <= loglikes_.NumRows () &&
120+ frames_to_discard >= 0 );
121+ if (frames_to_discard == loglikes_.NumRows ()) {
122+ loglikes_.Swap (loglikes);
123+ loglikes->Resize (0 , 0 );
124+ } else {
125+ int32 old_rows_kept = loglikes_.NumRows () - frames_to_discard,
126+ new_num_rows = old_rows_kept + loglikes->NumRows ();
127+ Matrix<BaseFloat> new_loglikes (new_num_rows, loglikes->NumCols ());
128+ new_loglikes.RowRange (0 , old_rows_kept).CopyFromMat (
129+ loglikes_.RowRange (frames_to_discard, old_rows_kept));
130+ new_loglikes.RowRange (old_rows_kept, loglikes->NumRows ()).CopyFromMat (
131+ *loglikes);
132+ loglikes_.Swap (&new_loglikes);
133+ }
134+ frame_offset_ += frames_to_discard;
135+ }
136+
137+ void InputIsFinished () { input_is_finished_ = true ; }
138+
139+ virtual int32 NumFramesReady () const {
140+ return loglikes_.NumRows () + frame_offset_;
141+ }
142+
143+ virtual bool IsLastFrame (int32 frame) const {
144+ KALDI_ASSERT (frame < NumFramesReady ());
145+ return (frame == NumFramesReady () - 1 && input_is_finished_);
146+ }
147+
148+ virtual BaseFloat LogLikelihood (int32 frame, int32 tid) {
149+ int32 index = frame - frame_offset_;
150+ KALDI_ASSERT (index >= 0 && index < loglikes_.NumRows ());
151+ return loglikes_ (index, trans_model_.TransitionIdToPdf (tid));
152+ }
153+
154+
155+
156+ virtual int32 NumIndices () const { return trans_model_.NumTransitionIds (); }
157+
158+ // nothing special to do in destructor.
159+ virtual ~DecodableMatrixMappedOffset () { }
160+ private:
161+ const TransitionModel &trans_model_; // for tid to pdf mapping
162+ Matrix<BaseFloat> loglikes_;
163+ int32 frame_offset_;
164+ bool input_is_finished_;
165+ KALDI_DISALLOW_COPY_AND_ASSIGN (DecodableMatrixMappedOffset);
166+ };
167+
86168
87169class DecodableMatrixScaled : public DecodableInterface {
88170 public:
0 commit comments