📄 hxaudses.cpp
字号:
* fake timeline if the presentation has atleast one media type other * than audio */ if (!theErr || theErr == HXR_AUDIO_DRIVER) { CreatePlaybackBuffer(); } // Reset the number of blocks we've written m_ulBlocksWritten = 0; // Open the audio device only if DisableWrite is OFF /* This probably needs to be moved at the top so that * when second player comes in and we are already intialized, * we check for new value of disablewrite again */ CheckDisableWrite(); m_bUseFinalHook = FALSE; if (!theErr && !m_bDisableWrite) { theErr = OpenDevice(); } /* If disable wirte is ON, release the audio device */ else if (!theErr) { m_pAudioDev = 0; } /* If the audio device is busy, check if we have * anything other than audio in the presentation. * If TRUE, play silence so that the rest of the * presentation can be played. */ if (theErr == HXR_AUDIO_DRIVER && !m_bDisableWrite) { if (!IsAudioOnlyTrue()) { m_bDisableWrite = TRUE; m_pAudioDev = 0; theErr = HXR_OK; } } } m_bInited = (!theErr) ? TRUE : FALSE; if (!theErr && m_pAudioDev && m_pHookList) { InitHooks(); } if (!theErr && m_pAudioDev && m_pFinalHook) { ProcessAudioHook(ACTION_ADD, m_pFinalHook); } if(m_pContext) { HX_RELEASE(m_pMPPSupport); m_pContext->QueryInterface(IID_IHXMultiPlayPauseSupport, (void**)&m_pMPPSupport); } return theErr;}HX_RESULTCHXAudioSession::OpenDevice(){ HX_RESULT theErr = HXR_OK; HXAudioFormat audioFormat; if (m_pFinalHook) { m_bUseFinalHook = TRUE; if (HXR_OK != ProcessAudioHook(ACTION_CHECK, m_pFinalHook)) { m_bUseFinalHook = FALSE; } if (m_bUseFinalHook) { memcpy( &audioFormat, &m_ActualDeviceFmt, sizeof(HXAudioFormat)); theErr = m_pFinalHook->OnInit(&audioFormat); } } if (!theErr && m_pFinalHook && m_bUseFinalHook) { m_bUseFinalHook = TRUE; /* Did the hook change the data format? */ if( 0!=memcmp(&audioFormat, &m_ActualDeviceFmt, sizeof(HXAudioFormat))) { memcpy( &m_BeforeHookDeviceFmt, &m_ActualDeviceFmt, sizeof(HXAudioFormat)); memcpy( &m_ActualDeviceFmt, &audioFormat, sizeof(HXAudioFormat)); } } else { m_bUseFinalHook = FALSE; } theErr = OpenAudio(); if (theErr && m_pFinalHook && m_bUseFinalHook) { /* Looks like the audio device does not support the format * specified by the final Hook * Revert back to the original format and try again */ memcpy( &m_ActualDeviceFmt, &m_BeforeHookDeviceFmt, sizeof(HXAudioFormat)); m_bUseFinalHook = FALSE; theErr = OpenAudio(); } return theErr;}/* *********************************************************************** * Method: * CHXAudioSession::GetDeviceFormat * Purpose: * Determine the device format for this session. * The session object needs to resolve the device format * among multiple players. */HX_RESULT CHXAudioSession::GetDeviceFormat(){ HX_RESULT theErr = HXR_OK; UINT16 uOrigSampleRate = 0; CHXAudioPlayer* p = NULL; UINT16 bAutoUpsampling = FALSE; HXAudioFormat audioFmt; // We no longer force audio device in stereo mode. However we // still try to open it in 16-bit mode since all of our processing // is done in 16 bit. m_DeviceFmt.uBitsPerSample = 16; //Just grab the first players stats to use as maximums. LISTPOSITION lp = m_pPlayerList->GetHeadPosition(); while(lp) { p = (CHXAudioPlayer*) m_pPlayerList->GetNext(lp); if(0!=p->GetStreamCount()) { p->GetFormat( &audioFmt ); m_DeviceFmt.uChannels = audioFmt.uChannels; m_DeviceFmt.ulSamplesPerSec = audioFmt.ulSamplesPerSec; m_DeviceFmt.uMaxBlockSize = audioFmt.uMaxBlockSize; break; } } //Now loop through the rest of the players and find all the //maximums. while(lp) { p = (CHXAudioPlayer*) m_pPlayerList->GetNext(lp); if( 0 != p->GetStreamCount() ) { p->GetFormat( &audioFmt ); m_DeviceFmt.uChannels = max(m_DeviceFmt.uChannels, audioFmt.uChannels); m_DeviceFmt.ulSamplesPerSec = max(m_DeviceFmt.ulSamplesPerSec, audioFmt.ulSamplesPerSec); m_DeviceFmt.uMaxBlockSize = max(m_DeviceFmt.uMaxBlockSize, audioFmt.uMaxBlockSize); } } // turn on the default upsampling to 44K only on IX86 platforms // which support MMX // XXXgfw this also uses more memory for each block we push down // XXXgfw to the audio device. You might not want it on MIN_HEAP // XXXgfw kind of MMX devices, if there are any.#if defined(_M_IX86) ReadPrefINT16(m_pPreferences, "AutoAudioUpsampling", bAutoUpsampling );#endif if(bAutoUpsampling) { //force 44khz as our first attempt to open audio device uOrigSampleRate = (UINT16)m_DeviceFmt.ulSamplesPerSec; m_DeviceFmt.ulSamplesPerSec = 44100; }#if defined(HELIX_FEATURE_PREFERENCES) else { UINT16 ulSamplesPerSecPreference = 0; ReadPrefINT16(m_pPreferences, "AudioDeviceSamplesPerSec", ulSamplesPerSecPreference ); if(ulSamplesPerSecPreference) { uOrigSampleRate = (UINT16)m_DeviceFmt.ulSamplesPerSec; m_DeviceFmt.ulSamplesPerSec = ulSamplesPerSecPreference; } }#endif /* HELIX_FEATURE_PREFERENCES */ //Start negotiating with the device. Generate a table that will //drive the different formats we want to try. Start with the //native rate (and any mods from the pref stuff above) and go up //in samplerate. If that fails, go down in sample rate. const int nNumberOfRates = sizeof(z_anValidSampleRates)/sizeof(z_anValidSampleRates[0]); //Total number of table entries per sample rate will be: //nNumberOfRates*4 (mono/16, mono/8, stereo/16, stereo/8) plus //native format + user defined samplerate entry. const int nTmp = nNumberOfRates*4+2; unsigned short nTableSize = 0; tableEntry* table = new tableEntry[nTmp]; HX_ASSERT(table); if( NULL == table ) return HXR_OUTOFMEMORY; //First entry is always our native format from above with any //samplerate changes the user made via prefs. table[nTableSize++].set( (UINT16)m_DeviceFmt.ulSamplesPerSec, (UINT8)m_DeviceFmt.uChannels, (UINT8)m_DeviceFmt.uBitsPerSample ); //Second entry is always the above with the clip's original //sample rate, if we changed it. if( uOrigSampleRate ) table[nTableSize++].set(uOrigSampleRate, (UINT8)m_DeviceFmt.uChannels, (UINT8)m_DeviceFmt.uBitsPerSample ); //Now generate the rest of the format table.... const UINT8 usNativeChannel = (UINT8)m_DeviceFmt.uChannels; const UINT8 usAltChannel = (2==m_DeviceFmt.uChannels)?1:2; const UINT8 usNativeBits = (UINT8)m_DeviceFmt.uBitsPerSample; const UINT8 usAltBits = (8==m_DeviceFmt.uBitsPerSample)?16:8; //First use all equal or higher sample rates. short nIdx = 0; while( nIdx<nNumberOfRates ) { UINT16 usRate = z_anValidSampleRates[nIdx]; if( usRate >= m_DeviceFmt.ulSamplesPerSec ) { table[nTableSize++].set(usRate, usNativeChannel, usNativeBits ); table[nTableSize++].set(usRate, usAltChannel, usNativeBits ); table[nTableSize++].set(usRate, usNativeChannel, usAltBits ); table[nTableSize++].set(usRate, usAltChannel, usAltBits ); } nIdx++; } //Now all the samle rates lower then the native rate. nIdx = nNumberOfRates-1; while( nIdx>=0) { UINT16 usRate = z_anValidSampleRates[nIdx]; if( usRate < m_DeviceFmt.ulSamplesPerSec ) { table[nTableSize++].set(usRate, usNativeChannel, usNativeBits ); table[nTableSize++].set(usRate, usAltChannel, usNativeBits ); table[nTableSize++].set(usRate, usNativeChannel, usAltBits ); table[nTableSize++].set(usRate, usAltChannel, usAltBits ); } nIdx--; } //Now loop through our table and find a supported format. nIdx = 0; theErr = HXR_FAIL; while( FAILED(theErr) && nIdx<nTableSize) { m_DeviceFmt.ulSamplesPerSec = table[nIdx].usSampleRate; m_DeviceFmt.uChannels = table[nIdx].usChannels; m_DeviceFmt.uBitsPerSample = table[nIdx].usBits; theErr = CheckAudioFormat(&m_DeviceFmt); nIdx++; } //We still need to create playback buffers since we will use the //fake timeline if the presentation has atleast one media type //other than audio //XXXgfw this code below needs to be looked at. I Don't want to //touch it now for fear of breaking something that will take //a long time to fix. if (!theErr || theErr == HXR_AUDIO_DRIVER) { m_ActualDeviceFmt = m_DeviceFmt; //All the calculations are done for 16 bit stereo. There are //VERY FEW sound cards out there which do not support 16 bit //stereo. They will incur a high performace hit because of //possible unnecessary up/down conversion. For now we will //live with that. //XXXgfw wrong. lots of handhelds/phones don't do 16bit-2 //channel output. m_DeviceFmt.uBitsPerSample = 16; m_BeforeHookDeviceFmt = m_ActualDeviceFmt; } HX_VECTOR_DELETE(table); return theErr;}/************************************************************************ * Method: * CHXAudioSession::CheckAudioFormat * Purpose: * The audio player calls this to check its audio format with the * the audio device. */HX_RESULT CHXAudioSession::CheckAudioFormat( HXAudioFormat* pAudioFormat){ HX_RESULT theErr = HXR_OK; if (!m_pAudioDev) { CreateAudioDevice(); m_pAudioDev = m_pCurrentAudioDev; } if (m_pAudioDev) { theErr = m_pAudioDev->CheckFormat(pAudioFormat); /* Any error from audio device other than memory error is * returned as HXR_AUDIO_DRIVER */ if (theErr != HXR_OK && theErr != HXR_OUTOFMEMORY) { theErr = HXR_AUDIO_DRIVER; } } return theErr;}/************************************************************************ * Method: * CHXAudioSession::PlayAudio * Purpose: * The player object call this to play audio. This method is called * again in the playback response function. */HX_RESULT CHXAudioSession::PlayAudio(UINT16 uNumBlocks){ HX_RESULT theErr = HXR_OK; BOOL bDisableWrite = FALSE; if ( !m_bInited ) return theErr; if (m_bInPlayAudio) { return HXR_OK; } m_pMutex->Lock(); if (m_bToBeRewound) { theErr = Rewind(); goto exit; } m_bInPlayAudio = TRUE; if (m_pAuxiliaryAudioBuffers && m_pAuxiliaryAudioBuffers->GetCount() > 0 && m_pAudioDev && !m_bDisableWrite) { if (HXR_OK == ProcessAudioDevice(ACTION_CHECK, m_pAudioDev)) { /* Try to stuff in as much backlog as possible */ while (!theErr && m_pAuxiliaryAudioBuffers->GetCount() > 0) { HXAudioData* pAudioData = (HXAudioData*) m_pAuxiliaryAudioBuffers->GetHead(); // Write session audio data to device. theErr = m_pAudioDev->Write(pAudioData); if( theErr == HXR_OUTOFMEMORY ) { goto exit; } if (!theErr) { m_ulBlocksWritten++; m_dNumBytesWritten += pAudioData->pData->GetSize(); m_pAuxiliaryAudioBuffers->RemoveHead(); pAudioData->pData->Release(); delete pAudioData; } /*All other error codes are translated into audio driver error*/ else if (theErr != HXR_OUTOFMEMORY && theErr != HXR_WOULD_BLOCK) { theErr = HXR_AUDIO_DRIVER; } } } } // If we have audio streams then play audio. if (!theErr && m_bHasStreams) { // Push down at least 3 secs of audio. UINT16 uPush = uNumBlocks; if (m_bFirstPlayAudio) { uPush = (UINT16) m_ulMinBlocksTobeQueued; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -