📄 hxaudses.cpp
字号:
// mask this error
if (theErr == HXR_WOULD_BLOCK)
{
theErr = HXR_OK;
}
// If we do not have audio.. OR if we do have audio but
// we have disabled writing to the device, then we need to
// fake the timeline.
if (!theErr && !m_ulCallbackID && (!m_bHasStreams || m_bDisableWrite))
{
if (m_bFirstPlayAudio)
{
// First time thru, we initialize callback time.
HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime();
m_pFakeAudioCBTime->tv_sec = lTime.tv_sec;
m_pFakeAudioCBTime->tv_usec = lTime.tv_usec;
m_ulIncreasingTimer = 0;
m_ulLastFakeCallbackTime = HX_GET_TICKCOUNT();
*m_pFakeAudioCBTime += (int) (m_ulGranularity*1000);
}
m_bFakeAudioTimeline = TRUE;
m_ulCallbackID = m_pScheduler->RelativeEnter( this, m_ulGranularity);
if (m_bFirstPlayAudio)
{
OnTimeSync(m_ulIncreasingTimer);
}
}
else if (!theErr && !m_ulCallbackID && m_bHasStreams && !m_bDisableWrite)
{
m_bFakeAudioTimeline = FALSE;
m_ulCallbackID = m_pScheduler->RelativeEnter(this, m_ulGranularity*9/10);
#if 0 // XXX HP don't send OnTimeSync() untill we resume the audio device
// the following logic caused OnTimeSync() sent to video renderer before the audio
// timeline is started after seeking, as a consequence, the A/V could be out of
// sync, video could be frozen for short period time in order to wait the audio
// timeline to catch up
if (m_bFirstPlayAudio)
{
OnTimeSync(m_ulIncreasingTimer);
}
#endif
}
exit:
m_bInPlayAudio = FALSE;
// can only happen in multi-player pause/resume/stop case
if (m_bDeferActualResume && theErr != HXR_OUTOFMEMORY)
{
m_bDeferActualResume = FALSE;
theErr = ActualResume();
}
m_bFirstPlayAudio = FALSE;
m_pMutex->Unlock();
return theErr;
}
HX_RESULT
CHXAudioSession::CheckForBufferReuse()
{
if (m_pSessionBuf)
{
m_pSessionBuf->AddRef();
if (m_pSessionBuf->Release() > 1)
{
/*
* Cannot use this buffer the next time
* release our reference and create a new one
*/
m_pSessionBuf->Release();
m_pSessionBuf = (IHXBuffer*) new CHXBuffer;
if( m_pSessionBuf )
{
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();
_NotifyTimelineWatchers(TLW_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);
_NotifyTimelineWatchers( TLW_CLOSE );
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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -