FORCE_INLINE int __ext_viterbi_brick_init_fast(int32 frame_len, int16 code_r, int16 depth) { ob_count = 0; m_viterbi.Reset(); frame_length = frame_len; code_rate = code_r; if (m_outbuf != NULL) free((void *)m_outbuf); TRELLIS_DEPTH = (size_t) depth; m_outbuf = (unsigned char*) malloc((size_t) (TRELLIS_DEPTH + 1)); if (m_outbuf == NULL) { printf("Viterbi memory allocation failure!\n"); exit(1); } return 0; }
FORCE_INLINE int16 __ext_viterbi_brick_decode_fast(num8 * intInput, int len1, unsigned char* bit, int len2) { static const int trellis_prefix = 6; // 6 bit zero prefix static const int trellis_lookahead = 24; //uchar m_outbuf[TRELLIS_DEPTH / 8 + 1]; unsigned int total_byte_count = 0; // vector128 constants #if defined(__GNUC__) && !defined(__ARM_NEON__) static const __m128i * const pVITMA = VIT_MA; // Branch Metric A static const __m128i * const pVITMB = VIT_MB; // Branch Metric B #else static const vub * const pVITMA = (const vub*)VIT_MA; // Branch Metric A static const vub * const pVITMB = (const vub*)VIT_MB; // Branch Metric B #endif //uchar* input = ipin.peek(); unsigned char* input = (unsigned char*)intInput; //uchar* input_end = input + NUM_INPUT; unsigned char* input_end = input + len1; while (input < input_end) { // advance branch if (code_rate == CR_12) { m_viterbi.BranchACS(pVITMA, input[0], pVITMB, input[1]); input += 2; // jump to data } else if (code_rate == CR_34) { m_viterbi.BranchACS(pVITMA, input[0], pVITMB, input[1]); m_viterbi.BranchACS(pVITMA, input[2]); m_viterbi.BranchACS(pVITMB, input[3]); input += 4; } else if (code_rate == CR_23) { m_viterbi.BranchACS(pVITMA, input[0], pVITMB, input[1]); m_viterbi.BranchACS(pVITMA, input[2]); input += 3; } unsigned int tr_index = m_viterbi.trellis_index(); if ((tr_index & 7) == 0) { m_viterbi.Normalize(); } // check trace_back unsigned int output_count = 0; unsigned int lookahead = 0; const unsigned int tr_index_end = frame_length * 8 + trellis_prefix; if (tr_index >= tr_index_end) { // all bytes have been processed - track back all of them output_count = tr_index_end - ob_count - trellis_prefix; lookahead = tr_index - tr_index_end; } else if (tr_index >= ob_count + TRELLIS_DEPTH + trellis_lookahead + trellis_prefix) { // trace back partially // Note: tr_index increase during 'BranchACS', to decode out complete bytes, we may lookahead the // trellis without output a few more than 'trellis_lookahead' unsigned int remain = (tr_index - (ob_count + TRELLIS_DEPTH + trellis_lookahead + trellis_prefix)) % 8; output_count = TRELLIS_DEPTH; lookahead = trellis_lookahead + remain; } if (output_count) { m_viterbi.Traceback((num8 *)m_outbuf, output_count, lookahead); ob_count += output_count; unsigned int last_byte_count = 0; while (last_byte_count < output_count / 8) { bit[total_byte_count] = m_outbuf[last_byte_count]; last_byte_count++; total_byte_count++; } } } return total_byte_count * 8; }
int16 __ext_viterbi_brick_decode_fast(char* intInput, int len1, uchar* bit, int len2) { static const int trellis_prefix = 6; // 6 bit zero prefix static const int trellis_lookahead = 24; //uchar m_outbuf[TRELLIS_DEPTH / 8 + 1]; uint ii = 0; // vector128 constants static const vub * const pVITMA = (const vub*)VIT_MA; // Branch Metric A static const vub * const pVITMB = (const vub*)VIT_MB; // Branch Metric B //uchar* input = ipin.peek(); uchar* input = (uchar*)intInput; //uchar* input_end = input + NUM_INPUT; uchar* input_end = input + len1; while (input < input_end) { // advance branch if (code_rate == CR_12) { m_viterbi.BranchACS(pVITMA, input[0], pVITMB, input[1]); input += 2; // jump to data } else if (code_rate == CR_34) { m_viterbi.BranchACS(pVITMA, input[0], pVITMB, input[1]); m_viterbi.BranchACS(pVITMA, input[2]); m_viterbi.BranchACS(pVITMB, input[3]); input += 4; } else if (code_rate == CR_23) { m_viterbi.BranchACS(pVITMA, input[0], pVITMB, input[1]); m_viterbi.BranchACS(pVITMA, input[2]); input += 3; } uint tr_index = m_viterbi.trellis_index(); if ((tr_index & 7) == 0) { m_viterbi.Normalize(); } // check trace_back uint output_count = 0; uint lookahead = 0; const uint tr_index_end = frame_length * 8 + 16 + trellis_prefix; if (tr_index >= tr_index_end) { // all bytes have been processed - track back all of them output_count = tr_index_end - ob_count - trellis_prefix; lookahead = tr_index - tr_index_end; } else if (tr_index >= ob_count + TRELLIS_DEPTH + trellis_lookahead + trellis_prefix) { // trace back partially // Note: tr_index increase during 'BranchACS', to decode out complete bytes, we may lookahead the // trellis without output a few more than 'trellis_lookahead' uint remain = (tr_index - (ob_count + TRELLIS_DEPTH + trellis_lookahead + trellis_prefix)) % 8; output_count = TRELLIS_DEPTH; lookahead = trellis_lookahead + remain; } if (output_count) { m_viterbi.Traceback((char*)m_outbuf, output_count, lookahead); ob_count += output_count; //output_count >>= 3; while (ii < output_count) { //uchar* po = opin().append(); //*po = m_outbuf[ii++]; uchar po = m_outbuf[ii]; bit[ii] = po; ii++; //printf ("%d (%x) \n", *po, *po ); //Next()->Process(opin0()); } //printf ( "\n" ); } } //ipin.pop(); return ii; }