📄 audbeos.cpp
字号:
m_pPendingBufferList->AddHead((void*) pNewBuffer); // no more space in the secondary buffer bCanContinue = FALSE; } m_player->UnlockCyclic(); m_ulNextWriteOffset += ulAudioBytesWritten1 + ulAudioBytesWritten2; if (pAudioOutData) m_bGotAWrite = TRUE; if (m_ulNextWriteOffset >= m_ulBufferSize) { m_ulNextWriteOffset -= m_ulBufferSize; } if (m_bFirstWrite) { m_bFirstWrite = FALSE; } } // lock else { bCanContinue = FALSE; if (!m_pPendingBufferList) { m_pPendingBufferList = new CHXSimpleList; } pBuffer->AddRef(); m_pPendingBufferList->AddHead((void*) pBuffer); } pBuffer->Release(); pBuffer = NULL; if (bCanContinue && m_pPendingBufferList && m_pPendingBufferList->GetCount() > 0) { pBuffer = (IHXBuffer*) m_pPendingBufferList->RemoveHead(); } } // while if (m_bPlaying) { UINT32 ulCurrentTime = HX_GET_TICKCOUNT(); if (CALCULATE_ELAPSED_TICKS(m_ulLastTimeSync, ulCurrentTime) > 100) { m_ulLastTimeSync = ulCurrentTime; OnTimeSync(); } }//@ This is an ugly hack, but it seems to work very well.// Hopefully I can figure it out and fix it properly at some point.// (mclifton 10/5/99)/*if (pAudioOutData && m_bPlaying && m_pPendingBufferList && m_pPendingBufferList->GetCount() > 0){snooze(50000);_Imp_Write(NULL);}if (pAudioOutData && m_bPlaying && m_pPendingBufferList && m_pPendingBufferList->GetCount() > 0){snooze(50000);_Imp_Write(NULL);}*/ return theErr;}HX_RESULT CAudioOutBeOS::_Imp_Reset(){ m_ulCurrentPlayTime = 0; m_bFirstWrite = TRUE; m_ulNextWriteOffset = 0; if (m_player) m_player->StopPlaying(); m_bPlaying = FALSE; return HXR_OK;}HX_RESULT CAudioOutBeOS::_Imp_Drain(){ return HXR_OK;}BOOL CAudioOutBeOS::_Imp_SupportsVolume(){ return TRUE;}UINT16 CAudioOutBeOS::_Imp_GetVolume(){ float vol = 0.0f; if (m_player) vol = m_player->Gain(); return (UINT16)(vol * 100.0f);}HX_RESULT CAudioOutBeOS::_Imp_SetVolume(const UINT16 uVolume){ float vol = (float)uVolume / 100.0f; if (m_player) m_player->SetGain(vol); return HXR_OK;}HX_RESULT CAudioOutBeOS::_Imp_CheckFormat(const HXAudioFormat* pFormat){ return HXR_OK;}HX_RESULT CAudioOutBeOS::_Imp_GetCurrentTime(ULONG32& ulCurrentTime){ size_t curPos = 0; if (m_player) { if (m_player->IsPlaying()) curPos = m_player->CurrentPosition() * m_ulFrameSize; // This method of calculating elapsed time was basically copied over from // the DirectSound code. The bad news is that it is error-prone. Converting // from bytes to milliseconds is prone to roundoff, leading to an accumulation // of error, causing a drift of synchronization between audio and video. // (That DirectSound code has caused me nothing but headaches...) //m_ulCurrentPlayTime += // CalcMs(CalculateElapsedBytes(m_ulLastPlayCursor, curPos)); // The more accurate way to do it is to accumulate elapsed bytes, then // convert the total to milliseconds. The elapsed bytes is accurate to // within a video frame or so. Even though it can't be absolutely accurate, // at least it won't drift over time. m_ulCurrentPlayTime += CalculateElapsedBytes(m_ulLastPlayCursor, curPos); m_ulLastPlayCursor = curPos; } // old method //ulCurrentTime = m_ulCurrentPlayTime; // new method ulCurrentTime = CalcMs(m_ulCurrentPlayTime); return HXR_OK;}UINT16CAudioOutBeOS::_NumberOfBlocksRemainingToPlay(void){ UINT32 res = 0; size_t curPos = 0; // add up the number of audio bytes queued up if (m_pPendingBufferList) { LISTPOSITION i = m_pPendingBufferList->GetHeadPosition(); while (i) { res += ((IHXBuffer *)m_pPendingBufferList->GetAt(i))->GetSize(); m_pPendingBufferList->GetNext(i); } } // add in the bytes that are currently in the playback buffer if (m_player) { UINT32 playingBytes = 0; if (m_player->IsPlaying()) curPos = m_player->CurrentPosition() * m_ulFrameSize; if (curPos < m_ulNextWriteOffset) playingBytes += m_ulNextWriteOffset - curPos; else playingBytes += (m_ulBufferSize - curPos) + m_ulNextWriteOffset; res += playingBytes; } if (m_bGotAWrite) m_ulOldBytesLeft = res; else if (res > m_ulOldBytesLeft) { fprintf(stderr, "Buffer overflow!\n"); // This is a bad situation - I wish this never happened. // But what should I do when it does happen? // I used to return 0, since I thought that would force more // audio buffers my way, but it also seems to introduce more glitches. //res = 0; } m_bGotAWrite = FALSE; res /= m_ulBlockSize; return res;}voidCAudioOutBeOS::SetFormat(const HXAudioFormat* pFormat){ ::memset(&m_gameSoundFormat, 0, sizeof(gs_audio_format)); m_gameSoundFormat.frame_rate = pFormat->ulSamplesPerSec; m_gameSoundFormat.channel_count = pFormat->uChannels; switch (pFormat->uBitsPerSample) { case 8: m_gameSoundFormat.format = gs_audio_format::B_GS_U8; break; case 16: m_gameSoundFormat.format = gs_audio_format::B_GS_S16; break; } m_gameSoundFormat.byte_order = B_MEDIA_LITTLE_ENDIAN; m_gameSoundFormat.buffer_size = 2048; m_ulFrameSize = m_gameSoundFormat.channel_count * ((m_gameSoundFormat.format==gs_audio_format::B_GS_U8)?1:2);}inline UINT32 CAudioOutBeOS::CalcMs(ULONG32 ulNumBytes){ return ( (ULONG32) (( 1000.0 / (m_ulFrameSize * m_gameSoundFormat.frame_rate) ) * ulNumBytes) );}inline UINT32CAudioOutBeOS::CalculateElapsedBytes(UINT32 ulLastBytePos, UINT32 ulCurrentBytePos){ return ((ulCurrentBytePos >= ulLastBytePos) ? (ulCurrentBytePos - ulLastBytePos) : (ulCurrentBytePos + (m_ulBufferSize - ulLastBytePos)));}#if _BEOS_AUDIODEV_CALLBACKvoidCAudioOutBeOS::DoTimeSyncs(void){ ReschedPlaybackCheck(); OnTimeSync(); return;}HX_RESULTCAudioOutBeOS::ReschedPlaybackCheck(){ HX_RESULT theErr = HXR_OK; if (m_bCallbackPending) return theErr; *m_pPlaybackCountCBTime += (int)(m_ulGranularity * 1000) / 2; // Put this back in the scheduler. HXPlaybackCountCb *pCallback = 0; pCallback = new HXPlaybackCountCb(TRUE); if (pCallback) { pCallback->m_pAudioDeviceObject = this; m_bCallbackPending = TRUE; m_PendingCallbackID = m_pScheduler->AbsoluteEnter(pCallback, *((HXTimeval *)m_pPlaybackCountCBTime)); } else theErr = HXR_OUTOFMEMORY; // but ignored, why? return theErr;}CAudioOutBeOS::HXPlaybackCountCb::HXPlaybackCountCb(BOOL timed) : m_lRefCount(0) , m_pAudioDeviceObject(0) , m_timed(timed){}CAudioOutBeOS::HXPlaybackCountCb::~HXPlaybackCountCb(){}/* * IUnknown methods *//////////////////////////////////////////////////////////////////////////// Method:// IUnknown::QueryInterface// Purpose:// Implement this to export the interfaces supported by your // object.//STDMETHODIMP CAudioOutBeOS::HXPlaybackCountCb::QueryInterface(REFIID riid, void** ppvObj){ if (IsEqualIID(riid, IID_IHXCallback)) { AddRef(); *ppvObj = (IHXCallback*)this; return HXR_OK; } else if (IsEqualIID(riid, IID_IUnknown)) { AddRef(); *ppvObj = this; return HXR_OK; } *ppvObj = NULL; return HXR_NOINTERFACE;}/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::AddRef// Purpose:// Everyone usually implements this the same... feel free to use// this implementation.//STDMETHODIMP_(ULONG32) CAudioOutBeOS::HXPlaybackCountCb::AddRef(){ return InterlockedIncrement(&m_lRefCount);}/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::Release// Purpose:// Everyone usually implements this the same... feel free to use// this implementation.//STDMETHODIMP_(ULONG32) CAudioOutBeOS::HXPlaybackCountCb::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}/* * IHXPlaybackCountCb methods */STDMETHODIMP CAudioOutBeOS::HXPlaybackCountCb::Func(void){ if (m_pAudioDeviceObject) { if (!m_timed) { m_pAudioDeviceObject->_Imp_Write(NULL); } else { m_pAudioDeviceObject->_Imp_Write(NULL); m_pAudioDeviceObject->m_bCallbackPending = FALSE; m_pAudioDeviceObject->DoTimeSyncs(); } } return HXR_OK;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -