📄 cpi_player_output_wave.c
字号:
#include "stdafx.h"
#include "globals.h"
#include "CPI_Player.h"
#include "CPI_Player_CoDec.h"
#include "CPI_Player_Output.h"
#include "CPI_Equaliser.h"
#define CPC_NUMBEROFOUTPUTBLOCKS 16
#define CPC_OUTPUTBLOCKSIZE 0x8000
typedef struct __CPs_OutputContext_Wave
{
HWAVEOUT m_hWaveOut;
WAVEHDR m_aryWaveBlocks[CPC_NUMBEROFOUTPUTBLOCKS];
DWORD m_aryBlockSizes[CPC_NUMBEROFOUTPUTBLOCKS];
void* m_pBlockBase;
int m_iLastReadBlockIDX;
CPs_EqualiserModule* m_pEqualiser;
} CPs_OutputContext_Wave;
////////////////////////////////////////////////////////////////////////////////
void CPP_OMWV_Initialise(CPs_OutputModule* pModule, const CPs_FileInfo* pFileInfo, CP_HEQUALISER hEqualiser);
void CPP_OMWV_Uninitialise(CPs_OutputModule* pModule);
void CPP_OMWV_RefillBuffers(CPs_OutputModule* pModule);
void CPP_OMWV_SetPause(CPs_OutputModule* pModule, const BOOL bPause);
BOOL CPP_OMWV_IsOutputComplete(CPs_OutputModule* pModule);
void CPP_OMWV_Flush(CPs_OutputModule* pModule);
void CPP_OMWV_OnEQChanged(CPs_OutputModule* pModule);
void CPP_OMWV_SetInternalVolume(CPs_OutputModule* pModule, const int iNewVolume);
////////////////////////////////////////////////////////////////////////////////
void CPI_Player_Output_Initialise_WaveMapper(CPs_OutputModule* pModule)
{
pModule->Initialise = CPP_OMWV_Initialise;
pModule->Uninitialise = CPP_OMWV_Uninitialise;
pModule->RefillBuffers = CPP_OMWV_RefillBuffers;
pModule->SetPause = CPP_OMWV_SetPause;
pModule->IsOutputComplete = CPP_OMWV_IsOutputComplete;
pModule->Flush = CPP_OMWV_Flush;
pModule->OnEQChanged = CPP_OMWV_OnEQChanged;
pModule->SetInternalVolume = CPP_OMWV_SetInternalVolume;
pModule->m_pModuleCookie = NULL;
pModule->m_pcModuleName = "Cooler Wave mapper";
pModule->m_pCoDec = NULL;
pModule->m_pEqualiser = NULL;
}
void CPP_OMWV_Initialise(CPs_OutputModule* pModule, const CPs_FileInfo* pFileInfo, CP_HEQUALISER hEqualiser)
{
MMRESULT mmErr;
CPs_OutputContext_Wave* pContext;
CP_ASSERT(pModule->m_pModuleCookie == NULL);
pContext = (CPs_OutputContext_Wave*)malloc(sizeof(CPs_OutputContext_Wave));
pModule->m_pModuleCookie = pContext;
CP_TRACE0("Wave out initialising");
pModule->m_evtBlockFree = CreateEvent(NULL, FALSE, FALSE, NULL);
{
WAVEFORMATEX waveformatex;
waveformatex.wFormatTag = WAVE_FORMAT_PCM;
waveformatex.nChannels = pFileInfo->m_bStereo ? 2 : 1;
waveformatex.nSamplesPerSec = pFileInfo->m_iFreq_Hz;
waveformatex.wBitsPerSample = pFileInfo->m_b16bit ? 16 : 8;
waveformatex.nBlockAlign = (waveformatex.nChannels * waveformatex.wBitsPerSample)>>3;
waveformatex.nAvgBytesPerSec = waveformatex.nSamplesPerSec * waveformatex.nBlockAlign;
waveformatex.cbSize = 0;
mmErr = waveOutOpen( &pContext->m_hWaveOut,
WAVE_MAPPER,
&waveformatex,
(DWORD)pModule->m_evtBlockFree,
0, CALLBACK_EVENT);
if(mmErr != MMSYSERR_NOERROR)
{
CP_TRACE1("Wave Open error 0x%X", mmErr);
pContext->m_hWaveOut = NULL;
DeleteObject(pModule->m_evtBlockFree);
}
}
pContext->m_pBlockBase = VirtualAlloc( NULL,
CPC_OUTPUTBLOCKSIZE * (CPC_NUMBEROFOUTPUTBLOCKS<<1),
MEM_COMMIT, PAGE_READWRITE);
pContext->m_iLastReadBlockIDX = 0;
{
void* pBlockCursor = pContext->m_pBlockBase;
int iWaveBlockIDX;
for(iWaveBlockIDX=0; iWaveBlockIDX < CPC_NUMBEROFOUTPUTBLOCKS; iWaveBlockIDX++)
{
pContext->m_aryWaveBlocks[iWaveBlockIDX].dwFlags = 0;
pContext->m_aryWaveBlocks[iWaveBlockIDX].lpData = pBlockCursor;
pContext->m_aryWaveBlocks[iWaveBlockIDX].dwBufferLength = CPC_OUTPUTBLOCKSIZE;
waveOutPrepareHeader(pContext->m_hWaveOut, pContext->m_aryWaveBlocks + iWaveBlockIDX, sizeof(*pContext->m_aryWaveBlocks));
pBlockCursor = (void*)( (BYTE*)pBlockCursor + CPC_OUTPUTBLOCKSIZE);
}
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
pModule->m_pEqualiser = hEqualiser;
}
void CPP_OMWV_Uninitialise(CPs_OutputModule* pModule)
{
CPs_OutputContext_Wave* pContext = (CPs_OutputContext_Wave*)pModule->m_pModuleCookie;
CP_CHECKOBJECT(pContext);
CP_TRACE0("Wave out shutting down");
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
if(pContext->m_hWaveOut)
{
waveOutRestart(pContext->m_hWaveOut);
waveOutReset(pContext->m_hWaveOut);
{
int iWaveBlockIDX;
for(iWaveBlockIDX=0; iWaveBlockIDX < CPC_NUMBEROFOUTPUTBLOCKS; iWaveBlockIDX++)
waveOutUnprepareHeader(pContext->m_hWaveOut, pContext->m_aryWaveBlocks + iWaveBlockIDX, sizeof(*pContext->m_aryWaveBlocks));
}
VirtualFree(pContext->m_pBlockBase, 0, MEM_RELEASE);
waveOutClose(pContext->m_hWaveOut);
DeleteObject(pModule->m_evtBlockFree);
}
free(pContext);
pModule->m_pModuleCookie = NULL;
}
//
void CPP_OMWV_RefillBuffers(CPs_OutputModule* pModule)
{
int iBlockIDX;
CPs_OutputContext_Wave* pContext = (CPs_OutputContext_Wave*)pModule->m_pModuleCookie;
CP_CHECKOBJECT(pContext);
if(!pContext->m_hWaveOut)
return;
for(iBlockIDX = 0; iBlockIDX < CPC_NUMBEROFOUTPUTBLOCKS; iBlockIDX++)
{
WAVEHDR* pOutputBlock = pContext->m_aryWaveBlocks + iBlockIDX;
if( (pOutputBlock->dwFlags & WHDR_INQUEUE) == 0)
{
BOOL bMoreData;
pOutputBlock->dwBufferLength = CPC_OUTPUTBLOCKSIZE;
bMoreData = pModule->m_pCoDec->GetPCMBlock(pModule->m_pCoDec, pOutputBlock->lpData, &pOutputBlock->dwBufferLength);
pContext->m_iLastReadBlockIDX = iBlockIDX;
pContext->m_aryBlockSizes[iBlockIDX] = pOutputBlock->dwBufferLength;
memcpy( ((BYTE*)pOutputBlock->lpData) + (CPC_OUTPUTBLOCKSIZE * CPC_NUMBEROFOUTPUTBLOCKS),
pOutputBlock->lpData,
pOutputBlock->dwBufferLength);
{
CPs_EqualiserModule* pEQModule = (CPs_EqualiserModule*)pModule->m_pEqualiser;
pEQModule->ApplyEQToBlock_Inplace(pEQModule, pOutputBlock->lpData, pOutputBlock->dwBufferLength);
}
if(pOutputBlock->dwBufferLength > 0)
waveOutWrite(pContext->m_hWaveOut, pOutputBlock, sizeof(*pOutputBlock));
if(bMoreData == FALSE)
{
pModule->m_pCoDec->CloseFile(pModule->m_pCoDec);
pModule->m_pCoDec = NULL;
break;
}
}
}
}
//
void CPP_OMWV_SetPause(CPs_OutputModule* pModule, const BOOL bPause)
{
CPs_OutputContext_Wave* pContext = (CPs_OutputContext_Wave*)pModule->m_pModuleCookie;
CP_CHECKOBJECT(pContext);
if(!pContext->m_hWaveOut)
return;
if(bPause == TRUE)
waveOutPause(pContext->m_hWaveOut);
else
waveOutRestart(pContext->m_hWaveOut);
}
//
BOOL CPP_OMWV_IsOutputComplete(CPs_OutputModule* pModule)
{
int iBlockIDX;
CPs_OutputContext_Wave* pContext = (CPs_OutputContext_Wave*)pModule->m_pModuleCookie;
CP_CHECKOBJECT(pContext);
if(!pContext->m_hWaveOut)
return TRUE;
for(iBlockIDX = 0; iBlockIDX < CPC_NUMBEROFOUTPUTBLOCKS; iBlockIDX++)
{
if( (pContext->m_aryWaveBlocks[iBlockIDX].dwFlags & WHDR_INQUEUE))
return FALSE;
}
return TRUE;
}
//
void CPP_OMWV_OnEQChanged(CPs_OutputModule* pModule)
{
CPs_OutputContext_Wave* pContext = (CPs_OutputContext_Wave*)pModule->m_pModuleCookie;
int iBlockIDX;
CP_CHECKOBJECT(pContext);
if(!pContext->m_hWaveOut)
return;
for(iBlockIDX = pContext->m_iLastReadBlockIDX + 1; iBlockIDX < CPC_NUMBEROFOUTPUTBLOCKS; iBlockIDX++)
{
if( (pContext->m_aryWaveBlocks[iBlockIDX].dwFlags & (WHDR_INQUEUE | WHDR_DONE) ))
{
WAVEHDR* pOutputBlock = pContext->m_aryWaveBlocks + iBlockIDX;
pOutputBlock->dwBufferLength = pContext->m_aryBlockSizes[iBlockIDX];
memcpy( pOutputBlock->lpData,
((BYTE*)pOutputBlock->lpData) + (CPC_OUTPUTBLOCKSIZE * CPC_NUMBEROFOUTPUTBLOCKS),
pOutputBlock->dwBufferLength);
{
CPs_EqualiserModule* pEQModule = (CPs_EqualiserModule*)pModule->m_pEqualiser;
pEQModule->ApplyEQToBlock_Inplace(pEQModule, pOutputBlock->lpData, pOutputBlock->dwBufferLength);
}
}
}
for(iBlockIDX = 0; iBlockIDX <= pContext->m_iLastReadBlockIDX; iBlockIDX++)
{
if( (pContext->m_aryWaveBlocks[iBlockIDX].dwFlags & (WHDR_INQUEUE | WHDR_DONE) ))
{
WAVEHDR* pOutputBlock = pContext->m_aryWaveBlocks + iBlockIDX;
pOutputBlock->dwBufferLength = pContext->m_aryBlockSizes[iBlockIDX];
memcpy( pOutputBlock->lpData,
((BYTE*)pOutputBlock->lpData) + (CPC_OUTPUTBLOCKSIZE * CPC_NUMBEROFOUTPUTBLOCKS),
pOutputBlock->dwBufferLength);
{
CPs_EqualiserModule* pEQModule = (CPs_EqualiserModule*)pModule->m_pEqualiser;
pEQModule->ApplyEQToBlock_Inplace(pEQModule, pOutputBlock->lpData, pOutputBlock->dwBufferLength);
}
}
}
}
void CPP_OMWV_Flush(CPs_OutputModule* pModule)
{
CPs_OutputContext_Wave* pContext = (CPs_OutputContext_Wave*)pModule->m_pModuleCookie;
CP_CHECKOBJECT(pContext);
if(!pContext->m_hWaveOut)
return;
waveOutRestart(pContext->m_hWaveOut);
waveOutReset(pContext->m_hWaveOut);
CP_ASSERT(CPP_OMWV_IsOutputComplete(pModule));
}
//
void CPP_OMWV_SetInternalVolume(CPs_OutputModule* pModule, const int iNewVolume)
{
CPs_OutputContext_Wave* pContext = (CPs_OutputContext_Wave*)pModule->m_pModuleCookie;
int iNewVolume_DWORD;
CP_CHECKOBJECT(pContext);
if(!pContext->m_hWaveOut)
return;
iNewVolume_DWORD = iNewVolume * 656;
if(iNewVolume_DWORD > 0xFFFF)
iNewVolume_DWORD = 0xFFFF;
iNewVolume_DWORD |= (iNewVolume_DWORD<<16);
waveOutSetVolume(pContext->m_hWaveOut, iNewVolume_DWORD);
}
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -