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

📄 winaudio.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}

HX_RESULT CAudioOutWindows::_Imp_Close()
{
#ifdef _TESTING
	if ( m_audfile > 0 ) 
		close(m_audfile);
	m_audfile = -1;
#endif

 zm_bClosed = TRUE;
    if (m_hWave) 
    {
	// NOTE: Before we can close, we need to reset!
	Reset();

	m_pMutex->Lock();

	if (m_pWaveHdrs)
	{
	    UINT16 unWHIndex;

	    // Unprepare the individual headers
	    for (unWHIndex = 0; unWHIndex < m_unAllocedBufferCnt; ++unWHIndex)
	    {
    		CWaveHeader* pWaveHeader = &m_pWaveHdrs[unWHIndex];
		if (pWaveHeader->m_pPrepared)
		{
		    LPWAVEHDR lpwHeader = LPWAVEHDR(&pWaveHeader->m_WAVEHDR);
		    
		    // By now all headers should be marked as done because they
		    // are back from the audio device or prepared because we
		    // prepared them but never used them
		    HX_ASSERT(lpwHeader->dwFlags & WHDR_DONE ||
			lpwHeader->dwFlags & WHDR_PREPARED);

		    //OutputDebugString("BEFORE CALL TO:waveOutUnprepareHeader\r\n");
		    HX_VERIFY(MMSYSERR_NOERROR == waveOutUnprepareHeader(m_hWave, 
					LPWAVEHDR(&pWaveHeader->m_WAVEHDR), sizeof(WAVEHDR)));
		    //OutputDebugString("AFTER CALL TO:waveOutUnprepareHeader\r\n");
		    pWaveHeader->m_pPrepared = FALSE;
		}
	    }
	}
	
	if (m_ppAllocedBuffers)
	{
	    UINT16 unIndex;

	    for (unIndex = 0; unIndex < m_unAllocedBufferCnt; unIndex++)
	    {
		delete[] m_ppAllocedBuffers[unIndex];
	    }
	    delete[] m_ppAllocedBuffers;
	    m_ppAllocedBuffers = NULL;
	}

	m_rAvailBuffers.FlushQueue();
	m_UsedBuffersList.RemoveAll();

	m_unAllocedBufferCnt = 0;
	
	m_pMutex->Unlock();

	for (int i = 0; 
		i < 5 && (WAVERR_STILLPLAYING == waveOutClose( m_hWave )); ++i)
	{
	    waveOutReset( m_hWave );
	}
	m_hWave = NULL;

	if (m_pWaveHdrs)
	{
	    delete[] m_pWaveHdrs;
	    m_pWaveHdrs = NULL;
	}
    }

    UnRegister();
    m_bIsFirstPacket	= TRUE;
    m_bInitialized	= FALSE;

    return HXR_OK;
}

HX_RESULT CAudioOutWindows::_Imp_Write
( 
    const HXAudioData* pAudioOutHdr 
)
{
    BOOL	    bTemp;
    CWaveHeader*    pWaveHeader;
    MMRESULT	    res;
    ULONG32	    ulBufLen = 0;
    UCHAR*	    pBuffer = 0;
    if (pAudioOutHdr->pData)
    {
	pBuffer	 = pAudioOutHdr->pData->GetBuffer();
	ulBufLen = pAudioOutHdr->pData->GetSize();
    }

    if (!m_bInitialized)
    {
	m_bInitialized = AllocateBuffers(MAX_REASONABLE_BUFFS,(UINT16)ulBufLen);
    }
    if (!m_bInitialized) return HXR_FAILED;

    m_pMutex->Lock();
    pWaveHeader = (CWaveHeader*)m_rAvailBuffers.DeQueuePtr(bTemp);
    m_pMutex->Unlock();

    if (!bTemp) 
    {
	return HXR_WOULD_BLOCK;
    }

#ifdef _TESTING
    if ( m_audfile > 0 )
        write(m_audfile, pBuffer,ulBufLen); 
#endif

    UINT32 ulBytesToCopy = ulBufLen;
    HX_ASSERT(ulBytesToCopy <= pWaveHeader->m_WAVEHDR.dwBufferLength);
    if (ulBytesToCopy > pWaveHeader->m_WAVEHDR.dwBufferLength)
        ulBytesToCopy = pWaveHeader->m_WAVEHDR.dwBufferLength;

    pWaveHeader->m_bAvail = FALSE;
        memcpy(pWaveHeader->m_WAVEHDR.lpData, pBuffer, HX_SAFESIZE_T(ulBytesToCopy)); /* Flawfinder: ignore */
    pWaveHeader->m_ulTimeEnd = pAudioOutHdr->ulAudioTime;

    /* This is needed for LIVE where audio packets may not start
     * from timestamp 0
     */
    if (m_bIsFirstPacket)
    {
	m_bIsFirstPacket = FALSE;
    }

    //OutputDebugString("BEFORE CALL TO:waveOutWrite\r\n");
    res = waveOutWrite(m_hWave, LPWAVEHDR(&pWaveHeader->m_WAVEHDR), sizeof(WAVEHDR));

    m_pMutex->Lock();
    m_UsedBuffersList.AddTail(pWaveHeader);
    m_pMutex->Unlock();
    //OutputDebugString("AFTER CALL TO:waveOutWrite\r\n");

    return HXR_OK;
}

HX_RESULT CAudioOutWindows::_Imp_Seek(ULONG32 ulSeekTime)
{
    return HXR_OK;
}

HX_RESULT CAudioOutWindows::_Imp_Pause()
{
    MMRESULT res;
    if (m_hWave) 
    {
//	OutputDebugString("BEFORE CALL TO:waveOutRestart\r\n");
        res = waveOutPause(m_hWave);
    }
    return HXR_OK;
}

HX_RESULT CAudioOutWindows::_Imp_Resume()
{
    MMRESULT res;
    if (m_hWave) 
    {
//	OutputDebugString("BEFORE CALL TO:waveOutRestart\r\n");
        res = waveOutRestart(m_hWave);
	//OutputDebugString("AFTER CALL TO:waveOutRestart\r\n");
    }

    OnTimeSync();

    return HXR_OK;
}

HX_RESULT CAudioOutWindows::_Imp_Reset()
{
//{FILE* f1 = ::fopen("c:\\audio.txt", "a+"); ::fprintf(f1, "Reset: \n");::fclose(f1);}
    MMRESULT res;
    m_bResetting = TRUE;
    if (m_hWave) 
    {
//	OutputDebugString("BEFORE CALL TO:waveOutReset\r\n");
	res = waveOutReset(m_hWave);
	// Need to be turned on after RC2000 XXXRA
	// commenting it out for safety reasons.
	//_Imp_Pause();
	//OutputDebugString("AFTER CALL TO:waveOutReset\r\n");
	m_bIsFirstPacket	= TRUE;

	m_llDeviceBytesPlayed = 0;
	m_llDeviceSamplesPlayed = 0;

	m_ulLastDeviceBytesPlayed = 0;
	m_ulLastDeviceSamplesPlayed = 0;
	m_ulDevPosRollOver = 0;
    }

    // First return the unused buffers to the available queue
    // Then pump out the wom_dones.
    //
    _NumberOfBlocksRemainingToPlay();

    // Make sure we handle all the wave-done messages,
    // but establish a time limit to cope with the 
    // unpredictable nature of Windows. Wait for up
    // to 1 second.

    DWORD start = HX_GET_TICKCOUNT();
    if (m_hWnd)
    {
	do
	{
	    MSG msg;

	    // Yield, and try to pump WOM_DONE's to the Async Window!
	    while (PeekMessage(&msg, m_hWnd, MM_WOM_DONE, MM_WOM_DONE, PM_REMOVE))
	    {
		if(msg.message == WM_QUIT) 
		{   
		    // When peeking WM_QUIT message in the main thread of an application 
		    // we have to put it back into message queue to allow the application 
		    // to exit correctly. SB
		    PostQuitMessage(0);
		    break;
		}
		else
		{
		    DispatchMessage(&msg);
		}
	    }

	    if (CALCULATE_ELAPSED_TICKS(start, HX_GET_TICKCOUNT()) >= 1000)
	    {

		// Brute force, mark them as free... We probably 
		// could do something better here, like close and
		// reopen the wave device... but this is what the
		// old code did, so lets try it as well!

		ULONG32 lTmp;
		m_pMutex->Lock();
		for (lTmp = 0; m_pWaveHdrs && (lTmp < m_unAllocedBufferCnt); ++lTmp)
		{
		    CWaveHeader *pwhDone = &m_pWaveHdrs[lTmp];
		    if (pwhDone && pwhDone->m_bAvail == FALSE)
		    {
			pwhDone->m_bAvail = TRUE;
			m_rAvailBuffers.EnQueuePtr(pwhDone);
		    }
		}
		m_pMutex->Unlock();

		//OutputDebugString("Bail WOM_DONE vacuum, passed timeout!\r\n");
		break;
	    }

	}
	while (_NumberOfBlocksRemainingToPlay());
    }
    //OutputDebugString("END: WOM_DONE vacuum!\r\n");

    m_bResetting = FALSE;
    return HXR_OK;
}

HX_RESULT CAudioOutWindows::_Imp_Drain()
{
    return HXR_OK;
}

HX_RESULT CAudioOutWindows::_Imp_CheckFormat
( 
    const HXAudioFormat* pFormat 
)
{
#if defined(_WIN32)
    LPWAVEFORMATEX	wavePtr;
#elif defined( _WINDOWS )
    LPWAVEFORMAT	wavePtr;
#endif

    m_WaveFormat.SetFormat(pFormat->ulSamplesPerSec, pFormat->uChannels, pFormat->uBitsPerSample);
   
	// Get the Windows style wave format!
    wavePtr = m_WaveFormat.GetWaveFormat();


    MMRESULT wRet = waveOutOpen(&m_hWave,WAVE_MAPPER,wavePtr,		
        0, (DWORD)this,WAVE_FORMAT_QUERY);

    switch (wRet)
    {
	case MMSYSERR_NOERROR:	    return( HXR_OK );
	case MMSYSERR_ALLOCATED:    return( HXR_AUDIO_DRIVER );
	case MMSYSERR_NOMEM:	    return( HXR_OUTOFMEMORY );
	case MMSYSERR_BADDEVICEID:  return( HXR_AUDIO_DRIVER );
	case WAVERR_BADFORMAT:	    return( HXR_AUDIO_DRIVER );
	case WAVERR_SYNC:	    return( HXR_AUDIO_DRIVER );
	case MMSYSERR_NODRIVER:	    return( HXR_AUDIO_DRIVER );
	default:		    return( HXR_AUDIO_DRIVER );
    }

}

BOOL CAudioOutWindows::AllocateBuffers(UINT16 unNumBuffers, UINT16 unBufSize)
{
    UCHAR**	    ppWaveBuffers;
    CWaveHeader*    pWaveHdrs;
    MMRESULT	    tRes;
    UINT16	    unWHIndex;


    ppWaveBuffers = NULL;
    pWaveHdrs = NULL;

    // Allocate memory for wave block headers and for wave data.
    if (!(pWaveHdrs = new CWaveHeader [unNumBuffers]))
    {
        goto OnError;
    }

    //	This array holds the buffer pointers so we can free them later
    //	There NO other purpose for this array.	
    if (!(ppWaveBuffers = new UCHAR*[unNumBuffers]))
    {
	goto OnError;
    }
    memset( ppWaveBuffers, 0, unNumBuffers * sizeof( UCHAR* ) );
				    
    // Mark all wave block headers as available, and point them
    // at their respective wave data blocks.
    // AND enqueue them in the AvailableBuffers Queue.
    // AND allocate their buffers!!!

    for (unWHIndex = 0; unWHIndex < unNumBuffers; unWHIndex++) 
    {
        UCHAR*	pBuff;

	// Try to allocate the individual audio buffers
    	pBuff = new UCHAR [unBufSize];
	if (!pBuff)
	{
	    goto OnError;
    	}
	ppWaveBuffers[unWHIndex] = pBuff;

	CWaveHeader* pWaveHeader = &pWaveHdrs[unWHIndex];

	// Init some header data before Preparing the header
	pWaveHeader->m_WAVEHDR.lpData = (char *)pBuff;
	pWaveHeader->m_WAVEHDR.dwUser = DWORD(pWaveHeader);
	pWaveHeader->m_WAVEHDR.dwFlags = 0L;
	pWaveHeader->m_WAVEHDR.dwBufferLength = unBufSize;
	pWaveHeader->m_WAVEHDR.dwLoops = 0L;
	pWaveHeader->m_bAvail = TRUE;
	pWaveHeader->m_pUser = this;

	m_pMutex->Lock();
	m_rAvailBuffers.EnQueuePtr(pWaveHeader);
	m_pMutex->Unlock();

	//OutputDebugString("BEFORE CALL TO:waveOutPrepareHeader\r\n");
        tRes = waveOutPrepareHeader(m_hWave, LPWAVEHDR(&pWaveHeader->m_WAVEHDR), sizeof(WAVEHDR));
	//OutputDebugString("AFTER CALL TO:waveOutPrepareHeader\r\n");
	if (tRes != MMSYSERR_NOERROR)
	{
	    goto OnError;
	}
	else
	{
	    pWaveHeader->m_pPrepared = TRUE;
    	}
    }
    m_unAllocedBufferCnt = unNumBuffers;
    m_unAllocedBuffSize = unBufSize;
    m_pWaveHdrs = pWaveHdrs;
    m_ppAllocedBuffers = ppWaveBuffers;

    return TRUE;

OnError:

    if (pWaveHdrs)
    {
	// Unprepare the individual headers
	for (unWHIndex = 0; unWHIndex < unNumBuffers; ++unWHIndex)
	{
    	    CWaveHeader* pWaveHeader = &pWaveHdrs[unWHIndex];
	    if (pWaveHeader->m_pPrepared)
	    {
		//OutputDebugString("BEFORE CALL TO:waveOutUnprepareHeader\r\n");
		tRes = waveOutUnprepareHeader(m_hWave, 
				    LPWAVEHDR(&pWaveHeader->m_WAVEHDR), sizeof(WAVEHDR));
		//OutputDebugString("AFTER CALL TO:waveOutUnprepareHeader\r\n");
		pWaveHeader->m_pPrepared = FALSE;
	    }
	}

	delete[] pWaveHdrs;
	pWaveHdrs = NULL;
    }
    //	ppWaveBuffers actually points at an array of pointers that need to be free'd
    if (ppWaveBuffers)
    {
	//	Free the individual buffers
	for (unWHIndex = 0; unWHIndex < unNumBuffers; ++unWHIndex)
	{
	    UCHAR* pBuff;

	    pBuff = ppWaveBuffers[unWHIndex];
	    if (pBuff)
	    {
    		delete[] pBuff;
	    }
	}
	//	Now free ppWaveBuffers itself
	delete[] ppWaveBuffers;
	ppWaveBuffers = NULL;
    }
    return FALSE;
}

/************************************************************************
 *  Method:
 *              CAudioOutWindows::_Imp_GetCurrentTime
 *      Purpose:
 *              Get the current time from the audio device.
 *              We added this to support the clock available in the
 *              Window's audio driver.
 */
HX_RESULT CAudioOutWindows::_Imp_GetCurrentTime
( 
        ULONG32& ulCurrentTime
)
{
	ULONG32 ulDeviceTime = 0;
	ULONG32 ulDeviceBytesPlayed = 0;
	UINT32	ulDeviceSamplesPlayed = 0;

	WAVEFMTPTR pWFmt = m_WaveFormat.GetWaveFormat();

	// Set the time to the playback time of the
	// wave device since it's the most accurate.
	MMTIME mmTime;

	// we want MS if we can get them
	mmTime.wType = TIME_MS;

	MMRESULT res = waveOutGetPosition(m_hWave, &mmTime, sizeof(MMTIME));

	if (MMSYSERR_NOERROR == res)
	{

⌨️ 快捷键说明

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