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

📄 audiorender.cpp

📁 播放被H264_AAC所压缩的avi文件的播放器。
💻 CPP
字号:

#include <windows.h>
#include "AudioRender.h"
#include "Log.h"

#define AAC_CHUNK_SIZE 1024

//##ModelId=4753B7E9011A
CAudioRender::CAudioRender()
{
	m_pDs = NULL;
	m_pSoundBuff = NULL;

	lInService = FALSE;
	m_dwCurPlayCursor = 0;
	m_dwBufOffset   = 0;

	m_pTimer = NULL;
	m_nBufService = 500;
	m_nLastChunkTime	= 0;
	m_bEmpty = TRUE;
}

//##ModelId=4753B7E9011B
CAudioRender::~CAudioRender()
{

}

//##ModelId=4753B7E9011C
BOOL CAudioRender::CreateAudioRender(HWND hWnd, int nSamplesPerSec, int nChannels, int nBitsPerSample)
{
	m_bEmpty = TRUE;
	if( nChannels <= 0 || nBitsPerSample <= 0 )
	{
		LogMsg(LOG_CRIT, HCLN, "Invalid Wave parameter Channel = %d BitsPerSample = %d", nChannels, nBitsPerSample);
		return FALSE;
	}
	//Initialize Wave header
	::memset(&m_WaveFormatEx, 0x00, sizeof(m_WaveFormatEx));
 	m_WaveFormatEx.wFormatTag		= WAVE_FORMAT_PCM;
	m_WaveFormatEx.nChannels		= nChannels;
	m_WaveFormatEx.wBitsPerSample	= nBitsPerSample;
	m_WaveFormatEx.cbSize			= 0;
 	m_WaveFormatEx.nSamplesPerSec	= nSamplesPerSec;
	m_WaveFormatEx.nBlockAlign		= (nBitsPerSample / 8) * nChannels;
	m_WaveFormatEx.nAvgBytesPerSec	= m_WaveFormatEx.nSamplesPerSec * m_WaveFormatEx.nBlockAlign;

    if (DirectSoundCreate(NULL, &m_pDs, NULL) == DS_OK)
    {
       if (m_pDs->SetCooperativeLevel(hWnd, DSSCL_NORMAL) != DS_OK)
       {
			LogMsg(LOG_CRIT, HCLN, "Can not Set CooperativeLevel!");
			return FALSE;
        }
	}
    else
    {
		LogMsg(LOG_CRIT, HCLN, "Can not create DirectSound!");
		return FALSE;
	}
	
	m_dwSampleSize = AAC_CHUNK_SIZE * m_WaveFormatEx.nChannels * nBitsPerSample / 8;
	// Calculate sound buffer size in bytes
	m_dwDSBufferSize = (m_WaveFormatEx.nAvgBytesPerSec * 2 / m_dwSampleSize) * m_dwSampleSize;

	ZeroMemory( &m_sDsbd, sizeof(DSBUFFERDESC) );
    m_sDsbd.dwSize			= sizeof(DSBUFFERDESC);
	//	Volume苞  Frequency甫 炼辆且荐 乐档废 汲沥茄促.
	m_sDsbd.dwFlags			= DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME;
    m_sDsbd.dwBufferBytes	= m_dwDSBufferSize;
    m_sDsbd.lpwfxFormat		= (LPWAVEFORMATEX)&m_WaveFormatEx;
	
	if (m_pDs->CreateSoundBuffer(&m_sDsbd, &m_pDSBuff, NULL) != DS_OK)
    {
		LogMsg(LOG_ERR, HCLN, "Can not create SoundBuffer!");
		return FALSE;
    }
	
	m_pDSBuff->SetVolume(-50);
	m_pSoundBuff = (BYTE *)malloc(m_dwDSBufferSize);
	memset(m_pSoundBuff, 0x00, m_dwDSBufferSize);
	m_dwBufOffset = 0;
	m_nLastChunkTime = 0;
	m_dwCurPlayCursor = 0;

	LogMsg(LOG_INFO, HCLN, "Create WaveOut!");
	return TRUE;
}

//##ModelId=4753B7E9012C
BOOL CAudioRender::DestroyAudioRender()
{
	if (m_pDs != NULL)
	{
		m_pDSBuff->Stop();
		m_pDSBuff->Release();
		m_pDs->Release();
//		m_pDSBuff = NULL;
	}

	if( m_pTimer )
	{
		m_pTimer->TimerStop();
		delete m_pTimer;
		m_pTimer = NULL;
	}
	if(m_pSoundBuff)
	{
		free(m_pSoundBuff);
		m_pSoundBuff = NULL;
	}
	LogMsg(LOG_INFO, HCLN, "Destroy WaveOut!");
	return TRUE;
}

//##ModelId=4753B7E9012D
BOOL CAudioRender::Play()
{
	//
	if( m_bEmpty )
	{
		m_pDSBuff->SetCurrentPosition(0);
		ServiceBuffer();
		m_bEmpty = FALSE;
	}
	else
		m_pDSBuff->SetCurrentPosition(m_dwCurPlayCursor);
	
	if( m_pDSBuff->Play(0, 0, DSBPLAY_LOOPING) != DS_OK )
	{
		LogMsg(LOG_ERR, HCLN, "Play Error!");
		return FALSE;
	}
	else
	{
		// Kick off timer to service buffer
		if( m_pTimer )
		{
			m_pTimer->TimerStop();
			delete m_pTimer;
			m_pTimer = NULL;
		}

		m_pTimer = new Timer();

		if (m_pTimer)
		{  
			m_pTimer->Create(m_nBufService, m_nBufService, DWORD(this), TimerCallback);
		}	
	}
	return TRUE;
}

//##ModelId=4753B7E9012E
BOOL CAudioRender::Stop()
{
	if (m_pTimer)
	{
		m_pTimer->TimerStop();
		delete m_pTimer;
		m_pTimer = NULL;
	}

	if (m_pDs)
	{
		m_pDSBuff->GetCurrentPosition(&m_dwCurPlayCursor, NULL);
		m_pDSBuff->Stop();
		m_pDSBuff->Restore();
	}

	return TRUE;
}

//##ModelId=4753B7E90138
void CAudioRender::EmptyWaveBuffer()
{
	LogMsg(LOG_INFO, HCLN, "Empty WaveOut! buffer offset = %d", m_dwBufOffset);
	m_bEmpty = TRUE;
	m_dwCurPlayCursor = 0;
	m_dwBufOffset = 0;
	m_nLastChunkTime = 0;

}
//##ModelId=4753B7E90139
DWORD CAudioRender::GetCurPlayTime()
{	
	DWORD dwPlayBufferSize;

	if (!m_pDs)
	{
		LogMsg(LOG_ERR, HCLN, "can't get current play time for directsound!");
		return 0; // DSound is Not Initialized.
	}

	dwPlayBufferSize = m_dwDSBufferSize - GetMaxWriteSize();
	
	DWORD dwBufferTimes = (DWORD)((dwPlayBufferSize * 1024000.0 / m_dwSampleSize)/ m_WaveFormatEx.nSamplesPerSec);

//	LogMsg(LOG_INFO, HCLN, "CurChunkTime = %d BufferTime = %d buffersize = %d", 
//							m_nLastChunkTime, dwBufferTimes, dwPlayBufferSize);

	if( m_nLastChunkTime > dwBufferTimes)
		return m_nLastChunkTime - dwBufferTimes;
	else
		return 0;
}
//##ModelId=4753B7E90158
PVOID CAudioRender::GetWaveData(UINT nSize, BOOL bSilence)
{
	UINT	nNumOfSample = nSize / m_dwSampleSize;
	PVOID	pWaveData = NULL;
	UINT	readsize;
	int		iLimitCounter = (int)nNumOfSample * 2;
	UINT	nCounter = 0;

	memset(m_pSoundBuff, 0x00, nSize);
	do 
	{
		iLimitCounter --;
		if(iLimitCounter <= 0)
		{
			LogMsg(LOG_INFO, HCLN, "Empty audio stream buffer!");
			break;
		}
		
		pWaveData = (BYTE*)m_pAudioStream->Pop(&readsize, &m_nLastChunkTime);
		if(pWaveData != NULL)
		{
			memcpy(m_pSoundBuff + nCounter * m_dwSampleSize, pWaveData, readsize);
			nCounter ++;
		}
		else
		{
			//LogMsg(LOG_DEBUG, HCLN, "Wait untile push to buffer! %d", nCounter);
			if(bSilence)
				break;
			else
				continue;
		}
	}while(nCounter < nNumOfSample);
	
	return m_pSoundBuff;
}

/* write sound buffer.
*/
//##ModelId=4753B7E9013C
BOOL CAudioRender::WriteWaveData(UINT cbSize)
{
	HRESULT hr;
    VOID*   pDSLockedBuffer      = NULL; // Pointer to locked first buffer memory
    DWORD   dwDSLockedBufferSize = 0;    // Size of the locked first DirectSound buffer
	VOID*   pDSLockedBuffer2     = NULL; // Pointer to locked second buffer memory
	DWORD   dwDSLockedBufferSize2 = 0;    // Size of the locked second DirectSound buffer
	PVOID	pWaveData = NULL;

	// Lock the buffer down
    if( FAILED( hr = m_pDSBuff->Lock( m_dwBufOffset, cbSize, 
										&pDSLockedBuffer, &dwDSLockedBufferSize, 
										&pDSLockedBuffer2, &dwDSLockedBufferSize2, 0L ) ) )
	{
		LogMsg(LOG_ERR, HCLN, "Faild Waveout Buffer Lock");
		return FALSE;
	}

	pWaveData = GetWaveData(cbSize, FALSE);
	if(pDSLockedBuffer)
	{
		memcpy(pDSLockedBuffer, pWaveData, dwDSLockedBufferSize);
		if(pDSLockedBuffer2)
		{
			memcpy(pDSLockedBuffer2, (BYTE*)pWaveData + dwDSLockedBufferSize, dwDSLockedBufferSize2);
		}
	}

    // Unlock the buffer, we don't need it anymore.
    m_pDSBuff->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, pDSLockedBuffer2, dwDSLockedBufferSize2 );

	m_dwBufOffset += (dwDSLockedBufferSize + dwDSLockedBufferSize2);
	m_dwBufOffset %= m_dwDSBufferSize;	 // Circular buffer

	return TRUE;
}


//##ModelId=4753B7E9014B
DWORD CAudioRender::GetMaxWriteSize()
{
	DWORD dwWriteCursor, dwPlayCursor, dwMaxSize;

	if (!m_pDs)
		return 0; // DSound is Not Initialized.
	
	// Get current play position
	if (m_pDSBuff->GetCurrentPosition(&dwPlayCursor, &dwWriteCursor) == DS_OK)
	{
		if (m_dwBufOffset < dwPlayCursor)
		{
			// Our write position trails play cursor
			dwMaxSize = dwPlayCursor - m_dwBufOffset;
		}
		
		else // (m_cbBufOffset > dwPlayCursor)
		{
			// Play cursor has wrapped
			dwMaxSize = m_dwDSBufferSize - m_dwBufOffset + dwPlayCursor;
		}
	}
	else
	{
		// GetCurrentPosition call failed
		//_ASSERT (0);
		dwMaxSize = 0;
	}
	return (dwMaxSize);
}

//##ModelId=4753B7E9014D
BOOL CAudioRender::ServiceBuffer (void)
{ 
	BOOL fRtn = TRUE;
	
	// Check for reentrance
	if (InterlockedExchange (&lInService, TRUE) == FALSE)
	{ // Not reentered, proceed normally

		// All of sound not played yet, send more data to buffer
		DWORD dwFreeSpace = GetMaxWriteSize ();
		
		// Determine free space in sound buffer
		if (dwFreeSpace)
		{
			// Fill free space in buffer with wave data
			if (!WriteWaveData ((dwFreeSpace / m_dwSampleSize) * m_dwSampleSize))
			{
				// Error writing wave data
				fRtn = FALSE;
			}
		}
		else
		{ // No free space in buffer for some reason
			fRtn = FALSE;
		}
		
		// Reset reentrancy semaphore
		InterlockedExchange (&lInService, FALSE);
	}
	else
	{ // Service routine reentered. Do nothing, just return
		fRtn = FALSE;
	}
	return (fRtn);
}

//##ModelId=4753B7E9013A
BOOL CAudioRender::SetVolume(int nVol)
{
	if(m_pDSBuff)
	{
		if(DS_OK == m_pDSBuff->SetVolume(nVol))
			return TRUE;
	}

	return FALSE;
}

//##ModelId=4753B7E9015B
BOOL CAudioRender::TimerCallback (DWORD dwUser)
{
	BOOL nRet;
	// dwUser contains ptr to AudioStream object
	CAudioRender* pWaveOut = (CAudioRender*) dwUser;
	nRet = pWaveOut->ServiceBuffer();
	return nRet;
}

⌨️ 快捷键说明

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