📄 decodeqam.cpp
字号:
// DecodeQAM.cpp: implementation of the CDecodeQAM class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DecodeQAM.h"
#include "math.h"
#include "CommonUtil.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define SAMPLING_RATE 48000
#define BAND_RATE 2400
#define TARGET_FREQUENCE 1700
#define BITS_PER_BAND 4
#define GOERTZEL_N (SAMPLING_RATE/BAND_RATE)
// SRRC 的值
const int h1_len = 21;
const double h1[21] = {
0.004934636876,-0.001977569656, -0.01100863516, -0.02090584859, -0.02358030528,
-0.009399720468, 0.02740905806, 0.08368061483, 0.1460207701, 0.1950501651,
0.2136619836, 0.1950501651, 0.1460207701, 0.08368061483, 0.02740905806,
-0.009399720468, -0.02358030528, -0.02090584859, -0.01100863516,-0.001977569656,
0.004934636876
};
const int h2_len = 11;
const double h2[11] = {
0.02130498923, 0, -0.06827166677, 0, 0.3037347198,
0.5, 0.3037347198, 0, -0.06827166677, 0,
0.02130498923
};
const int h3_len = 11;
const double h3[11] = {
0.02130498923, 0, -0.06827166677, 0, 0.3037347198,
0.5, 0.3037347198, 0, -0.06827166677, 0,
0.02130498923
};
CDecodeQAM::CDecodeQAM()
{
}
CDecodeQAM::~CDecodeQAM()
{
}
BOOL CDecodeQAM::DecodeQAM(LPBYTE lpBuffer,
DWORD dwLen,
LPBYTE lpData,
DWORD dwDataLen,
DWORD *pwSize)
{
const double M_PI = 2*asin(1.0);
const int M_SAMPLE_RATE = 48000; //48k采样
const int M_BIT_RATE = 9600; // 比特率
const int M_BAND_RATE = 2400; // 波特率
const int M_FREQUENCE = 1700; // 载频1700
const int M_SAMPLE_PER_BAND = (M_SAMPLE_RATE/M_BAND_RATE); // 每个波特的采样点
const int M_BITS_PER_BAND = (M_BIT_RATE/M_BAND_RATE);
double m_du1700 = 0.0f;
LPBYTE lpIBuffer;
LPBYTE lpQBuffer;
int iLoop = 0;
memset(lpData, 0, dwDataLen * sizeof(BYTE));
m_du1700 = 2*M_PI/((double)M_SAMPLE_RATE/M_FREQUENCE);
//goertzel(lpBuffer, dwLen, lpData, dwDataLen, pwSize);
lpIBuffer = new BYTE[dwLen];
for (iLoop = 0; iLoop < dwLen; iLoop++)
{
lpIBuffer[iLoop] = (BYTE)(((lpBuffer[iLoop]-0x80)*cos(m_du1700*iLoop))) + 0x80;
}
WriteToWaveFile(lpIBuffer, dwLen);
return TRUE;
}
BOOL CDecodeQAM::EncodeQAM(LPBYTE lpBuffer,
DWORD dwLen,
LPBYTE lpWave,
DWORD dwWaveLen,
DWORD *pwRetSize)
{
const double M_PI = 2*asin(1.0);
const int M_SAMPLE_RATE = 48000; // 48k采样
const int M_BIT_RATE = 9600; // 比特率
const int M_BAND_RATE = 2400; // 波特率
const int M_FREQUENCE = 1700; // 载频1700
const int M_AMPLITUDE_SCALE = 0x10; // 幅度放大
const int M_SAMPLE_PER_BAND = (M_SAMPLE_RATE/M_BAND_RATE); // 每个波特的采样点
const int M_BITS_PER_BAND = (M_BIT_RATE/M_BAND_RATE);
const float M_SYNC_SIN_DURATION = 0.2;
const int M_TRAINING_LENGTH = 25600;
const int M_TRAINING_BAND = 608;
double m_du1700 = 0.0f;
int iLoop = 0;
int nPhase = 0;
int* piInphase = NULL;
int* piQuadrature = NULL;
double* pSRRCReal = NULL;
double* pSRRCImag = NULL;
unsigned int dwSize = 0;
unsigned int pos = 0;
unsigned int Ipos = 0;
unsigned int Qpos = 0;
LPBYTE lpTempBuffer;
unsigned int uiTempLen;
m_du1700 = 2*M_PI*(double)M_FREQUENCE/(double)M_SAMPLE_RATE;
// Total sample data
int m_SampleLength = 2*dwLen*M_SAMPLE_PER_BAND + M_TRAINING_BAND*M_SAMPLE_PER_BAND + (int)(M_SAMPLE_RATE*M_SYNC_SIN_DURATION); // sin + training + data
LPBYTE m_lpSoundData = new BYTE[m_SampleLength+1024];
memset(m_lpSoundData, 0, (m_SampleLength+1024));
// I/Q signal
piInphase = new int[2*dwLen + M_TRAINING_BAND];
piQuadrature = new int[2*dwLen + M_TRAINING_BAND];
// Temp buffer
uiTempLen = dwLen + 24;
lpTempBuffer = new BYTE[uiTempLen+128]; // 128 just for robust
memset(lpTempBuffer, 0, (uiTempLen+128));
// 1, 生成同步的正弦波
unsigned int nSinLen = (unsigned int)(M_SAMPLE_RATE*M_SYNC_SIN_DURATION);
for (iLoop = 0; iLoop < nSinLen; iLoop++)
{
m_lpSoundData[pos++] = (BYTE)(M_AMPLITUDE_SCALE*sin(m_du1700*iLoop)) + 0x80;
}
// 2, 训练第一部分-无发送能量
unsigned int nPart1Len = 48 * M_SAMPLE_PER_BAND;
for (iLoop = 0; iLoop < nPart1Len; iLoop++)
{
m_lpSoundData[pos++] = 0 + 0x80;
}
// 3, 训练第二部分-交替信号
unsigned int nPart2Len = 128;
for (iLoop = 0; iLoop < nPart2Len; iLoop++)
{
if (iLoop % 2 == 0)
{
piInphase[Ipos++] = -3;
piQuadrature[Qpos++] = 0;
}
else
{
piInphase[Ipos++] = 3;
piQuadrature[Qpos++] = -3;
}
}
// 4, 训练第三部分-均衡器调节码型
unsigned int nPart3Len = 384;
unsigned char uiRandom = 0x2a; // 伪随机序列初始状态:00101010
for (iLoop = 0; iLoop < nPart3Len; iLoop++)
{
uiRandom <<= 1;
if ((((uiRandom>>6)&0x01) ^ ((uiRandom>>7)&0x01)) == 0x01)
{
uiRandom += 1;
}
if (((uiRandom>>7)&0x01) == 0)
{
piInphase[Ipos++] = 3;
piQuadrature[Qpos++] = 0;
nPhase = 0;
}
else
{
piInphase[Ipos++] = -3;
piQuadrature[Qpos++] = 3;
nPhase = 3;
}
}
// 5, 训练第四部分-已扰码的二进制数全1
unsigned int nPart4Len = 48;
for (iLoop = 0; iLoop < (int)(nPart4Len/2); iLoop++)
{
lpTempBuffer[iLoop] = 0xff;
}
memcpy(&(lpTempBuffer[iLoop]), lpBuffer, dwLen);
// 第一步,原始数据经过扰码器进行加扰
BitsScramble(lpTempBuffer, uiTempLen);
// 第二步,星座图编码
for (iLoop = 0; iLoop < 2*uiTempLen; iLoop++)
{
BYTE Q1Q2Q3Q4 = 0;
// 1, 串/并转换
if (iLoop % 2 == 0)
{
Q1Q2Q3Q4 = (lpTempBuffer[iLoop/2] >> 4) & 0x0F;
}
else
{
Q1Q2Q3Q4 = lpTempBuffer[iLoop/2] & 0x0F;
}
// 2, 星座映射
nPhase += CalcPhaseOffset(Q1Q2Q3Q4&0x07);
nPhase = nPhase % 8;
MapConstellation((Q1Q2Q3Q4>>3)&0x01, nPhase, &(piInphase[Ipos++]), &(piQuadrature[Qpos++]));
}
// 第三步:根升余弦成形滤波器
unsigned int uiSRRCLen = (MAX(Ipos, Qpos)) * M_SAMPLE_PER_BAND;
pSRRCReal = new double[uiSRRCLen+1024];
pSRRCImag = new double[uiSRRCLen+1024];
memset(pSRRCReal, 0, uiSRRCLen*sizeof(double));
memset(pSRRCImag, 0, uiSRRCLen*sizeof(double));
srrc_tx_filter(piInphase, Ipos, pSRRCReal, &dwSize);
srrc_tx_filter(piQuadrature, Qpos, pSRRCImag, &dwSize);
//SRRCFilter(piInphase, Ipos, pSRRCReal, &dwSize);
//SRRCFilter(piQuadrature, Qpos, pSRRCImag, &dwSize);
/*for (iLoop = 0; iLoop < 2*dwLen; iLoop++)
{
int nStartIndex = 0;
int nEndIndex = 120;
int nPos = iLoop*M_SAMPLE_PER_BAND-50;
// 计算起始位置
if (nPos < 0)
{
nStartIndex += abs(nPos);
nPos = 0;
}
if (iLoop >= (2*dwLen-3))
{
nEndIndex -= ((iLoop-(2*dwLen-3))*20 + 10);
}
// 开始累加升余弦波
for (iSubLoop = nStartIndex; iSubLoop < nEndIndex; iSubLoop++)
{
pRICoeff[nPos].Real += pIQBuffer[iLoop].I * SRRC[iSubLoop];
pRICoeff[nPos].Imag += pIQBuffer[iLoop].Q * SRRC[iSubLoop];
nPos++;
}
}*/
// 第四步:将相位和幅度的调制载波叠加
for (iLoop = 0; iLoop < (uiSRRCLen-1); iLoop++)
{
//m_lpSoundData[iLoop] = (BYTE)((pSRRCReal[iLoop]*cos(m_du1700*iLoop) - pSRRCImag[iLoop]*sin(m_du1700*iLoop)) * M_AMPLITUDE_SCALE) + 0x80;
m_lpSoundData[pos++] = (BYTE)((pSRRCReal[iLoop]*cos(m_du1700*iLoop) - pSRRCImag[iLoop]*sin(m_du1700*iLoop)) * M_AMPLITUDE_SCALE * 10) + 0x80;
}
// 加上WAVE文件头
CCommonUtil::WriteToWaveBuffer(m_lpSoundData, m_SampleLength, lpWave, pwRetSize);
CCommonUtil::WriteToWaveFile(m_lpSoundData, m_SampleLength, "K:\\Fax\\a.wav");
delete[] piInphase;
delete[] piQuadrature;
delete[] lpTempBuffer;
delete[] pSRRCReal;
delete[] pSRRCImag;
delete[] m_lpSoundData;
return TRUE;
}
void CDecodeQAM::goertzel(LPBYTE lpBuffer, DWORD wLen, LPBYTE lpData, DWORD dwDataLen, DWORD* pwSize)
{
const double M_PI = 2 * asin(1.0);
const double M_PHASE_OFFSET = 17 * M_PI / 12;
unsigned long n, m;
double q0 = 0.0f, q1 = 0.0f, q2 = 0.0f;
double real = 0.0f, imag = 0.0f, magnitude = 0.0f, phase = 0.0f;
double coefs = 0.0f;
int k = 0;
int count = 0;
BYTE data = 0;
double prePhase = 0.0f;
double curPhase = 0.0f;
double diff = 0.0f;
// 得到Goertzel变换的系数coefs
k = (int)(0.5 + ((float)GOERTZEL_N * TARGET_FREQUENCE) / (double)SAMPLING_RATE);
coefs = 2.0f * cos(8.0 * atan(1.0) * k / (double)GOERTZEL_N);
double cosw = cos(8.0 * atan(1.0) * k / (double)GOERTZEL_N);
double sinw = sin(8.0 * atan(1.0) * k / (double)GOERTZEL_N);
// 分析每一块的数据,得出此块的幅值和相位
for (n = 0; n < (wLen-GOERTZEL_N); n += GOERTZEL_N)
{
q0 = 0.0f;
q1 = 0.0f;
q2 = 0.0f;
// 计算Q0,Q1和Q2的相应值
for (m = 0; m < GOERTZEL_N; m++)
{
q0 = coefs * q1 - q2 + (lpBuffer[n + m] - 0x80);
q2 = q1;
q1 = q0;
}
// 计算实部,虚部,幅值和相位
real = q1 - q2 * cosw;
imag = q2 * sinw;
magnitude = sqrt(real * real + imag * imag);
phase = atan(imag / real);
// 调整相位的值
if (real < 0)
{
phase = M_PI + phase;
}
if (phase < 0)
{
phase = phase + 2 * M_PI;
}
// 计算相对相位(当前绝对相位-上个的绝对相位)
curPhase = phase - M_PHASE_OFFSET;
while (curPhase < 0)
{
curPhase += 2 * M_PI;
}
curPhase = fmod(curPhase, 2 * M_PI);
diff = curPhase - prePhase;
while (diff < 0)
{
diff += 2 * M_PI;
}
prePhase = phase;
// 通过门限值,得到此块波形对应的比特数据Q0Q1Q2Q3
data = 0;
// 幅值
if (magnitude > 310)
{
data |= 0x08;
}
else
{
data |= 0x00;
}
// 相位
if (diff <= (M_PI/8) || diff > (15*M_PI/8))
{
data |= 0x01;
}
else if (diff <= (3*M_PI/8) && diff > (M_PI/8))
{
data |= 0x00;
}
else if (diff <= (5*M_PI/8) && diff > (3*M_PI/8))
{
data |= 0x02;
}
else if (diff <= (7*M_PI/8) && diff > (5*M_PI/8))
{
data |= 0x03;
}
else if (diff <= (9*M_PI/8) && diff > (7*M_PI/8))
{
data |= 0x07;
}
else if (diff <= (11*M_PI/8) && diff > (9*M_PI/8))
{
data |= 0x06;
}
else if (diff <= (13*M_PI/8) && diff > (11*M_PI/8))
{
data |= 0x04;
}
else if (diff <= (15*M_PI/8) && diff > (13*M_PI/8))
{
data |= 0x5;
}
// 保存数据
if ((count/2) >= dwDataLen)
{
continue;
}
if (count%2 == 0)
{
lpData[count/2] |= ((data & 0x0F) << 4);
}
else
{
lpData[count/2] |= (data & 0x0F);
}
// DEBUG
if (count%2 == 1)
{
TRACE("%#x ", lpData[count/2]);
if (count%21 == 0)
{
TRACE("\n");
}
}
count++;
*pwSize = count/2 + 1;
}
}
BYTE CDecodeQAM::Decimal2Gray(BYTE x)
{
return (x & 0x08) | ((x ^ (x >> 1)) & 0x07);
}
BYTE CDecodeQAM::Gray2Decimal(BYTE x)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -