📄 tapiwave.c
字号:
if (MMSYSERR_NOERROR == waveInGetDevCaps(WaveInID, &in, sizeof(in)))
{
MyPrintf(
TEXT("WaveInDevCaps:\r\n")
TEXT(" wMid: 0x%04X\r\n")
TEXT(" wPid: 0x%04X\r\n")
TEXT(" vDriverVersion: 0x%04X\r\n")
TEXT(" pszPname: %s\r\n")
TEXT(" dwFormats: 0x%08X\r\n")
TEXT(" dwChannels: 0x%04X\r\n")
,
in.wMid, in.wPid, in.vDriverVersion, in.szPname, in.dwFormats, in.wChannels);
}
else
MyPrintf(TEXT("waveInGetDevCaps failed.\r\n"));
if (MMSYSERR_NOERROR == waveOutGetDevCaps(WaveOutID, &out, sizeof(out)))
{
MyPrintf(
TEXT("WaveOutDevCaps:\r\n")
TEXT(" wMid: 0x%04X\r\n")
TEXT(" wPid: 0x%04X\r\n")
TEXT(" vDriverVersion: 0x%04X\r\n")
TEXT(" pszPname: %s\r\n")
TEXT(" dwFormats: 0x%08X\r\n")
TEXT(" dwChannels: 0x%04X\r\n")
,
out.wMid, out.wPid, out.vDriverVersion, out.szPname, out.dwFormats, out.wChannels);
}
else
MyPrintf(TEXT("waveInGetDevCaps failed.\r\n"));
// TODO Find out if its capable of simultaneous recording and playing
}
PMYWAVEDATA LoadWaveInfo(WAVEFORMATEX* pFormat)
{
MMRESULT mmResult;
HMMIO hmmio = {0};
MMCKINFO mmckinfoParent;
MMCKINFO mmckinfoSubchunk;
DWORD dwFmtSize;
DWORD dwChunkSize;
PMYWAVEDATA pWaveHead = NULL,
pWaveCurr = NULL,
pWavePrev = NULL;
BOOL bLooping = TRUE;
DWORD dwBuffers = 0;
// Open the given file for reading using buffered I/O.
if(!(hmmio = mmioOpen(szFileName, NULL, MMIO_READ | MMIO_ALLOCBUF)))
{
MyPrintf(TEXT("mmioOpen failed to open file.\r\n"));
return NULL;
}
// Locate a 'RIFF' chunk with a 'WAVE' form type to make sure it's a WAVE file.
mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
if (mmResult = mmioDescend(hmmio, &mmckinfoParent, NULL, MMIO_FINDRIFF))
{
MyPrintf(TEXT("mmioDescend RIFF WAVE returned %s\r\n"), FormatWaveOutError(mmResult));
goto end;
}
// Now, find the format chunk (form type 'fmt '). It should be
// a subchunk of the 'RIFF' parent chunk.
mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
MMIO_FINDCHUNK))
{
MyPrintf(TEXT("Wave file corrupt.\r\n"));
goto end;
}
// Get the size of the format chunk, allocate and lock memory for it.
dwFmtSize = mmckinfoSubchunk.cksize;
if (pFormat->cbSize < dwFmtSize)
{
MyPrintf(TEXT("Format chunk not big enough.\r\n"));
goto end;
}
// Read the format chunk.
if (mmioRead(hmmio, (HPSTR) pFormat, dwFmtSize) != (LONG) dwFmtSize)
{
MyPrintf(TEXT("mmioRead: failed to read FMT chunk.\r\n"));
goto end;
}
MyPrintf(TEXT("wFormatTag = %lu\r\n"), (DWORD) pFormat->wFormatTag);
MyPrintf(TEXT("nChannels = %lu\r\n"), (DWORD) pFormat->nChannels );
MyPrintf(TEXT("nSamplesPerSec = %lu\r\n"), (DWORD) pFormat->nSamplesPerSec);
MyPrintf(TEXT("nAvgBytesPerSec = %lu\r\n"), (DWORD) pFormat->nAvgBytesPerSec);
MyPrintf(TEXT("nBlockAlign = %lu\r\n"), (DWORD) pFormat->nBlockAlign);
MyPrintf(TEXT("wBitsPerSample = %lu\r\n"), (DWORD) pFormat->wBitsPerSample);
MyPrintf(TEXT("cbSize = %lu\r\n"), (DWORD) pFormat->cbSize);
// Ascend out of the format subchunk.
mmioAscend(hmmio, &mmckinfoSubchunk, 0);
// Find the data subchunk.
mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
MMIO_FINDCHUNK))
{
MyPrintf(TEXT("mmioDescend: No DATA chunk.\r\n"));
goto end;
}
// Get the size of the data subchunk.
if (mmckinfoSubchunk.cksize == 0L)
{
MyPrintf(TEXT("Data chunk actually has no data.\r\n"));
goto end;
}
MyPrintf(TEXT("Size of data is %lu\r\n"),mmckinfoSubchunk.cksize);
// Now read the data and allocate MYWAVEDATA buffers
dwChunkSize = (pFormat->nAvgBytesPerSec/4);
dwChunkSize -= dwChunkSize % pFormat->nBlockAlign;
if (dwChunkSize < pFormat->nBlockAlign)
{
MyPrintf(TEXT("Couldn't calculate a good block size\r\n"));
goto end;
}
while(bLooping)
{
LONG lRead;
pWaveCurr = (PMYWAVEDATA) LocalAlloc(LPTR, dwChunkSize + sizeof(MYWAVEDATA));
pWaveCurr->wavehdr.lpData = pWaveCurr->data;
if (pWaveHead == NULL)
pWaveHead = pWaveCurr;
// Read the waveform data subchunk.
lRead = mmioRead(hmmio, pWaveCurr->data, dwChunkSize);
pWaveCurr->wavehdr.dwBufferLength = lRead;
if (lRead == -1)
{
MyPrintf(TEXT("Error reading from file.\r\n"));
pWaveHead = NULL; // Leak leak
goto end;
}
if (lRead == 0)
{
LocalFree(pWaveCurr);
break;
}
if ((DWORD)lRead != dwChunkSize)
{
bLooping = FALSE;
}
if (pWavePrev != NULL)
pWavePrev->pNext = pWaveCurr;
pWavePrev = pWaveCurr;
dwBuffers++;
}
MyPrintf(TEXT("There were %lu buffers read from %s\r\n"), dwBuffers, szFileName);
end:
mmioClose(hmmio, 0);
return pWaveHead;
}
/*=== Printing routines =============================================================*/
/*
This is easily used to do error messages like this:
MyPrintf(TEXT("API blah failed with error: %s\r\n"), FormatError(GetLastError()));
*/
#define MAX_PRINT_STRING 1024
//#define MSG_BOX_PRINT
#ifdef _DEBUG
#define MSG_DEBUG_PRINT
#endif
#define MSG_CONSOLE_PRINT
//#define MSG_FILE_PRINT
#ifdef MSG_FILE_PRINT
TCHAR szFilePrint[MAX_PATH] = TEXT(".\\out.txt");
BOOL bZeroFile = FALSE;
#endif
LPTSTR FormatWaveError(MMRESULT mmrError, MMRESULT (WINAPI *pfn) (MMRESULT, LPTSTR, UINT), LPTSTR szErr)
{
_declspec(thread) static TCHAR szOutput[MAX_PRINT_STRING];
MMRESULT mmResult2;
mmResult2 = pfn(mmrError, szOutput, MAX_PRINT_STRING);
if (mmResult2 != MMSYSERR_NOERROR)
{
TCHAR szTmp[256];
MMRESULT mmResult3;
mmResult3 = pfn(mmResult2, szOutput, 256);
if (mmResult2 != MMSYSERR_NOERROR)
wsprintf(szOutput, TEXT("%s returned an %lu on %lu"), szErr, mmResult2, mmrError);
else
wsprintf(szOutput, TEXT("%s on error %lu"), szTmp, mmrError);
}
return szOutput;
}
LPTSTR FormatWaveOutError(MMRESULT mmrError)
{
return FormatWaveError(mmrError, waveOutGetErrorText, TEXT("waveOutGetError"));
}
LPTSTR FormatWaveInError(MMRESULT mmrError)
{
return FormatWaveError(mmrError, waveInGetErrorText, TEXT("waveInGetError"));
}
// Turn a TAPI Line error into a printable string.
LPTSTR FormatTapiError (long lError)
{
static LPTSTR pszLineError[] =
{
TEXT("LINEERR No Error"),
TEXT("LINEERR_ALLOCATED"),
TEXT("LINEERR_BADDEVICEID"),
TEXT("LINEERR_BEARERMODEUNAVAIL"),
TEXT("LINEERR Unused constant, ERROR!!"),
TEXT("LINEERR_CALLUNAVAIL"),
TEXT("LINEERR_COMPLETIONOVERRUN"),
TEXT("LINEERR_CONFERENCEFULL"),
TEXT("LINEERR_DIALBILLING"),
TEXT("LINEERR_DIALDIALTONE"),
TEXT("LINEERR_DIALPROMPT"),
TEXT("LINEERR_DIALQUIET"),
TEXT("LINEERR_INCOMPATIBLEAPIVERSION"),
TEXT("LINEERR_INCOMPATIBLEEXTVERSION"),
TEXT("LINEERR_INIFILECORRUPT"),
TEXT("LINEERR_INUSE"),
TEXT("LINEERR_INVALADDRESS"),
TEXT("LINEERR_INVALADDRESSID"),
TEXT("LINEERR_INVALADDRESSMODE"),
TEXT("LINEERR_INVALADDRESSSTATE"),
TEXT("LINEERR_INVALAPPHANDLE"),
TEXT("LINEERR_INVALAPPNAME"),
TEXT("LINEERR_INVALBEARERMODE"),
TEXT("LINEERR_INVALCALLCOMPLMODE"),
TEXT("LINEERR_INVALCALLHANDLE"),
TEXT("LINEERR_INVALCALLPARAMS"),
TEXT("LINEERR_INVALCALLPRIVILEGE"),
TEXT("LINEERR_INVALCALLSELECT"),
TEXT("LINEERR_INVALCALLSTATE"),
TEXT("LINEERR_INVALCALLSTATELIST"),
TEXT("LINEERR_INVALCARD"),
TEXT("LINEERR_INVALCOMPLETIONID"),
TEXT("LINEERR_INVALCONFCALLHANDLE"),
TEXT("LINEERR_INVALCONSULTCALLHANDLE"),
TEXT("LINEERR_INVALCOUNTRYCODE"),
TEXT("LINEERR_INVALDEVICECLASS"),
TEXT("LINEERR_INVALDEVICEHANDLE"),
TEXT("LINEERR_INVALDIALPARAMS"),
TEXT("LINEERR_INVALDIGITLIST"),
TEXT("LINEERR_INVALDIGITMODE"),
TEXT("LINEERR_INVALDIGITS"),
TEXT("LINEERR_INVALEXTVERSION"),
TEXT("LINEERR_INVALGROUPID"),
TEXT("LINEERR_INVALLINEHANDLE"),
TEXT("LINEERR_INVALLINESTATE"),
TEXT("LINEERR_INVALLOCATION"),
TEXT("LINEERR_INVALMEDIALIST"),
TEXT("LINEERR_INVALMEDIAMODE"),
TEXT("LINEERR_INVALMESSAGEID"),
TEXT("LINEERR Unused constant, ERROR!!"),
TEXT("LINEERR_INVALPARAM"),
TEXT("LINEERR_INVALPARKID"),
TEXT("LINEERR_INVALPARKMODE"),
TEXT("LINEERR_INVALPOINTER"),
TEXT("LINEERR_INVALPRIVSELECT"),
TEXT("LINEERR_INVALRATE"),
TEXT("LINEERR_INVALREQUESTMODE"),
TEXT("LINEERR_INVALTERMINALID"),
TEXT("LINEERR_INVALTERMINALMODE"),
TEXT("LINEERR_INVALTIMEOUT"),
TEXT("LINEERR_INVALTONE"),
TEXT("LINEERR_INVALTONELIST"),
TEXT("LINEERR_INVALTONEMODE"),
TEXT("LINEERR_INVALTRANSFERMODE"),
TEXT("LINEERR_LINEMAPPERFAILED"),
TEXT("LINEERR_NOCONFERENCE"),
TEXT("LINEERR_NODEVICE"),
TEXT("LINEERR_NODRIVER"),
TEXT("LINEERR_NOMEM"),
TEXT("LINEERR_NOREQUEST"),
TEXT("LINEERR_NOTOWNER"),
TEXT("LINEERR_NOTREGISTERED"),
TEXT("LINEERR_OPERATIONFAILED"),
TEXT("LINEERR_OPERATIONUNAVAIL"),
TEXT("LINEERR_RATEUNAVAIL"),
TEXT("LINEERR_RESOURCEUNAVAIL"),
TEXT("LINEERR_REQUESTOVERRUN"),
TEXT("LINEERR_STRUCTURETOOSMALL"),
TEXT("LINEERR_TARGETNOTFOUND"),
TEXT("LINEERR_TARGETSELF"),
TEXT("LINEERR_UNINITIALIZED"),
TEXT("LINEERR_USERUSERINFOTOOBIG"),
TEXT("LINEERR_REINIT"),
TEXT("LINEERR_ADDRESSBLOCKED"),
TEXT("LINEERR_BILLINGREJECTED"),
TEXT("LINEERR_INVALFEATURE"),
TEXT("LINEERR_NOMULTIPLEINSTANCE")
};
_declspec(thread) static TCHAR szError[512];
DWORD dwError;
HMODULE hTapiUIMod = GetModuleHandle(TEXT("TAPIUI.DLL"));
if (hTapiUIMod)
{
dwError = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,
(LPCVOID)hTapiUIMod, TAPIERROR_FORMATMESSAGE(lError),
0, szError, sizeof(szError)/sizeof(TCHAR), NULL);
if (dwError)
return szError;
}
// Strip off the high bit to make the error code positive.
dwError = (DWORD)lError & 0x7FFFFFFF;
if ((lError > 0) || (dwError > sizeof(pszLineError)/sizeof(pszLineError[0])))
{
wsprintf(szError, TEXT("Unknown TAPI error code: 0x%lx"), lError);
return szError;
}
return pszLineError[dwError];
}
void __cdecl MyPrintf(LPCTSTR pszFormat, ...)
{
_declspec(thread) static TCHAR szOutput[MAX_PRINT_STRING]; // max printable string length
va_list v1;
DWORD dwSize;
va_start(v1, pszFormat);
dwSize = wvsprintf(szOutput, pszFormat, v1);
#ifdef MSG_DEBUG_PRINT
OutputDebugString(szOutput);
#endif
#ifdef MSG_CONSOLE_PRINT
_tprintf(szOutput);
#endif
#ifdef MSG_BOX_PRINT
MessageBox(NULL, szOutput,TEXT("MyPrintf Output"), MB_OK);
#endif
#ifdef MSG_FILE_PRINT
{
static HANDLE hFile = NULL;
DWORD dwNumWritten;
if (hFile == NULL)
{
hFile = CreateFile(szFilePrint, GENERIC_WRITE, FILE_SHARE_READ, NULL,
bZeroFile ? CREATE_ALWAYS : OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
MyPrintf(TEXT("CreateFile output log file %s failed with %s\r\n"), szFilePrint, FormatError(GetLastError()));
else
SetFilePointer(hFile, 0, NULL, FILE_END);
}
if (hFile != INVALID_HANDLE_VALUE)
{
OVERLAPPED ol = {0};
LockFileEx(hFile, 0, 0, 1, 0, &ol);
WriteFile(hFile, szOutput, dwSize*sizeof(TCHAR), &dwNumWritten, NULL);
UnlockFileEx(hFile, 0, 1, 0, &ol);
}
}
#endif
}
LPCTSTR FormatError(DWORD dwError)
{
_declspec(thread) static TCHAR szBuff[MAX_PRINT_STRING];
return FormatErrorBuffer(dwError, szBuff, MAX_PRINT_STRING);
}
LPCTSTR FormatErrorBuffer(DWORD dwError, LPTSTR pszBuff, DWORD dwNumChars)
{
DWORD dwRetFM = 0;
dwRetFM = wsprintf(pszBuff, TEXT("%lu - "), dwError);
dwRetFM = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0,
&pszBuff[dwRetFM], dwNumChars - dwRetFM, NULL);
if (dwRetFM == 0)
{
wsprintf(pszBuff, TEXT("FormatMessage failed on %lu with %lu"),
dwError, GetLastError());
}
return pszBuff;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -