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

📄 output.cpp

📁 PPC流行的播放软件gsplayer源码2.24版
💻 CPP
📖 第 1 页 / 共 2 页
字号:

BOOL COutput::IsFlushed()
{
	return GetCurrent() >= m_dwWritten;
}

void COutput::GetBufferInfo(DWORD* pcbTotal, DWORD* pcbBuffered)
{
	if (!m_pHdr) {
		*pcbTotal = 0;
		*pcbBuffered = 0;
		return;
	}

	*pcbTotal = m_cBuf * m_cbBuf; 
	*pcbBuffered = m_cWritten * m_cbBuf; 
}

void COutput::CheckPeek(WAVEHDR* pHdr)
{
	// 愨懳抣偲偭偰側偄偗偳傑偁偄偄偐乮徫
	// 僆儗偭偰偄偄偐偘傫乮徫
	int nSamples;
	if (m_pcm.wBitsPerSample == 16) {
		short* p = (short*)pHdr->lpData;
		m_nLPeek = m_nRPeek = 0;
		nSamples = pHdr->dwBufferLength / 2 / m_pcm.wf.nChannels;

		if (m_pcm.wf.nChannels == 2) {
			for (int i = 0; i < nSamples; i++) {
				m_nLPeek = m_nLPeek > *p ? m_nLPeek : *p;
				p++;
				m_nRPeek = m_nRPeek > *p ? m_nRPeek : *p;
				p++;
			}
			m_nLPeek = m_nLPeek * 100 / 0x7FFF;
			m_nRPeek = m_nRPeek * 100 / 0x7FFF;
		}
		else {
			for (int i = 0; i < nSamples; i++) {
				m_nLPeek = m_nLPeek > *p ? m_nLPeek : *p;
				p++;
			}
			m_nLPeek = m_nLPeek * 100 / 0x8FFF;
			m_nRPeek = m_nLPeek;
		}
	}
	else {
		unsigned char* p = (unsigned char*)pHdr->lpData;
		m_nLPeek = m_nRPeek = 0x80;
		nSamples = pHdr->dwBufferLength / m_pcm.wf.nChannels;
		if (m_pcm.wf.nChannels == 2) {
			for (int i = 0; i < nSamples; i++) {
				m_nLPeek = m_nLPeek > *p ? m_nLPeek : *p;
				p++;
				m_nRPeek = m_nRPeek > *p ? m_nRPeek : *p;
				p++;
			}
			m_nLPeek = (m_nLPeek - 0x80) * 100 / 0x7F;
			m_nRPeek = (m_nRPeek - 0x80) * 100 / 0x7F;
		}
		else {
			for (int i = 0; i < nSamples; i++) {
				m_nLPeek = m_nLPeek > *p ? m_nLPeek : *p;
				p++;
			}
			m_nLPeek = (m_nLPeek - 0x80) * 100 / 0x7F;
			m_nRPeek = m_nLPeek;
		}
	}
}

void COutput::FadeIn(LPBYTE pbBuf, DWORD cbBuf)
{
	int n;
	DWORD cb = 0;
	while ((cbBuf - cb) && m_nFadeSamples) {
		for (int nChannel = 0; nChannel < m_pcm.wf.nChannels; nChannel++) {
			if (m_pcm.wBitsPerSample == 16) {
				n = ((int)*((short*)(pbBuf + cb))) * m_nFadeCurrent;
				*((short*)(pbBuf + cb)) = n >> FADE_BITS;
				cb += 2;
			}
			else {
				n = (UINT8_TO_INT16((int)*(pbBuf + cb))) * m_nFadeCurrent;
				*(pbBuf + cb) = INT16_TO_UINT8(n >> FADE_BITS);
				cb++;
			}
		}
		m_nFadeCurrent += m_nFadeRate;
		m_nFadeSamples--;

		if (m_nFadeCurrent >= (1 << FADE_BITS)) {
			m_nFadeSamples = 0;
			break;
		}
	}
}

short Clip16(int s);
unsigned char Clip8(int s);
void COutput::Preamp(LPBYTE pbBuf, DWORD cbBuf, int nRate)
{
	int n;

	if (nRate == PREAMP_FIXED_FLAT)
		return;

	if (m_pcm.wBitsPerSample == 16) {
		for (DWORD cb = 0; cb < cbBuf; ) {
			for (int nChannel = 0; nChannel < m_pcm.wf.nChannels; nChannel++) {
				n = (int)*((short*)(pbBuf + cb)) * nRate;
				*((short*)(pbBuf + cb)) = Clip16(n >> PREAMP_FIXED_BITS);
				cb += 2;
			}
		}
	}
	else {
		for (DWORD cb = 0; cb < cbBuf; ) {
			for (int nChannel = 0; nChannel < m_pcm.wf.nChannels; nChannel++) {
				n = UINT8_TO_INT16((int)*(pbBuf + cb)) * nRate;
				*(pbBuf + cb) = Clip8(INT16_TO_UINT8(n >> PREAMP_FIXED_BITS));
				cb++;
			}
		}
	}
}

#define ZERO_SAMPLE_MAX		16
DWORD COutput::ScanZeroSamples(BOOL fForward, LPBYTE pbBuf, DWORD cbBuf)
{
	int nZeroSamples = 0;
	int nBytesPerSample = m_pcm.wf.nChannels * m_pcm.wBitsPerSample / 8;
	int nSamples = cbBuf / nBytesPerSample;

	if (m_pcm.wBitsPerSample == 16) {
		short* pSample;
		if (fForward) {
			pSample = (short*)pbBuf;
		}
		else {
			pSample = (short*)(pbBuf + cbBuf - nBytesPerSample);
			nBytesPerSample = -nBytesPerSample;
		}

		if (m_pcm.wf.nChannels == 2) {
			for (int i = 0; i < nSamples; i++) {
				if ((*pSample > ZERO_SAMPLE_MAX) || (*pSample < -ZERO_SAMPLE_MAX) ||
					(*(pSample + 1) > ZERO_SAMPLE_MAX) || (*(pSample + 1) < -ZERO_SAMPLE_MAX))
					break;
				nZeroSamples++;
				pSample = (short*)((BYTE*)pSample + nBytesPerSample);
			}
		}
		else {
			for (int i = 0; i < nSamples; i++) {
				if ((*pSample > ZERO_SAMPLE_MAX) || (*pSample < -ZERO_SAMPLE_MAX))
					break;
				nZeroSamples++;
				pSample = (short*)((BYTE*)pSample + nBytesPerSample);
			}
		}
	}
	else {
		BYTE* pSample;
		if (fForward) {
			pSample = pbBuf;
		}
		else {
			pSample = pbBuf + cbBuf - nBytesPerSample;
			nBytesPerSample = -nBytesPerSample;
		}

		if (m_pcm.wf.nChannels == 2) {
			for (int i = 0; i < nSamples; i++) {
				if (*pSample != 0x80 || *(pSample + 1) != 0x80)
					break;
				nZeroSamples++;
				pSample += nBytesPerSample;
			}
		}
		else {
			for (int i = 0; i < nSamples; i++) {
				if (*pSample != 0x80)
					break;
				nZeroSamples++;
				pSample += nBytesPerSample;
			}
		}
	}

	return nZeroSamples * m_pcm.wf.nChannels * (m_pcm.wBitsPerSample / 8);
}

void COutput::CloseAll()
{
	if (m_hThread) {
		PostThreadMessage(m_dwThreadId, WM_QUIT, 0, 0);
		WaitForSingleObject(m_hThread, INFINITE);
		CloseHandle(m_hThread);
		m_hThread = NULL;
	}
	if (m_hwo) {
		Reset();

		CAutoLock lockDev(&m_csecDevice);
		if (m_fDoubleBuf) {
			m_fPaused = TRUE;
			waveOutReset(m_hwo);

			CAutoLock lock(&m_csecBuff);
			for (UINT i = 0; i < SUBBUF_COUNT; i++)
				waveOutUnprepareHeader(m_hwo, &m_HdrOut[i] , sizeof(WAVEHDR));
		}
		else {
			CAutoLock lock(&m_csecBuff);
			for (UINT i = 0; i < m_cBuf; i++)
				waveOutUnprepareHeader(m_hwo, &m_pHdr[i] , sizeof(WAVEHDR));
		}

		waveOutClose(m_hwo);
		m_hwo = NULL;
	}

	if (m_hEventThread) {
		CloseHandle(m_hEventThread);
		m_hEventThread = NULL;
	}

	FreeSubBuffer();
	FreeBuffer();
	memset(&m_pcm, 0, sizeof(m_pcm));
}

DWORD WINAPI COutput::WaveOutThreadProc(LPVOID pParam)
{
	((COutput*)pParam)->WaveOutThread();
	return 0;
}

void COutput::WaveOutThread()
{
	DWORD cb;
	while (MsgWaitForMultipleObjects(1, &m_hEventThread, FALSE, INFINITE, QS_ALLEVENTS) == WAIT_OBJECT_0) {
		InterlockedDecrement((long*)&m_nSubBuf);
		if (!m_nSubBuf) ResetEvent(m_hEventThread);
		CAutoLock lockDev(&m_csecDevice);
		m_HdrOut[m_nHdrOut].dwBytesRecorded = 0;
		while (m_HdrOut[m_nHdrOut].dwBytesRecorded < m_HdrOut[m_nHdrOut].dwBufferLength) {
			if (!m_cWritten || m_fPaused) {
				if (!m_HdrClear[m_nHdrOut]) {
					if (!m_HdrOut[m_nHdrOut].dwBytesRecorded)
						m_HdrClear[m_nHdrOut] = 1;

					memset(m_HdrOut[m_nHdrOut].lpData + m_HdrOut[m_nHdrOut].dwBytesRecorded, 0, 
						m_HdrOut[m_nHdrOut].dwBufferLength - m_HdrOut[m_nHdrOut].dwBytesRecorded);
					m_HdrOut[m_nHdrOut].dwBytesRecorded = m_HdrOut[m_nHdrOut].dwBufferLength;
				}
				break;
			}
			
			CAutoLock lockBuf(&m_csecBuff);
			cb = min(m_HdrOut[m_nHdrOut].dwBufferLength - m_HdrOut[m_nHdrOut].dwBytesRecorded, 
					m_pHdr[m_nWriteCur].dwBytesRecorded - m_pHdr[m_nWriteCur].dwUser);
			memcpy(m_HdrOut[m_nHdrOut].lpData + m_HdrOut[m_nHdrOut].dwBytesRecorded, 
				m_pHdr[m_nWriteCur].lpData + m_pHdr[m_nWriteCur].dwUser, cb);
	
			m_pHdr[m_nWriteCur].dwUser += cb;
			m_HdrOut[m_nHdrOut].dwBytesRecorded += cb;
			m_HdrClear[m_nHdrOut] = 0;
			m_dwTotalSamples += cb / m_pcm.wf.nBlockAlign;
			if (m_pHdr[m_nWriteCur].dwUser == m_pHdr[m_nWriteCur].dwBytesRecorded) { 
				m_pHdr[m_nWriteCur].dwUser = 0;
				m_nWriteCur = (m_nWriteCur + 1) % m_cBuf;
				m_cWritten--;
				SetEvent(m_hEvent);
			}
		}

		waveOutWrite(m_hwo, &m_HdrOut[m_nHdrOut], sizeof(WAVEHDR));
		m_nHdrOut = (m_nHdrOut + 1) % SUBBUF_COUNT;
	}
}

BOOL COutput::PrepareSubBuffer()
{
	CAutoLock lock(&m_csecBuff);
	if (m_pbSubBuf)
		return FALSE;

	int cb = SUBBUF_SIZE;
	if (m_pcm.wf.nSamplesPerSec > 11025)
		cb *= 2;
	if (m_pcm.wf.nSamplesPerSec > 22050)
		cb *= 2;
	if (m_pcm.wBitsPerSample > 8)
		cb *= 2;
	cb *= m_pcm.wf.nChannels;

	m_pbSubBuf = new BYTE[cb * SUBBUF_COUNT];
	memset(m_pbSubBuf, 0, cb * SUBBUF_COUNT);
	for (UINT i = 0; i < SUBBUF_COUNT; i++) {
		memset(&m_HdrOut[i], 0, sizeof(WAVEHDR));
		m_HdrOut[i].lpData = (LPSTR)m_pbSubBuf + (cb * i);
		m_HdrOut[i].dwBufferLength = cb;
		m_HdrOut[i].dwUser = (DWORD)this;
		waveOutPrepareHeader(m_hwo, &m_HdrOut[i] , sizeof(WAVEHDR));
		m_HdrClear[i] = 1;
	}
	m_nHdrOut = 0;
	m_nWriteCur = 0;
	m_nSubBuf = SUBBUF_COUNT;
	m_dwTotalSamples = 0;

	m_hEventThread = CreateEvent(NULL, TRUE, TRUE, NULL);
	m_hThread = CreateThread(NULL, 0, WaveOutThreadProc, this, CREATE_SUSPENDED, &m_dwThreadId);
	if (!m_hThread)
		return FALSE;

#ifdef _WIN32_WCE
	SetThreadPriority(m_hThread, THREAD_PRIORITY_TIME_CRITICAL);
	HMODULE hModule = LoadLibrary(_T("Coredll.dll"));
	if (hModule) {
		BOOL (WINAPI *pCeSetThreadPriority)(HANDLE hThread, int nPriority); 
		(FARPROC&)pCeSetThreadPriority = GetProcAddress(hModule, _T("CeSetThreadPriority"));
		if (pCeSetThreadPriority) 
			pCeSetThreadPriority(GetCurrentThread(), 160);
		FreeLibrary(hModule);
	}
#else
	SetThreadPriority(m_hThread, THREAD_PRIORITY_TIME_CRITICAL);
#endif
	ResumeThread(m_hThread);
	return TRUE;
}

void COutput::FreeSubBuffer()
{
	CAutoLock lock(&m_csecBuff);
	if (m_pbSubBuf) {
		delete m_pbSubBuf;
		m_pbSubBuf = NULL;
	}
	memset(m_HdrOut, 0, sizeof(m_HdrOut));
}

DWORD COutput::GetBufferingSamples()
{
	DWORD dwCurrent = GetCurrent();
	return m_dwWritten - dwCurrent;
}

⌨️ 快捷键说明

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