The purpose of executing the Viterbi algorithm is to get an
{\em alignment\/} between the states of the HMM that models an
utterance and the feature vectors generated by the signal processing
module. The programs that analyze alignment files in order to compute
new HMM network models or compute statistics need to be able to read
the alignment data.
\begin{haskell}{Alignments}
> module Alignments(
> FrameData, Alignment, readAlignment,
> strip_off_frame_number
> ) where
> import MaybeStateT
> import PlainTextIO
> import Phones
> import HmmDigraphs
> import Char(isSpace)--1.3
\end{haskell}
Formally, an {\em alignment\/}\index{alignment} is a sequence
of triples. The first element is the feature vector number, the
second element is the phonetic symbol (i.e., which HMM), and the third
component is the HMM state.
\begin{haskell}{Alignment}
> type FrameData = (Int, Phone, HmmState)
> type Alignment = [FrameData]
\end{haskell}
The function \verb~readAlignment~ reads alignment data from a
file. It is assumed that the file contains nothing but alignment
data.
\begin{haskell}{readAlignment}
> readAlignment :: [Char] -> Alignment
> readAlignment cs =
> let
> cs' = dropWhile isSpace cs
> in
> case readAlignmentFrame cs of
> Nothing -> if null cs'
> then []
> else error "unparsable chars"
> Just (f, cs'') -> f : readAlignment cs''
\end{haskell}
\begin{haskell}{readAlignmentFrame}
> readAlignmentFrame :: MST [Char] FrameData
> readAlignmentFrame = readsItem `thenMST` \ i ->
> readsItem `thenMST` \ p ->
> readsItem `thenMST` \ s ->
> returnMST (i, p, s)
\end{haskell}
\begin{haskell}{strip_off_frame_number}
> strip_off_frame_number :: [(a,b,c)] -> [(b,c)]
> strip_off_frame_number = map drop_frame_number
> drop_frame_number :: (a,b,c) -> (b,c)
> drop_frame_number (_,b,c) = (b,c)
\end{haskell}
|