?? hxaudstr.cpp
字號:
HX_RESULT CHXAudioStream::Setup( HXAudioFormat* pFormat, ULONG32 ulGranularity){ HX_RESULT theErr = HXR_OK; m_DeviceFmt.uChannels = pFormat->uChannels; m_DeviceFmt.uBitsPerSample = pFormat->uBitsPerSample; m_DeviceFmt.ulSamplesPerSec = pFormat->ulSamplesPerSec; m_DeviceFmt.uMaxBlockSize = pFormat->uMaxBlockSize; m_ulGranularity = ulGranularity; m_bSetupDone = TRUE; /* we have all the info now.. so setup the resampler */ if (m_bAudioFormatKnown && !m_bInited) { theErr = ProcessInfo(); } return theErr;}/************************************************************************ * Method: * IHXAudioStream::ResetStream * Purpose: */void CHXAudioStream::ResetStream(){ m_bInited = FALSE; m_bCanBeRewound = FALSE; m_bSetupDone = FALSE; m_bAudioFormatKnown = FALSE; m_bIsResumed = FALSE; UnRegister(); while (m_pAvailableBuffers && m_pAvailableBuffers->GetCount() > 0) { IHXBuffer* pBuffer = (IHXBuffer*) m_pAvailableBuffers->RemoveHead(); HX_RELEASE(pBuffer); } HX_DELETE(m_pAvailableBuffers); // Delete all entries in the audio data list FlushBuffers(); HX_DELETE(m_pDataList); HX_DELETE(m_pInstantaneousList); CleanupRAByToTs(); HX_DELETE(m_pRAByToTsInList); HX_DELETE(m_pRAByToTsAdjustedList); // Delete resample buffer HX_VECTOR_DELETE(m_pResampleBuf); // Delete tmp resample buffer HX_VECTOR_DELETE(m_pTmpResBuf); HX_VECTOR_DELETE(m_pCrossFadeBuffer); HX_VECTOR_DELETE(m_pExcessInterpBuffer); HX_VECTOR_DELETE(m_pTempInterpBuffer); m_ulExcessInterpBufferSize = m_ulPreviousExcessInterpBufferSize = 0; #if defined(HELIX_FEATURE_CROSSFADE) HX_DELETE(m_pCrossFader);#endif /* HELIX_FEATURE_CROSSFADE */ // Free the resampler HX_RELEASE(m_pResampler); m_bGotHooks = FALSE; m_llLastWriteTime = 0; m_ulTSRollOver = 0;#ifdef _TESTING if ( g_log > 0 ) close(g_log); g_log = -1;#endif HX_RELEASE(m_pValues);#if defined(HELIX_FEATURE_AUDIO_PREMIXHOOK) // Delete all entries in the pre-mix hook list. if ( m_PreMixHookMap.GetCount() > 0) { HXAudioHookInfo* h = 0; CHXMapPtrToPtr::Iterator lIter = m_PreMixHookMap.Begin(); for (; lIter != m_PreMixHookMap.End(); ++lIter) { h = (HXAudioHookInfo*) (*lIter); ProcessAudioHook(ACTION_REMOVE, h->pHook); h->pHook->Release(); delete h; } m_PreMixHookMap.RemoveAll(); }#endif /* HELIX_FEATURE_AUDIO_PREMIXHOOK */#if defined(HELIX_FEATURE_VOLUME) // Delete IRMA volume object. if (m_pStreamVolume && m_pVolumeAdviseSink) { m_pStreamVolume->RemoveAdviseSink(m_pVolumeAdviseSink); m_pVolumeAdviseSink->m_pCHXAudioStream = 0; } HX_RELEASE(m_pVolumeAdviseSink);#endif /* HELIX_FEATURE_VOLUME */ HX_RELEASE(m_pStreamVolume); HX_DELETE(m_pInDataPtr); HX_DELETE(m_pOutDataPtr); if (m_DryNotificationMap.GetCount() > 0) { IHXDryNotification* pDryNotification = 0; CHXMapPtrToPtr::Iterator lIter = m_DryNotificationMap.Begin(); for (; lIter != m_DryNotificationMap.End(); ++lIter) { pDryNotification = (IHXDryNotification*) (*lIter); pDryNotification->Release(); } m_DryNotificationMap.RemoveAll(); } HX_RELEASE(m_pCrossFadeStream); HX_RELEASE(m_pCommonClassFactory);#if defined(HELIX_FEATURE_PREFERENCES) HX_RELEASE(m_pPreferences);#endif /* HELIX_FEATURE_PREFERENCES */ HX_RELEASE(m_Owner); return;}HX_RESULTCHXAudioStream::ProcessAudioHook(PROCESS_ACTION action, IHXAudioHook* pAudioHook){ return HXR_OK;}// Dummy version of this method - real version would be in hxaudstr_new.cppBOOL CHXAudioStream::ConvertIntoBuffer(tAudioSample* buffer, UINT32 nSamples, INT64 llStartTimeInSamples){ return FALSE;}/************************************************************************ * Method: * IHXAudioStream::InitHooks * Purpose: * Init any pre-mix hooks. Return TRUE if hooks exist else return * FALSE. */void CHXAudioStream::InitHooks(){#if defined(HELIX_FEATURE_AUDIO_PREMIXHOOK) /* Iterate thru the hook list and call the hook's OnInit(). * If any of the hooks have disabled write set to TRUE, then * we will let this override any set to FALSE. */ if ( m_PreMixHookMap.GetCount() > 0 ) { HXAudioHookInfo* h = 0; CHXMapPtrToPtr::Iterator lIter = m_PreMixHookMap.Begin(); for (; lIter != m_PreMixHookMap.End(); ++lIter) { h = (HXAudioHookInfo*) (*lIter); if (h->bIgnoreAudioData || HXR_OK == ProcessAudioHook(ACTION_CHECK, h->pHook)) { h->pHook->OnInit( &m_AudioFmt ); } } }#endif /* HELIX_FEATURE_AUDIO_PREMIXHOOK */ m_bHooksInitialized = TRUE;}/************************************************************************ * Method: * IHXAudioStream::ProcessHooks * Purpose: */HX_RESULT CHXAudioStream::ProcessHooks( HXAudioData* pInData, HXAudioData* pOutData){ HX_RESULT theErr = HXR_OK;#if defined(HELIX_FEATURE_AUDIO_PREMIXHOOK) m_pInDataPtr->pData = pInData->pData; m_pInDataPtr->pData->AddRef(); m_pInDataPtr->ulAudioTime = pInData->ulAudioTime; m_pOutDataPtr->pData = NULL; m_pOutDataPtr->ulAudioTime = pInData->ulAudioTime; m_pInDataPtr->uAudioStreamType = pInData->uAudioStreamType; m_pOutDataPtr->uAudioStreamType = pInData->uAudioStreamType; if ( m_PreMixHookMap.GetCount() > 0 ) { HXAudioHookInfo* pPreMixHookInfo = 0; CHXMapPtrToPtr::Iterator lIter = m_PreMixHookMap.Begin(); for (; !theErr && lIter != m_PreMixHookMap.End(); ++lIter) { pPreMixHookInfo = (HXAudioHookInfo*) (*lIter); if (HXR_OK == ProcessAudioHook(ACTION_CHECK, pPreMixHookInfo->pHook)) { theErr = pPreMixHookInfo->pHook->OnBuffer( m_pInDataPtr, m_pOutDataPtr); /* Check to see if renderer changed the buffer. If so, then * make this output as input to the next Hook. */ if (!theErr && m_pOutDataPtr->pData) { m_pInDataPtr->pData->Release(); m_pInDataPtr->pData = m_pOutDataPtr->pData; m_pInDataPtr->ulAudioTime = m_pOutDataPtr->ulAudioTime; m_pOutDataPtr->pData = 0; } } else if (pPreMixHookInfo->bIgnoreAudioData) { IHXBuffer* pTempBuf = m_pInDataPtr->pData; m_pInDataPtr->pData = NULL; theErr = pPreMixHookInfo->pHook->OnBuffer( m_pInDataPtr, m_pOutDataPtr); m_pInDataPtr->pData = pTempBuf; } } } /* Final output is always in InDataPtr*/ pOutData->pData = m_pInDataPtr->pData; pOutData->ulAudioTime = m_pInDataPtr->ulAudioTime; pOutData->uAudioStreamType = m_pInDataPtr->uAudioStreamType;#endif /* HELIX_FEATURE_AUDIO_PREMIXHOOK */ return theErr;}/************************************************************************ * Method: * CHXAudioStream::MixIntoBuffer * Purpose: * Mix stream data into this pPlayerBuf. * Note: * * Resampler always works on 16 bit PCM. If the input is * 8 bit, it converts it first to 16 bit before making * any resampling calculations. * We always try to open audio device in 16 bit stereo mode. * This is because a new player/stream may be instantiated in the * midst of a presentation and this new stream may be stereo. If we * earlier opened the device as mono, we will have to force this stereo * stream to be played as mono! Not a good idea. Also any mono-streo * conversion almost comes for free (some extra memory usage and * an extra assignment) since it can be done in the mixing loop in * MixBuffer(). * * Any 8-16 and stereo-mono conversion, if required, SHOULD be done * before resampling. * Any mono-stereo conversion should be done after resampling. * * Stereo-Mono conversion code resides in the resampler. * Mono-Stereo conversion code resides in the mixer. * */HX_RESULT CHXAudioStream::MixIntoBuffer( UCHAR* pPlayerBuf, ULONG32 ulBufSize, ULONG32& ulBufTime, BOOL& bIsMixBufferDirty, BOOL bGetCrossFadeData){ BOOL bCrossFadeThisTime = FALSE; UINT32 ulTimeActuallyFaded = m_ulGranularity; if (!m_bInited) { return HXR_NOT_INITIALIZED; }//{FILE* f1 = ::fopen("c:\\temp\\rasync.txt", "a+"); ::fprintf(f1, "Call MixIntoBuffer: %lu\n", m_ulLastWriteTime);::fclose(f1);} /* If this is a *FROM* stream, we may have already mixed * data during cross-fade with *TO* stream */ if (m_bFadeAlreadyDone && !m_bFadeToThisStream) { m_bFadeAlreadyDone = FALSE; return HXR_OK; } HX_ASSERT(!bGetCrossFadeData || !m_bFadeToThisStream); /* If we need to mix cross fade data from the *from* stream, * it better be available */ HX_ASSERT(!bGetCrossFadeData || m_pDataList->GetCount() > 0); /* If this stream needs to be cross-faded and is a * NOT a fade-to stream, it would have been already taken * care of by the fade-to stream in an earlier call to * MixIntoBuffer() */ if (m_bCrossFadingToBeDone && m_pDataList->GetCount() > 0) { HXAudioInfo* pInfo = (HXAudioInfo*) m_pDataList->GetHead(); INT64 llActualStartTime = 0; if (pInfo) { llActualStartTime = CAST_TO_INT64 (pInfo->ulStartTime) + CAST_TO_INT64 (CalcMs(pInfo->pBuffer->GetSize() - pInfo->ulBytesLeft)) + CAST_TO_INT64 m_ulTSRollOver * CAST_TO_INT64 MAX_UINT32; if (m_bFadeToThisStream) { /* Cool! It is time for cross-fading */ if ((m_llLastWriteTime <= m_llCrossFadeStartTime && m_llCrossFadeStartTime - m_llLastWriteTime <= CAST_TO_INT64 m_ulGranularity) || (m_llLastWriteTime > m_llCrossFadeStartTime && m_llLastWriteTime - m_llCrossFadeStartTime <= CAST_TO_INT64 m_ulFudge)) { bCrossFadeThisTime = TRUE; if (m_llLastWriteTime <= m_llCrossFadeStartTime) { ulTimeActuallyFaded = m_ulGranularity - INT64_TO_UINT32(m_llCrossFadeStartTime - m_llLastWriteTime); }//{FILE* f1 = ::fopen("c:\\raroot\\racross.txt", "a+"); ::fprintf(f1, "m_ulLastWriteTime: %lu ulStartTime: %lu m_ulCrossFadeStartTime: %lu pInfo->ulStartTime: %lu pInfo->pBuffer->GetSize(): %lu pInfo->ulBytesLeft: %lu\n", m_ulLastWriteTime, ulStartTime, m_ulCrossFadeStartTime, pInfo->ulStartTime, pInfo->pBuffer->GetSize(), pInfo->ulBytesLeft);::fclose(f1);} HX_ASSERT( (llActualStartTime >= m_llCrossFadeStartTime && (llActualStartTime <= m_llCrossFadeStartTime + m_ulCrossFadeDuration)) || (llActualStartTime < m_llCrossFadeStartTime && (m_llCrossFadeStartTime - llActualStartTime <= CAST_TO_INT64 m_ulFudge))); } } } } UINT32 ulLastWriteTime = INT64_TO_UINT32(m_llLastWriteTime - CAST_TO_INT64 m_ulTSRollOver * CAST_TO_INT64 MAX_UINT32); if (!bGetCrossFadeData && ulBufTime < ulLastWriteTime) { ulBufTime = ulLastWriteTime; } /* If there are any DryNotifications and the data list is empty * we need to notify them so that they can write more data. */ if (m_DryNotificationMap.GetCount() > 0 || m_Owner->GetAudioStreamCount() == 1) { UINT32 ulNumMsRequired = m_ulGranularity; if (m_pDataList->IsEmpty() || !EnoughDataAvailable(ulLastWriteTime, ulNumMsRequired)) { if (!bIsMixBufferDirty && !bGetCrossFadeData && !m_Owner->m_Owner->ReallyNeedData()) { return HXR_WOULD_BLOCK; } if (m_DryNotificationMap.GetCount() > 0) { IHXDryNotification* pDryNotification = 0; CHXMapPtrToPtr::Iterator lIter = m_DryNotificationMap.Begin(); for (; lIter != m_DryNotificationMap.End(); ++lIter) { pDryNotification = (IHXDryNotification*) (*lIter); pDryNotification->OnDryNotification(ulLastWriteTime, ulNumMsRequired); } if (m_Owner->GetState() != E_PLAYING) { return HXR_OK; } } } } m_Owner->DataInAudioDevice(TRUE); // ///////////////////////////////////////////////////////////// // There may be no buffers in the list. No packets? Play silence. // Still need to increment time. if ( m_pDataList->IsEmpty() && m_pInstantaneousList->IsEmpty() ) { m_llLastWriteTime += CAST_TO_INT64 m_ulGranularity;//{FILE* f1 = ::fopen("e:\\MixIntoBuffer.txt", "a+"); ::fprintf(f1, "%lu\t%p\t%lu\n", HX_GET_BETTERTICKCOUNT(), this, (UINT32)m_llLastWriteTime);::fclose(f1);} return HXR_NO_DATA; } UCHAR* pSourceBuffer = 0; ULONG32 ulMaxBytes = 0; ULONG32 ulMaxFramesIn = 0; ULONG32 ulMaxFramesOut = 0; ULONG32 ulNumBytesMixed = 0; BOOL bMonoToStereoMayBeConverted = TRUE; BOOL bResampleBufferDirty = FALSE;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -