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); 
}