⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decodeqam.cpp

📁 QAM数据调制的编码过程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -