// -*- C++ -*- #ifndef _VITERBI_HPP_ #define _VITERBI_HPP_ #include #include #include #include #include // soft-decision viterbi decoder // based on Phil Karn's libfec template class viterbi { public: enum { M = 1<<(K-1) }; typedef std::vector vec_type; typedef std::array arr_type; viterbi(std::array const& polys) // ={0x6d,0x4f} : _decisions() // len<<(K-1)) , _metric() , _bits() , _prev() , _last_max_metric(0) { make_tables(polys); } void reset() { std::fill_n(_metric.begin(), _metric.size(), 0); _last_max_metric = 0; } void resize(size_t len) { _decisions.resize(len<<(K-1)); } void update(int j, std::arrayconst& sym) { int s[N]; for (int l=0; l (1<<15)) { _last_max_metric -= imin; for (int i=0; i& v) { return chainback(v.begin(), v.end()); } float chainback(std::vector::iterator begin, std::vector::iterator end) { assert(std::distance(begin, end) == ssize_t((_decisions.size()>>(K-1)))); auto const imax = std::max_element(_metric.begin(), _metric.end()); int idx_max = std::distance(_metric.begin(), imax); for (int k=_decisions.size()>>(K-1); k!=0; --k) { begin[k-1] = idx_max&1; //idx_max = _prev[idx_max][decision(k-1)[idx_max]]; idx_max = (idx_max>>1) + (decision(k-1)[idx_max] != 0)*M/2; } int const max_metric = *imax; float const quality = float(max_metric - _last_max_metric)/255.0; _last_max_metric = max_metric; return quality; } protected: vec_type::iterator decision(int i) { return _decisions.begin() + (i<<(K-1)); } void make_tables(std::array const& polys) { for (int i=0, n=1< const b(polys[l]&i); _bits[i>>1][i%2][l] = 255*(b.count()%2); } } for (int i=0; i>1); _prev[i][1] = _prev[i][0] + M/2; } } private: vec_type _decisions; arr_type _metric; int _bits[M][2][N]; int _prev[M][2]; int _last_max_metric; } ; #endif // _VITERBI2_HPP_