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

📄 hxaudstr.cpp

📁 symbian 下的helix player源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            {
                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;


    // /////////////////////////////////////////////////////////////
    // If no  resampling, mix stream data directly into the player
    // buffer.
    if ( !m_pResampler)
    {
        pSourceBuffer   = pPlayerBuf;
        ulMaxBytes      = m_ulInputBytesPerGran;

        /* For only those sound cards which do not
         * support stereo - a RARE (non-existent) case 
         */
        if (m_AudioFmt.uChannels == 2 && m_DeviceFmt.uChannels == 1)
        {
            /* We should never reach here since this case
             * should be handled by the Resampler
             * Temporary ASSERT... 
             */
            HX_ASSERT(FALSE);
        }
        /* Mono->Stereo conversion*/
        else if (m_bChannelConvert)
        {
            HX_ASSERT(ulMaxBytes <= ulBufSize/2);
            
            /* Avoid GPF in retail builds! */
            if (ulMaxBytes > ulBufSize/2)
            {
                ulMaxBytes = ulBufSize/2;
            }
        }
        else
        {
            HX_ASSERT(ulMaxBytes <= ulBufSize);
            
            /* Avoid GPF in retail builds! */
            if (ulMaxBytes > ulBufSize)
            {
                ulMaxBytes = ulBufSize;
            }
        }
    }
#if defined(HELIX_FEATURE_RESAMPLER)
    // /////////////////////////////////////////////////////////////
    // If resampling, mix stream data into a tmp buffer. Then
    // resample this buffer and mix the final resampled buffer into
    // the player buffer.
    else
    {
        bMonoToStereoMayBeConverted = FALSE;

//      memset(m_pTmpResBuf, 0, HX_SAFESIZE_T(m_ulMaxBlockSize));
        pSourceBuffer = m_pTmpResBuf;

        /* 
         * Audio Session will always ask for m_ulOutputBytesPerGran bytes to be mixed
         * in MixIntoBuffer() call. So we need to produce these many number of bytes.
         * If there is any mono-stereo conversion that happens in the mixing, number
         * of output bytes required from the resampler are half the number of 
         * m_ulOutputBytesPerGran bytes.
         */

        if (m_pResampler)
        {
            ulMaxFramesOut = m_ulOutputBytesPerGran/(m_DeviceFmt.uBitsPerSample==8 ? 1 : 2);

            if (m_DeviceFmt.uChannels == 2)
            {
                ulMaxFramesOut /= 2;
            }

            ulMaxFramesIn = m_pResampler->Requires(ulMaxFramesOut);

            ulMaxBytes = ulMaxFramesIn *  ((m_AudioFmt.uBitsPerSample==8)? 1 : 2)
                                            * m_AudioFmt.uChannels;
        }
        else
        {
            ulMaxBytes = m_ulInputBytesPerGran;
        }

        HX_ASSERT(ulMaxBytes <= m_ulMaxBlockSize);
    }
#endif /* HELIX_FEATURE_RESAMPLER */

    // /////////////////////////////////////////////////////////////
    // Mix n bytes of data into buffer
    ulNumBytesMixed = MixData(pSourceBuffer, ulMaxBytes, bMonoToStereoMayBeConverted, 
        (!m_pResampler) ? bIsMixBufferDirty : bResampleBufferDirty);

/*
    if (ulNumBytesMixed > 0)
    {
        ::fwrite(pSourceBuffer, ulNumBytesMixed, 1, fdbefore);
    }
*/

#if defined(HELIX_FEATURE_RESAMPLER)
    // /////////////////////////////////////////////////////////////
    // If we need to resample , then do this and then mix data into
    // the player buffer.
    // Only resample and mix if volume is *not* zero and there 
    // are some bytes to mix.
    if (m_pResampler && ulNumBytesMixed > 0 && m_uVolume > 0 && !m_bMute)
    {
        if(ulNumBytesMixed < ulMaxBytes  &&  8==m_AudioFmt.uBitsPerSample)
        {
            //fill remainder with 128's (-1), silence:
            UCHAR* pTmp = &pSourceBuffer[ulNumBytesMixed];
            ULONG32 ulNumBytesLeftToSilence = ulMaxBytes-ulNumBytesMixed;
            do
            {
                *pTmp = 128;
                pTmp++;
            } while(--ulNumBytesLeftToSilence);
        }

        ULONG32 ulOutBytes      = 0;
        if (m_pResampler)
        {
            ulOutBytes = m_pResampler->Resample((UINT16*)pSourceBuffer,
                                                ulMaxBytes,
                                                (UINT16*)m_pResampleBuf);

/*
            FILE* fp = fopen("c:\\temp\\audio.txt", "w+");
            ::fwrite(m_pResampleBuf, ulOutBytes, 1, fp);
            fclose(fp);
*/
            /* Resampler will do stereo to mono conversion for us.*/
            HX_ASSERT(ulMaxFramesOut == (ulOutBytes / 2 / 
                      (m_AudioFmt.uChannels == 2 && m_DeviceFmt.uChannels == 1 ? 1 : m_AudioFmt.uChannels))) ;
        }

        if (m_bChannelConvert)
        {
            HX_ASSERT(ulOutBytes*2 <= ulBufSize);
            if ( ulOutBytes > ulBufSize/2 )
            {           
                ulOutBytes = ulBufSize/2;
            }
        }
        else
        {
            HX_ASSERT(ulOutBytes <= ulBufSize);
            ulOutBytes = ulBufSize;
        }

        BOOL bBeforeMixBufferDirty = bIsMixBufferDirty;
        UINT32 ulMixedNumBytes = 0;

#if defined(HELIX_FEATURE_MIXER)
        ulMixedNumBytes = CHXMixer::MixBuffer( m_pResampleBuf, pPlayerBuf, 
                             ulOutBytes, m_bChannelConvert,
                             m_uVolume, m_DeviceFmt.uBitsPerSample, bIsMixBufferDirty);
#else
        ::memcpy(pPlayerBuf, m_pResampleBuf, ulOutBytes); /* Flawfinder: ignore */
        bIsMixBufferDirty = TRUE;
        ulMixedNumBytes = ulOutBytes;
#endif /* HELIX_FEATURE_MIXER */

        // If we mixed only a partial buffer, make the remaining buffer silent
        if (!bBeforeMixBufferDirty && ulMixedNumBytes < ulBufSize)
        {
            ::memset(pPlayerBuf+ulMixedNumBytes, 0, ulBufSize-ulMixedNumBytes);
        }
    }

afterMixing:
#endif /* HELIX_FEATURE_RESAMPLER */

#ifdef _TESTING
    if ( g_log > 0 )
    {
        write( g_log, pPlayerBuf, ulNumBytesMixed);
    }

#endif

    /* This is for *FROM* stream */
    if (bGetCrossFadeData)
    {
        m_bFadeAlreadyDone = TRUE;
    }
    /* If we are cross-fading, we have data from this stream in pPlayerBuf
     * Now get data to be  cross-faded from *From* stream in 
     * m_pCrossFadeBuffer
     */
#if defined(HELIX_FEATURE_CROSSFADE) && defined(HELIX_FEATURE_MIXER)
    else if (bCrossFadeThisTime)
    {
        /* Allocate CrossFade Buffer */
        if (!m_pCrossFadeBuffer)
        {
            m_ulCrossFadeBufferSize = ulBufSize;
            m_pCrossFadeBuffer = new UCHAR[m_ulCrossFadeBufferSize];
        }

        memset(m_pCrossFadeBuffer, 0, HX_SAFESIZE_T(m_ulCrossFadeBufferSize));

        UINT32 ulCrossFadeLen = m_ulCrossFadeBufferSize;
        UINT32 ulTmpBufTime   = 0;
        BOOL bIsDrity = FALSE;
        m_pCrossFadeStream->MixIntoBuffer(m_pCrossFadeBuffer,
                                         ulCrossFadeLen, ulTmpBufTime, bIsDrity, TRUE);
        /* Now it is time to perform cross-fading between
         * pPlayerBuf and m_pCrossFadeBuffer
         */
        
        UINT32 ulStartByteToFade            = 0;
        UINT32 ulNumMsInThisBuffer          = CalcDeviceMs(ulBufSize);
        UINT32 ulNumBytesToBeCrossFaded = ulBufSize;
        UINT32 ulSampleSize = ((m_DeviceFmt.uBitsPerSample==8)? 1 : 2)
                            * m_DeviceFmt.uChannels;

        /* Make sure we have integral number of samples */
        HX_ASSERT(ulBufSize == (ulBufSize/ulSampleSize) * ulSampleSize);


        /* Only partial buffer needs to be cross-faded.
         *   -------------
         * ~~_____________|
         *
         *       -----------
         *      |___________~~
         *
         *      
         *     -----
         *    |_____|  <-- Granularity size block that is mixed.
         *
         *       <--> Only partial block needs to be faded
         */
        
        if (ulTimeActuallyFaded < ulNumMsInThisBuffer)
        {
            ulNumBytesToBeCrossFaded = (UINT32) (ulBufSize * 
                (ulTimeActuallyFaded*1./ulNumMsInThisBuffer)) ;

            UINT32 ulOutOfPhase = ulNumBytesToBeCrossFaded % ulSampleSize;
            if (ulOutOfPhase > 0)
            {
                ulNumBytesToBeCrossFaded = 
                    ulNumBytesToBeCrossFaded - ulOutOfPhase;
            }

            ulStartByteToFade = ulBufSize - ulNumBytesToBeCrossFaded;
        }

        if (ulTimeActuallyFaded > m_ulCrossFadeDuration)
        {
            ulNumBytesToBeCrossFaded = (UINT32) (ulBufSize * 
                (m_ulCrossFadeDuration*1./ulNumMsInThisBuffer)) ;

            UINT32 ulOutOfPhase = ulNumBytesToBeCrossFaded % ulSampleSize;
            if (ulOutOfPhase > 0)
            {
                ulNumBytesToBeCrossFaded = 
                    ulNumBytesToBeCrossFaded - ulOutOfPhase;
            }
        }

        UINT16 uNumSamples = (UINT16) (ulNumBytesToBeCrossFaded/
                                       ulSampleSize);

        BOOL bWasDirty = bIsMixBufferDirty;
        /* Mix the initial bytes that are not cross-faded*/
        if (ulStartByteToFade > 0)
        {
            CHXMixer::MixBuffer( m_pCrossFadeBuffer, pPlayerBuf, 
                        ulStartByteToFade, FALSE, 100, 8, bWasDirty);
        }

        m_pCrossFader->CrossFade((INT16*) (m_pCrossFadeBuffer+ulStartByteToFade), 
                                 (INT16*) (pPlayerBuf+ulStartByteToFade), 
                                 uNumSamples);

        /* make sure we have silence in bytes that were not touched */
        if (!bIsMixBufferDirty &&
            (ulStartByteToFade + (uNumSamples*ulSampleSize)) < ulBufSize)
        {
            ::memset(pPlayerBuf+ulStartByteToFade + (uNumSamples*ulSampleSize), 0, 
                ulBufSize - (ulStartByteToFade + (uNumSamples*ulSampleSize)));
        }

        bIsMixBufferDirty = TRUE;
    }

    if (bGetCrossFadeData || bCrossFadeThisTime)
    {
        if (bGetCrossFadeData)
        {
            HX_ASSERT(m_llLastWriteTime >= m_llCrossFadeStartTime);
            if (m_llLastWriteTime >= m_llCrossFadeStartTime)
            {
                HX_ASSERT(m_llLastWriteTime - m_llCrossFadeStartTime < MAX_TIMESTAMP_GAP);
                ulTimeActuallyFaded = INT64_TO_UINT32(m_llLastWriteTime - m_llCrossFadeStartTime);
            }
        }

        if (ulTimeActuallyFaded >= m_ulCrossFadeDuration)
        {
            m_bCrossFadingToBeDone = FALSE;
            HX_RELEASE(m_pCrossFadeStream);

            /* We should release any extra buffers if it is a
             * *from* stream
             */
            if (!m_bFadeToThisStream)
            {
                /* Do not remove any instantaenous buffers */
                FlushBuffers(FALSE);
            }
        }
        else
        {
            m_ulCrossFadeDuration   -= ulTimeActuallyFaded;
            m_llCrossFadeStartTime  += CAST_TO_INT64 ulTimeActuallyFaded;
        }
    }
    else if (m_bCrossFadingToBeDone && !m_bFadeToThisStream)
    {
        m_pCrossFadeStream->SyncStream(m_llLastWriteTime);
    }
#endif /* HELIX_FEATURE_CROSSFADE && HELIX_FEATURE_MIXER */

//{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_OK;
}


/************************************************************************
 *  Method:
 *      CHXAudioStream::MixData
 *  Purpose:
 *      Mix all valid data in my auxilliary list into the buffer.
 *
 *  Thoughts:
 *      while there are buffers available
 *          if (buffertime is more than endtime) break;
 *          if (any part of buffer is >startime and < endtime)
 *              we are in business. 
 *              mix that part of the buffer, update offset, 
 *              update max of num bytes written in this round.
     * Looks like we need to keep LastWrite time and offsets for all buffers
     * that get written in one pass.
     * Consider this scenario:
     *  
     *
        ----------------- -----------------
       |________________| |_______________|  -> Skew  1
          ________ __________   
         |_______| |_________|              ->Skew    2  5
          ____________________________________
         |__________________|_|_______________| Skew in opposite direction 3
               _______
              |_______|                               4

         ____________
        |____________|      <- Buffer to be mixed currently
               
      

⌨️ 快捷键说明

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