www.pudn.com > tapi3.zip > WAVEX.CPP
// Source for wave functions for the talker32 app // (c) Dialogic corp 1995, 1996 #include "stdafx.h" #include#include #include "wavstate.h" #include "wavex.h" IMPLEMENT_DYNAMIC(CTapiWave, CObject) // Do initialization as needed WAVEFORMATEX CTapiWave::wfDialogicFormats[] = {{WAVE_FORMAT_DIALOGIC_OKI_ADPCM, 1, 6000, 3000, 1,4}, {WAVE_FORMAT_DIALOGIC_OKI_ADPCM, 1, 8000, 4000, 1,4}, {WAVE_FORMAT_MULAW, 1, 6000, 6000, 1,8}, {WAVE_FORMAT_MULAW, 1, 8000, 8000, 1,8}, {WAVE_FORMAT_MULAW, 1, 11025, 11025, 1,8}, {WAVE_FORMAT_ALAW, 1, 6000, 6000, 1,8}, {WAVE_FORMAT_ALAW, 1, 8000, 8000, 1,8}, {WAVE_FORMAT_ALAW, 1, 11025, 11025, 1,8}, {WAVE_FORMAT_PCM, 1, 6000, 6000, 1,8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1,8}, {WAVE_FORMAT_PCM, 1, 11025, 11025, 1,8}, {0,0,0,0,0,0}}; CTapiWave::CTapiWave() { m_hWaveIn = NULL; m_hWaveOut = NULL; m_lpvLine = NULL; m_lpvCall = NULL; ctwSetState(WAVE_IDLE); } // Constructor CTapiWave::CTapiWave(LPVOID lpvLine, LPVOID lpvCall, DWORD dwLineID) { // Note that there is no direct reference to any of the TAPI-related classes m_lpvLine = lpvLine; m_lpvCall = lpvCall; m_dwLineID = dwLineID; if(m_lpvLine != NULL) // one file name per line ONLY sprintf(m_szRecFileName, "record%.2d.wav", m_dwLineID); else sprintf(m_szRecFileName, "%8.8x.wav", (LPVOID) this); m_hWaveIn = NULL; m_hWaveOut = NULL; m_lpvLine = NULL; m_lpvCall = NULL; m_dwVolume = MAX_ABS_VOLUME; //default=full volume ctwSetState(WAVE_IDLE); } // Public wrapper around the real play BOOL CTapiWave::ctwPlay(HWND hWnd, UINT nID, LPSTR lpFileName) { if(WAVE_IDLE != ctwGetState()) return FALSE; ctwSetState(PREPARING_TO_PLAY); m_hWaveOut = WavexPlay(hWnd, nID, lpFileName); if(m_hWaveOut != NULL) ctwSetState(PLAYING); else ctwSetState(WAVE_IDLE); return (m_hWaveOut != NULL); } // Play the WAVE file specified on input HWAVEOUT CTapiWave::WavexPlay(HWND hWnd, UINT nID, LPSTR lpFileName) { WAVEFORMATEX *lpwfWaveFormat = NULL; WAVEHDR *lpwhWaveHdr = NULL; HMMIO hmmH; HWAVEOUT hWave = NULL; MMCKINFO mmParent, mmSubchunk; DWORD dwFmtSize, dwDataSize, dwFlags; HPSTR lpWaveData = NULL; char szErr[128]; MMRESULT mmrc; TRACE("*** TALKER32 ***: enter Play\n"); // Open wave file hmmH = mmioOpen(lpFileName, NULL, MMIO_READ); //| MMIO_ALLOCBUF); if(!hmmH) { MessageBox(NULL, "Input WAVE file open failed", NULL, MB_ICONSTOP); return FALSE; } // Locate a ‘RIFF’ chunk with a ‘WAVE’ form type mmParent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); if (mmioDescend(hmmH, (LPMMCKINFO) &mmParent, NULL, MMIO_FINDRIFF)) { mmioClose(hmmH, 0); MessageBox(NULL, "Corrupted WAVE file(no WAVE form type)", NULL, MB_ICONSTOP); return FALSE; } // Find the format chunk mmSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' '); if (mmioDescend(hmmH, &mmSubchunk, &mmParent, MMIO_FINDCHUNK)) { mmioClose(hmmH, 0); MessageBox(NULL, "Corrupted WAVE file(no fmt chunk)", NULL, MB_ICONSTOP); return FALSE; } // Get the size of the format chunk, allocate memory for it dwFmtSize = mmSubchunk.cksize; lpwfWaveFormat = (WAVEFORMATEX *) malloc(dwFmtSize); if (!lpwfWaveFormat) { MessageBox(NULL, "Memory alloc for waveformat failed", NULL, MB_ICONSTOP); mmioClose(hmmH, 0); return FALSE; } ZeroMemory((PVOID)lpwfWaveFormat, dwFmtSize); // Read the format chunk if (mmioRead(hmmH, (HPSTR) lpwfWaveFormat, dwFmtSize) != (LONG) dwFmtSize) { MessageBox(NULL, "Read fmt chunk failed", NULL, MB_ICONSTOP); mmioClose(hmmH, 0); goto PlayFailed; } // Ascend out of the format subchunk mmioAscend(hmmH, &mmSubchunk, 0); // Find the data subchunk mmSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hmmH, &mmSubchunk, &mmParent, MMIO_FINDCHUNK)) { MessageBox(NULL, "Could not find data subchunk)", NULL, MB_ICONSTOP); mmioClose(hmmH, 0); goto PlayFailed; } // Get the size of the data subchunk dwDataSize = mmSubchunk.cksize; if (dwDataSize == 0L) { MessageBox(NULL, "No data to play", NULL, MB_ICONSTOP); mmioClose(hmmH, 0); goto PlayFailed; } // Allocate and lock memory for the waveform data. lpWaveData = (HPSTR) malloc(dwDataSize); if (!lpWaveData) { MessageBox(NULL, "Memory alloc for data to play failed", NULL, MB_ICONSTOP); mmioClose(hmmH, 0); goto PlayFailed; } // Read the waveform data subchunk if(mmioRead(hmmH, (HPSTR) lpWaveData, dwDataSize) != (LONG) dwDataSize) { MessageBox(NULL, "Data read failed", NULL, MB_ICONSTOP); mmioClose(hmmH, 0); goto PlayFailed; } // We’re done with the file, close it mmioClose(hmmH, 0); // Allocate a waveform data header lpwhWaveHdr = (WAVEHDR *) malloc((DWORD)sizeof(WAVEHDR)); if (!lpwhWaveHdr) { MessageBox(NULL, "Memory alloc for WAVE header failed", NULL, MB_ICONSTOP); goto PlayFailed; } // Set up WAVEHDR structure and prepare it to be written to wave device lpwhWaveHdr->lpData = lpWaveData; lpwhWaveHdr->dwBufferLength = dwDataSize; lpwhWaveHdr->dwFlags = 0L; lpwhWaveHdr->dwLoops = 0L; lpwhWaveHdr->dwUser = (DWORD) nID; // lpwfWaveFormat->cbSize = 0; /* make sure wave device can play our format */ // lpwfWaveFormat->cbSize = 0; dwFlags = WAVE_FORMAT_QUERY | WAVE_MAPPED; if (mmrc = waveOutOpen((LPHWAVEOUT)NULL, nID, lpwfWaveFormat, 0L, 0L, dwFlags)) { sprintf(szErr, "First waveOutOpen failed err=%d", mmrc); MessageBox (NULL, szErr, NULL, MB_ICONSTOP); goto PlayFailed; } dwFlags = CALLBACK_WINDOW | WAVE_MAPPED; // open the wave device corresponding to the line if (mmrc = waveOutOpen (&hWave, nID, lpwfWaveFormat, (DWORD)hWnd, 0L, dwFlags)) { wsprintf(szErr, "Error #%d opening wave device", mmrc); MessageBox (NULL, szErr, NULL, MB_ICONSTOP); goto PlayFailed; } // prepare the message header for playing if (waveOutPrepareHeader (hWave, lpwhWaveHdr, sizeof(WAVEHDR))) { MessageBox (NULL, "Error preparing message header", NULL, MB_OK); goto PlayFailed; } // Set the volume before playing waveOutSetVolume(hWave, m_dwVolume); // play the message right from the data segment; set the play message flag if (waveOutWrite (hWave, lpwhWaveHdr, sizeof (WAVEHDR))) { MessageBox (NULL, "Error writing wave message", NULL, MB_ICONSTOP); goto PlayFailed; } free( lpwfWaveFormat ); lpwfWaveFormat = NULL; TRACE("*** TALKER32 ***: end of Play\n"); return hWave; // DONE !!! PlayFailed: if(lpwfWaveFormat) free( lpwfWaveFormat ); if(lpWaveData) free(lpWaveData); if(lpwhWaveHdr) free(lpwhWaveHdr); if(hWave) waveOutClose(hWave); return FALSE; } // public wrapper for finish play void CTapiWave::ctwFinishPlay(WPARAM wParam, LPARAM lParam) { ctwSetState(FINISHING_PLAY); WavexFinishPlay(wParam, lParam); m_hWaveOut = NULL; ctwSetState(WAVE_IDLE); } // WOM message handler void CTapiWave::WavexFinishPlay(WPARAM wParam, LPARAM lParam) { LPWAVEHDR lpwhWaveHdr = (LPWAVEHDR)lParam; int nID = (int)(lpwhWaveHdr->dwUser); HWAVEIN hWaveIn = NULL; // hWaveOut; // Unprepare the header TRACE("*** TALKER32 ***: enter FinishPlay\n"); waveOutUnprepareHeader((HWAVEOUT)wParam,(LPWAVEHDR)lParam, sizeof(WAVEHDR)); waveOutClose((HWAVEOUT)wParam); // close wave device free(lpwhWaveHdr->lpData); // free the wave data free(lpwhWaveHdr); // free the header TRACE("*** TALKER32 ***: end FinishPlay\n"); return; } // Public wrapper for record BOOL CTapiWave::ctwRecord(HWND hWnd, UINT nID, int nFormatID, DWORD dwBufSize) { if(WAVE_IDLE != ctwGetState()) return FALSE; ctwSetState(PREPARING_TO_RECORD); m_hWaveIn = WavexRecord(hWnd, nID, nFormatID, dwBufSize); if(m_hWaveIn == NULL) ctwSetState(WAVE_IDLE); else ctwSetState(RECORDING); return (m_hWaveIn != NULL); } HWAVEIN CTapiWave::WavexRecord(HWND hWnd, UINT nID, int nFormatID, DWORD dwBufSize) { HWAVEIN hWaveIn; //DWORD dwBufSize = 0xfffe;//10L * (LONG)pcwfGWaveFormat.wf.nSamplesPerSec * // (LONG)pcwfGWaveFormat.wBitsPerSample/8L; WAVEFORMATEX pcwfWaveFormat; //= {WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8, 0}; LPWAVEHDR lpwhInWaveHdr = NULL; PCASHEDINFO pCash = (PCASHEDINFO)new CASHEDINFO; WORD wrc; char szErr[128]; if(!pCash) { MessageBox (NULL, "Memory allocation failed in record", NULL, MB_ICONSTOP); return NULL; } pCash->nFormatID = nFormatID; // save information to use when finished pCash->WF = wfDialogicFormats[nFormatID]; pcwfWaveFormat = pCash->WF; // open recorder if (wrc = waveInOpen( &hWaveIn, (WORD) nID, (LPWAVEFORMATEX)&pcwfWaveFormat, (DWORD)hWnd, NULL, CALLBACK_WINDOW | WAVE_MAPPED)) { wsprintf(szErr, "Error #%d opening wave record device", wrc); MessageBox (NULL, szErr, NULL,MB_ICONSTOP); delete pCash; return NULL; } // allocate wave header if(NULL == (lpwhInWaveHdr = (LPWAVEHDR) malloc((long)sizeof(WAVEHDR)))) { MessageBox (NULL, "Memory alloc for in/header failed", NULL, MB_ICONSTOP); delete pCash; return NULL; } // allocates message buffer if (NULL == (lpwhInWaveHdr->lpData = (HPSTR) malloc(dwBufSize))) { MessageBox (NULL, "Memory alloc for record failed", NULL, MB_ICONSTOP); delete pCash; return NULL; } lpwhInWaveHdr->dwBufferLength = dwBufSize; lpwhInWaveHdr->dwFlags=0L; lpwhInWaveHdr->dwLoops=0L; lpwhInWaveHdr->dwUser = (DWORD)pCash; if (waveInPrepareHeader(hWaveIn, lpwhInWaveHdr, sizeof(WAVEHDR))) { MessageBox (NULL, "Error preparing message header.", NULL, MB_ICONSTOP); delete pCash; free(lpwhInWaveHdr->lpData); return FALSE; } // pass down a 6s buffer to record into if (waveInAddBuffer (hWaveIn, lpwhInWaveHdr, sizeof(WAVEHDR))) { MessageBox (NULL, "Error adding buffer", NULL, MB_ICONSTOP); delete pCash; free(lpwhInWaveHdr->lpData); return FALSE; } if(waveInStart(hWaveIn)) { MessageBox (NULL, "Failed to start recording", NULL, MB_ICONSTOP); delete pCash; free(lpwhInWaveHdr->lpData); return FALSE; } return hWaveIn; } // Public wrapper for finish record void CTapiWave::ctwFinishRecord(WPARAM wParam, LPARAM lParam, LPSTR lpName) { ctwSetState(FINISHING_RECORD); WavexFinishRecord(wParam, lParam, lpName); m_hWaveIn = NULL; ctwSetState(WAVE_IDLE); } // WIM message handler void CTapiWave::WavexFinishRecord(WPARAM wParam, LPARAM lParam, LPSTR lpName) { LPWAVEHDR lpwhWaveHdr = (LPWAVEHDR) lParam; TRACE("*** TALKER32 ***: enter FinishRecord\r\n"); waveInUnprepareHeader((HWAVEIN) wParam, lpwhWaveHdr, sizeof(WAVEHDR)); waveInStop((HWAVEIN) wParam); waveInClose((HWAVEIN) wParam); WavexSaveData(lpwhWaveHdr, lpName); free(lpwhWaveHdr->lpData); free((LPSTR)lpwhWaveHdr); TRACE("*** TALKER32 ***: end FinishRecord\r\n"); return; } // Borrowed from tam.c void CTapiWave::WavexSaveData(LPWAVEHDR lpwhWH, LPSTR lpName) { PCASHEDINFO pCash = (PCASHEDINFO)lpwhWH->dwUser; PCMWAVEFORMAT *ppcwfWF; //={WAVE_FORMAT_PCM, 1, 11025, 11025, 1,8}; LPSTR lpszName; char szErr[64]; if(!pCash) { MessageBox(NULL, "Corrupted header!!!", NULL, MB_ICONSTOP); return; } ppcwfWF = (PCMWAVEFORMAT *)&pCash->WF; // RIFF chunk BYTE abRiffchunk[] = {'R','I','F','F', 0,0,0,0, 'W','A','V','E'}; // format chunk tag BYTE abFormatchunktag[] = {'f','m','t',' ', 0,0,0,0}; // data chunk header BYTE abDatachunktag[] = {'d','a','t','a', 0,0,0,0}; HFILE hFile; if(lpName == NULL) lpszName = m_szRecFileName; // for now one name per line else lpszName = lpName; if(HFILE_ERROR == (hFile = _lcreat (lpszName, 0))) // O_CREAT | O_BINARY | O_WRONLY)) { sprintf(szErr,"Error opening %s", lpszName); MessageBox (NULL, szErr, NULL, MB_ICONSTOP); delete pCash; return; } // write out the RIFF chunk *((DWORD *)&abRiffchunk[4])=4 + sizeof(abFormatchunktag) + sizeof(PCMWAVEFORMAT) + sizeof(abDatachunktag) + lpwhWH->dwBytesRecorded; _lwrite(hFile, (const char *)abRiffchunk, sizeof(abRiffchunk)); *((DWORD *)&abFormatchunktag[4]) = sizeof(PCMWAVEFORMAT); // write tag _lwrite(hFile, (const char *)abFormatchunktag, sizeof(abFormatchunktag)); // write out the canned format header _lwrite (hFile, (const char *)ppcwfWF, sizeof(PCMWAVEFORMAT)); // write out the data chunk tag *((DWORD *)&abDatachunktag[4]) = lpwhWH->dwBytesRecorded; _lwrite(hFile, (const char *)abDatachunktag, sizeof(abDatachunktag)); // write out the data chunk _hwrite (hFile, lpwhWH->lpData, lpwhWH->dwBytesRecorded); _lclose (hFile); delete pCash; return; } // Public pause function BOOL CTapiWave::ctwPause() { if(PLAYING != ctwGetState()) return FALSE; if(MMSYSERR_NOERROR != waveOutPause(m_hWaveOut)) return FALSE; //failed to pause ctwSetState(PAUSED); return TRUE; } // Resume after pause BOOL CTapiWave::ctwResume() { if(PAUSED != ctwGetState()) return FALSE; if(MMSYSERR_NOERROR != waveOutRestart(m_hWaveOut)) return FALSE; //failed to resume ctwSetState(PLAYING); return TRUE; } // Public stop function BOOL CTapiWave::ctwStop() { DWORD dwState = ctwGetState(); if (dwState == PLAYING || dwState == PAUSED) { if(MMSYSERR_NOERROR != waveOutReset(m_hWaveOut)) return FALSE; } else if (dwState == RECORDING) { if(MMSYSERR_NOERROR != waveInReset(m_hWaveIn)) return FALSE; } return TRUE; } // Public set volume void CTapiWave::ctwSetVolume(DWORD dwVol) { DWORD dwState = ctwGetState(); m_dwVolume = dwVol; if (dwState == PLAYING || dwState == PAUSED) waveOutSetVolume(m_hWaveOut, dwVol); }