📄 output.cpp
字号:
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 + -