void rateMatchFunc(BitVector &in,BitVector &out, int eini) { int nin = in.size(); int nout = out.size(); if (nout == nin) { in.copyTo(out); return; } int eplus = 2 * nin; // eplus = a * Ni,j int eminus = 2 * (nout - nin); // eminus = a * abs(deltaNi,j) if (eminus < 0) { eminus = - eminus; } float e = eini; int m; // index of current bit, except zero-based as opposed to spec that is 1 based. char *inp = in.begin(); // cheating just a bit for efficiency. char *outp = out.begin(); char *outend = out.end(); if (nout < nin) { // Puncture bits as necessary. // Note from spec: loop termination Xi == Xij == number of bits before rate matching == nin. for (m=0; m < nin && outp < outend; m++) { e = e - eminus; if (e <= 0) { e = e + eplus; continue; // skip the bit. } *outp++ = inp[m]; } } else { // Repeat bits as necessary. for (m=0; m < nin && outp < outend; m++) { e = e - eminus; while (e <= 0) { if (outp >= outend) goto failed; *outp++ = inp[m]; // repeat the bit. e = e + eplus; } *outp++ = inp[m]; } } if (m != nin || outp != outend) { failed: LOG(ERR) << "rate matching mis-calculation, results:" <<LOGVAR(nin)<<LOGVAR(m)<<LOGVAR(nout)<<LOGVAR2(outp,outp-out.begin()) <<LOGVAR(e)<<LOGVAR(eplus)<<LOGVAR(eminus)<<LOGVAR(eini); } }
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; i<sz; i++) { accum = (accum<<1) | bits.bit(i); history[i] = accum; } // Repeat last bit at the end. for (size_t i=sz; i<ctsz; i++) { accum = (accum<<1) | (accum & 0x01); history[i] = accum; } } // Precompute metric tables. float matchCostTable[ctsz]; float mismatchCostTable[ctsz]; { const float *dp = in.begin(); for (size_t i=0; i<sz; i++) { // pVal is the probability that a bit is correct. // ipVal is the probability that a bit is incorrect. float pVal = dp[i]; if (pVal>0.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<ctsz; i++) { matchCostTable[i] = 0.5F; mismatchCostTable[i] = 0.5F; } } { decoder.initializeStates(); // Each sample of history[] carries its history. // So we only have to process every iRate-th sample. const unsigned step = decoder.iRate(); // input pointer const uint32_t *ip = history + step - 1; // output pointers char *op = target.begin(); const char *const opt = target.end(); // table pointers const float* match = matchCostTable; const float* mismatch = mismatchCostTable; size_t oCount = 0; while (op<opt) { // Viterbi algorithm assert(match-matchCostTable<(int)(sizeof(matchCostTable)/sizeof(matchCostTable[0])-1)); assert(mismatch-mismatchCostTable<(int)(sizeof(mismatchCostTable)/sizeof(mismatchCostTable[0])-1)); const ViterbiTCH_AFS7_4::vCand &minCost = decoder.step(*ip, match, mismatch); ip += step; match += step; mismatch += step; // output if (oCount>=deferral) *op++ = (minCost.iState >> deferral)&0x01; oCount++; } } }