📄 wave.cpp
字号:
}
else
{
for( i=0; i < (Length*m_InFormat.nChannels); i++ )
{
m_usTemp.bytes.lsb = *(m_pInBuffer + (m_InBufPosition++) );
m_usTemp.bytes.msb = *(m_pInBuffer + (m_InBufPosition++) );
*( pData + i) = (double)m_usTemp.both;
}
}
if( m_InBufPosition >= m_InBufferSize )
m_InBufPosition = 0; // need to read another buffer's worth
return(Length);
}
//////////////////////////////////////////////////////////////////////
// Closes the Input wave file if open.
//
//////////////////////////////////////////////////////////////////////
void CWave::InClose()
{
if( m_INhmmio )
{
mmioClose( m_INhmmio, 0 );
m_INhmmio = NULL;
}
if( m_pInBuffer )
{
delete m_pInBuffer;
m_pInBuffer = NULL;
}
m_InputOpen = FALSE;
}
//////////////////////////////////////////////////////////////////////
// This function opens a wave file for writing.
// Number of samples can be 1,2 or 4 bytes long depending on
// bits per sample and number of channels.
//( ie. a 1000 sample buffer for 16 bit stereo will be a 4000 byte buffer)
// parameters:
// pPathName = CString containing file path name
// pWFX = WAVEFORMATEX structure with desired wavefile settings
// BufSize = DWORD specifies the wave file buffer size in
// number of samples.
// SampleLimit = limit on number of samples to be written.
// returns:
// 0 if opened OK
// ErrorCode if not
//////////////////////////////////////////////////////////////////////
UINT CWave::OutOpen( CString* pPathName, WAVEFORMATEX* pWFX,
DWORD BufSize, DWORD SampleLimit)
{
GetFreeSpace(pPathName);
m_OutputOpen = FALSE;
m_ErrorCode = NO_ERRORS;
m_pOutBuffer = NULL;
m_OutBufPosition = 0;
m_OutSamplesWritten = 0;
m_OutSampleLimit = SampleLimit;
memset( &m_mmcktRIFF,0,sizeof(MMCKINFO));
memset( &m_mmcktSubchunk,0,sizeof(MMCKINFO));
m_OutFormat = *pWFX;
m_OutBytesPerSample = (m_OutFormat.wBitsPerSample/8)*m_OutFormat.nChannels;
m_OutBufferSize = BufSize * m_OutBytesPerSample;
if( !(m_OUThmmio = mmioOpen( (LPSTR)(LPCTSTR(*pPathName)), NULL,
MMIO_WRITE|MMIO_ALLOCBUF|MMIO_CREATE )))
{
m_ErrorCode = WAVOUT_ERR_OPEN;
}
else
{ // Create the output file RIFF chunk of form type 'WAVE'.
m_mmcktRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
if( mmioCreateChunk(m_OUThmmio, &m_mmcktRIFF, MMIO_CREATERIFF) != 0)
{
mmioClose(m_OUThmmio,0);
m_ErrorCode = WAVOUT_ERR_WRITING;
}
else
{ // Are now descended into the 'RIFF' chunk just created.
// Now create the 'fmt ' chunk. Since the size of this chunk is known,
// specify it in the MMCKINFO structure so MMIO doesn't have to seek
// back and set the chunk size after ascending from the chunk.
m_mmcktSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
m_mmcktSubchunk.cksize = sizeof(WAVEFORMATEX); // we know the size of this ck.
if( mmioCreateChunk(m_OUThmmio, &m_mmcktSubchunk, 0) != 0)
{
mmioClose(m_OUThmmio,0);
m_ErrorCode = WAVOUT_ERR_WRITING;
}
else
{ // Write the WAVEFORMATEX structure to the 'fmt ' chunk.
if( mmioWrite(m_OUThmmio, (HPSTR)pWFX, sizeof(WAVEFORMATEX))
!= sizeof(WAVEFORMATEX))
{
mmioClose(m_OUThmmio,0);
m_ErrorCode = WAVOUT_ERR_WRITING;
}
else
{ // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk.
if( mmioAscend(m_OUThmmio, &m_mmcktSubchunk, 0) != 0)
{
mmioClose(m_OUThmmio,0);
m_ErrorCode = WAVOUT_ERR_WRITING;
}
else
{ // Create the 'data' chunk that holds the waveform samples.
m_mmcktSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
if (mmioCreateChunk(m_OUThmmio, &m_mmcktSubchunk, 0) != 0)
{
mmioClose(m_OUThmmio,0);
m_ErrorCode = WAVOUT_ERR_WRITING;
}
}
}
}
}
}
if( m_ErrorCode == NO_ERRORS )
{
// allocate intermediate byte buffer
m_pOutBuffer = new char[ m_OutBufferSize ];
if( m_pOutBuffer == NULL )
{
OutClose();
m_ErrorCode = MEMORY_ERROR;
}
else
{
m_OutputOpen = TRUE;
}
}
return m_ErrorCode;
}
///////////////////////////////////////////////////////////////////////
// Writes 'Length' doubles to the open wavefile.
// parameters:
// pData = pointer to block of 'Length' SHORT INT's to output.
// Length = Number of samples to write from pData. If is zero
// then the output file is closed.
//
// Returns:
// 'Length' if data was succesfully placed in the output buffers.
// 0 if output has finished( reached the specified sample limit )
// -1 if error ( use GetError() to retrieve error )
///////////////////////////////////////////////////////////////////////
LONG CWave::OutWrite( double* pData, INT Length)
{
INT i;
if( !m_OutputOpen )
{
OutClose();
m_ErrorCode = WAVOUT_ERR_NOTOPEN;
return -1;
}
if( Length == 0 )
{
if( mmioWrite( m_OUThmmio, m_pOutBuffer, m_OutBufPosition ) < 0 )
{
OutClose();
m_ErrorCode = WAVOUT_ERR_WRITING;
return -1;
}
OutClose();
return 0;
}
if( Length > 0 )
{
if(m_OutFormat.wBitsPerSample == 16)
{
for( i=0; i < (Length*m_OutFormat.nChannels); i++ )
{
m_usTemp.both = (SHORT)(*( pData + i));
*(m_pOutBuffer + (m_OutBufPosition++)) = m_usTemp.bytes.lsb;
*(m_pOutBuffer + (m_OutBufPosition++)) = m_usTemp.bytes.msb;
}
}
else
{
for( i=0; i < (Length*m_OutFormat.nChannels); i++ )
{
m_usTemp.both = (SHORT)(*(pData + i) + 32768.0);
*(m_pOutBuffer + (m_OutBufPosition++)) = (char)m_usTemp.bytes.msb;
}
}
}
if( m_OutBufPosition >= m_OutBufferSize )
{
m_OutBufPosition = 0; // need to write another buffer's worth
if( mmioWrite( m_OUThmmio, m_pOutBuffer, m_OutBufferSize ) < 0 )
{
OutClose();
m_ErrorCode = WAVOUT_ERR_WRITING;
return -1;
}
}
m_OutSamplesWritten += Length;
if( m_OutSamplesWritten >= m_OutSampleLimit )
{
OutClose();
return 0;
}
return Length;
}
//////////////////////////////////////////////////////////////////////
// Closes the Output wave file by first updating the information chunk
// with the length of data that was written then closing it.
//////////////////////////////////////////////////////////////////////
void CWave::OutClose()
{
if( m_OUThmmio )
{
if( m_OutputOpen ) // need to update file and data lengths in
{ // the wave header if the file was opened
if( mmioWrite( m_OUThmmio, m_pOutBuffer, m_OutBufPosition ) >= 0 )
{
// Ascend out of the 'data' chunk, back into the 'RIFF' chunk.
if( mmioAscend(m_OUThmmio, &m_mmcktSubchunk, 0) == 0)
// Ascend out of the 'RIFF' chunk, writing the RIFF file length.
mmioAscend(m_OUThmmio, &m_mmcktRIFF, 0);
}
}
mmioClose( m_OUThmmio, 0 );
m_OUThmmio = FALSE;
}
if( m_pOutBuffer )
{
delete m_pOutBuffer;
m_pOutBuffer = NULL;
}
m_OutputOpen = FALSE;
}
/////////////////////////////////////////////////////////////////
// returns free disk space on drive specified by pPathName.
// The extra logic is for dealing with early Win95 versions that don't
// support the extended disk space function "GetDiskFreeSpaceEx(..)".
/////////////////////////////////////////////////////////////////
LONGLONG CWave::GetDriveFreeSpace(CString* pPathName)
{
typedef BOOL (CALLBACK* LPFNDLLFUNC)(LPCTSTR, PULARGE_INTEGER,
PULARGE_INTEGER, PULARGE_INTEGER);
LONGLONG SpaceFree;
SpaceFree = 0; // see if it exists
HMODULE hKernel = GetModuleHandle( _T("kernel32.dll"));
LPFNDLLFUNC pFunct = (LPFNDLLFUNC)GetProcAddress( hKernel,"GetDiskFreeSpaceExA");
if(pFunct != NULL) //if function is in kernel32.dll
{
ULARGE_INTEGER TotalSpace;
ULARGE_INTEGER FreeSpace;
pFunct( pPathName->Left(3), &FreeSpace, &TotalSpace, NULL);
SpaceFree = FreeSpace.QuadPart;
}
else //else is WIn95 pre OSR2 so use old function
{
DWORD SectorsPerCluster, BytesPerSector;
DWORD NumberOfFreeClusters, TotalNumberOfClusters;
if( GetDiskFreeSpace( pPathName->Left(3),
&SectorsPerCluster, &BytesPerSector,
&NumberOfFreeClusters, &TotalNumberOfClusters ) )
SpaceFree = (LONGLONG)(NumberOfFreeClusters*SectorsPerCluster*BytesPerSector);
}
return SpaceFree;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -