www.pudn.com > Éù²¨ÆµÂÊÏÔʾ .zip > PeakLevelDlg.cpp
/********************************************************************/
/* */
/* PeakLevelDlg.cpp */
/* */
/* Implementation of the CPeakLevelDlg. */
/* */
/* Programmed by Pablo van der Meer */
/* Copyright Pablo Software Solutions 2003 */
/* http://www.pablovandermeer.nl */
/* */
/* Last updated: 11 January 2003 */
/* */
/********************************************************************/
#include "stdafx.h"
#include "PeakLevel.h"
#include "PeakLevelDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CPeakLevelDlg::CPeakLevelDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPeakLevelDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CPeakLevelDlg)
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CPeakLevelDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPeakLevelDlg)
DDX_Control(pDX, IDC_HOMEPAGE, m_Homepage);
DDX_Control(pDX, IDC_GRAPH_RIGHT, m_OscilloGraphRight);
DDX_Control(pDX, IDC_GRAPH_LEFT, m_OscilloGraphLeft);
DDX_Control(pDX, IDC_VUMETER_RIGHT, m_VuMeterRight);
DDX_Control(pDX, IDC_VUMETER_LEFT, m_VuMeterLeft);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPeakLevelDlg, CDialog)
//{{AFX_MSG_MAP(CPeakLevelDlg)
ON_BN_CLICKED(IDC_START, OnStart)
ON_BN_CLICKED(IDC_STOP, OnStop)
//}}AFX_MSG_MAP
ON_MESSAGE(MM_WIM_DATA, OnMMWimData)
END_MESSAGE_MAP()
/********************************************************************/
/* */
/* Function name : OnInitDialog */
/* Description : Initialize dialog */
/* */
/********************************************************************/
BOOL CPeakLevelDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
m_VuMeterLeft.SetRange(0, 127);
m_VuMeterRight.SetRange(0, 127);
m_OscilloGraphLeft.SetPixelColor(RGB(255, 255, 0));
return TRUE; // return TRUE unless you set the focus to a control
}
/********************************************************************/
/* */
/* Function name : OnStart */
/* Description : Start monitoring the input */
/* */
/********************************************************************/
void CPeakLevelDlg::OnStart()
{
StartInput();
}
/********************************************************************/
/* */
/* Function name : OnStop */
/* Description : Stop monitoring the input */
/* */
/********************************************************************/
void CPeakLevelDlg::OnStop()
{
StopInput();
}
/********************************************************************/
/* */
/* Function name : OnMMWimData */
/* Description : Called when the input buffer is full. */
/* */
/********************************************************************/
LRESULT CPeakLevelDlg::OnMMWimData(WPARAM wParam, LPARAM lParam)
{
int nLeft = 0, nRight = 0;
SetOscilloGraphData((LPWAVEHDR)lParam);
// analyse input data
if (AnalyseDataBlock((LPWAVEHDR)lParam, nLeft, nRight))
{
m_VuMeterLeft.SetValue(nLeft);
m_VuMeterRight.SetValue(nRight);
}
return 0L;
}
/********************************************************************/
/* */
/* Function name : StartInput */
/* Description : Start monitoring the audio input */
/* */
/********************************************************************/
BOOL CPeakLevelDlg::StartInput()
{
int i;
m_PcmWaveFormat.wf.nChannels = NUM_CHANNELS;
m_PcmWaveFormat.wBitsPerSample = 8;
m_PcmWaveFormat.wf.nSamplesPerSec = 11025;
m_PcmWaveFormat.wf.wFormatTag = WAVE_FORMAT_PCM;
m_PcmWaveFormat.wf.nBlockAlign = m_PcmWaveFormat.wf.nChannels * m_PcmWaveFormat.wBitsPerSample / 8;
m_PcmWaveFormat.wf.nAvgBytesPerSec = m_PcmWaveFormat.wf.nSamplesPerSec * m_PcmWaveFormat.wf.nBlockAlign;
// calculate buffer size for specified update interval
m_dwBufferLength = m_PcmWaveFormat.wf.nAvgBytesPerSec/UPDATE_INTERVAL;
m_hWave = NULL;
if (waveInOpen(&m_hWave, WAVE_MAPPER, (LPWAVEFORMATEX)&m_PcmWaveFormat, (DWORD)m_hWnd, 0, CALLBACK_WINDOW))
{
return FALSE;
}
// initialize to null
for (i = 0; i < NUM_CHANNELS; i++)
{
m_WaveHeader[i] = NULL;
}
// allocate memory, prepare headers and add the buffers
for (i = 0; i < NUM_CHANNELS; i++)
{
HGLOBAL hGlobalMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE, sizeof(WAVEHDR) + m_dwBufferLength);
m_WaveHeader[i] = (LPWAVEHDR)GlobalLock(hGlobalMem);
if (m_WaveHeader[i] == NULL)
{
return FALSE;
}
m_WaveHeader[i]->lpData = (LPSTR) (m_WaveHeader[i] + 1);
m_WaveHeader[i]->dwBufferLength = m_dwBufferLength;
m_WaveHeader[i]->dwBytesRecorded = 0;
m_WaveHeader[i]->dwUser = 0;
m_WaveHeader[i]->dwFlags = 0;
m_WaveHeader[i]->dwLoops = 0;
if (waveInPrepareHeader(m_hWave, m_WaveHeader[i], sizeof(WAVEHDR)))
{
return FALSE;
}
if (waveInAddBuffer(m_hWave, m_WaveHeader[i], sizeof(WAVEHDR)))
{
return FALSE;
}
}
waveInStart(m_hWave);
return TRUE;
}
/********************************************************************/
/* */
/* Function name : StopInput */
/* Description : Stop monitoring the audio input */
/* */
/********************************************************************/
void CPeakLevelDlg::StopInput()
{
if (m_hWave == NULL)
{
return;
}
// stop streaming data
waveInStop(m_hWave);
// release buffers
waveInReset(m_hWave);
// clean up
for (int i = 0; i < NUM_CHANNELS; i++)
{
if (m_WaveHeader[i])
{
waveInUnprepareHeader(m_hWave, m_WaveHeader[i], sizeof(WAVEHDR));
HGLOBAL hGlobalMem = GlobalHandle(m_WaveHeader[i]);
GlobalFree(hGlobalMem);
m_WaveHeader[i] = NULL;
}
}
waveInClose(m_hWave);
}
/********************************************************************/
/* */
/* Function name : AnalyseDataBlock */
/* Description : Analyse received data and get maximum levels. */
/* */
/********************************************************************/
BOOL CPeakLevelDlg::AnalyseDataBlock(LPWAVEHDR pWaveHdr, int &nLevelLeft, int &nLevelRight)
{
if (m_hWave == NULL)
{
return FALSE;
}
int nSampleLevel;
// find maximum absolute level
for (DWORD i=0; ilpData[i]) - 128;
// get maximum
nLevelLeft = __max(nLevelLeft, abs(nSampleLevel));
// skip to right channel
i++;
// adjust to be in range 0..128
nSampleLevel = (int)((unsigned char) pWaveHdr->lpData[i]) - 128;
// get maximum
nLevelRight = __max(nLevelRight, abs(nSampleLevel));
}
// put the buffer back on the queue
if (waveInAddBuffer(m_hWave, pWaveHdr, sizeof(WAVEHDR)))
{
return FALSE;
}
return TRUE;
}
/********************************************************************/
/* */
/* Function name : SetOscilloGraphData */
/* Description : Copy received data to oscillograph. */
/* */
/********************************************************************/
void CPeakLevelDlg::SetOscilloGraphData(LPWAVEHDR pWaveHdr)
{
if (m_hWave == NULL)
{
return;
}
BYTE *pBytesLeft = new BYTE[m_dwBufferLength/2];
BYTE *pBytesRight = new BYTE[m_dwBufferLength/2];
// copy wave data
for (DWORD i=0; ilpData[i]);
// copy data for right channel
pBytesRight[i/2] = (int)((unsigned char) pWaveHdr->lpData[i+1]);
}
m_OscilloGraphLeft.SetData(pBytesLeft, m_dwBufferLength/2);
m_OscilloGraphRight.SetData(pBytesRight, m_dwBufferLength/2);
delete pBytesLeft;
delete pBytesRight;
}