///////////////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved. // // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation. // // Other brand and product names used herein are trademarks of their respective owners. // // The entire program and user interface including the structure, sequence, selection, // and arrangement of the dialog, the exclusively "yes" and "no" choices represented // by "1" and "2," and each dialog message are protected by copyrights registered in // the United States and by international treaties. // // Protected by one or more of the following United States patents: 5,070,526, 5,488,650, // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054. // // Active Voice Corporation // Seattle, Washington // USA // ///////////////////////////////////////////////////////////////////////////////////////// //// // wavfmt.c - wave format functions //// #include "winlocal.h" #include #include #include "wavfmt.h" #include "calc.h" #include "mem.h" #include "trace.h" //// // private definitions //// #define SAMPLERATE_DEFAULT 11025 #define SAMPLERATE_MAX 64000 #define SAMPLERATE_MIN 1000 #define SAMPLESIZE_DEFAULT 8 #define SAMPLESIZE_MAX 32 #define SAMPLESIZE_MIN 0 #define CHANNELS_DEFAULT 1 #define CHANNELS_MAX 2 #define CHANNELS_MIN 1 //// // public functions //// // WavFormatPcm - fill WAVEFORMATEX struct based on PCM characteristics // (i) sample rate // -1 default sample rate (11025) // (i) sample size // -1 default sample size (8) // (i) number of channels (1=mono, 2=stereo) // -1 default (mono) // (o) pointer to output buffer // NULL allocate new buffer to hold result // return pointer to WAVEFORMATEX struct, NULL if error // // NOTE: if points to a WAVEFORMATEX struct, this struct // is filled in, and this function returns . // If is NULL, space is dynamically allocated for the output // buffer, and this function returns a pointer to the output buffer. // Use WavFormatFree() to free the buffer. // LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatPcm(long nSamplesPerSec, WORD nBitsPerSample, WORD nChannels, LPWAVEFORMATEX lpwfx) { BOOL fSuccess = TRUE; LPWAVEFORMATEX lpwfxNew = lpwfx; if (nSamplesPerSec == -1) nSamplesPerSec = SAMPLERATE_DEFAULT; if (nBitsPerSample == -1) nBitsPerSample = SAMPLESIZE_DEFAULT; if (nChannels == -1) nChannels = CHANNELS_DEFAULT; // user passed struct to fill // if (lpwfx != NULL && IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX))) fSuccess = TraceFALSE(NULL); // we allocate struct to fill // else if (lpwfx == NULL && (lpwfxNew = WavFormatAlloc(sizeof(WAVEFORMATEX))) == NULL) fSuccess = TraceFALSE(NULL); // fill the struct // else { lpwfxNew->wFormatTag = WAVE_FORMAT_PCM; lpwfxNew->nChannels = nChannels; lpwfxNew->nSamplesPerSec = nSamplesPerSec; lpwfxNew->nBlockAlign = nChannels * (((nBitsPerSample - 1) / 8) + 1); lpwfxNew->nAvgBytesPerSec = lpwfxNew->nBlockAlign * nSamplesPerSec; lpwfxNew->wBitsPerSample = nBitsPerSample; lpwfxNew->cbSize = 0; } return fSuccess ? lpwfxNew : NULL; } // WavFormatAlloc - allocate WAVEFORMATEX struct buffer // (i) size of struct, including extra bytes // return pointer to WAVEFORMATEX struct, NULL if error // // NOTE: use WavFormatFree() to free the buffer. // LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatAlloc(WORD cbSize) { BOOL fSuccess = TRUE; LPWAVEFORMATEX lpwfx; if (cbSize < sizeof(WAVEFORMATEX)) fSuccess = TraceFALSE(NULL); // memory is allocated such that the client owns it // else if ((lpwfx = (LPWAVEFORMATEX) MemAlloc(NULL, cbSize, 0)) == NULL) fSuccess = TraceFALSE(NULL); else lpwfx->cbSize = cbSize - sizeof(WAVEFORMATEX); return fSuccess ? lpwfx : NULL; } // WavFormatDup - duplicate WAVEFORMATEX structure // (i) pointer to WAVEFORMATEX struct // return pointer to new WAVEFORMATEX struct, NULL if error // // NOTE: use WavFormatFree() to free the buffer. // LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatDup(LPWAVEFORMATEX lpwfx) { BOOL fSuccess = TRUE; LPWAVEFORMATEX lpwfxNew; if (lpwfx == NULL) fSuccess = TraceFALSE(NULL); else if (IsBadReadPtr(lpwfx, WavFormatGetSize(lpwfx))) fSuccess = TraceFALSE(NULL); else if ((lpwfxNew = WavFormatAlloc((WORD) WavFormatGetSize(lpwfx))) == NULL) fSuccess = TraceFALSE(NULL); else MemCpy(lpwfxNew, lpwfx, WavFormatGetSize(lpwfx)); return fSuccess ? lpwfxNew : NULL; } // WavFormatFree - free WAVEFORMATEX struct // (i) pointer returned from WavFormatAlloc/Dup/Pcm // return 0 if success // int DLLEXPORT WINAPI WavFormatFree(LPWAVEFORMATEX lpwfx) { BOOL fSuccess = TRUE; if (lpwfx == NULL) fSuccess = TraceFALSE(NULL); else if ((lpwfx = MemFree(NULL, lpwfx)) != NULL) fSuccess = TraceFALSE(NULL); return fSuccess ? 0 : -1; } // WavFormatIsValid - check format for validity // (i) pointer to WAVEFORMATEX struct // return TRUE if valid format // BOOL DLLEXPORT WINAPI WavFormatIsValid(LPWAVEFORMATEX lpwfx) { BOOL fSuccess = TRUE; if (lpwfx == NULL) fSuccess = TraceFALSE(NULL); else if (IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX))) fSuccess = TraceFALSE(NULL); else if (IsBadReadPtr(lpwfx, WavFormatGetSize(lpwfx))) fSuccess = TraceFALSE(NULL); else if (lpwfx->nSamplesPerSec < SAMPLERATE_MIN || lpwfx->nSamplesPerSec > SAMPLERATE_MAX) fSuccess = TraceFALSE(NULL); else if (lpwfx->wBitsPerSample < SAMPLESIZE_MIN || lpwfx->wBitsPerSample > SAMPLESIZE_MAX) fSuccess = TraceFALSE(NULL); else if (lpwfx->nChannels < CHANNELS_MIN || lpwfx->nChannels > CHANNELS_MAX) fSuccess = TraceFALSE(NULL); return fSuccess ? TRUE : FALSE; } // WavFormatCmp - compare one format with another // (i) pointer to WAVEFORMATEX struct // (i) pointer to WAVEFORMATEX struct // return 0 if identical // #if 0 // NOTE: this function does NOT compare the cbSize field or the extra bytes #else // NOTE: this function does NOT compare the extra bytes beyond the cbSize field #endif // int DLLEXPORT WINAPI WavFormatCmp(LPWAVEFORMATEX lpwfx1, LPWAVEFORMATEX lpwfx2) { BOOL fSuccess = TRUE; int nCmp = 0; // assume identical if (!WavFormatIsValid(lpwfx1)) fSuccess = TraceFALSE(NULL); else if (!WavFormatIsValid(lpwfx2)) fSuccess = TraceFALSE(NULL); else { #if 0 // compare up to (but not including) the cbSize field // nCmp = MemCmp(lpwfx1, lpwfx2, offsetof(WAVEFORMATEX, cbSize)); #else // compare up to and including the cbSize field // nCmp = MemCmp(lpwfx1, lpwfx2, sizeof(WAVEFORMATEX)); #endif } return fSuccess ? nCmp : -1; } // WavFormatCopy - copy one format to another // (i) pointer to destination WAVEFORMATEX struct // (i) pointer to source WAVEFORMATEX struct // return 0 if success // #if 0 // NOTE: this function does NOT copy the cbSize field or the extra bytes #else // NOTE: make sure lpwfxDst points to enough memory to contain the entire // WAVEFORMATEX struct plus any extra bytes beyond it #endif // int DLLEXPORT WINAPI WavFormatCopy(LPWAVEFORMATEX lpwfxDst, LPWAVEFORMATEX lpwfxSrc) { BOOL fSuccess = TRUE; if (!WavFormatIsValid(lpwfxSrc)) fSuccess = TraceFALSE(NULL); else if (lpwfxDst == NULL) fSuccess = TraceFALSE(NULL); #if 0 // make sure destination is at least as big as WAVEFORMATEX struct // else if (IsBadReadPtr(lpwfxDst, sizeof(WAVEFORMATEX)) fSuccess = TraceFALSE(NULL); else { // copy up to (but not including) the cbSize field // MemCpy(lpwfxDst, lpwfxSrc, offsetof(WAVEFORMATEX, cbSize)); } #else // make sure destination is at least as big as source // else if (IsBadReadPtr(lpwfxDst, WavFormatGetSize(lpwfxSrc))) fSuccess = TraceFALSE(NULL); else { // copy entire structure, including any extra bytes // MemCpy(lpwfxDst, lpwfxSrc, WavFormatGetSize(lpwfxSrc)); } #endif return fSuccess ? 0 : -1; } // WavFormatGetSize - check size of format structure // (i) pointer to WAVEFORMATEX struct // return size of structure, 0 if error // int DLLEXPORT WINAPI WavFormatGetSize(LPWAVEFORMATEX lpwfx) { BOOL fSuccess = TRUE; int sizwfx = 0; if (lpwfx == NULL) fSuccess = TraceFALSE(NULL); // ignore cbSize value if pcm format // else if (lpwfx->wFormatTag == WAVE_FORMAT_PCM) sizwfx = sizeof(WAVEFORMATEX); else sizwfx = sizeof(WAVEFORMATEX) + lpwfx->cbSize; return fSuccess ? sizwfx : 0; } // WavFormatDump - dump WAVEFORMATEX struct to debug // (i) pointer to WAVEFORMATEX struct // return 0 if success // int DLLEXPORT WINAPI WavFormatDump(LPWAVEFORMATEX lpwfx) { BOOL fSuccess = TRUE; if (lpwfx == NULL) fSuccess = TraceFALSE(NULL); else if (IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX))) fSuccess = TraceFALSE(NULL); else { TracePrintf_7(NULL, 1, TEXT("struct tWAVEFORMATEX\n") TEXT("{\n") TEXT("\tWORD\twFormatTag = %u;\n") TEXT("\tWORD\tnChannels = %u;\n") TEXT("\tDWORD\tnSamplesPerSec = %lu;\n") TEXT("\tDWORD\tnAvgBytesPerSec = %lu;\n") TEXT("\tWORD\tnBlockAlign = %u;\n") TEXT("\tWORD\twBitsPerSample = %u;\n") TEXT("\tWORD\tcbSize = %u;\n") TEXT("} WAVEFORMATEX\n"), (unsigned int) lpwfx->wFormatTag, (unsigned int) lpwfx->nChannels, (unsigned long) lpwfx->nSamplesPerSec, (unsigned long) lpwfx->nAvgBytesPerSec, (unsigned int) lpwfx->nBlockAlign, (unsigned int) lpwfx->wBitsPerSample, (unsigned int) lpwfx->cbSize); } return fSuccess ? 0 : -1; } // WavFormatBytesToMilleseconds - convert bytes to milleseconds // (i) pointer to WAVEFORMATEX struct // (i) bytes // return milleseconds // DWORD DLLEXPORT WINAPI WavFormatBytesToMilleseconds(LPWAVEFORMATEX lpwfx, DWORD dwBytes) { if (lpwfx == NULL || lpwfx->nAvgBytesPerSec == 0) return 0; else return MULDIVU32(dwBytes, 1000, (DWORD) lpwfx->nAvgBytesPerSec); } // WavFormatMillesecondsToBytes - convert milleseconds to bytes // (i) pointer to WAVEFORMATEX struct // (i) milleseconds // return milleseconds // DWORD DLLEXPORT WINAPI WavFormatMillesecondsToBytes(LPWAVEFORMATEX lpwfx, DWORD dwMilleseconds) { if (lpwfx == NULL || lpwfx->nAvgBytesPerSec == 0) return 0; else return MULDIVU32(dwMilleseconds, (DWORD) lpwfx->nAvgBytesPerSec, 1000); } // WavFormatSpeedAdjust - adjust format to reflect specified speed // (i/o) pointer to WAVEFORMATEX struct // (i) speed level // 50 half speed // 100 normal speed // 200 double speed, etc. // (i) reserved; must be zero // return 0 if success // int DLLEXPORT WINAPI WavFormatSpeedAdjust(LPWAVEFORMATEX lpwfx, int nLevel, DWORD dwFlags) { BOOL fSuccess = TRUE; if (lpwfx == NULL) fSuccess = TraceFALSE(NULL); else if (nLevel != 100) { lpwfx->nSamplesPerSec = lpwfx->nSamplesPerSec * nLevel / 100; lpwfx->nAvgBytesPerSec = lpwfx->nBlockAlign * lpwfx->nSamplesPerSec; } return fSuccess ? 0 : -1; } // WavFormatVoxadpcm - fill WAVEFORMATEX struct for Dialogic OKI ADPCM // (o) pointer to output buffer // NULL allocate new buffer to hold result // (i) sample rate // -1 default sample rate (6000) // return pointer to WAVEFORMATEX struct, NULL if error // // NOTE: if points to a WAVEFORMATEX struct, this struct // is filled in, and this function returns . // If is NULL, space is dynamically allocated for the output // buffer, and this function returns a pointer to the output buffer. // Use WavFormatFree() to free the buffer. // LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatVoxadpcm(LPWAVEFORMATEX lpwfx, long nSamplesPerSec) { BOOL fSuccess = TRUE; LPWAVEFORMATEX lpwfxNew = lpwfx; WORD nBitsPerSample = 4; WORD nChannels = 1; #if 0 // nBlockAlign is 4 so that chunk size of 5188 is returned from // WavCalcChunkSize(VoxFormat(NULL, 6000), 1962, TRUE); // 5188 is optimal for Dialogic buffer logic (((12 * 1024) - 512) / 2) // WORD nBlockAlign = 4; #else WORD nBlockAlign = 1; #endif if (nSamplesPerSec == -1) nSamplesPerSec = 6000; // user passed struct to fill // if (lpwfx != NULL && IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX))) fSuccess = TraceFALSE(NULL); // we allocate struct to fill // else if (lpwfx == NULL && (lpwfxNew = WavFormatAlloc(sizeof(WAVEFORMATEX))) == NULL) fSuccess = TraceFALSE(NULL); // fill the struct // else { lpwfxNew->wFormatTag = WAVE_FORMAT_DIALOGIC_OKI_ADPCM; lpwfxNew->nChannels = nChannels; lpwfxNew->nSamplesPerSec = nSamplesPerSec; lpwfxNew->nBlockAlign = nBlockAlign; lpwfxNew->nAvgBytesPerSec = nSamplesPerSec / 2; lpwfxNew->wBitsPerSample = nBitsPerSample; lpwfxNew->cbSize = 0; } return fSuccess ? lpwfxNew : NULL; } // WavFormatMulaw - fill WAVEFORMATEX struct for CCITT u-law format // (o) pointer to output buffer // NULL allocate new buffer to hold result // (i) sample rate // -1 default sample rate (8000) // return pointer to WAVEFORMATEX struct, NULL if error // // NOTE: if points to a WAVEFORMATEX struct, this struct // is filled in, and this function returns . // If is NULL, space is dynamically allocated for the output // buffer, and this function returns a pointer to the output buffer. // Use WavFormatFree() to free the buffer. // LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatMulaw(LPWAVEFORMATEX lpwfx, long nSamplesPerSec) { BOOL fSuccess = TRUE; LPWAVEFORMATEX lpwfxNew = lpwfx; WORD nBitsPerSample = 8; WORD nChannels = 1; WORD nBlockAlign = 1; if (nSamplesPerSec == -1) nSamplesPerSec = 8000; // user passed struct to fill // if (lpwfx != NULL && IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX))) fSuccess = TraceFALSE(NULL); // we allocate struct to fill // else if (lpwfx == NULL && (lpwfxNew = WavFormatAlloc(sizeof(WAVEFORMATEX))) == NULL) fSuccess = TraceFALSE(NULL); // fill the struct // else { lpwfxNew->wFormatTag = WAVE_FORMAT_MULAW; lpwfxNew->nChannels = nChannels; lpwfxNew->nSamplesPerSec = nSamplesPerSec; lpwfxNew->nBlockAlign = nBlockAlign; lpwfxNew->nAvgBytesPerSec = lpwfxNew->nBlockAlign * nSamplesPerSec; lpwfxNew->wBitsPerSample = nBitsPerSample; lpwfxNew->cbSize = 0; } return fSuccess ? lpwfxNew : NULL; } // WavFormatAlaw - fill WAVEFORMATEX struct for CCITT a-law format // (o) pointer to output buffer // NULL allocate new buffer to hold result // (i) sample rate // -1 default sample rate (8000) // return pointer to WAVEFORMATEX struct, NULL if error // // NOTE: if points to a WAVEFORMATEX struct, this struct // is filled in, and this function returns . // If is NULL, space is dynamically allocated for the output // buffer, and this function returns a pointer to the output buffer. // Use WavFormatFree() to free the buffer. // LPWAVEFORMATEX DLLEXPORT WINAPI WavFormatAlaw(LPWAVEFORMATEX lpwfx, long nSamplesPerSec) { BOOL fSuccess = TRUE; LPWAVEFORMATEX lpwfxNew = lpwfx; WORD nBitsPerSample = 8; WORD nChannels = 1; WORD nBlockAlign = 1; if (nSamplesPerSec == -1) nSamplesPerSec = 8000; // user passed struct to fill // if (lpwfx != NULL && IsBadReadPtr(lpwfx, sizeof(WAVEFORMATEX))) fSuccess = TraceFALSE(NULL); // we allocate struct to fill // else if (lpwfx == NULL && (lpwfxNew = WavFormatAlloc(sizeof(WAVEFORMATEX))) == NULL) fSuccess = TraceFALSE(NULL); // fill the struct // else { lpwfxNew->wFormatTag = WAVE_FORMAT_ALAW; lpwfxNew->nChannels = nChannels; lpwfxNew->nSamplesPerSec = nSamplesPerSec; lpwfxNew->nBlockAlign = nBlockAlign; lpwfxNew->nAvgBytesPerSec = lpwfxNew->nBlockAlign * nSamplesPerSec; lpwfxNew->wBitsPerSample = nBitsPerSample; lpwfxNew->cbSize = 0; } return fSuccess ? lpwfxNew : NULL; }