📄 hxaudses.cpp
字号:
{
m_pSessionBuf->AddRef();
}
else
{
return HXR_OUTOFMEMORY;
}
}
}
else
{
/* create this buffer */
m_pSessionBuf = (IHXBuffer*) new CHXBuffer;
if( m_pSessionBuf )
{
m_pSessionBuf->AddRef();
}
else
{
return HXR_OUTOFMEMORY;
}
}
if (m_pPlayerBuf)
{
m_pPlayerBuf->AddRef();
if (m_pPlayerBuf->Release() > 1)
{
/*
* Cannot use this buffer the next time
* release our reference and create a new one
*/
m_pPlayerBuf->Release();
m_pPlayerBuf = (IHXBuffer*) new CHXBuffer;
if( m_pSessionBuf )
{
m_pPlayerBuf->AddRef();
}
else
{
return HXR_OUTOFMEMORY;
}
}
}
return HXR_OK;
}
void CHXAudioSession::ConvertTo8BitAndOrMono(HXAudioData* pAudioData)
{
BOOL bChannelConversion = (m_BeforeHookDeviceFmt.uChannels == 1) &&
(m_DeviceFmt.uChannels == 2);
BOOL bBitConversion = m_BeforeHookDeviceFmt.uBitsPerSample == 8;
/* Atleast one of them should be true to be in this function */
HX_ASSERT(bChannelConversion || bBitConversion);
ULONG32 ulLen = pAudioData->pData->GetSize();
short int* pShortBuf = (short int*) pAudioData->pData->GetBuffer();
UCHAR* pOutUCharBuf = pAudioData->pData->GetBuffer();
short int* pOutShortBuf = (short int*) pAudioData->pData->GetBuffer();
ULONG32 ulLoopCount = ulLen;
if (bBitConversion && bChannelConversion)
{
ulLen = pAudioData->pData->GetSize() / 4;
ulLoopCount = pAudioData->pData->GetSize() / 4;
}
else if (bBitConversion && !bChannelConversion)
{
ulLen = pAudioData->pData->GetSize() / 2;
ulLoopCount = pAudioData->pData->GetSize() / 2;
}
else /*if (!bBitConversion && bChannelConversion) */
{
ulLen = pAudioData->pData->GetSize() / 2;
ulLoopCount = pAudioData->pData->GetSize() / 4;
}
for(ULONG32 j = 0; j < ulLoopCount; j++)
{
if (bBitConversion && bChannelConversion)
{
*pOutUCharBuf++ = (UCHAR) (
((LONG32) ((*pShortBuf++ + 32768L) >> 8) +
(LONG32) ((*pShortBuf++ + 32768L) >> 8))/2
);
}
else if (bBitConversion && !bChannelConversion)
{
*pOutUCharBuf++ = (UCHAR)((*pShortBuf++ + 32768L) >> 8);
}
else /*if (!bBitConversion && bChannelConversion) */
{
*pOutShortBuf++ = (short int) (((LONG32) *pShortBuf++ + (LONG32) *pShortBuf++)/2);
}
}
pAudioData->pData->SetSize(ulLen);
}
/************************************************************************
* Method:
* CHXAudioSession::ConvertToEight
* Purpose:
*/
void CHXAudioSession::ConvertToEight()
{
UCHAR* pSessionBuf = m_pSessionBuf->GetBuffer();
ULONG32 ulLen = m_ulBytesPerGran / sizeof(short);
short int* iTmp = (short int*) pSessionBuf;
for(ULONG32 j = 0; j < ulLen; j++ )
{
pSessionBuf[j] = (UCHAR) ((*iTmp++ + 32768L) >> 8);
}
}
/************************************************************************
* Method:
* CHXAudioSession::TryOpenAudio
* Purpose:
* Try to open the audio device.
*/
HX_RESULT CHXAudioSession::TryOpenAudio()
{
HX_RESULT theErr = HXR_OK;
BOOL bDeviceOpened = FALSE;
// Free the audio device if it is ours so that we can create it on the core thread!
if ((!m_bReplacedDev || !m_bUsingReplacedDevice) && m_pCurrentAudioDev)
{
ReleaseAudioDevice();
RestoreReplacedDevice();
m_pAudioDev = NULL;
}
theErr = CreateAudioDevice();
if (!theErr && m_pCurrentAudioDev)
{
m_pAudioDev = m_pCurrentAudioDev;
if (!m_bReplacedDev || !m_bUsingReplacedDevice)
{
((CHXAudioDevice*)m_pAudioDev)->SetGranularity( m_ulGranularity, m_ulBytesPerGran);
}
theErr = m_pAudioDev->Open( &m_ActualDeviceFmt, this );
bDeviceOpened = TRUE;
m_ulBlocksWritten = 0;
/* we always open in a PAUSED state */
if (!theErr)
{
theErr = m_pAudioDev->Pause();
}
if (theErr != HXR_OK)
{
m_pAudioDev = NULL;
}
if (!theErr && m_pAudioDev)
{
/* Set the initial device volume */
m_pAudioDev->SetVolume(m_bMute ? 0 : m_uVolume);
}
}
/* Any error from audio device other than memory error is returned
* as HXR_AUDIO_DRIVER
*/
if (theErr != HXR_OK && theErr != HXR_OUTOFMEMORY)
{
theErr = HXR_AUDIO_DRIVER;
}
#ifndef _CARBON
if (!theErr && bDeviceOpened && m_bShouldOpenOnCoreThread &&
m_pInterruptState && !m_pInterruptState->AtInterruptTime())
{
// we should re-open on the core thread!!!
m_bToBeReOpened = TRUE;
if( !m_pDeviceCallback )
{
m_pDeviceCallback = new HXDeviceSetupCallback(this);
m_pDeviceCallback->AddRef();
}
if (!m_pDeviceCallback->PendingID())
{
m_pDeviceCallback->PendingID( m_pScheduler->RelativeEnter(m_pDeviceCallback, 0));
}
}
else
#endif
{
m_bToBeReOpened = FALSE;
}
return theErr;
}
HX_RESULT
CHXAudioSession::CreateAudioDevice()
{
HX_RESULT theErr = HXR_OK;
if (!m_pCurrentAudioDev)
{
// create the audioout object
CHXAudioDevice* pAudioDev = CHXAudioDevice::Create(m_pPreferences);
if (pAudioDev)
{
pAudioDev->AddRef();
pAudioDev->Init(m_pContext);
if (pAudioDev->InitVolume(0, 100) == TRUE)
{
m_bAudioDeviceSupportsVolume = TRUE;
}
else
{
m_bAudioDeviceSupportsVolume = FALSE;
}
m_pCurrentAudioDev = (IHXAudioDevice*) pAudioDev;
}
else
{
theErr = HXR_OUTOFMEMORY;
}
}
return theErr;
}
void
CHXAudioSession::ReleaseAudioDevice()
{
if (m_pCurrentAudioDev)
{
ProcessAudioDevice(ACTION_REMOVE, m_pCurrentAudioDev);
}
m_pCurrentAudioDev->Close(FALSE);
HX_RELEASE(m_pCurrentAudioDev);
m_bToBeReOpened = FALSE;
if (m_pDeviceCallback && m_pDeviceCallback->PendingID())
{
m_pScheduler->Remove(m_pDeviceCallback->PendingID());
m_pDeviceCallback->PendingID(0);
}
}
void
CHXAudioSession::RestoreReplacedDevice()
{
if (m_bReplacedDev && !m_bUsingReplacedDevice && !m_pCurrentAudioDev)
{
m_pCurrentAudioDev = m_pReplacedAudioDev;
m_pCurrentAudioDev->AddRef();
m_bUsingReplacedDevice = TRUE;
}
}
/************************************************************************
* Method:
* CHXAudioSession::OpenAudio
* Purpose:
* Open the audio device.
*/
HX_RESULT CHXAudioSession::OpenAudio()
{
HX_RESULT theErr = TryOpenAudio();
if (theErr == HXR_AUDIO_DRIVER)
{
StopAllOtherPlayers();
theErr = TryOpenAudio();
}
return theErr;
}
/************************************************************************
* Method:
* CHXAudioSession::CreatePlaybackBuffer
* Purpose:
* This is the buffer that we mix all player buffers into
* and the one we write to the audio device.
*/
HX_RESULT CHXAudioSession::CreatePlaybackBuffer()
{
// Calculate the number of bytes per granularity.
m_ulBytesPerGran = (ULONG32)
(((m_DeviceFmt.uChannels * ((m_DeviceFmt.uBitsPerSample==8)?1:2) * m_DeviceFmt.ulSamplesPerSec)
/ 1000.0) * m_ulGranularity);
/* Number of samples required at output should be a multiple of 8 if
* sampling rate is 8K/16K/32K...or a multiple of 11 for 11K/22K...
* This is needed since the resamplerequires works reliably ONLY if
* this condition is true. Ken is working on this problem. This is
* an interim fix
*/
ULONG32 ulExtraGranularity = 1;
if (m_DeviceFmt.ulSamplesPerSec % 8 == 0)
{
ulExtraGranularity = 8;
}
else
{
ulExtraGranularity = 11;
}
if (m_ulBytesPerGran % (2*m_DeviceFmt.uChannels*ulExtraGranularity) != 0)
{
m_ulBytesPerGran -= m_ulBytesPerGran % (2*m_DeviceFmt.uChannels*ulExtraGranularity);
m_dGranularity = (double) m_ulBytesPerGran / (double) ((double) (m_DeviceFmt.uChannels * ((m_DeviceFmt.uBitsPerSample==8)?1:2) * m_DeviceFmt.ulSamplesPerSec)
/ 1000.0);
}
// Readjust the max size of the block
m_ActualDeviceFmt.uMaxBlockSize = (UINT16) m_ulBytesPerGran;
HX_RELEASE(m_pSessionBuf);
HX_RELEASE(m_pPlayerBuf);
m_pSessionBuf = new CHXBuffer;
m_pSessionBuf->AddRef();
m_pSessionBuf->SetSize(m_ulBytesPerGran);
m_DeviceFmt.uMaxBlockSize = (UINT16) m_ulBytesPerGran;
m_ActualDeviceFmt.uMaxBlockSize = m_DeviceFmt.uMaxBlockSize;
return HXR_OK;
}
/************************************************************************
* Method:
* CHXAudioSession::Pause
* Purpose:
* Pause playback of this Player's audio.
*/
HX_RESULT CHXAudioSession::Pause( CHXAudioPlayer* p)
{
m_pMutex->Lock();
BOOL bUseStopInPause = FALSE;
#if defined _DEBUG && defined HELIX_FEATURE_AUDIO_MULTIPLAYER_PAUSE
bUseStopInPause = HXDebugOptionEnabled("zUseStopInPause");
#endif
if (!bUseStopInPause && NumberOfResumedPlayers() == 0)
{
m_bPaused = TRUE;
if(m_ulCallbackID)
{
m_pScheduler->Remove(m_ulCallbackID);
m_ulCallbackID = 0;
}
// Check to see if all audio players are paused, then and only
// then will we pause the device
if ( m_pAudioDev )
{
m_pAudioDev->Pause();
}
m_bAtLeastOneTimeReceived = FALSE;
m_pLastPausedPlayer = p;
}
/*
* more than one audio player is currently active.
* We need to do the following:
* 1. get the current time from the device
* 2. get the time for data we have already pushed down to the device
* 3. flush the audio device
* 4. instruct all streams to "rewind" by the "written but not played" duration
*/
#ifdef HELIX_FEATURE_AUDIO_MULTIPLAYER_PAUSE
else if (!GetDisableMultiPlayPauseSupport() && m_pAudioDev && p->HasDataInAudioDevice())
{
HX_ASSERT(!m_bPaused && !m_bStoppedDuringPause);
RewindSession();
// this if is temporary
if (NumberOfResumedPlayers() > 0)
{
ActualResume();
}
}
#endif
m_pMutex->Unlock();
return HXR_OK;
}
/************************************************************************
* Method:
* CHXAudioSession::Resume
* Purpose:
* Resume playback of this Player's audio.
*/
HX_RES
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -