/* * Copyright 2013, 2014 Range Networks, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. */ #include "BitVector.h" #include "AmrCoder.h" #include #include #include using namespace std; ViterbiTCH_AFS12_2::ViterbiTCH_AFS12_2() { assert(mDeferral < 32); mCoeffs[0] = 0x019; mCoeffsFB[0] = 0x019; mCoeffs[1] = 0x01b; mCoeffsFB[1] = 0x019; for (unsigned i = 0; i < mIRate; i++) { computeStateTables(i); } computeGeneratorTable(); } //void BitVector::encode(const ViterbiTCH_AFS12_2& coder, BitVector& target) const void ViterbiTCH_AFS12_2::encode(const BitVector& in, BitVector& target) const { assert(in.size() == 250); assert(target.size() == 508); const char *u = in.begin(); char *C = target.begin(); const unsigned H = 4; BitVector r(254+H); for (int k = -H; k <= -1; k++) r[k+H] = 0; for (unsigned k = 0; k <= 249; k++) { r[k+H] = u[k] ^ r[k-3+H] ^ r[k-4+H]; C[2*k] = u[k]; C[2*k+1] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; } // termination for (unsigned k = 250; k <= 253; k++) { r[k+H] = 0; C[2*k] = r[k-3+H] ^ r[k-4+H]; C[2*k+1] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; } } //void BitVector::encode(const ViterbiTCH_AFS10_2& coder, BitVector& target) void ViterbiTCH_AFS10_2::encode(const BitVector& in, BitVector& target) const { assert(in.size() == 210); assert(target.size() == 642); const char *u = in.begin(); char *C = target.begin(); const unsigned H = 4; BitVector r(214+H); for (int k = -H; k <= -1; k++) r[k+H] = 0; for (unsigned k = 0; k <= 209; k++) { r[k+H] = u[k] ^ r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; C[3*k] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[3*k+1] = r[k+H] ^ r[k-2+H] ^ r[k-4+H]; C[3*k+2] = u[k]; } // termination for (unsigned k = 210; k <= 213; k++) { r[k+H] = 0; C[3*k] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[3*k+1] = r[k+H] ^ r[k-2+H] ^ r[k-4+H]; C[3*k+2] = r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; } } //void BitVector::encode(const ViterbiTCH_AFS7_95& coder, BitVector& target) void ViterbiTCH_AFS7_95::encode(const BitVector& in, BitVector& target) const { assert(in.size() == 165); assert(target.size() == 513); const char *u = in.begin(); char *C = target.begin(); const unsigned H = 6; BitVector r(171+H); for (int k = -H; k <= -1; k++) r[k+H] = 0; for (unsigned k = 0; k <= 164; k++) { r[k+H] = u[k] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-5+H] ^ r[k-6+H]; C[3*k] = u[k]; C[3*k+1] = r[k+H] ^ r[k-1+H] ^ r[k-4+H] ^ r[k-6+H]; C[3*k+2] = r[k+H] ^ r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H] ^ r[k-6+H]; } // termination for (unsigned k = 165; k <= 170; k++) { r[k+H] = 0; C[3*k] = r[k-2+H] ^ r[k-3+H] ^ r[k-5+H] ^ r[k-6+H]; C[3*k+1] = r[k+H] ^ r[k-1+H] ^ r[k-4+H] ^ r[k-6+H]; C[3*k+2] = r[k+H] ^ r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H] ^ r[k-6+H]; } } void ViterbiTCH_AFS7_4::encode(const BitVector& in, BitVector& target) const { assert(in.size() == 154); assert(target.size() == 474); const char *u = in.begin(); char *C = target.begin(); const unsigned H = 4; BitVector r(158+H); for (int k = -H; k <= -1; k++) r[k+H] = 0; for (unsigned k = 0; k <= 153; k++) { r[k+H] = u[k] ^ r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; C[3*k] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[3*k+1] = r[k+H] ^ r[k-2+H] ^ r[k-4+H]; C[3*k+2] = u[k]; } // termination for (unsigned k = 154; k <= 157; k++) { r[k+H] = 0; C[3*k] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[3*k+1] = r[k+H] ^ r[k-2+H] ^ r[k-4+H]; C[3*k+2] = r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; } } void ViterbiTCH_AFS6_7::encode(const BitVector& in, BitVector& target) const { assert(in.size() == 140); assert(target.size() == 576); const char *u = in.begin(); char *C = target.begin(); const unsigned H = 4; BitVector r(144+H); for (int k = -H; k <= -1; k++) r[k+H] = 0; for (unsigned k = 0; k <= 139; k++) { r[k+H] = u[k] ^ r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; C[4*k] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[4*k+1] = r[k+H] ^ r[k-2+H] ^ r[k-4+H]; C[4*k+2] = u[k]; C[4*k+3] = u[k]; } // termination for (unsigned k = 140; k <= 143; k++) { r[k+H] = 0; C[4*k] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[4*k+1] = r[k+H] ^ r[k-2+H] ^ r[k-4+H]; C[4*k+2] = r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; C[4*k+3] = r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; } } void ViterbiTCH_AFS5_9::encode(const BitVector& in, BitVector& target) const { assert(in.size() == 124); assert(target.size() == 520); const char *u = in.begin(); char *C = target.begin(); const unsigned H = 6; BitVector r(130+H); for (int k = -H; k <= -1; k++) r[k+H] = 0; for (unsigned k = 0; k <= 123; k++) { r[k+H] = u[k] ^ r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H] ^ r[k-6+H]; C[4*k] = r[k+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-5+H] ^ r[k-6+H]; C[4*k+1] = r[k+H] ^ r[k-1+H] ^ r[k-4+H] ^ r[k-6+H]; C[4*k+2] = u[k]; C[4*k+3] = u[k]; } // termination for (unsigned k = 124; k <= 129; k++) { r[k+H] = 0; C[4*k] = r[k+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-5+H] ^ r[k-6+H]; C[4*k+1] = r[k+H] ^ r[k-1+H] ^ r[k-4+H] ^ r[k-6+H]; C[4*k+2] = r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H] ^ r[k-6+H]; C[4*k+3] = r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H] ^ r[k-6+H]; } } void ViterbiTCH_AFS5_15::encode(const BitVector& in, BitVector& target) const { assert(in.size() == 109); assert(target.size() == 565); const char *u = in.begin(); char *C = target.begin(); const unsigned H = 4; BitVector r(113+H); for (int k = -H; k <= -1; k++) r[k+H] = 0; for (unsigned k = 0; k <= 108; k++) { r[k+H] = u[k] ^ r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; C[5*k] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[5*k+1] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[5*k+2] = r[k+H] ^ r[k-2+H] ^ r[k-4+H]; C[5*k+3] = u[k]; C[5*k+4] = u[k]; } // termination for (unsigned k = 109; k <= 112; k++) { r[k+H] = 0; C[5*k] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[5*k+1] = r[k+H] ^ r[k-1+H] ^ r[k-3+H] ^ r[k-4+H]; C[5*k+2] = r[k+H] ^ r[k-2+H] ^ r[k-4+H]; C[5*k+3] = r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; C[5*k+4] = r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H]; } } void ViterbiTCH_AFS4_75::encode(const BitVector& in, BitVector& target) const { assert(in.size() == 101); assert(target.size() == 535); const char *u = in.begin(); char *C = target.begin(); const unsigned H = 6; BitVector r(107+H); for (int k = -H; k <= -1; k++) r[k+H] = 0; for (unsigned k = 0; k <= 100; k++) { r[k+H] = u[k] ^ r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H] ^ r[k-6+H]; C[5*k] = r[k+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-5+H] ^ r[k-6+H]; C[5*k+1] = r[k+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-5+H] ^ r[k-6+H]; C[5*k+2] = r[k+H] ^ r[k-1+H] ^ r[k-4+H] ^ r[k-6+H]; C[5*k+3] = u[k]; C[5*k+4] = u[k]; } // termination for (unsigned k = 101; k <= 106; k++) { r[k+H] = 0; C[5*k] = r[k+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-5+H] ^ r[k-6+H]; C[5*k+1] = r[k+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-5+H] ^ r[k-6+H]; C[5*k+2] = r[k+H] ^ r[k-1+H] ^ r[k-4+H] ^ r[k-6+H]; C[5*k+3] = r[k+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H] ^ r[k-6+H]; C[5*k+4] = r[k-1+H] ^ r[k-2+H] ^ r[k-3+H] ^ r[k-4+H] ^ r[k-6+H]; } } void ViterbiTCH_AFS12_2::initializeStates() { for (unsigned i=0; ioState) << mIRate; for (unsigned in = 0; in <= 1; in++) { mCandidates[cand+in].iState = ((sp->iState) << 1) | in; mCandidates[cand+in].cost = sp->cost; uint32_t outputs = oStateShifted; for (unsigned out = 0; out < mIRate; out++) { char feedback = applyPoly(sp->rState[out], mCoeffsFB[out] ^ 1, mOrder+1); char rState = (((sp->rState[out]) ^ feedback) << 1) | in; mCandidates[cand+in].rState[out] = rState; outputs |= (mGeneratorTable[rState & mCMask] & (1 << (mIRate - out - 1))); } mCandidates[cand+in].oState = outputs; } sp++; } } void ViterbiTCH_AFS12_2::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) { const float *cTab[2] = {matchCost,mismatchCost}; for (unsigned i=0; i>i)&0x01][mIRate-i-1]; } } } void ViterbiTCH_AFS12_2::pruneCandidates() { const vCand* c1 = mCandidates; // 0-prefix const vCand* c2 = mCandidates + mIStates; // 1-prefix for (unsigned i=0; i=minCost) continue; minCost = thisCost; minIndex=i; } return mSurvivors[minIndex]; } const ViterbiTCH_AFS12_2::vCand& ViterbiTCH_AFS12_2::step(uint32_t inSample, const float *probs, const float *iprobs) { branchCandidates(); getSoftCostMetrics(inSample,probs,iprobs); pruneCandidates(); return minCost(); } void ViterbiTCH_AFS12_2::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS12_2 &decoder = *this; const size_t sz = in.size() - 8; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } } ViterbiTCH_AFS10_2::ViterbiTCH_AFS10_2() { assert(mDeferral < 32); mCoeffs[0] = 0x01b; mCoeffsFB[0] = 0x01f; mCoeffs[1] = 0x015; mCoeffsFB[1] = 0x01f; mCoeffs[2] = 0x01f; mCoeffsFB[2] = 0x01f; for (unsigned i = 0; i < mIRate; i++) { computeStateTables(i); } computeGeneratorTable(); } void ViterbiTCH_AFS10_2::initializeStates() { for (unsigned i=0; ioState) << mIRate; for (unsigned in = 0; in <= 1; in++) { mCandidates[cand+in].iState = ((sp->iState) << 1) | in; mCandidates[cand+in].cost = sp->cost; uint32_t outputs = oStateShifted; for (unsigned out = 0; out < mIRate; out++) { char feedback = applyPoly(sp->rState[out], mCoeffsFB[out] ^ 1, mOrder+1); char rState = (((sp->rState[out]) ^ feedback) << 1) | in; mCandidates[cand+in].rState[out] = rState; outputs |= (mGeneratorTable[rState & mCMask] & (1 << (mIRate - out - 1))); } mCandidates[cand+in].oState = outputs; } sp++; } } void ViterbiTCH_AFS10_2::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) { const float *cTab[2] = {matchCost,mismatchCost}; for (unsigned i=0; i>i)&0x01][mIRate-i-1]; } } } void ViterbiTCH_AFS10_2::pruneCandidates() { const vCand* c1 = mCandidates; // 0-prefix const vCand* c2 = mCandidates + mIStates; // 1-prefix for (unsigned i=0; i=minCost) continue; minCost = thisCost; minIndex=i; } return mSurvivors[minIndex]; } const ViterbiTCH_AFS10_2::vCand& ViterbiTCH_AFS10_2::step(uint32_t inSample, const float *probs, const float *iprobs) { branchCandidates(); getSoftCostMetrics(inSample,probs,iprobs); pruneCandidates(); return minCost(); } void ViterbiTCH_AFS10_2::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS10_2 &decoder = *this; const size_t sz = in.size() - 12; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } } ViterbiTCH_AFS7_95::ViterbiTCH_AFS7_95() { assert(mDeferral < 32); mCoeffs[0] = 0x06d; mCoeffsFB[0] = 0x06d; mCoeffs[1] = 0x053; mCoeffsFB[1] = 0x06d; mCoeffs[2] = 0x05f; mCoeffsFB[2] = 0x06d; for (unsigned i = 0; i < mIRate; i++) { computeStateTables(i); } computeGeneratorTable(); } void ViterbiTCH_AFS7_95::initializeStates() { for (unsigned i=0; ioState) << mIRate; for (unsigned in = 0; in <= 1; in++) { mCandidates[cand+in].iState = ((sp->iState) << 1) | in; mCandidates[cand+in].cost = sp->cost; uint32_t outputs = oStateShifted; for (unsigned out = 0; out < mIRate; out++) { char feedback = applyPoly(sp->rState[out], mCoeffsFB[out] ^ 1, mOrder+1); char rState = (((sp->rState[out]) ^ feedback) << 1) | in; mCandidates[cand+in].rState[out] = rState; outputs |= (mGeneratorTable[rState & mCMask] & (1 << (mIRate - out - 1))); } mCandidates[cand+in].oState = outputs; } sp++; } } void ViterbiTCH_AFS7_95::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) { const float *cTab[2] = {matchCost,mismatchCost}; for (unsigned i=0; i>i)&0x01][mIRate-i-1]; } } } void ViterbiTCH_AFS7_95::pruneCandidates() { const vCand* c1 = mCandidates; // 0-prefix const vCand* c2 = mCandidates + mIStates; // 1-prefix for (unsigned i=0; i=minCost) continue; minCost = thisCost; minIndex=i; } return mSurvivors[minIndex]; } const ViterbiTCH_AFS7_95::vCand& ViterbiTCH_AFS7_95::step(uint32_t inSample, const float *probs, const float *iprobs) { branchCandidates(); getSoftCostMetrics(inSample,probs,iprobs); pruneCandidates(); return minCost(); } void ViterbiTCH_AFS7_95::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS7_95 &decoder = *this; const size_t sz = in.size() - 18; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } } ViterbiTCH_AFS7_4::ViterbiTCH_AFS7_4() { assert(mDeferral < 32); mCoeffs[0] = 0x01b; mCoeffsFB[0] = 0x01f; mCoeffs[1] = 0x015; mCoeffsFB[1] = 0x01f; mCoeffs[2] = 0x01f; mCoeffsFB[2] = 0x01f; for (unsigned i = 0; i < mIRate; i++) { computeStateTables(i); } computeGeneratorTable(); } void ViterbiTCH_AFS7_4::initializeStates() { for (unsigned i=0; ioState) << mIRate; for (unsigned in = 0; in <= 1; in++) { mCandidates[cand+in].iState = ((sp->iState) << 1) | in; mCandidates[cand+in].cost = sp->cost; uint32_t outputs = oStateShifted; for (unsigned out = 0; out < mIRate; out++) { char feedback = applyPoly(sp->rState[out], mCoeffsFB[out] ^ 1, mOrder+1); char rState = (((sp->rState[out]) ^ feedback) << 1) | in; mCandidates[cand+in].rState[out] = rState; outputs |= (mGeneratorTable[rState & mCMask] & (1 << (mIRate - out - 1))); } mCandidates[cand+in].oState = outputs; } sp++; } } void ViterbiTCH_AFS7_4::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) { const float *cTab[2] = {matchCost,mismatchCost}; for (unsigned i=0; i>i)&0x01][mIRate-i-1]; } } } void ViterbiTCH_AFS7_4::pruneCandidates() { const vCand* c1 = mCandidates; // 0-prefix const vCand* c2 = mCandidates + mIStates; // 1-prefix for (unsigned i=0; i=minCost) continue; minCost = thisCost; minIndex=i; } return mSurvivors[minIndex]; } const ViterbiTCH_AFS7_4::vCand& ViterbiTCH_AFS7_4::step(uint32_t inSample, const float *probs, const float *iprobs) { branchCandidates(); getSoftCostMetrics(inSample,probs,iprobs); pruneCandidates(); return minCost(); } void ViterbiTCH_AFS7_4::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS7_4 &decoder = *this; const size_t sz = in.size() - 12; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } } ViterbiTCH_AFS6_7::ViterbiTCH_AFS6_7() { assert(mDeferral < 32); mCoeffs[0] = 0x01b; mCoeffsFB[0] = 0x01f; mCoeffs[1] = 0x015; mCoeffsFB[1] = 0x01f; mCoeffs[2] = 0x01f; mCoeffsFB[2] = 0x01f; mCoeffs[3] = 0x01f; mCoeffsFB[3] = 0x01f; for (unsigned i = 0; i < mIRate; i++) { computeStateTables(i); } computeGeneratorTable(); } void ViterbiTCH_AFS6_7::initializeStates() { for (unsigned i=0; ioState) << mIRate; for (unsigned in = 0; in <= 1; in++) { mCandidates[cand+in].iState = ((sp->iState) << 1) | in; mCandidates[cand+in].cost = sp->cost; uint32_t outputs = oStateShifted; for (unsigned out = 0; out < mIRate; out++) { char feedback = applyPoly(sp->rState[out], mCoeffsFB[out] ^ 1, mOrder+1); char rState = (((sp->rState[out]) ^ feedback) << 1) | in; mCandidates[cand+in].rState[out] = rState; outputs |= (mGeneratorTable[rState & mCMask] & (1 << (mIRate - out - 1))); } mCandidates[cand+in].oState = outputs; } sp++; } } void ViterbiTCH_AFS6_7::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) { const float *cTab[2] = {matchCost,mismatchCost}; for (unsigned i=0; i>i)&0x01][mIRate-i-1]; } } } void ViterbiTCH_AFS6_7::pruneCandidates() { const vCand* c1 = mCandidates; // 0-prefix const vCand* c2 = mCandidates + mIStates; // 1-prefix for (unsigned i=0; i=minCost) continue; minCost = thisCost; minIndex=i; } return mSurvivors[minIndex]; } const ViterbiTCH_AFS6_7::vCand& ViterbiTCH_AFS6_7::step(uint32_t inSample, const float *probs, const float *iprobs) { branchCandidates(); getSoftCostMetrics(inSample,probs,iprobs); pruneCandidates(); return minCost(); } void ViterbiTCH_AFS6_7::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS6_7 &decoder = *this; const size_t sz = in.size() - 16; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } } ViterbiTCH_AFS5_9::ViterbiTCH_AFS5_9() { assert(mDeferral < 32); mCoeffs[0] = 0x06d; mCoeffsFB[0] = 0x05f; mCoeffs[1] = 0x053; mCoeffsFB[1] = 0x05f; mCoeffs[2] = 0x05f; mCoeffsFB[2] = 0x05f; mCoeffs[3] = 0x05f; mCoeffsFB[3] = 0x05f; for (unsigned i = 0; i < mIRate; i++) { computeStateTables(i); } computeGeneratorTable(); } void ViterbiTCH_AFS5_9::initializeStates() { for (unsigned i=0; ioState) << mIRate; for (unsigned in = 0; in <= 1; in++) { mCandidates[cand+in].iState = ((sp->iState) << 1) | in; mCandidates[cand+in].cost = sp->cost; uint32_t outputs = oStateShifted; for (unsigned out = 0; out < mIRate; out++) { char feedback = applyPoly(sp->rState[out], mCoeffsFB[out] ^ 1, mOrder+1); char rState = (((sp->rState[out]) ^ feedback) << 1) | in; mCandidates[cand+in].rState[out] = rState; outputs |= (mGeneratorTable[rState & mCMask] & (1 << (mIRate - out - 1))); } mCandidates[cand+in].oState = outputs; } sp++; } } void ViterbiTCH_AFS5_9::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) { const float *cTab[2] = {matchCost,mismatchCost}; for (unsigned i=0; i>i)&0x01][mIRate-i-1]; } } } void ViterbiTCH_AFS5_9::pruneCandidates() { const vCand* c1 = mCandidates; // 0-prefix const vCand* c2 = mCandidates + mIStates; // 1-prefix for (unsigned i=0; i=minCost) continue; minCost = thisCost; minIndex=i; } return mSurvivors[minIndex]; } const ViterbiTCH_AFS5_9::vCand& ViterbiTCH_AFS5_9::step(uint32_t inSample, const float *probs, const float *iprobs) { branchCandidates(); getSoftCostMetrics(inSample,probs,iprobs); pruneCandidates(); return minCost(); } void ViterbiTCH_AFS5_9::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS5_9 &decoder = *this; const size_t sz = in.size() - 24; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } } ViterbiTCH_AFS5_15::ViterbiTCH_AFS5_15() { assert(mDeferral < 32); mCoeffs[0] = 0x01b; mCoeffsFB[0] = 0x01f; mCoeffs[1] = 0x01b; mCoeffsFB[1] = 0x01f; mCoeffs[2] = 0x015; mCoeffsFB[2] = 0x01f; mCoeffs[3] = 0x01f; mCoeffsFB[3] = 0x01f; mCoeffs[4] = 0x01f; mCoeffsFB[4] = 0x01f; for (unsigned i = 0; i < mIRate; i++) { computeStateTables(i); } computeGeneratorTable(); } void ViterbiTCH_AFS5_15::initializeStates() { for (unsigned i=0; ioState) << mIRate; for (unsigned in = 0; in <= 1; in++) { mCandidates[cand+in].iState = ((sp->iState) << 1) | in; mCandidates[cand+in].cost = sp->cost; uint32_t outputs = oStateShifted; for (unsigned out = 0; out < mIRate; out++) { char feedback = applyPoly(sp->rState[out], mCoeffsFB[out] ^ 1, mOrder+1); char rState = (((sp->rState[out]) ^ feedback) << 1) | in; mCandidates[cand+in].rState[out] = rState; outputs |= (mGeneratorTable[rState & mCMask] & (1 << (mIRate - out - 1))); } mCandidates[cand+in].oState = outputs; } sp++; } } void ViterbiTCH_AFS5_15::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) { const float *cTab[2] = {matchCost,mismatchCost}; for (unsigned i=0; i>i)&0x01][mIRate-i-1]; } } } void ViterbiTCH_AFS5_15::pruneCandidates() { const vCand* c1 = mCandidates; // 0-prefix const vCand* c2 = mCandidates + mIStates; // 1-prefix for (unsigned i=0; i=minCost) continue; minCost = thisCost; minIndex=i; } return mSurvivors[minIndex]; } const ViterbiTCH_AFS5_15::vCand& ViterbiTCH_AFS5_15::step(uint32_t inSample, const float *probs, const float *iprobs) { branchCandidates(); getSoftCostMetrics(inSample,probs,iprobs); pruneCandidates(); return minCost(); } void ViterbiTCH_AFS5_15::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS5_15 &decoder = *this; const size_t sz = in.size() - 20; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } } ViterbiTCH_AFS4_75::ViterbiTCH_AFS4_75() { assert(mDeferral < 32); mCoeffs[0] = 0x06d; mCoeffsFB[0] = 0x05f; mCoeffs[1] = 0x06d; mCoeffsFB[1] = 0x05f; mCoeffs[2] = 0x053; mCoeffsFB[2] = 0x05f; mCoeffs[3] = 0x05f; mCoeffsFB[3] = 0x05f; mCoeffs[4] = 0x05f; mCoeffsFB[4] = 0x05f; for (unsigned i = 0; i < mIRate; i++) { computeStateTables(i); } computeGeneratorTable(); } void ViterbiTCH_AFS4_75::initializeStates() { for (unsigned i=0; ioState) << mIRate; for (unsigned in = 0; in <= 1; in++) { mCandidates[cand+in].iState = ((sp->iState) << 1) | in; mCandidates[cand+in].cost = sp->cost; uint32_t outputs = oStateShifted; for (unsigned out = 0; out < mIRate; out++) { char feedback = applyPoly(sp->rState[out], mCoeffsFB[out] ^ 1, mOrder+1); char rState = (((sp->rState[out]) ^ feedback) << 1) | in; mCandidates[cand+in].rState[out] = rState; outputs |= (mGeneratorTable[rState & mCMask] & (1 << (mIRate - out - 1))); } mCandidates[cand+in].oState = outputs; } sp++; } } void ViterbiTCH_AFS4_75::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost) { const float *cTab[2] = {matchCost,mismatchCost}; for (unsigned i=0; i>i)&0x01][mIRate-i-1]; } } } void ViterbiTCH_AFS4_75::pruneCandidates() { const vCand* c1 = mCandidates; // 0-prefix const vCand* c2 = mCandidates + mIStates; // 1-prefix for (unsigned i=0; i=minCost) continue; minCost = thisCost; minIndex=i; } return mSurvivors[minIndex]; } const ViterbiTCH_AFS4_75::vCand& ViterbiTCH_AFS4_75::step(uint32_t inSample, const float *probs, const float *iprobs) { branchCandidates(); getSoftCostMetrics(inSample,probs,iprobs); pruneCandidates(); return minCost(); } void ViterbiTCH_AFS4_75::decode(const SoftVector &in, BitVector& target) { ViterbiTCH_AFS4_75 &decoder = *this; const size_t sz = in.size() - 30; const unsigned deferral = decoder.deferral(); const size_t ctsz = sz + deferral*decoder.iRate(); assert(sz == decoder.iRate()*target.size()); // Build a "history" array where each element contains the full history. uint32_t history[ctsz]; { BitVector bits = in.sliced(); uint32_t accum = 0; for (size_t i=0; i0.5F) pVal = 1.0F-pVal; float ipVal = 1.0F-pVal; // This is a cheap approximation to an ideal cost function. if (pVal<0.01F) pVal = 0.01; if (ipVal<0.01F) ipVal = 0.01; matchCostTable[i] = 0.25F/ipVal; mismatchCostTable[i] = 0.25F/pVal; } // pad end of table with unknowns for (size_t i=sz; i=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } }