⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hsound.cpp

📁 一个使用tapi实现的自动语音应答的例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        mmioClose(hmmio, 0);
		dwDataSize = 0;
        return NULL;
    }
					 /* We're done with the file, let's close it */
    mmioClose(hmmio, 0);

	if (!m_bContinue)
	{
		free(lpWaveFmt);
		free(lpData);
		dwDataSize = 0;
        return NULL;
	}
	return lpData;
}

 /*****************************************************************
 * Pauses playing
 *****************************************************************/
BOOL CHSound::Pause()
{
	return FALSE;
}

 /*****************************************************************
 * Stops playing
 *****************************************************************/
BOOL CHSound::Stop()
{
	return FALSE;
}

 /*****************************************************************
 * Closes the device
 *****************************************************************/
BOOL CHSound::Close()
{
	m_bContinue = FALSE;
	m_bForceClose = TRUE;

	SetStatus(STT_RSTTING);
	MMRESULT mmRes = waveOutReset(m_hWaveOut);

	int	ptcn = 0;
						/* If we were playng */
	if (mmRes==0) {
		while(GetStatus()!=STT_ASLEEP) {
			WaitForSingleObject(m_hStatEvent,100);
			if (ptcn++>10) break;
			ResetEvent(m_hStatEvent);
		}
//		return TRUE;
	}

	KillTimer();
	CleanPlayList();
	SetStatus(STT_ASLEEP);

	return TRUE;
}

 /*****************************************************************
 * Indicates wheather this device is playing a sound or not
 *****************************************************************/
BOOL CHSound::IsPlaying()
{
	if (GetStatus()==STT_PLAYING)
		return TRUE;

	return FALSE;
}

 /*****************************************************************
 * Thread to receive and process sound messages
 ******************************************************************
 *
 * MSDN says it's not possible to do waveOutUnprepareHeader in the
 * callback function, so I do it here + I do cleanup.
 *
 *****************************************************************/
UINT CHSound::CallBackThread(LPVOID pParam)
{
	CHSound* pParent = (CHSound*) pParam;
	MSG msg;

	while (m_bThreadContinue) {
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
									/* One file playback is done */
			if ( msg.message==MM_WOM_DONE ) {
				if (msg.lParam)
					pParent->PlayNextBuffer(msg);/* Inform parent */
			}
		} else Sleep(5);
	}

	return 0;
}

void CHSound::SetStatus(DWORD dwCurStat)
{
	EnterCriticalSection(&m_statusCrtcSec);
	m_dwStatus ^= m_dwStatus;
	m_dwStatus |= dwCurStat;
	LeaveCriticalSection(&m_statusCrtcSec);
	
	SetEvent(m_hStatEvent);
}

DWORD CHSound::GetStatus()
{
	return m_dwStatus;
}

void CHSound::PlayNextBuffer(MSG msg)
{
	if (!m_bContinue) {
		goto PNB_EXIT;
							// Any more buffers to read?
	} else if (m_dwCurrtBufIndex<m_dwBufCnt) {

		mmRes = waveOutWrite(
			m_hWaveOut,
			m_lpWHdr,
			sizeof(WAVEHDR) );

										/* Can't Do the last job :(( */
		if ( MMSYSERR_NOERROR != mmRes ) {
			SetStatus(STT_RSTTING);
			waveOutUnprepareHeader(m_hWaveOut,m_lpWHdr,sizeof(WAVEHDR));
			SetStatus(STT_CLOSING);
			waveOutClose(m_hWaveOut);
			goto PNB_EXIT;
		}

		// Prepare next buffer
		m_dwCurrtBufIndex++;
		if ((m_dwCurrtBufIndex+1)==m_dwBufCnt) {
			m_dwBLength = 
				m_dwDataSize-((m_dwCurrtBufIndex)*m_dwMinBufSize);
		} else {
			m_dwBLength = m_dwMinBufSize;
		}
		m_lpBuf2 += m_dwMinBufSize;
		m_lpWHdr->lpData = m_lpBuf2;
		m_lpWHdr->dwBufferLength = m_dwBLength;
	} else {
//		m_dwCurrtBufIndex = 0;
//		m_dwBufCnt = 0;
		goto PNB_EXIT;
	}
	return;

PNB_EXIT:;
	SetStatus(STT_RSTTING);
	m_lpWHdr->dwBufferLength = m_dwDataSize;
	m_lpWHdr->lpData = m_lpData;

	waveOutUnprepareHeader(
		m_hWaveOut,
		m_lpWHdr,
		sizeof(WAVEHDR));
	SetStatus(STT_CLOSING);
											/* close wave device */
	waveOutClose((HWAVEOUT)msg.wParam);
										   /* free the wave data */
	SetStatus(STT_RSTTING);
	free (m_lpData);
	free (m_lpWHdr);						  /* free the header */
	SetStatus(STT_ASLEEP);

	if (m_bContinue)
		PlayNextFile();
}

BOOL CHSound::PlayNextFile()
{
	if (!m_bContinue) return FALSE;

	int patience = 0,retryP = 0;
	CString str = _T("");

retry:;
	  patience = 0;
									/* Give me next file to play */
						/* If, for any reason, FileName is empty */
	while (str==_T("")) {
		str = m_playList.GetNext();

		if (++patience>1000) return FALSE;
		if (!m_bContinue) return FALSE;
	}
									 /* If play list is finished */
	if ( str == _T("END_OF_LIST") ) {
		if (m_bExitAfter) {
			KillTimer();
			PostThreadMessage(m_boss,WM_SOUND_DONE,1,0);
			
		} else {
						   /* Playback ended, so set a timer to  */
			SetTimer();				/* restart playing last menu */
		}									   /* in an interval */
		return TRUE;
	} else if ( str==_T("DELAY")) {
		if (!m_bContinue) return FALSE;
		Sleep(500);
		str = _T("");
		patience = 0;
		goto retry;
	}

		  /* We are going to play, so tell the timer to shut up! */
	KillTimer();

											   /* Start playback */
	if (!Play( m_dwDevId, str )) {
		if (!m_bContinue) return FALSE;
		else {
			TRACE(L"Cant play  [%s] \n",str);
								 /* Skip this file if can't play */
			if (++retryP>10) {
				retryP = 0;
				str=_T("");
			}
//			Sleep(100);
			goto retry;
		}
	}
	return TRUE;
}
 /*****************************************************************
 * We need a window to start or kill a timer. I'm too lazy writing 
 * my own class!
 ******************************************************************
 *
 * WARNING: If you need a timer, rhis function MUST be called
 *			In a class that has a pointer to a dialog, or any
 *			type of a window, & the window MUST process Timer
 *			events. Look at DaliaDlg here.
 *
 *****************************************************************/
void CHSound::SetTimerWindow(CWnd *wndTimer)
{
	m_wndTimer = wndTimer;
}

 /*****************************************************************
 * Sets a timer
 *****************************************************************/
void CHSound::SetTimer()
{
	if (m_wndTimer) {
		if (m_wndTimer->GetSafeHwnd())
			m_wndTimer->SendMessage(
				WM_S_TIMER, SET,0);
	}
}

 /*****************************************************************
 * Kills the timer, though No more notifications
 *****************************************************************/
void CHSound::KillTimer()
{
	if (m_wndTimer) {
		if (m_wndTimer->GetSafeHwnd())
			m_wndTimer->SendMessage(
				WM_S_TIMER, KILL,0);
	}
}

 /*****************************************************************
 * Start playing 'play list'
 *****************************************************************/
BOOL CHSound::PlayList(DWORD dwDeviceId, BOOL bExitAfter, BOOL bDisableForceExit)
{
	if (m_bForceClose && (!bDisableForceExit) ) return FALSE;

	if (bDisableForceExit) {
		m_bForceClose  = FALSE;
	}

	m_dwDevId	 = dwDeviceId;
	m_bExitAfter = bExitAfter;
	m_bContinue  = TRUE;
								   /* Now start playing new list */
	return PlayNextFile();
}

 /*****************************************************************
 * Adds a file to our 'play list'
 *****************************************************************/
void CHSound::AddToPlayList(CString szWaveFile)
{
	m_playList.Add(szWaveFile);
}

 /*****************************************************************
 * Removes all files from the 'play list'
 *****************************************************************/
void CHSound::CleanPlayList()
{
	m_playList.Reset();
}

 /*****************************************************************
 * Makes sound class ready to get new inputs
 *****************************************************************/
BOOL CHSound::Reset()
{
	EnterCriticalSection(&m_externalResetCrtcSec);

	if (GetStatus()==STT_EXTRNRS || 
		!m_bContinue) {
		LeaveCriticalSection(&m_externalResetCrtcSec);
		return FALSE;
	}

	LeaveCriticalSection(&m_externalResetCrtcSec);

	m_bContinue = FALSE;
	SetStatus(STT_EXTRNRS);
	MMRESULT mmRes = waveOutReset(m_hWaveOut);

	int	ptcn = 0;
						/* If we were playng */
	if (mmRes==0) {
		while(GetStatus()!=STT_ASLEEP) {
			WaitForSingleObject(m_hStatEvent,100);
			if (ptcn++>10) break;
			ResetEvent(m_hStatEvent);
		}
//		return TRUE;
	}

	KillTimer();
	CleanPlayList();
	SetStatus(STT_ASLEEP);

	return TRUE;
}

 /*****************************************************************
 * Set a thread ID and use it to talk to parent manager
 *****************************************************************/
void CHSound::SetManager(unsigned long mngrThread)
{
	m_boss = mngrThread;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -