📄 twave.cpp
字号:
}
delete [] pData;
}
}
m_listWaveData.RemoveAll();
// Close message file
CloseHandle(hFile);
m_nTotalRecording = 0;
return true;
}
//***********************************************************************
// Plays previosly loaded WAV data by sending to Wave Driver.
bool CtWave::Play(UINT nWaveOut, bool bLoop)
{
// Make sure we've got some data
if( !m_pDataOut1 ) //***
{
return false;
}
MMRESULT mr;
// Make sure we're stopped
// Stop();
assert(!m_hWaveOut);
// assert(!m_pWaveHdr1); //***
assert(m_pFormat);
// Make sure a waveform output device supports this format
mr = waveOutOpen(0, nWaveOut, m_pFormat, 0, 0L,
WAVE_FORMAT_QUERY | (nWaveOut == WAVE_MAPPER ? 0 : WAVE_MAPPED));
if( mr )
{
WOTRACE(mr, __TEXT("waveOutOpen"));
return false;
}
// Make sure window is created
if( !m_wnd.GetHwnd() && !m_wnd.Create(this) )
{
OutputDebugString("Couldn't create window for callbacks\n");
return false;
}
// Open a waveform output device
HWAVEOUT hWaveOut;
DWORD fdwOpen = CALLBACK_WINDOW | (nWaveOut == WAVE_MAPPER ? 0 : WAVE_MAPPED);
mr = waveOutOpen(&hWaveOut, nWaveOut, m_pFormat, (DWORD)m_wnd.GetHwnd(), 0, fdwOpen);
if( mr )
{
WOTRACE(mr, __TEXT("waveOutOpen"));
return false;
}
// Set up WAVEHDR structure and prepare it to be written to wave device
WAVEHDR* pWaveHdr = new WAVEHDR;
if( !pWaveHdr )
{
OutputDebugString("new[] -- Out of memory\n");
Stop();
return false;
}
pWaveHdr->lpData = m_pDataOut1; //***
pWaveHdr->dwBufferLength = m_nOutputSize;
pWaveHdr->dwFlags = (bLoop ? WHDR_BEGINLOOP | WHDR_ENDLOOP : 0);
pWaveHdr->dwLoops = (bLoop ? 0xffffffff : 0);
mr = waveOutPrepareHeader(hWaveOut, pWaveHdr, sizeof(WAVEHDR));
if( mr )
{
WOTRACE(mr, __TEXT("waveOutPrepareHeader"));
Stop();
return false;
}
// Then the data block can be sent to the output device
mr = waveOutWrite(hWaveOut, pWaveHdr, sizeof(WAVEHDR));
if( mr )
{
WOTRACE(mr, __TEXT("waveOutWrite"));
Stop();
return false;
}
// Cache results
m_pWaveOutHdr1 = pWaveHdr;
m_hWaveOut = hWaveOut;
return true;
}
//********************************************************************
// Record a "lump" of WAV data from Wave Driver.
bool CtWave::Record(UINT nWaveIn, double nSecs)
{
// Make sure we're closed first
Close();
assert(!m_nRecordedSize);
assert(!m_nFormatSize);
assert(!m_pFormat);
// assert(!m_pWaveHdr1);
// assert(!m_pWaveHdr2);
// assert(!m_hWaveIn);
MMRESULT mr;
WAVEFORMATEX* pFormat = (WAVEFORMATEX*)(new BYTE[sizeof(WAVEFORMATEX)]);
if( !pFormat )
{
OutputDebugString("new[] -- Out of memory\n");
return false;
}
pFormat->wFormatTag = WAVE_FORMAT_PCM; // Pulse Code Modulation
pFormat->nChannels = 1; // Mono
pFormat->nSamplesPerSec = 8000; // 8.0 kHz
pFormat->wBitsPerSample = 16; // 16 bits/sample
// PCM required calculations
assert(pFormat->wFormatTag == WAVE_FORMAT_PCM);
pFormat->nBlockAlign = pFormat->nChannels * pFormat->wBitsPerSample/8;
pFormat->nAvgBytesPerSec = pFormat->nSamplesPerSec * pFormat->nBlockAlign;
// No user data
pFormat->cbSize = 0;
// Check support for format
mr = waveInOpen(0, nWaveIn, pFormat, 0, 0,
WAVE_FORMAT_QUERY | (nWaveIn == WAVE_MAPPER ? 0 : WAVE_MAPPED));
if( mr )
{
WITRACE(mr, __TEXT("waveInOpen"));
delete[] pFormat;
return false;
}
// Make sure window is created
if( !m_wnd.GetHwnd() && !m_wnd.Create(this) )
{
OutputDebugString("Couldn't create window for callbacks\n");
delete[] pFormat;
return false;
}
// Open recorder
HWAVEIN hWaveIn;
DWORD fdwOpen = CALLBACK_WINDOW | (nWaveIn == WAVE_MAPPER ? 0 : WAVE_MAPPED);
mr = waveInOpen(&hWaveIn, nWaveIn, pFormat, (DWORD)m_wnd.GetHwnd(), 0, fdwOpen);
if( mr )
{
WITRACE(mr, __TEXT("waveInOpen"));
delete[] pFormat;
return false;
}
// Allocate message buffer
WAVEHDR* pWaveHdr = new WAVEHDR;
if( !pWaveHdr )
{
OutputDebugString("new[] -- Out of memory\n");
delete[] pFormat;
return false;
}
ZeroMemory(pWaveHdr, sizeof(WAVEHDR));
DWORD nDataSize = (DWORD)(nSecs * (double)(pFormat->nSamplesPerSec * pFormat->wBitsPerSample/8));
HPSTR pData = (HPSTR)(new BYTE[nDataSize]);
m_nDataBlockSize = nDataSize;
if( !pData )
{
OutputDebugString("new[] -- Out of memory\n");
delete pWaveHdr;
delete[] pFormat;
return false;
}
pWaveHdr->dwBufferLength = nDataSize;
pWaveHdr->lpData = pData;
mr = waveInPrepareHeader(hWaveIn, pWaveHdr, sizeof(WAVEHDR));
if( mr )
{
WITRACE(mr, __TEXT("waveInPrepareHeader"));
delete[] pData;
delete pWaveHdr;
delete[] pFormat;
return false;
}
// Pass down the buffer to record into
mr = waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR));
if( mr )
{
WITRACE(mr, __TEXT("waveInAddBuffer"));
delete[] pData;
delete pWaveHdr;
delete[] pFormat;
return false;
}
// Start recording
mr = waveInStart(hWaveIn);
if( mr )
{
WITRACE(mr, __TEXT("waveInStart"));
delete[] pData;
delete pWaveHdr;
delete[] pFormat;
return false;
}
// Cache results
m_hWaveIn = hWaveIn;
m_nRecordedSize = 0;
m_nFormatSize = sizeof(WAVEFORMATEX);
m_pFormat = pFormat;
m_bWaveInHdr1InUse = true;
m_pDataIn1 = pData;
m_pWaveInHdr1 = pWaveHdr;
m_bOwnData = true;
return true;
}
bool CtWave::ContinueRecord(double nSecs)
{
// Allocate message buffer
WAVEHDR* pWaveHdr = new WAVEHDR;
if( !pWaveHdr )
{
OutputDebugString("new[] -- Out of memory\n");
return false;
}
ZeroMemory(pWaveHdr, sizeof(WAVEHDR));
HPSTR pData = (HPSTR)(new BYTE[m_nDataBlockSize]);
if( !pData )
{
OutputDebugString("new[] -- Out of memory\n");
delete pWaveHdr;
return false;
}
pWaveHdr->dwBufferLength = m_nDataBlockSize;
pWaveHdr->lpData = pData;
MMRESULT mr = waveInPrepareHeader(m_hWaveIn, pWaveHdr, sizeof(WAVEHDR));
if( mr )
{
WITRACE(mr, __TEXT("waveInPrepareHeader"));
delete[] pData;
delete pWaveHdr;
return false;
}
// Pass down the buffer to record into
mr = waveInAddBuffer(m_hWaveIn, pWaveHdr, sizeof(WAVEHDR));
if( mr )
{
WITRACE(mr, __TEXT("waveInAddBuffer"));
delete[] pData;
delete pWaveHdr;
return false;
}
// Continue recording
/* mr = waveInStart(m_hWaveIn);
if( mr )
{
WITRACE(mr, __TEXT("waveInStart"));
delete[] pData;
delete pWaveHdr;
return false;
}
*/
// Cache results
if (m_bWaveInHdr1InUse)
{
m_pDataIn2 = pData;
m_pWaveInHdr2 = pWaveHdr;
m_bWaveInHdr1InUse = false;
}
else
{
m_pDataIn1 = pData;
m_pWaveInHdr1 = pWaveHdr;
m_bWaveInHdr1InUse = true;
}
m_nRecordedSize = 0;
m_bOwnData = true;
return true;
}
//*****************************************************************
// Stop either recording or playback of WAV data.
bool CtWave::Stop()
{
// Only stop if we're playing/recording
if( (m_pWaveInHdr1 || m_pWaveInHdr2 || m_pWaveOutHdr1) && !m_bStopping )
{
MMRESULT mr;
// Important to avoid a manual Stop(),
// followed by a stop notification,
// followed by an automatic stop,
// followed by a stop notification, etc.
m_bStopping = true;
if( m_hWaveOut )
{
mr = waveOutReset(m_hWaveOut);
WOTRACE(mr, __TEXT("waveOutReset"));
mr = waveOutUnprepareHeader(m_hWaveOut, m_pWaveOutHdr1, sizeof(WAVEHDR)); //***
WOTRACE(mr, __TEXT("waveOutUnprepareHeader"));
mr = waveOutClose(m_hWaveOut);
WOTRACE(mr, __TEXT("waveOutClose"));
m_hWaveOut = 0;
}
/*else*/ if( m_hWaveIn )
{
mr = waveInReset(m_hWaveIn);
WITRACE(mr, __TEXT("waveInReset"));
/* mr = waveInUnprepareHeader(m_hWaveIn, m_pWaveHdr, sizeof(WAVEHDR));
WITRACE(mr, __TEXT("waveInUnprepareHeader"));
// Cache recorded length
m_nRecordedSize = m_pWaveHdr->dwBytesRecorded;
mr = waveInClose(m_hWaveIn);
WITRACE(mr, __TEXT("waveInClose"));
m_hWaveIn = 0;
// Remember the total size.
m_nTotalRecording += m_nRecordedSize;
*/ }
// delete m_pWaveHdr;
// m_pWaveHdr = 0;
m_bStopping = false;
}
return true;
}
//*****************************************************************
// STop and clean up.
bool CtWave::Close()
{
// Make sure we're stopped
Stop();
if (m_pFormat)
delete[] m_pFormat;
m_pFormat = 0;
m_nFormatSize = 0;
// if( m_pData1 && m_bOwnData)
// delete[] m_pData1;
// m_pDataOut1 = 0; //***
m_nRecordedSize = 0;
m_bOwnData = false;
return true;
}
//*****************************************************************
// Event handlers
LRESULT CtWave::OnWindowMessage(HWND hwnd, UINT nMsg, WPARAM wparam, LPARAM lparam)
{
CtWave* pw = reinterpret_cast<CtWave*>(GetWindowLong(hwnd, GWL_USERDATA));
if( pw )
{
CtWaveSink* pSink = pw->m_pSink;
switch( nMsg )
{
case WOM_CLOSE: if( pSink ) pSink->OnWaveOutClose(); return 0;
case WOM_DONE: pw->Stop(); if( pSink ) pSink->OnWaveOutDone(); return 0;
case WOM_OPEN: if( pSink ) pSink->OnWaveOutOpen(); return 0;
case WIM_CLOSE: if( pSink ) pSink->OnWaveInClose(); return 0;
case WIM_DATA: /*pw->Stop();*/ if( pSink ) pSink->OnWaveInData(); return 0;
case WIM_OPEN: if( pSink ) pSink->OnWaveInOpen(); return 0;
}
}
return DefWindowProc(hwnd, nMsg, wparam, lparam);
}
void CtWave::SwitchInputBuffer()
{
if (m_bWaveInHdr1InUse)
m_bWaveInHdr1InUse = false;
else
m_bWaveInHdr1InUse = true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -