📄 wavsrc.cpp
字号:
/******************************************************************************
|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|* PARTICULAR PURPOSE.
|*
|* Copyright 1995-2003 Ahead Software AG. All Rights Reserved.
|*-----------------------------------------------------------------------------
|* PROJECT: Nero Plugin Manager Example
|*
|* FILE: WavSrc.cpp
|*
|* PURPOSE: Implementation of the wave source class
******************************************************************************/
#include "stdafx.h"
#include "WavSrc.h"
// helper functions for file access
#include "FileHelper.h"
// IURLHolder implementation
bool CWavSrc::SetURL(const char* szURL, IStatus** ppStatus)
{
RETURN_ERROR(AE_CallNotImplemented);
}
const char* CWavSrc::GetURL()
{
return m_csURL;
}
EURLType CWavSrc::GetType()
{
return URL_LocalFile;
}
// IProcess implementation
bool CWavSrc::Start(IStatus** ppStatus)
{
if(NULL != ppStatus)
{
*ppStatus = NULL;
}
m_dwCurPos = 0;
if(SetFilePointer(m_hFile, m_dwDataStart, 0, FILE_BEGIN) !=
m_dwDataStart)
{
RETURN_ERROR(GetLastError());
}
m_bStarted = true;
return true;
}
bool CWavSrc::End(IStatus** ppStatus)
{
if(NULL != ppStatus)
{
*ppStatus = NULL;
}
m_bStarted = false;
return true;
}
bool CWavSrc::IsInProcess()
{
return m_bStarted;
}
// IAudioItem implementation
bool CWavSrc::GetCreator(IAudioComponent** pCreator)
{
if(!pCreator)
{
ASSERT(FALSE);
return false;
}
*pCreator = m_pCreator;
(*pCreator)->AddRef();
return true;
}
EAuxFlags CWavSrc::GetAuxFlags()
{
return SRC_FLAGS;
}
void CWavSrc::SetAuxFlags(EAuxFlags flags)
{
// Nothing to do here
}
// IAudioSource implementation
SWavFormat CWavSrc::GetRawFormat()
{
SWavFormat format;
format.m_iSamplesPerSecond= m_format.wf.nSamplesPerSec;
format.m_iBitsPerSample = m_format.wBitsPerSample;
format.m_iChannels = m_format.wf.nChannels;
return format;
}
// iBufSize must contain the size in bytes of the buffer pointed by pBuf.
bool CWavSrc::RawRead(BYTE* pBuf, int iBufSize, int* piRead,
EAudioRawState& state,
IStatus** ppStatus)
{
if(!(pBuf && iBufSize && piRead))
{
RETURN_ERROR(AE_InvalidParameter);
}
if(NULL != ppStatus)
{
*ppStatus = NULL;
}
state = ERS_None;
if(m_dwCurPos >= m_dwDataLen)
{
state = ERS_EndOfFile;
RETURN_ERROR(AE_EOF);
}
DWORD dwRead = 0;
DWORD dwRemaining = m_dwDataLen - m_dwCurPos;
if(iBufSize > (int)dwRemaining)
{
iBufSize = dwRemaining;
state = ERS_EndOfFile;
}
if (!(ReadFile(m_hFile, pBuf, iBufSize, (DWORD*)piRead, NULL) && *piRead))
{
// That means that the file is over or
// something is wrong, in any case
// stopping the process
m_dwCurPos = m_dwDataLen;
}
else
{
m_dwCurPos += *piRead;
}
return true;
}
// Returns free-form text string about the item.
const char* CWavSrc::GetInfo()
{
if(m_csInfo.IsEmpty())
{
m_csInfo.Format("PCM Wav file. Format: %d, Channels: %d,"
" Sample rate: %d, Bits per sample: %d",
m_format.wf.wFormatTag,
m_format.wf.nChannels,
m_format.wf.nSamplesPerSec,
m_format.wBitsPerSample);
CString* pcsStrings[] =
{ &m_csArtist, &m_csTitle, &m_csCopyright, &m_csDate, &m_csComments };
char* szarNames[5] =
{ "Artist", "Title", "Copyright", "Date", "Comments" };
for(int i = 0; i < 5; i++)
{
CString* pcs = pcsStrings[i];
if (pcs->IsEmpty())
continue;
m_csInfo += ",\r\n";
CString csTemp;
csTemp.Format("%s: %s", szarNames[i], (LPCTSTR)(*pcs));
m_csInfo += csTemp;
}
}
return m_csInfo;
}
// Returns the file duration in milliseconds.
ULONGLONG CWavSrc::GetDuration()
{
return m_qwDuration;
}
// Returns RAW data length in bytes.
ULONGLONG CWavSrc::GetRawLen()
{
return m_dwDataLen;
}
// ISeekable implementation
bool CWavSrc::Seek(ULONGLONG pos, IStatus** ppStatus)
{
if(NULL == ppStatus)
{
*ppStatus = NULL;
}
DWORD dwLastPos = SetFilePointer(m_hFile, 0, 0, FILE_CURRENT);
DWORD dwNewPos = (DWORD)(m_dwDataStart + pos * m_iBlockSize);
bool bRetCode = false;
if(SetFilePointer(m_hFile, dwNewPos, 0, FILE_BEGIN) != dwNewPos)
{
SetFilePointer(m_hFile, dwLastPos, 0, FILE_BEGIN);
}
else
{
m_dwCurPos = (DWORD)(pos * m_iBlockSize);
bRetCode = true;
}
if((false == bRetCode) && (NULL != ppStatus))
{
*ppStatus = new CStatus(AE_SeekFailed);
}
return bRetCode;
}
ULONGLONG CWavSrc::GetPos()
{
return (m_dwCurPos / m_iBlockSize);
}
ULONGLONG CWavSrc::GetBlockSize()
{
return m_iBlockSize;
}
ULONGLONG CWavSrc::GetDataLength()
{
return (m_dwDataLen / m_iBlockSize);
}
// ISrcInfoViewerEditor implementation
bool CWavSrc::GetCallback(ISrcInfoCallback** ppCB)
{
if(NULL == ppCB)
{
ASSERT(FALSE);
return false;
}
*ppCB = m_pCallback;
if(NULL != *ppCB)
{
(*ppCB)->AddRef();
}
return true;
}
void CWavSrc::SetCallback(ISrcInfoCallback* pNewCallback)
{
m_pCallback = pNewCallback;
}
bool CWavSrc::DoModal(IStatus** ppStatus)
{
CWavSrcInfoDlg dlg(this);
m_pAdvInfoDlg = &dlg;
dlg.DoModal();
m_pAdvInfoDlg = NULL;
return true;
}
bool CWavSrc::CloseModal(IStatus** ppStatus)
{
if(!(m_pAdvInfoDlg && IsWindow(m_pAdvInfoDlg->m_hWnd)))
{
return false;
}
m_pAdvInfoDlg->EndDialog(IDCANCEL);
if (0 != IsWindow(m_pAdvInfoDlg->m_hWnd))
{
return true;
}
else
{
return false;
}
}
bool CWavSrc::SaveDialogToObject(IStatus** ppStatus)
{
return false;
}
bool CWavSrc::SaveObjectToFile(IStatus** ppStatus)
{
return false;
}
bool CWavSrc::CanSaveObjectToFile()
{
return false;
}
// IInfoReader implementation
const char* CWavSrc::GetTitle()
{
return m_csTitle;
}
const char* CWavSrc::GetArtist()
{
return m_csArtist;
}
const char* CWavSrc::GetAlbum()
{
return NULL;
}
const char* CWavSrc::GetYear()
{
return NULL;
}
const char* CWavSrc::GetGenre()
{
return NULL;
}
CWavSrc::CWavSrc(const char* szURL, IAudioComponent* pCreator,
IStatus** ppStatus)
: CAggregatable (0),
m_pCreator (pCreator),
m_hFile (INVALID_HANDLE_VALUE),
m_bRiffChunk (FALSE),
m_bWavChunk (FALSE),
m_dwDataStart (0),
m_dwDataLen (0),
m_dwCurPos (0),
m_iBlockSize (0),
m_bOK (false),
m_bStarted (false)
{
try
{
m_csURL = szURL;
// CreateFile - create or open an object: Consoles, Communications resources
// Directories (open only), Files etc.
//
// LPCTSTR lpFileName - file name
// DWORD dwDesiredAccess - access mode
// DWORD dwShareMode - share mode
// LPSECURITY_ATTRIBUTES lpSecurityAttributes - [in] Pointer to a SECURITY_ATTRIBUTES
// structure that determines whether the returned
// handle can be inherited by child processes.
// If lpSecurityAttributes is NULL, the handle cannot
// be inherited.
// DWORD dwCreationDisposition - how to create
// DWORD dwFlagsAndAttributes - file attributes
// HANDLE hTemplateFile - handle to template file
m_hFile = CreateFile(szURL, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if(INVALID_HANDLE_VALUE == m_hFile )
{
if(NULL != ppStatus)
{
*ppStatus = new CStatus(GetLastError());
}
throw false;
}
// Trying to recognize the file
DWORD dwRead = 0,
dwFileSize = 0;
try
{
ReadMMIO();
}
catch(BOOL )
{
// If we're here - something is wrong in this file
// Sometimes files can contain some wrong information at the end,
// but if the rest is OK we can accept such files.
}
// make sure that we are dealing with a valid file format
if(false == ((INVALID_HANDLE_VALUE != m_hFile) &&
(true == m_bRiffChunk) &&
(true == m_bWavChunk) &&
(0 != m_dwDataStart) &&
(0 != m_dwDataLen)))
{
if(NULL != ppStatus)
{
*ppStatus = new CStatus(AE_BadFormat);
}
throw false;
}
// make sure that we are dealing with a valid wave format
if(false == (((8 == m_format.wBitsPerSample) ||
(16 == m_format.wBitsPerSample)) &&
((1 == m_format.wf.nChannels) ||
(2 == m_format.wf.nChannels)) &&
((m_format.wf.nSamplesPerSec) >= 1000 &&
(m_format.wf.nSamplesPerSec <= 100000))))
{
if(NULL != ppStatus)
{
*ppStatus = new CStatus(AE_BadFormat);
}
throw false;
}
// Calculating the file duration
m_iBlockSize = (m_format.wBitsPerSample / BITS_PER_BYTE) *
m_format.wf.nChannels;
m_qwDuration = (ULONGLONG)m_dwDataLen * (ULONGLONG)1000 /
m_format.wf.nAvgBytesPerSec;
}
catch(bool )
{
// Error occured
return;
}
m_bOK = true;
}
CWavSrc::~CWavSrc()
{
if(m_hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hFile);
}
}
HANDLE CWavSrc::GetFileHandle()
{
return m_hFile;
}
PCMWAVEFORMAT CWavSrc::GetWavSrcFormat()
{
return m_format;
}
HRESULT CWavSrc::ReadMMIO()
{
// Convert the CString URL to LPTSTR
LPTSTR lpsz = new TCHAR[m_csURL.GetLength()+1];
_tcscpy(lpsz, m_csURL);
// MM I/O handle for the WAVE
HMMIO hmmio;
// Open the file with the appropriate multimedia function
hmmio = mmioOpen(lpsz, NULL, MMIO_ALLOCBUF | MMIO_READ );
// Free the temporay pointer
delete lpsz;
// Make sure that the file could be opened
if( NULL != hmmio )
{
// Use in opening a WAVE file
MMCKINFO ckRiff;
// Use for subchunks
MMCKINFO ck;
// Search for the first chunk
if( ( 0 != mmioDescend( hmmio, &ckRiff, NULL, 0 ) ) )
{
return E_FAIL;
}
// Make sure this is a valid wave file
if( (ckRiff.ckid != FOURCC_RIFF) || (ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
{
return E_FAIL;
}
// If we got here, we can be sure that there is a riff chunk, and the type is WAVE
m_bRiffChunk = true;
m_bWavChunk = true;
// Search the input file for for the 'fmt ' chunk.
ck.ckid = mmioFOURCC('f', 'm', 't', ' ');
if( 0 != mmioDescend( hmmio, &ck, &ckRiff, MMIO_FINDCHUNK))
{
return E_FAIL;
}
// Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>;
// if there are extra parameters at the end, we'll ignore them
if( ck.cksize < (LONG) sizeof(PCMWAVEFORMAT))
{
return E_FAIL;
}
// Read the 'fmt ' chunk into m_format
if( mmioRead( hmmio, (HPSTR) &m_format, sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
{
return E_FAIL;
}
if( m_format.wf.wFormatTag == WAVE_FORMAT_PCM )
{
// Seek to the data
if( -1 == mmioSeek( hmmio, ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET))
{
return E_FAIL;
}
// Search the input file for the 'data' chunk.
ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
if( 0 != mmioDescend( hmmio, &ck, &ckRiff, MMIO_FINDCHUNK))
{
return E_FAIL;
}
// store offset and size of the data
m_dwDataStart = ck.dwDataOffset;
m_dwDataLen = ck.cksize;
}
else
{
// Wrong format
return E_FAIL;
}
// Close the file
mmioClose( hmmio, 0 );
return S_OK;
}
else
{
// File could not be openend
return E_FAIL;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -