📄 wavein.cpp
字号:
//****************************************************************************
//
//
//
MMRESULT WaveIn::Open
(
WAVEOPENDESC *pOpenDesc,
DWORD dwFlags
)
{
WAVEFORMATEX * pFormat = pOpenDesc->lpFormat;
MMRESULT mmRet = MMSYSERR_NOERROR;
ASSERT(pFormat);
FUNC_WAVEIN((L"+WaveIn::Open"));
if(dwFlags & WAVE_FORMAT_QUERY)
{
WIDM_MSG((L"Wave Format Query: \n"));
}
else
{
WIDM_MSG((L"Wave Format Open: \n"));
}
WIDM_MSG((L" nSamplesPerSec = %d\n",pFormat->nSamplesPerSec));
WIDM_MSG((L" nChannels = %d\n",pFormat->nChannels));
WIDM_MSG((L" wBitsPerSample = %d\n",pFormat->wBitsPerSample));
//
// Allow PCM, mono or stereo, 8 or 16 bit at any frequency supported
// by the AC97 Codec.
//
if( (pFormat->wFormatTag != WAVE_FORMAT_PCM) ||
(pFormat->nChannels != 1 && pFormat->nChannels != 2) ||
(pFormat->wBitsPerSample != 8 && pFormat->wBitsPerSample != 16))
{
mmRet = WAVERR_BADFORMAT;
}
//
// Check to see if the sample rate is correct.
//
if(MMSUCCESS(mmRet))
{
if(m_pCodec->HasSRC())
{
switch( pFormat->nSamplesPerSec)
{
case 48000:
case 44100:
case 32000:
case 22050:
case 16000:
case 11025:
case 8000:
break;
default:
mmRet = WAVERR_BADFORMAT;
break;
}
}
else
{
switch( pFormat->nSamplesPerSec)
{
case 44100:
case 22050:
case 11025:
case 8000:
break;
default:
mmRet = WAVERR_BADFORMAT;
break;
}
}
}
//
// If the Application is querying if we can play a certain format,
// then just return.
//
if(dwFlags & WAVE_FORMAT_QUERY)
{
FUNC_WAVEIN((L"-WaveIn::Open\n"));
return mmRet;
}
//
// Only one playback stream is allowed.
//
if(m_pCodec->m_bRecordOpened)
{
mmRet = MMSYSERR_ALLOCATED;
}
//
// Initialize the codec.
//
if(MMSUCCESS(mmRet))
{
if(m_pCodec->HasSRC())
{
mmRet = m_pCodec->SetRecordSampleRate(pFormat->nSamplesPerSec, 0);
}
else if(pFormat->nSamplesPerSec != 44100)
{
//
// Get the settings for an external SRC.
//
int iReturn;
iReturn = SRCInit
(
&m_Src,
44100,
pFormat->nSamplesPerSec,
(pFormat->wBitsPerSample == 8),
(pFormat->nChannels ==1)
);
if(!iReturn)
{
mmRet = WAVERR_BADFORMAT;
}
}
ASSERT(MMSUCCESS(mmRet));
}
if (MMSUCCESS(mmRet))
{
m_WaveFormat = *pFormat;
m_dwRecordedBytes = 0;
m_bIsRecording = FALSE;
m_pfnCallback = (DRVCALLBACK *) pOpenDesc->dwCallback;
m_hCallback = pOpenDesc->hWave;
m_dwInstance = pOpenDesc->dwInstance;
m_pWaveHead = 0;
m_pWaveNext = 0;
m_dwDmaSampleSize = m_pCodec->DmaSampleSize();
//
// Check to see if we are using an AC97 codec. If so we have a sample
// rate converter.
//
if(m_dwDmaSampleSize == 16)
{
m_dwSourceFactor = 2;
if((pFormat->nChannels == 1) && (pFormat->wBitsPerSample == 8))
{
m_dwDestFactor = 0;
m_pfnWaveCopyFunc = (WaveInConversionFunc *)&ConvertShortsToBytesStereoToMono;
}
else if((pFormat->nChannels == 1) && (pFormat->wBitsPerSample == 16))
{
m_dwDestFactor = 1;
m_pfnWaveCopyFunc = (WaveInConversionFunc *)&ConvertShortsStereoToMono;
}
else if((pFormat->nChannels == 2) && (pFormat->wBitsPerSample == 8))
{
m_dwDestFactor = 1;
m_pfnWaveCopyFunc = (WaveInConversionFunc *)&ConvertShortsToBytes;
}
else if((pFormat->nChannels == 2) && (pFormat->wBitsPerSample == 16))
{
m_dwDestFactor = 2;
m_pfnWaveCopyFunc = (WaveInConversionFunc *)&ConvertShortsToShorts;
}
m_bUseSrc = FALSE;
m_pBuffer = m_pDmaBuffer;
}
else if(pFormat->nSamplesPerSec == 44100)
{
m_dwSourceFactor = 3;
if((pFormat->nChannels ==1) && (pFormat->wBitsPerSample == 8))
{
m_dwDestFactor = 0;
m_pfnWaveCopyFunc = (WaveInConversionFunc *)&ConvertWordsToBytesStereoToMono;
}
else if((pFormat->nChannels ==1) && (pFormat->wBitsPerSample == 16))
{
m_dwDestFactor = 1;
m_pfnWaveCopyFunc = (WaveInConversionFunc *)&ConvertWordsToShortsStereoToMono;
}
else if((pFormat->nChannels ==2) && (pFormat->wBitsPerSample == 8))
{
m_dwDestFactor = 1;
m_pfnWaveCopyFunc = (WaveInConversionFunc *)&ConvertWordsToBytes;
}
else if((pFormat->nChannels ==2) && (pFormat->wBitsPerSample == 16))
{
m_dwDestFactor = 2;
m_pfnWaveCopyFunc = (WaveInConversionFunc *)&ConvertWordsToShorts;
}
m_bUseSrc = FALSE;
m_pBuffer = m_pDmaBuffer;
}
else
{
m_dwSourceFactor = 3;
m_dwDestFactor = (pFormat->nChannels == 2) + (pFormat->wBitsPerSample == 16);
m_pfnWaveCopyFunc = (WaveInConversionFunc *)&Filter;
m_bUseSrc = TRUE;
m_pBuffer = PVOID(ULONG(m_pRateConverterBuffer) +
((MAX_FILTER_SIZE) * sizeof(ULONG) * 2));
}
//else
//{
// PRINTMSG
// (
// ZONE_ERROR,
// (
// TEXT("ERROR: Did not catch bad format\r\n")
// )
// );
// mmRet = WAVERR_BADFORMAT;
//}
}
//
// If there was no failures then the stream was allocated correctly.
//
if(MMSUCCESS(mmRet))
{
m_pCodec->m_bRecordOpened = TRUE;
//
// Make the callback function call to the Wave API Manager
//
WIDM_MSG((L"WaveIn: WIM_OPEN\r\n"));
m_pfnCallback(m_hCallback, MM_WIM_OPEN, m_dwInstance, 0, 0);
}
//
// Initialize the buffer to zero.
//
memset(m_pDmaBuffer,0,m_ulDmaBufferSize);
FUNC_WAVEIN((L"-WaveIn::Open"));
return(mmRet);
}
//****************************************************************************
// WaveIn::Reset
//****************************************************************************
//
//
//
MMRESULT WaveIn::Reset()
{
FUNC_WAVEIN((L"+WaveIn::Reset"));
EnterCriticalSection( &m_CriticalSection);
//
// If we're recording, stop the DSP task
//
if(m_bIsRecording == TRUE)
{
m_pDma->Stop();
Sleep(1);
m_pCodec->StopRecord(0);
}
//
// We're not recording anymore
//
m_bIsRecording = FALSE;
//
// Reset the wave device state
//
m_dwRecordedBytes = 0;
//
// Mark all buffers as done, return the buffers to the application and
// initialize the list to zero.
//
MarkAllAsDone(m_pWaveHead);
RemoveCompleteBlocks();
m_pWaveNext = 0;
LeaveCriticalSection( &m_CriticalSection);
FUNC_WAVEIN((L"-WaveIn::Reset"));
return(MMSYSERR_NOERROR);
}
//****************************************************************************
// WaveIn::Start
//****************************************************************************
//
//
//
MMRESULT WaveIn::Start()
{
FUNC_WAVEIN((L"+WaveIn::Start"));
if(!m_bIsRecording)
{
m_bIsRecording = TRUE;
//
// If there is an Software SRC zero out the samples before the
// buffer.
//
if(m_bUseSrc)
{
memset
(
PULONG(m_pBuffer) - (m_Src.sFilterSize * 2),
0,
(2 * sizeof(ULONG) * m_Src.sFilterSize)
);
}
m_pCodec->StartRecord(0);
Sleep(1);
m_pDma->Start();
}
FUNC_WAVEIN((L"-WaveIn::Start"));
return(MMSYSERR_NOERROR);
}
//****************************************************************************
// WaveIn::Stop
//****************************************************************************
//
//
//
MMRESULT WaveIn::Stop()
{
WAVEHDR *pWave;
FUNC_WAVEIN((L"+WaveIn::Stop"));
//
// If not recording, ignore call according to DDK
// documentation.
//
if(m_bIsRecording)
{
m_bIsRecording = FALSE;
m_pDma->Stop();
Sleep(1);
m_pCodec->StopRecord(0);
//********************************************************************
// When a WIDM_STOP occurs, this section of code marks the last buffer
// as WIM_DONE even if the the buffer has no data copied into it. It
// also tells the application via a callback that the driver is
// finished with the buffer in the header.
//
// We need to check to make sure that there is a buffer in the header.
//********************************************************************
if(m_pWaveHead)
{
pWave = m_pWaveHead;
m_pWaveHead = m_pWaveHead->lpNext;
//
// If we release the buffer make sure it is not in the next queue.
//
if(pWave == m_pWaveNext)
{
m_pWaveNext = m_pWaveHead;
}
MARK_BUFFER_DONE(pWave);
MARK_BUFFER_DEQUEUED(pWave);
//
// Make the callback function call to the Wave API Manager
//
m_pfnCallback
(
m_hCallback,
MM_WIM_DATA,
m_dwInstance,
(DWORD) pWave,
0
);
}
}
FUNC_WAVEIN((L"-WaveIn::Stop"));
return(MMSYSERR_NOERROR);
}
//****************************************************************************
// ConvertWordsToBytes
//****************************************************************************
// Converts a stream of 24 bit Right justified words to bytes
//
// pUnused - Unused pointer.
// pulSrc - Signed 24 bit values right justified.
// pucDst - Unsigned 8 bit values.
// pulSrcSamples - IN/OUT Number of Source Samples Available/Used
// pulDstSamples - IN/OUT Number of Destination Samples Available/Used
//
void ConvertWordsToBytes
(
PVOID pUnused,
PULONG pulSrc,
PUCHAR pucDst,
PULONG pulSrcSamples,
PULONG pulDstSamples
)
{
ULONG ulTemp;
ULONG ulSamples;
PUCHAR pucEnd;
if(*pulSrcSamples > *pulDstSamples)
{
ulSamples = *pulSrcSamples = *pulDstSamples;
}
else
{
ulSamples = *pulDstSamples = *pulSrcSamples;
}
//
// Copy the number of samples. The samples are stereo
// so we must copy both the right and left.
//
pucEnd = pucDst + (ulSamples<<1);
do
{
ulTemp = *pulSrc++;
*pucDst++ = UCHAR(ulTemp>>16) + 0x80;
}
while(pucDst < pucEnd);
}
//****************************************************************************
// ConvertWordsToShort
//****************************************************************************
// Converts a stream of bytes to words.
//
// pUnused - Unused pointer.
// pulSrc - Signed 24 bit values right justified.
// pusDst - Signed 16 bit values.
// pulSrcSamples - IN/OUT Number of Source Samples Available/Used
// pulDstSamples - IN/OUT Number of Destination Samples Available/Used
//
void ConvertWordsToShorts
(
PVOID pUnused,
PULONG pulSrc,
PUSHORT pusDst,
PULONG pulSrcSamples,
PULONG pulDstSamples
)
{
ULONG ulSamples;
ULONG ulTemp;
PUSHORT pusEnd;
if(*pulSrcSamples > *pulDstSamples)
{
ulSamples = *pulSrcSamples = *pulDstSamples;
}
else
{
ulSamples = *pulDstSamples = *pulSrcSamples;
}
//
// Copy the number of samples. The samples are stereo
// so we must copy both the right and left.
//
pusEnd = pusDst + (ulSamples<<1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -