📄 lawavecapture.cpp
字号:
#include "StdAfx.h"
#include "lawavecapture.h"
CLaWaveCapture::CLaWaveCapture(IPaintableParent* pParent, const RECT* pRect, int nSamplePerSec, int nAnalyzeSamples, ICwEventListener* pCwEventListener/* = NULL */)
{
m_pFont = new CFont("Arial", 8, CFont::THIN);
m_pParent = pParent;
m_oRect = *pRect;
SetRect(&m_oPaintRect, 0, 0, m_oRect.right - m_oRect.left, m_oRect.bottom - m_oRect.top - 9);
SetRect(&m_oRulerRect, 0, m_oRect.bottom - m_oRect.top - 9, m_oRect.right - m_oRect.left, m_oRect.bottom - m_oRect.top);
m_pPaintBoard = pParent->NewGraphics(pRect->right - pRect->left, pRect->bottom - pRect->top);
m_pPaintBoard->DrawRect(&m_oRulerRect);
m_pCwEventListener = pCwEventListener;
m_pDsCap = NULL;
m_pDsCapBuff = NULL;
memset(&m_oFormat, 0, sizeof(m_oFormat));
m_oFormat.wFormatTag = WAVE_FORMAT_PCM;
m_oFormat.nChannels = 1;
m_oFormat.nSamplesPerSec = nSamplePerSec;
m_oFormat.wBitsPerSample = 16;
m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
m_oFormat.nBlockAlign = m_oFormat.wBitsPerSample / 8 * m_oFormat.nChannels;
m_oFormat.cbSize = 0;
memset(&m_oCaptureBufferDesc, 0, sizeof(m_oCaptureBufferDesc));
m_oCaptureBufferDesc.dwSize = sizeof(m_oCaptureBufferDesc);
m_oCaptureBufferDesc.dwFlags = 0;
m_oCaptureBufferDesc.dwBufferBytes = m_oFormat.nAvgBytesPerSec;
m_oCaptureBufferDesc.lpwfxFormat = &m_oFormat;
m_oCaptureBufferDesc.dwFXCount = 0;
m_oCaptureBufferDesc.lpDSCFXDesc = NULL;
m_nAnalyzeSamples = nAnalyzeSamples;
m_pWavBuff = new short int[m_nAnalyzeSamples * 2];
m_pDctBuff = new short int[m_nAnalyzeSamples];
m_pFreqRuler = new short int[m_nAnalyzeSamples];
DrawRuler();
m_nRecvThreshold = (short int)(32768 * 0.5l);
m_nRecvFreqStart = 850;
m_nRecvFreqEnd = 1250;
m_bState = FALSE;
m_pFft = new TCosFFT<short int>(m_nAnalyzeSamples);
}
CLaWaveCapture::~CLaWaveCapture(void)
{
delete m_pFont;
delete m_pPaintBoard;
if (NULL != m_pDsCap)
{
if (NULL != m_pDsCapBuff)
{
m_pDsCapBuff->Release();
m_pDsCapBuff = NULL;
}
m_pDsCap->Release();
m_pDsCap = NULL;
}
delete[] m_pWavBuff;
delete[] m_pDctBuff;
delete[] m_pFreqRuler;
}
void CLaWaveCapture::SetThresholdLevel(double rThresholdLevel)
{
m_nRecvThreshold = (short int)(32768 * rThresholdLevel);
}
void CLaWaveCapture::SetFreqRange(int nLowFreq, int nHighFreq)
{
m_nRecvFreqStart = nLowFreq;
m_nRecvFreqEnd = nHighFreq;
}
void CLaWaveCapture::DrawRuler()
{
double rTotalLogNum = log10(15000.0l) - 2;
int nGradCount = m_oRulerRect.right - m_oRulerRect.left;
for (int i = 0; i < nGradCount; ++i)
{
m_pFreqRuler[i] = (short int)pow(10, 2 + (i * rTotalLogNum / nGradCount));
}
m_pPaintBoard->SetColor(RGB(192,192,192));
m_pPaintBoard->DrawLine(m_oRulerRect.left, m_oRulerRect.top, m_oRulerRect.right, m_oRulerRect.top);
m_pPaintBoard->SetFont(m_pFont);
double d = nGradCount / rTotalLogNum;
RECT r = m_oRulerRect;
r.top += 1;
for (int i = 0; i < rTotalLogNum; ++i)
{
char grad[8];
r.left = (int)(d * i);
if (0 == i)
sprintf(grad, "%.0lfHz", pow(10.0, i + 2));
else if (3 > i + 2)
sprintf(grad, "%.0lf", pow(10.0, i + 2));
else
sprintf(grad, "%.0lfK", pow(10.0, i + 2) / 1000);
m_pPaintBoard->SetColor(RGB(192, 192, 192));
m_pPaintBoard->DrawText(&r, grad, DT_LEFT);
m_pPaintBoard->SetColor(RGB(224, 224, 224));
m_pPaintBoard->DrawLine(r.left, 0 == i ? 0 : m_oRulerRect.top, r.left, m_oRulerRect.bottom - 1);
if (4 > i)
{
for (int j = 2; j < 6; ++j)
{
r.left = (int)(d * (i + log10((double)j)));
sprintf(grad, "%d", j);
m_pPaintBoard->SetColor(RGB(192, 192, 192));
m_pPaintBoard->DrawText(&r, grad, DT_LEFT);
m_pPaintBoard->SetColor(RGB(224, 224, 224));
m_pPaintBoard->DrawLine(r.left, m_oRulerRect.top, r.left, m_oRulerRect.bottom - 5);
}
}
}
}
BOOL CLaWaveCapture::Initialize()
{
if (FAILED(DirectSoundCaptureCreate8(NULL, &m_pDsCap, NULL)))
return FALSE;
if (FAILED(m_pDsCap->CreateCaptureBuffer(&m_oCaptureBufferDesc, &m_pDsCapBuff, NULL)))
return FALSE;
return FAILED(m_pDsCapBuff->Start(DSCBSTART_LOOPING));
}
BOOL CLaWaveCapture::IsRelated(int x, int y)
{
return IControl::PointInRect(&m_oRect, x, y);
}
void CLaWaveCapture::GetRect(RECT* r)
{
*r = m_oRect;
}
void CLaWaveCapture::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
int w = m_oRect.right - m_oRect.left;
int h = m_oRect.bottom - m_oRect.top;
RECT r;
r.top = 0; r.bottom = h;
r.left = 0; r.right = w;
g->Copy(&r, m_pPaintBoard, 0, 0);
}
BOOL CLaWaveCapture::Refresh()
{
DWORD nStatus = 0;
m_pDsCapBuff->GetStatus(&nStatus);
if ((DSCBSTATUS_CAPTURING & nStatus) && (DSCBSTATUS_LOOPING & nStatus))
{
DWORD nReadPosEnd;
DWORD nCapturePos;
if (FAILED(m_pDsCapBuff->GetCurrentPosition(&nCapturePos, &nReadPosEnd)))
return FALSE;
int nReadPosStart = nReadPosEnd - m_nAnalyzeSamples * sizeof(short int) * 2;
if (0 > nReadPosStart)
nReadPosStart += m_oCaptureBufferDesc.dwBufferBytes;
short int *pHeadPortion, *pTailPortion;
DWORD nHpBytes, nTpBytes;
if (FAILED(m_pDsCapBuff->Lock(nReadPosStart, m_nAnalyzeSamples * sizeof(short int) * 2, (LPVOID *)&pHeadPortion, &nHpBytes, (LPVOID *)&pTailPortion, &nTpBytes, 0)))
return FALSE;
DWORD i;
for (i = 0; i < nHpBytes / sizeof(short int); ++i)
{
m_pWavBuff[i] = pHeadPortion[i];
}
for (; i < m_nAnalyzeSamples * 2; ++i)
{
m_pWavBuff[i] = pTailPortion[i];
}
m_pDsCapBuff->Unlock(pHeadPortion, nHpBytes, pTailPortion, nTpBytes);
//synchronize the wave
int nStep = 1;
DWORD nSyncStart;
for (nSyncStart = 0; nSyncStart < m_nAnalyzeSamples && 0 < nStep; ++nSyncStart)
{
switch(nStep)
{
case 1:
if (m_pWavBuff[nSyncStart] < m_pWavBuff[nSyncStart + 1])
nStep = 2;
break;
case 2:
if (m_pWavBuff[nSyncStart] >= 0 && m_pWavBuff[nSyncStart] > m_pWavBuff[nSyncStart + 1])
nStep = 0;
/* for sin wave
case 1: // look for negative
if (m_vWavBuff[nSyncStart] < 0)
nStep = 2;
break;
case 2: // through the X axis
if (m_vWavBuff[nSyncStart] >= 0)
nStep = 0;
break;
*/
}
}
m_pPaintBoard->SetColor(RGB(255, 255, 255));
m_oPaintRect.left += 1;
m_pPaintBoard->DrawRect(&m_oPaintRect);
m_oPaintRect.left -= 1;
m_pPaintBoard->SetColor(RGB(192, 192, 192));
short int* pSyncWavBuff = m_pWavBuff + nSyncStart;
int last = m_oPaintRect.bottom / 2 - pSyncWavBuff[0] * m_oPaintRect.bottom / 65536;
for (i = 1; i < m_nAnalyzeSamples && i < (DWORD)(m_oPaintRect.right - m_oPaintRect.left); ++i)
{
int curr = m_oPaintRect.bottom / 2 - pSyncWavBuff[i] * m_oPaintRect.bottom / 65536;
m_pPaintBoard->DrawLine(i - 1, last, i, curr);
last = curr;
}
//FFT
m_pFft->Compute(m_pDctBuff, pSyncWavBuff);
m_pPaintBoard->SetColor(RGB(0, 0, 0));
int l = 0;
BOOL bState = FALSE;
int nGridCount = m_oRulerRect.right - m_oRulerRect.left;
for (i = 0; i < m_nAnalyzeSamples; ++i)
{
short int nFreq = (short int)((i) * (m_oFormat.nSamplesPerSec / 2 / m_nAnalyzeSamples));
for (; l < nGridCount; ++l)
{
if (m_pFreqRuler[l] >= nFreq)
{
m_pPaintBoard->DrawLine(l, m_oPaintRect.bottom - abs(m_pDctBuff[i]) * m_oPaintRect.bottom / 32768, l, m_oPaintRect.bottom);
break;
}
}
if (!bState && m_nRecvThreshold <= abs(m_pDctBuff[i]))
if (m_nRecvFreqStart <= nFreq && nFreq <= m_nRecvFreqEnd)
bState = TRUE;
}
RECT r = m_oPaintRect;
OffsetRect(&r, m_oRect.left, m_oRect.top);
m_pParent->Invalidate(&r);
if (NULL != m_pCwEventListener)
m_pCwEventListener->OnCwEvent(bState);
return TRUE;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -