mirror of
https://github.com/n5ac/mmvari.git
synced 2025-12-06 04:12:03 +01:00
548 lines
16 KiB
C++
548 lines
16 KiB
C++
|
|
//Copyright+LGPL
|
|||
|
|
|
|||
|
|
//-----------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba
|
|||
|
|
//-----------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
// This file is part of MMVARI.
|
|||
|
|
|
|||
|
|
// MMVARI is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
|
|||
|
|
// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|||
|
|
|
|||
|
|
// MMVARI 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 Lesser General Public License for more details.
|
|||
|
|
|
|||
|
|
// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see
|
|||
|
|
// <http://www.gnu.org/licenses/>.
|
|||
|
|
//-----------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*=============================================================================
|
|||
|
|
MFSK16<EFBFBD>̎<EFBFBD><EFBFBD><EFBFBD> 2004/JUL/28<EFBFBD>ɍ쐬<EFBFBD>J<EFBFBD>n by Mako JE3HHT
|
|||
|
|
=============================================================================*/
|
|||
|
|
#include <vcl.h>
|
|||
|
|
#pragma hdrstop
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <math.h>
|
|||
|
|
#include <limits.h>
|
|||
|
|
|
|||
|
|
#include "mfsk.h"
|
|||
|
|
#include "dsp.h"
|
|||
|
|
|
|||
|
|
#if DEBUG && 0 // InterLeaver<65>̃f<CC83>o<EFBFBD>b<EFBFBD>O
|
|||
|
|
#define TEST_BITS 5 // MFSK8 = 5, MFSK16 = 4, MFSK31 = 3
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
int IVTest(void)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
CInterLeaver IVE, IVD;
|
|||
|
|
|
|||
|
|
BYTE syms[256];
|
|||
|
|
|
|||
|
|
LPCSTR p = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"
|
|||
|
|
"--------------------------------------------------------------"
|
|||
|
|
"--------------------------------------------------------------"
|
|||
|
|
"--------------------------------------------------------------";
|
|||
|
|
FILE *fp = fopen("TEST.TXT", "wt");
|
|||
|
|
|
|||
|
|
int i;
|
|||
|
|
IVE.Init(TEST_BITS);
|
|||
|
|
IVD.Init(TEST_BITS);
|
|||
|
|
int stage = 1;
|
|||
|
|
while(*p){
|
|||
|
|
LPCSTR pp = p;
|
|||
|
|
fprintf(fp, "%2u ", stage++);
|
|||
|
|
for( i = 0; i < TEST_BITS; i++ ){
|
|||
|
|
fprintf(fp, "%c", *pp);
|
|||
|
|
if( *pp ) pp++;
|
|||
|
|
}
|
|||
|
|
fprintf(fp, "\t");
|
|||
|
|
for( i = 0; i < TEST_BITS; i++ ){
|
|||
|
|
if( *p ){
|
|||
|
|
syms[i] = *p++;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
syms[i] = '-';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
IVE.EncodeSyms(syms);
|
|||
|
|
for( i = 0; i < TEST_BITS; i++ ){
|
|||
|
|
fprintf(fp, "%c", syms[i] ? syms[i] : ' ');
|
|||
|
|
}
|
|||
|
|
IVD.DecodeSyms(syms);
|
|||
|
|
fprintf(fp, "\t");
|
|||
|
|
for( i = 0; i < TEST_BITS; i++ ){
|
|||
|
|
fprintf(fp, "%c", syms[i] ? syms[i] : ' ');
|
|||
|
|
}
|
|||
|
|
fprintf(fp, "\n");
|
|||
|
|
}
|
|||
|
|
fclose(fp);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
int n = IVTest();
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
|
|||
|
|
#if DEBUG && 0 // g_tGray2Bin[], g_tBin2Gray, g_tParityOdd<64>̐<EFBFBD><CC90><EFBFBD>
|
|||
|
|
/*=============================================================================
|
|||
|
|
g_tGray2Bin[], g_tBin2Gray, g_tParity
|
|||
|
|
=============================================================================*/
|
|||
|
|
//---------------------------------------------------------------------------
|
|||
|
|
static int __fastcall GetParity(UINT c)
|
|||
|
|
{
|
|||
|
|
int i, n;
|
|||
|
|
for( i = n = 0; i < 32; i++, c = c >> 1 ){
|
|||
|
|
if( c & 1 ) n++;
|
|||
|
|
}
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
static int CreateTable(void)
|
|||
|
|
{
|
|||
|
|
int tbl[32];
|
|||
|
|
int i;
|
|||
|
|
|
|||
|
|
FILE *fp = fopen("test.txt", "wt");
|
|||
|
|
fprintf(fp, "const BYTE g_tBin2Gray[]={\t//Decode");
|
|||
|
|
for( i = 0; i < MFSK_MAXTONES; i++ ){
|
|||
|
|
tbl[i] = (i >> 1) ^ i; // <20>O<EFBFBD><4F><EFBFBD>[<5B>R<EFBFBD>[<5B>h<EFBFBD>ɕϊ<C995>
|
|||
|
|
if( !(i % 8) ) fprintf(fp, "\n\t");
|
|||
|
|
fprintf(fp, "0x%02X,", tbl[i]);
|
|||
|
|
}
|
|||
|
|
fprintf(fp, "\n};\nconst BYTE g_tGray2Bin[]={\t//Encode");
|
|||
|
|
for( i = 0; i < MFSK_MAXTONES; i++ ){
|
|||
|
|
if( !(i % 8) ) fprintf(fp, "\n\t");
|
|||
|
|
for( int j = 0; j < 32; j++ ){
|
|||
|
|
if( i == tbl[j] ) fprintf(fp, "0x%02X,", j);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
fprintf(fp, "\n};\n");
|
|||
|
|
// <20>p<EFBFBD><70><EFBFBD>e<EFBFBD>B<EFBFBD>e<EFBFBD>[<5B>u<EFBFBD><75><EFBFBD><EFBFBD><EFBFBD>쐬
|
|||
|
|
fprintf(fp, "const BYTE g_tParityOdd[]={\t//Odd parity");
|
|||
|
|
for( i = 0; i < 256; i++ ){
|
|||
|
|
if( !(i % 32) ) fprintf(fp, "\n\t");
|
|||
|
|
fprintf(fp, "%d,", GetParity(i) & 1);
|
|||
|
|
}
|
|||
|
|
fprintf(fp, "\n};\n");
|
|||
|
|
fclose(fp);
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
int n = CreateTable();
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
const BYTE g_tBin2Gray[]={ //Decode
|
|||
|
|
0x00,0x01,0x03,0x02,0x06,0x07,0x05,0x04,
|
|||
|
|
0x0C,0x0D,0x0F,0x0E,0x0A,0x0B,0x09,0x08,
|
|||
|
|
0x18,0x19,0x1B,0x1A,0x1E,0x1F,0x1D,0x1C,
|
|||
|
|
0x14,0x15,0x17,0x16,0x12,0x13,0x11,0x10,
|
|||
|
|
};
|
|||
|
|
const BYTE g_tGray2Bin[]={ //Encode
|
|||
|
|
0x00,0x01,0x03,0x02,0x07,0x06,0x04,0x05,
|
|||
|
|
0x0F,0x0E,0x0C,0x0D,0x08,0x09,0x0B,0x0A,
|
|||
|
|
0x1F,0x1E,0x1C,0x1D,0x18,0x19,0x1B,0x1A,
|
|||
|
|
0x10,0x11,0x13,0x12,0x17,0x16,0x14,0x15,
|
|||
|
|
};
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*=============================================================================
|
|||
|
|
MFSK type <EFBFBD>w<EFBFBD><EFBFBD><EFBFBD>p<EFBFBD><EFBFBD>
|
|||
|
|
=============================================================================*/
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
int __fastcall MFSK_Speed2Type(double speed)
|
|||
|
|
{
|
|||
|
|
if( speed < 5.0 ){
|
|||
|
|
return typMFSK4;
|
|||
|
|
}
|
|||
|
|
else if( speed < 10.0 ){
|
|||
|
|
return typMFSK8;
|
|||
|
|
}
|
|||
|
|
else if( speed < 13.0 ){
|
|||
|
|
return typMFSK11;
|
|||
|
|
}
|
|||
|
|
else if( speed < 20.0 ){
|
|||
|
|
return typMFSK16;
|
|||
|
|
}
|
|||
|
|
else if( speed < 28.0 ){
|
|||
|
|
return typMFSK22;
|
|||
|
|
}
|
|||
|
|
else if( speed < 32.0 ){
|
|||
|
|
return typMFSK31;
|
|||
|
|
}
|
|||
|
|
else if( speed < 50.0 ){
|
|||
|
|
return typMFSK32;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return typMFSK64;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
void __fastcall MFSK_SetPara(int type, int *pTones, double *pSpeed, int *pBits)
|
|||
|
|
{
|
|||
|
|
switch(type){
|
|||
|
|
case typMFSK16:
|
|||
|
|
if( pTones ) *pTones = 16;
|
|||
|
|
if( pSpeed ) *pSpeed = 15.625;
|
|||
|
|
if( pBits ) *pBits = 4;
|
|||
|
|
break;
|
|||
|
|
case typMFSK8:
|
|||
|
|
if( pTones ) *pTones = 32;
|
|||
|
|
if( pSpeed ) *pSpeed = 7.8125;
|
|||
|
|
if( pBits ) *pBits = 5;
|
|||
|
|
break;
|
|||
|
|
case typMFSK31:
|
|||
|
|
if( pTones ) *pTones = 8;
|
|||
|
|
if( pSpeed ) *pSpeed = 31.25;
|
|||
|
|
if( pBits ) *pBits = 3;
|
|||
|
|
break;
|
|||
|
|
case typMFSK11:
|
|||
|
|
if( pTones ) *pTones = 16;
|
|||
|
|
if( pSpeed ) *pSpeed = 11025.0/1024.0;
|
|||
|
|
if( pBits ) *pBits = 4;
|
|||
|
|
break;
|
|||
|
|
case typMFSK22:
|
|||
|
|
if( pTones ) *pTones = 16;
|
|||
|
|
if( pSpeed ) *pSpeed = 11025.0/512.0;
|
|||
|
|
if( pBits ) *pBits = 4;
|
|||
|
|
break;
|
|||
|
|
case typMFSK32:
|
|||
|
|
if( pTones ) *pTones = 16;
|
|||
|
|
if( pSpeed ) *pSpeed = 31.25;
|
|||
|
|
if( pBits ) *pBits = 4;
|
|||
|
|
break;
|
|||
|
|
case typMFSK64:
|
|||
|
|
if( pTones ) *pTones = 16;
|
|||
|
|
if( pSpeed ) *pSpeed = 62.5;
|
|||
|
|
if( pBits ) *pBits = 4;
|
|||
|
|
break;
|
|||
|
|
case typMFSK4:
|
|||
|
|
if( pTones ) *pTones = 32;
|
|||
|
|
if( pSpeed ) *pSpeed = 3.90625;
|
|||
|
|
if( pBits ) *pBits = 5;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/*=============================================================================
|
|||
|
|
CViterbiEncode<EFBFBD>N<EFBFBD><EFBFBD><EFBFBD>X
|
|||
|
|
=============================================================================*/
|
|||
|
|
const BYTE g_tParityOdd[]={ //Odd parity
|
|||
|
|
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
|
|||
|
|
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
|
|||
|
|
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
|
|||
|
|
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
|
|||
|
|
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
|
|||
|
|
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
|
|||
|
|
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
|
|||
|
|
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
|
|||
|
|
};
|
|||
|
|
#define POLY2(d,p1,p2) ((g_tParityOdd[d&p1]<<1)|g_tParityOdd[d&p2])
|
|||
|
|
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
__fastcall CViterbiEncode::CViterbiEncode(void)
|
|||
|
|
{
|
|||
|
|
Init(MFSK_VITERBI_K, MFSK_VITERBI_POLY1, MFSK_VITERBI_POLY2);
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
void __fastcall CViterbiEncode::Init(int k, int poly1, int poly2)
|
|||
|
|
{
|
|||
|
|
m_K = k;
|
|||
|
|
m_Poly1 = poly1; m_Poly2 = poly2;
|
|||
|
|
Reset();
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
// b1 = 1st, b0 = 2nd
|
|||
|
|
BYTE __fastcall CViterbiEncode::Do(BOOL bit)
|
|||
|
|
{
|
|||
|
|
m_EncData = m_EncData << 1;
|
|||
|
|
if( bit ) m_EncData |= 1;
|
|||
|
|
return BYTE(POLY2(m_EncData, m_Poly1, m_Poly2));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*=============================================================================
|
|||
|
|
CViterbi<EFBFBD>N<EFBFBD><EFBFBD><EFBFBD>X
|
|||
|
|
=============================================================================*/
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
__fastcall CViterbi::CViterbi(void)
|
|||
|
|
{
|
|||
|
|
m_BlockSize = 1;
|
|||
|
|
m_TraceBack = 45;
|
|||
|
|
m_States = 0;
|
|||
|
|
|
|||
|
|
m_pPoly = NULL;
|
|||
|
|
|
|||
|
|
memset(m_pMetrics, 0, sizeof(m_pMetrics));
|
|||
|
|
memset(m_pHistory, 0, sizeof(m_pHistory));
|
|||
|
|
memset(m_tSeq, 0, sizeof(m_tSeq));
|
|||
|
|
memset(m_tMetrics, 0, sizeof(m_tMetrics));
|
|||
|
|
|
|||
|
|
m_CurPtr = NULL;
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
void __fastcall CViterbi::Free(void)
|
|||
|
|
{
|
|||
|
|
if( m_pPoly ){
|
|||
|
|
delete m_pPoly; m_pPoly = NULL;
|
|||
|
|
}
|
|||
|
|
for( int i = 0; i < VITERBI_PATHMAX; i++ ){
|
|||
|
|
delete m_pMetrics[i]; m_pMetrics[i] = NULL;
|
|||
|
|
delete m_pHistory[i]; m_pHistory[i] = NULL;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
void __fastcall CViterbi::Init(int k, int poly1, int poly2)
|
|||
|
|
{
|
|||
|
|
int i;
|
|||
|
|
|
|||
|
|
if( m_pPoly ){
|
|||
|
|
#if DEBUG
|
|||
|
|
Application->MainForm->Caption = "Init duplication in CViterbi";
|
|||
|
|
#endif
|
|||
|
|
Free();
|
|||
|
|
}
|
|||
|
|
int size = _tBitData[k] * 2;
|
|||
|
|
#if DEBUG
|
|||
|
|
if( size > 256 ){
|
|||
|
|
Application->MainForm->Caption = "Over size in CViterbi";
|
|||
|
|
size = 256;
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
m_States = size / 2;
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̂<EFBFBD><CC82>߂ɓW<C993>J<EFBFBD>f<EFBFBD>[<5B>^<5E><><EFBFBD><EFBFBD><EFBFBD>炩<EFBFBD><E782A9><EFBFBD>ߍ쐬<DF8D><EC90AC><EFBFBD>Ă<EFBFBD><C482><EFBFBD>
|
|||
|
|
m_pPoly = new int[size];
|
|||
|
|
for( i = 0; i < size; i++ ){
|
|||
|
|
m_pPoly[i] = POLY2(i, poly1, poly2);
|
|||
|
|
}
|
|||
|
|
for( i = 0; i < VITERBI_PATHMAX; i++ ){
|
|||
|
|
m_pMetrics[i] = new int[m_States];
|
|||
|
|
m_pHistory[i] = new int[m_States];
|
|||
|
|
}
|
|||
|
|
for( i = 0; i < 256; i++ ){ // s = 0 to 255
|
|||
|
|
m_tMetrics[0][i] = 128 - i; // 128 to -127
|
|||
|
|
m_tMetrics[1][i] = i - 128; // -128 to 127
|
|||
|
|
}
|
|||
|
|
m_CurPtr = 0;
|
|||
|
|
Reset();
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
BOOL __fastcall CViterbi::SetTraceBack(int traceback)
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
if( (traceback < 0) || (traceback > (VITERBI_PATHMAX - 1)) ) return FALSE;
|
|||
|
|
m_TraceBack = traceback;
|
|||
|
|
return TRUE;
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
BOOL __fastcall CViterbi::SetBlockSize(int blocksize)
|
|||
|
|
{
|
|||
|
|
if( (blocksize < 1) || (blocksize > m_TraceBack) ) return FALSE;
|
|||
|
|
m_BlockSize = blocksize;
|
|||
|
|
return TRUE;
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
void __fastcall CViterbi::Reset(void)
|
|||
|
|
{
|
|||
|
|
if( !m_pMetrics[0] ) return;
|
|||
|
|
|
|||
|
|
memset(m_tSeq, 0, sizeof(m_tSeq));
|
|||
|
|
int i;
|
|||
|
|
for( i = 0; i < VITERBI_PATHMAX; i++) {
|
|||
|
|
memset(m_pMetrics[i], 0, m_States * sizeof(int));
|
|||
|
|
memset(m_pHistory[i], 0, m_States * sizeof(int));
|
|||
|
|
}
|
|||
|
|
m_CurPtr = 0;
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
int __fastcall CViterbi::TraceBack(int *pMetric)
|
|||
|
|
{
|
|||
|
|
int i;
|
|||
|
|
|
|||
|
|
UINT pn = CIRCULATE(m_CurPtr - 1, VITERBI_PATHMAX);
|
|||
|
|
int *ip = m_pMetrics[pn];
|
|||
|
|
int MaxMetric = INT_MIN;
|
|||
|
|
int MaxState = 0;
|
|||
|
|
for( i = 0; i < m_States; i++, ip++ ){
|
|||
|
|
if( *ip > MaxMetric ){
|
|||
|
|
MaxState = i;
|
|||
|
|
MaxMetric = *ip;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_tSeq[pn] = MaxState;
|
|||
|
|
for( i = 0; i < m_TraceBack; i++ ){
|
|||
|
|
UINT prev = CIRCULATE(pn - 1, VITERBI_PATHMAX);
|
|||
|
|
m_tSeq[prev] = m_pHistory[pn][m_tSeq[pn]];
|
|||
|
|
pn = prev;
|
|||
|
|
}
|
|||
|
|
if( pMetric ) *pMetric = m_pMetrics[pn][m_tSeq[pn]];
|
|||
|
|
|
|||
|
|
UINT c = 0;
|
|||
|
|
for( i = 0; i < m_BlockSize; i++ ){
|
|||
|
|
c = (c << 1) | (m_tSeq[pn] & 1);
|
|||
|
|
pn = CIRCULATE(pn + 1, VITERBI_PATHMAX);
|
|||
|
|
}
|
|||
|
|
if( pMetric ) *pMetric = m_pMetrics[pn][m_tSeq[pn]] - *pMetric;
|
|||
|
|
|
|||
|
|
return c;
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
// s[0] = 1st, s[1] = 2nd
|
|||
|
|
int __fastcall CViterbi::Decode(int *pMetric, BYTE s[2])
|
|||
|
|
{
|
|||
|
|
int i, j, m[4], n;
|
|||
|
|
|
|||
|
|
UINT curp = m_CurPtr;
|
|||
|
|
UINT prevp = CIRCULATE(curp - 1, VITERBI_PATHMAX);
|
|||
|
|
|
|||
|
|
m[0] = m_tMetrics[0][s[0]] + m_tMetrics[0][s[1]];
|
|||
|
|
m[1] = m_tMetrics[0][s[0]] + m_tMetrics[1][s[1]];
|
|||
|
|
m[2] = m_tMetrics[1][s[0]] + m_tMetrics[0][s[1]];
|
|||
|
|
m[3] = m_tMetrics[1][s[0]] + m_tMetrics[1][s[1]];
|
|||
|
|
|
|||
|
|
int *mp = m_pMetrics[curp];
|
|||
|
|
int *hp = m_pHistory[curp];
|
|||
|
|
for( n = 0; n < m_States; n++ ){
|
|||
|
|
int p0, p1, s0, s1, m0, m1;
|
|||
|
|
|
|||
|
|
s0 = n; s1 = n + m_States;
|
|||
|
|
p0 = s0 >> 1; p1 = s1 >> 1;
|
|||
|
|
m0 = m_pMetrics[prevp][p0] + m[m_pPoly[s0]];
|
|||
|
|
m1 = m_pMetrics[prevp][p1] + m[m_pPoly[s1]];
|
|||
|
|
if( m0 > m1 ){
|
|||
|
|
*mp++ = m0;
|
|||
|
|
*hp++ = p0;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
*mp++ = m1;
|
|||
|
|
*hp++ = p1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
m_CurPtr = CIRCULATE(m_CurPtr + 1, VITERBI_PATHMAX);
|
|||
|
|
if( !(m_CurPtr % m_BlockSize) ) return TraceBack(pMetric);
|
|||
|
|
|
|||
|
|
if( m_pMetrics[curp][0] > (INT_MAX / 2) ){
|
|||
|
|
for( i = 0; i < VITERBI_PATHMAX; i++ ){
|
|||
|
|
mp = m_pMetrics[i];
|
|||
|
|
for( j = 0; j < m_States; j++ ){
|
|||
|
|
*mp++ -= INT_MAX / 2;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if( m_pMetrics[curp][0] < (INT_MIN / 2) ){
|
|||
|
|
for( i = 0; i < VITERBI_PATHMAX; i++){
|
|||
|
|
mp = m_pMetrics[i];
|
|||
|
|
for( j = 0; j < m_States; j++){
|
|||
|
|
*mp++ += INT_MIN / 2;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*=============================================================================
|
|||
|
|
CInterLeaver<EFBFBD>N<EFBFBD><EFBFBD><EFBFBD>X
|
|||
|
|
|
|||
|
|
1 2 3 4 5 6 7 8 9 0 1 2 3 4
|
|||
|
|
To encode: ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz--------------------------------------------------------------------------------------
|
|||
|
|
Encoded: A E I M Q U Y 2 6 a eB iF mJ qN uR yV -Z -3 -7 -b -fC -jG -nK -rO -vS -zW --0 --4 --8 --c --gD--kH--oL--sP--wT---X---1
|
|||
|
|
|
|||
|
|
1234567890 12
|
|||
|
|
-------------
|
|||
|
|
AEIMQUY26a ei
|
|||
|
|
BFJNRVZ37b fj
|
|||
|
|
CGKOSW048c gk
|
|||
|
|
DHLPTX159d hl
|
|||
|
|
|
|||
|
|
=============================================================================*/
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
__fastcall CInterLeaver::CInterLeaver(void)
|
|||
|
|
{
|
|||
|
|
Init(4);
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
void __fastcall CInterLeaver::Init(int bitsize)
|
|||
|
|
{
|
|||
|
|
#if DEBUG
|
|||
|
|
if( bitsize > MFSK_MAXBITS ){
|
|||
|
|
Application->MainForm->Caption = "Over BitSize in InterLeaver";
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
m_Stages = 10;
|
|||
|
|
m_BitSize = bitsize;
|
|||
|
|
m_BitSizeM = bitsize - 1;
|
|||
|
|
if( bitsize == 5 ){ // for comminucate with Stream on MFSK8
|
|||
|
|
m_Stages = 5;
|
|||
|
|
}
|
|||
|
|
Reset();
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
void __fastcall CInterLeaver::Reset(void)
|
|||
|
|
{
|
|||
|
|
memset(m_tTable, 0, sizeof(m_tTable));
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
void __fastcall CInterLeaver::Bits2Syms(BYTE *pSyms, int b)
|
|||
|
|
{
|
|||
|
|
for( int i = 0; i < m_BitSize; i++ ){
|
|||
|
|
*pSyms++ = BYTE(b & _tBitData[m_BitSizeM-i]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
int __fastcall CInterLeaver::Syms2Bits(BYTE *pSyms)
|
|||
|
|
{
|
|||
|
|
int b = 0;
|
|||
|
|
for( int i = 0; i < m_BitSize; i++ ){
|
|||
|
|
b = b << 1;
|
|||
|
|
if( *pSyms++ ) b |= 1;
|
|||
|
|
}
|
|||
|
|
return b;
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
// MFSK16 = pSyms[4], MFSK8 = pSyms[5], MFSK31 = pSym[3]
|
|||
|
|
void __fastcall CInterLeaver::DecodeSyms(BYTE *pSyms)
|
|||
|
|
{
|
|||
|
|
for( int N = 0; N < m_Stages; N++ ){
|
|||
|
|
int i;
|
|||
|
|
for( i = 0; i < m_BitSize; i++ ){
|
|||
|
|
for( int j = 0; j < m_BitSizeM; j++ ) m_tTable[N][i][j] = m_tTable[N][i][j+1];
|
|||
|
|
}
|
|||
|
|
for(i = 0; i < m_BitSize; i++) m_tTable[N][i][m_BitSizeM] = pSyms[i];
|
|||
|
|
for(i = 0; i < m_BitSize; i++) pSyms[i] = m_tTable[N][i][i];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
// MFSK16 = pSyms[4], MFSK8 = pSyms[5], MFSK31 = pSym[3]
|
|||
|
|
void __fastcall CInterLeaver::EncodeSyms(BYTE *pSyms)
|
|||
|
|
{
|
|||
|
|
for( int N = 0; N < m_Stages; N++ ){
|
|||
|
|
int i;
|
|||
|
|
for( i = 0; i < m_BitSize; i++ ){
|
|||
|
|
for( int j = 0; j < m_BitSizeM; j++ ) m_tTable[N][i][j] = m_tTable[N][i][j+1];
|
|||
|
|
}
|
|||
|
|
for(i = 0; i < m_BitSize; i++) m_tTable[N][i][m_BitSizeM] = pSyms[i];
|
|||
|
|
for(i = 0; i < m_BitSize; i++) pSyms[i] = m_tTable[N][i][m_BitSizeM-i];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
// MFSK8 = b4 to b0, MFSK16 = b3 to b0
|
|||
|
|
int __fastcall CInterLeaver::DecodeBits(int b)
|
|||
|
|
{
|
|||
|
|
BYTE tSyms[MFSK_MAXBITS];
|
|||
|
|
|
|||
|
|
Bits2Syms(tSyms, b);
|
|||
|
|
DecodeSyms(tSyms);
|
|||
|
|
return Syms2Bits(tSyms);
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
// MFSK8 = b4 to b0, MFSK16 = b3 to b0
|
|||
|
|
int __fastcall CInterLeaver::EncodeBits(int b)
|
|||
|
|
{
|
|||
|
|
BYTE tSyms[MFSK_MAXBITS];
|
|||
|
|
|
|||
|
|
Bits2Syms(tSyms, b);
|
|||
|
|
EncodeSyms(tSyms);
|
|||
|
|
return Syms2Bits(tSyms);
|
|||
|
|
}
|
|||
|
|
//--------------------------------------------------------------------------
|
|||
|
|
|