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

📄 hxaudply.cpp

📁 symbian 下的helix player源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    if ( m_eState == E_PLAYING )
    {
	return HXR_OK;
    }

    m_bIsDonePlayback = FALSE;
    m_eState          = E_PLAYING;
    m_bCanBeRewound   = TRUE;


    /* Use Audio Session Object ONLY if there are any audio streams
     * in the presentation
     */
    if (m_bHasStreams)
    {
	CHXAudioStream* s = 0;
	CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
	for (; lIter != m_pStreamList->End(); ++lIter)
	{
	    s = (CHXAudioStream*) (*lIter);
	    if ( s )
		s->Resume(TRUE);
	}

	// This is the audio device playback time that corresponds to
	// when this audio player resumed.
	m_ulADresumeTime = m_Owner->GetCurrentPlayBackTime();

	// This is this player's start time within its timeline. This is
	// modified when the player is seeked or resumed.
	m_ulAPstartTime = m_ulAPplaybackTime;

	UpdateStreamLastWriteTime();

	// Resume the audio device playback
	if ( !theErr )
	    theErr = m_Owner->Resume(this);
    }
    else
    {
	theErr = ResumeFakeTimeline();

	/* Send time 0 at first Resume */
	if (!theErr && m_bIsFirstResume)
	{
	    m_bIsFirstResume = FALSE;
	    OnTimeSync(m_ulIncreasingTimer);
	}
    }

    m_bIsResumed = TRUE;
    return ( !theErr ) ? HXR_OK : HXR_FAILED;
}

/************************************************************************
 *  Method:
 *		CHXAudioPlayer::Pause
 *	Purpose:
 *		The player object calls this function to pause audio playback.
 */
HX_RESULT CHXAudioPlayer::Pause()
{
    if (m_eState == E_PAUSED)
    {
	return HXR_OK;
    }

    m_eState = E_PAUSED;

    if (m_bHasStreams)
    {
	CHXAudioStream* s = 0;
	CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
	for (; lIter != m_pStreamList->End(); ++lIter)
	{
	    s = (CHXAudioStream*) (*lIter);
	    if ( s )
		s->Pause(TRUE);
	}

	m_Owner->Pause(this);
    }
    else
    {
	StopFakeTimeline();
    }

    m_bCanBeRewound = FALSE;

    return HXR_OK;
}

/************************************************************************
 *  Method:
 *		CHXAudioPlay::Stop
 *	Purpose:
 *      The player object calls this function to stop audio playback.
 *		If bFlush is TRUE, flush any data in the audio device.
 */
HX_RESULT CHXAudioPlayer::Stop
(
    const BOOL bFlush
)
{
    m_eState = E_STOPPED;

    m_ulAPstartTime 	= 0;

    if (m_bHasStreams)
    {
	CHXAudioStream* s = 0;
	CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
	for (; lIter != m_pStreamList->End(); ++lIter)
	{
	    s = (CHXAudioStream*) (*lIter);
	    if ( s )
		s->Stop();
	}

	m_Owner->Stop(this, bFlush);
    }
    else
    {
	StopFakeTimeline();
    }

    ResetPlayer();

    return HXR_OK;
}

/************************************************************************
 *  Method:
 *		CHXAudioPlayer::Seek
 *	Purpose:
 *		The player object calls this function to seek audio playback to
 *		the time (in milliseconds) given.
 */
HX_RESULT CHXAudioPlayer::Seek
(
const 	UINT32			ulSeekTime
)
{
    /* always remember this seek time.. even though there may not be any streams
     * yet for this player. This is because the streams may be created later and
     * we need to correctly apply the seek time to get the accurate time.
     */
    m_ulAPstartTime = m_ulAPplaybackTime = ulSeekTime;	// current start time for this player
    m_llLastWriteTime = (INT64) ulSeekTime;

    if (m_bHasStreams)
    {
	// Make each stream seek, too, since they own the resampling buffers.
	CHXAudioStream* s = 0;
	CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
	for (; lIter != m_pStreamList->End(); ++lIter)
	{
	    s = (CHXAudioStream*) (*lIter);
	    if ( s )
		s->Seek(ulSeekTime);
	}

	m_Owner->Seek( this, ulSeekTime );

	m_ulADresumeTime = m_Owner->GetCurrentPlayBackTime();
    }
    else
    {
	StopFakeTimeline();
	m_bIsFirstResume    = TRUE;
    }

    m_ulCurrentTime	    = ulSeekTime;

    m_ulLastCurrentTimeReturned	= m_ulCurrentTime;
    m_bTimeReturned	    = FALSE;
    m_bHasDataInAudioDevice = FALSE;

    return HXR_OK;
}

void CHXAudioPlayer::ResetPlayer(void)
{
    m_bInited		= FALSE;
    m_bHasStreams	= FALSE;
    m_bIsFirstResume	= TRUE;

    m_ulAPstartTime	= 0;
    m_ulAPplaybackTime	= 0;
    m_ulADresumeTime	= 0;

    m_ulCurrentTime	= 0;
    m_ulLastCurrentTimeReturned	= 0;
    m_ulLastDeviceTimeAdjusted = 0;
    m_bTimeReturned	= FALSE;
    m_bIsLive		= FALSE;
    m_bIsResumed	= FALSE;
    m_bIsDonePlayback	= TRUE;
    m_llLastWriteTime	= 0;
    m_bCanBeRewound	= FALSE;
    m_bHasDataInAudioDevice = FALSE;

    // Delete all streams.  Remove all list items.
    if ( m_pStreamList )
    {
	CHXAudioStream* pAudioStream = 0;
	while(!m_pStreamList->IsEmpty())
	{
	    pAudioStream = (CHXAudioStream*) m_pStreamList->RemoveHead();
	    pAudioStream->ResetStream();
	    pAudioStream->Release();
	}
    }

    /* We do not remove post mix hooks any more */
    /* We do not remove Stream Response Objects any more */

    /* Default value of Player format */
    m_PlayerFmt.uChannels	= 2;
    m_PlayerFmt.uBitsPerSample	= 16;
    m_PlayerFmt.ulSamplesPerSec	= 16000;
    m_PlayerFmt.uMaxBlockSize	= 64000;

    m_ulLastFakeCallbackTime = 0;

    StopFakeTimeline();
}

/************************************************************************
 *  Method:
 *		CHXAudioPlayer::SetupStreams
 *	Purpose:
 *		Tell each stream about the audio device format so
 *		they can setup their resamplers and buffer.
 */
void CHXAudioPlayer::SetupStreams(void)
{
    // Get audio device format
    m_Owner->GetFormat(&m_DeviceFmt);

    // Calculate bytes per gran
    m_ulBytesPerGran = (ULONG32)
                (((m_DeviceFmt.uChannels * ((m_DeviceFmt.uBitsPerSample==8)?1:2) *  m_DeviceFmt.ulSamplesPerSec)
                                / 1000.0) * m_ulGranularity);

    // Make sure that number of bytes per granularity is an even number.
    if ( (m_ulBytesPerGran % 2) != 0 )
        m_ulBytesPerGran++;
    /* Don't we have to calculate granularity again if we adjust
     * for even byte boundary - XXX Rahul 06/15/97
     */

    // Notify each stream
    CHXAudioStream* s = 0;
    CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
    for (; lIter != m_pStreamList->End(); ++lIter)
    {
	s = (CHXAudioStream*) (*lIter);
	if ( s )
	{
	    s->Setup( &m_DeviceFmt, m_ulGranularity );
	}
    }
}

/************************************************************************
 *  Method:
 *		CHXAudioPlayer::OnTimeSync
 *	Purpose:
 */
HX_RESULT	CHXAudioPlayer::OnTimeSync(ULONG32 ulCurrentTime)
{
    HX_RESULT theErr = HXR_OK;

#ifdef _MACINTOSH
    if (InterlockedIncrement(&gTIMELINE_MUTEX) > 1)
    {
       InterlockedDecrement(&gTIMELINE_MUTEX);
       return;
    }
    InterlockedDecrement(&gTIMELINE_MUTEX);
#endif

    if (m_bHasStreams)
    {
	ULONG32 ulADplaybackTime;

	ulADplaybackTime = m_Owner->GetCurrentPlayBackTime();
	m_ulAPplaybackTime = (ulADplaybackTime - m_ulADresumeTime) +
			      m_ulAPstartTime;
    }
    else
    {
	m_ulAPplaybackTime  = ulCurrentTime;
    }

    m_ulCurrentTime = m_ulAPplaybackTime ;

    AdjustForRealAudio();

    // Here we need to fudge the actual time for this player
    // For now we support only one player/timeline
    if (m_pPlayerResponse)
    {
	// The current playback time of any player is the difference
	// of the current audio device playback time minus the audio
	// device time when this player started (resumed) playback
	// plus the initial start time of playback within this player's
	// timeline (usually 0 but can be something else esp. after a
	// seek).
	theErr = m_pPlayerResponse->OnTimeSync(m_ulCurrentTime);
    }
    return theErr;
}

/************************************************************************
 *  Method:
 *		CHXAudioPlayer::Setup
 *	Purpose:
 *		This is called after AS receives format and stream info
 *		from the renderers AND before packets are received from
 *		the renderer.
 */
HX_RESULT CHXAudioPlayer::Setup( ULONG32 ulGranularity)
{
    HX_RESULT theErr = HXR_OK;


    if (m_bInited)
	return HXR_OK;

    /* Always write 100ms audio blocks for now. */
    m_ulGranularity = MAXIMUM_AUDIO_GRANULARITY;	//ulGranularity;

    /* We do not go below MINIMUM_AUDIO_GRANULARITY. This will not affect
     * sending timesyncs at this lower granularity since HXPlayer object
     * uses the scheduler to send individual timesyncs anyway
     */
    if (m_ulGranularity < MINIMUM_AUDIO_GRANULARITY)
    {
	m_ulGranularity = MINIMUM_AUDIO_GRANULARITY;
    }
    else if (m_ulGranularity > MAXIMUM_AUDIO_GRANULARITY)
    {
	m_ulGranularity = MAXIMUM_AUDIO_GRANULARITY;
    }

    if (!m_bHasStreams)
    {
	m_bInited = TRUE;
	return HXR_OK;
    }

    /* If this is the second player, session object may overide
     * the granularity value.
     */
    m_ulGranularity = m_Owner->SetGranularity(m_ulGranularity);

    // Determine this player's audio format parameters based on
    // the mixer channels attributes supplied in RegisterRenderer.
    //
    // 1. Spin thru the list of registered streams and
    //    determine the desired audio device parameters.
    // 2. Check the audio format with the audio device.
    //
    CHXAudioStream* pAudioStream = 0;
    ULONG32 maxSamplesPerSec = 8000;
    ULONG32 minSamplesPerSec = 44100;
    BOOL    bFirst = TRUE;
    UINT16  maxChannels = 1;
    UINT16  maxBlocksize = 0;
    UINT16  maxBitsPerSample = 0;
    HXAudioFormat audioFmt;

    theErr = GetAudioPrefs();

    if (!theErr && m_pStreamList->GetCount() > 0)
    {
	CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
	for (;lIter != m_pStreamList->End(); ++lIter)
	{
	    pAudioStream = (CHXAudioStream*) (*lIter); //m_pStreamList->GetNext(lp);

	    if (!pAudioStream->IsAudioFormatKnown())
	    {
		continue;
	    }

	    pAudioStream->GetFormat( &audioFmt );

	    if (bFirst)
	    {
		bFirst = FALSE;
		maxSamplesPerSec    = audioFmt.ulSamplesPerSec;
		minSamplesPerSec    = audioFmt.ulSamplesPerSec;
		maxChannels	    = audioFmt.uChannels;
		maxBlocksize	    = audioFmt.uMaxBlockSize;
		maxBitsPerSample    = audioFmt.uBitsPerSample;
	    }
	    else
	    {
		//
		// NOTE: upsampling typically costs more CPU than downsampling
		if ( audioFmt.ulSamplesPerSec > maxSamplesPerSec )
		    maxSamplesPerSec = audioFmt.ulSamplesPerSec;
		if ( audioFmt.ulSamplesPerSec < minSamplesPerSec)
		    minSamplesPerSec = audioFmt.ulSamplesPerSec;
		//
		// NOTE: converting mono to stereo and vice versa cost about the
		// same in CPU usage.
		if ( audioFmt.uChannels > maxChannels)
		    maxChannels = audioFmt.uChannels;

		// Get max block size.
		if ( audioFmt.uMaxBlockSize > maxBlocksize )
		    maxBlocksize = audioFmt.uMaxBlockSize;

		// Get max sample width.
		if ( audioFmt.uBitsPerSample > maxBitsPerSample )
		    maxBitsPerSample = audioFmt.uBitsPerSample;
	    }
	}

	// Set the audio format for this Player.
	m_PlayerFmt.uMaxBlockSize 	= maxBlocksize;
	m_PlayerFmt.uChannels		= maxChannels;
	m_PlayerFmt.uBitsPerSample 	= maxBitsPerSample;

	// If user wants upsampling
	if ( m_uPrefAudioQuality > 2 )
	    m_PlayerFmt.ulSamplesPerSec = maxSamplesPerSec;
	else
	    m_PlayerFmt.ulSamplesPerSec = minSamplesPerSec;
    }

    if (m_bPrefUse11khz)
    {
	m_PlayerFmt.ulSamplesPerSec = 11025;
    }

    // Do audio session setup. (e.g., determine device audio
    // format, etc.
    if ( !theErr )
	theErr = m_Owner->Setup( m_bHasStreams );

    // Now let all streams know the final audio format so they
    // can resample to this format.
    if ( !theErr )
    {
	SetupStreams();
    }
    // if audio device is failed to initialized, we
    // will keep the video playing if this is not audio only source
    else if (!IsAudioOnlyTrue())
    {
	m_bHasStreams = FALSE;
	m_bInited = TRUE;
	return HXR_OK;
    }

    // Let all stream response know total number of streams.
    if (!theErr && m_pStreamRespList)
    {
	IHXAudioStreamInfoResponse* pAudioStreamInfoResponse = 0;
	CHXSimpleList::Iterator lIter = m_pStreamRespList->Begin();
	for (; lIter != m_pStreamRespList->End(); ++lIter)
 	{
	    pAudioStreamInfoResponse = (IHXAudioStreamInfoResponse*) (*lIter);

	    CHXSimpleList::Iterator lIter2 = m_pStreamList->Begin();

	    for (; lIter2 != m_pStreamList->End(); ++lIter2)
 	    {
		CHXAudioStream* pStream = (CHXAudioStream*) (*lIter2);
		/* Only if a stream is initialized, send it to
		 * Response object. If not, we will send it when it
		 * gets initialized (in StreamInitialized() call)
		 */
		if (pStream->IsInitialized())
		{
		    pAudioStreamInfoResponse->OnStream(pStream);
		}
	    }
	}
    }

    // All renderers should have checked in by now!
    // Call post mix process hooks in list and provide the audio format.
    if (!theErr && m_pPMixHookList)
    {
	HXAudioFormat audioFmt;
	m_Owner->GetFormat( &audioFmt );
	HXAudioHookInfo* pPMixHookInfo = 0;
	CHXSimpleList::Iterator lIter = m_pPMixHookList->Begin();
	for (; lIter != m_pPMixHookList->End(); ++lIter)
	{
	    pPMixHookInfo = (HXAudioHookInfo*) (*lIter);
	    if (pPMixHookInfo->bIgnoreAudioData ||
		HXR_OK == ProcessAudioHook(ACTION_CHECK, pPMixHookInfo->pHook))
	    {
		pPMixHookInfo->pHook->OnInit( &audioFmt );
	    }
	}
    }

    if (!theErr)
    {
    	m_bInited = TRUE;
	/* Only change the state to initialized if we were in a stopped
	 * state earlier. It is possible to be in Playing state and be still
	 * in this function. This will happen if we have started the
	 * timeline as a fake timeline and later an audio stream joins the
	 * presentation thereby converting fake to audio timeline
	 * (delayed audio source in SMIL playback)
	 */
	if (m_eState == E_STOPPED)
	{
	    m_eState = E_INITIALIZED;
	}
    }

    return theErr;
}

ULONG32	CHXAudioPlayer::GetCurrentPlayBackTime(void)
{


    if (m_eState != E_PLAYING)
    {
	return m_ulCurrentTime;
    }

    // The current playback time of any player is the difference
    // of the current audio device playback time minus the audio
    // device time when this player started (resumed) playback
    // plus the initial start time of playback within this player's
    // timeline (usually 0 but can be something else esp. after a
    // seek).
    if (!m_bHasStreams)
    {
	ULONG32 ulCurrentTime	= HX_GET_TICKCOUNT();

	m_ulIncreasingTimer	    += CALCULATE_ELAPSED_TICKS(m_ulLastFakeCallbackTime, ulCurrentTime);
	m_ulLastFakeCallbackTime    = ulCurrentTime;

	m_ulCurrentTime		    = m_ulIncreasingTimer;
    }
    else
    {
	m_ulCurrentTime	= (m_Owner->GetCurrentPlayBackTime() -
		    m_ulADresumeTime) + m_ulAPstartTime;
    }

    m_ulAPplaybackTime = m_ulCurrentTime;


    AdjustForRealAudio();

    return m_ulCurrentTime;
}

⌨️ 快捷键说明

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