⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hxaudstr.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    pAudioFormat->uChannels       = m_AudioFmt.uChannels;
    pAudioFormat->uBitsPerSample  = m_AudioFmt.uBitsPerSample;
    pAudioFormat->ulSamplesPerSec = m_AudioFmt.ulSamplesPerSec;
    pAudioFormat->uMaxBlockSize   = m_AudioFmt.uMaxBlockSize;

    return HXR_OK;
}

/************************************************************************
 *  Method:
 *              IHXAudioStream::Setup
 *      Purpose:
 *              This is called by the player's Setup method. At this
 *              time the audio device format is set and we can now
 *              set up the streams pre-mixing buffer. This buffer
 *              contains data that has been resampled to match the
 *              audio device format.
 */
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_RESULT
CHXAudioStream::ProcessAudioHook(PROCESS_ACTION action, 
                                 IHXAudioHook* pAudioHook)
{
    return HXR_OK;
}

// Dummy version of this method - real version would be in hxaudstr_new.cpp
BOOL 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)
                {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -