Ok - that sounds good to me. Eric
> -----Original Message----- > From: Greg Wright [mailto:[EMAIL PROTECTED] > Sent: Wednesday, August 17, 2005 5:11 PM > To: [EMAIL PROTECTED] > Cc: [EMAIL PROTECTED]; > [EMAIL PROTECTED] > Subject: Re: [Audio-dev] CR-Client: Make audio pushdown > calculations more robust. > > > > Eric Hyche wrote: > > > > Some general questions: > > > > 1) GetBlocksRemainingToPlay() seems to depend on the accuracy > > of m_dGranularity. Where do we get m_dGranularity and > > how do we know it's accurate? > > It gets set in CHXAudioSession::SetGranularity(), and the value > passed in is hardcoded to 50 or 100ms by the defines: > > +# define MINIMUM_AUDIO_GRANULARITY 50 > +# define MAXIMUM_AUDIO_GRANULARITY MINIMUM_AUDIO_GRANULARITY > ... > ... > +# define MINIMUM_AUDIO_GRANULARITY 50 > +# define MAXIMUM_AUDIO_GRANULARITY 100 > > > > > 2) This seems to round either up or down: > > > ulBlocksPlayed = > (ULONG32)(ulCurTime/m_dGranularity+.5); > > but I would think we would always want to round up, right? > > Then we would be always err on the side of sometimes > *over-estimating* > > the number of blocks played, which would tend to make us err > > on the side of writing more to the device quicker. > > > There is a trade off here between HEAP/latency and being conservative > with regards to pushing down PCM data to the device. My feelings on > this is that it is much more important to be accurate then it is to be > conservative. Some of the problems we have had in the buffering and > audio pushdown logic have arisen from each component in the system > being conservative in its own way. If you add up all of the difference > through the system that result from these conservative algorithms you > can see that it is hard to determine actual performance given a > certain stream. Also, at least in this case, we are free to change the > constants to control the minimum pushdown values. This can be changed > for each device and/or build profile to prevent any underflow that > might happen. As an example, look at the following charts. They > represent the amount of PCM data in the audio device at any given > random time that we happen to check. The first chart shows the values > for rounding to the nearest block, the 2nd charts shows rounding > up. Each chart starts at the value of the maximum attainable pushdown > for each algorithm used, and therefore the maximum we would compute > for each algorithm. The math was done every MS level, but I have > just shown every 5ms in the charts to save space. Also, these > show values for a MIN_HEAP build, 100ms pushdown, 50ms granularity: > > > Rounding to nearest: > Device Blocks Pushed Total > MS Remain Blocks MS After > ------ ------ ------ ------------ > 125 3 0 125 > 120 2 0 120 > 115 2 0 115 > 110 2 0 110 > 105 2 0 105 > 100 2 0 100 > 95 2 0 95 > 90 2 0 90 > 85 2 0 85 > 80 2 0 80 > 75 2 0 75 > 70 1 1 120 > 65 1 1 115 > 60 1 1 110 > 55 1 1 105 > 50 1 1 100 > 45 1 1 95 > 40 1 1 90 > 35 1 1 85 > 30 1 1 80 > 25 1 1 75 > 20 0 2 120 > 15 0 2 115 > 10 0 2 110 > 5 0 2 105 > 0 0 2 100 > ------ ------ ------ ------------ > Average in device: 99.504950 > Min: 75 Max: 124 > > > Device Blocks Pushed Total > MS Remain Blocks MS After > ------ ------ ------ ------------ > 150 3 0 150 > 145 2 0 145 > 140 2 0 140 > 135 2 0 135 > 130 2 0 130 > 125 2 0 125 > 120 2 0 120 > 115 2 0 115 > 110 2 0 110 > 105 2 0 105 > 100 2 0 100 > 95 1 1 145 > 90 1 1 140 > 85 1 1 135 > 80 1 1 130 > 75 1 1 125 > 70 1 1 120 > 65 1 1 115 > 60 1 1 110 > 55 1 1 105 > 50 1 1 100 > 45 0 2 145 > 40 0 2 140 > 35 0 2 135 > 30 0 2 130 > 25 0 2 125 > 20 0 2 120 > 15 0 2 115 > 10 0 2 110 > 5 0 2 105 > 0 0 2 100 > ------ ------ ------ ------------ > Average in device: 124.257426 > Min: 100 Max: 149 > > > Notice how rounding up keeps us about 25% above our target for > pushdown on average and almost 49% at the worst. Rounding to the > nearest, on average, is just -.5% low and at worst is ~24% high. > > Now, I can see that if you wanted the minimum pushdown to mean that > there should never be less then that many blocks in the device at any > given time then the 2nd option is better. However, I prefer > to interpret > the pushdown value as the average latency from the time you > write to the > device to the time it gets consumed by the hardware. I > believe this 2nd > interpretation better lets us determine and tweak the > performance of the > system. If it turns out that the given build can not handle > that low of > a latency without underflowing, then is should just be raised. > > I am open to other interpretations and use cases or something I might > be missing. > > Also, for non MIN_HEAP builds, this is irrelevent because we > will always > be within 100ms of a full second of pushdown. > > > > 3) Are there any concurrency issues? Do we know that the code that's > > modifying m_ulBlocksWritten is on the same thread as the > code that's > > running GetBlocksRemainingToPlay()? Perhaps we might want to read > > m_ulBlocksWritten into a local variable.... > > If there are (I will look) then they already existed. The only place > we call GetBlocksRemainingToPlay() is the same place we used > m_ulBlocksWritten > before. > > > > --greg. > > > > > Changes themselves look good. > > > > Eric > > > > > >>-----Original Message----- > >>From: [EMAIL PROTECTED] > >>[mailto:[EMAIL PROTECTED] On Behalf Of > Greg Wright > >>Sent: Tuesday, August 16, 2005 5:11 PM > >>To: [EMAIL PROTECTED]; > >>[EMAIL PROTECTED] > >>Subject: [Audio-dev] CR-Client: Make audio pushdown > >>calculations more robust. > >> > >> > >>Synopsis > >>======== > >> > >>MIN_HEAP Playback. With MIN_HEAP builds (or very low latency > >>modes) it was possible to have glitches in the audio. This was > >>from audio underflows as a result of not being able to accurately > >>determine how much push down we had across platforms. This was > >>mostly due to differences in how different platforms calculated > >>the number of block remaining to play, but also had to do with > >>differences in certain constants used. > >> > >>Fix > >>=== > >> > >>The first thing to do was to bring all the different defines into > >>one place, they were in 3 separate files. All defines that control > >>the pushdown, granularity and scheduling are now in one big section. > >>This should keep problem from occurring when one of these > was changed > >>without knowledge of the others. Here is the pertinent part of that > >>chage: > >> > >>+// These defines control how much audio PCM data we push > >>down into the > >>+// audio device. MINIMUM_AUDIO_STARTUP_PUSHDOWN determines > >>how much we > >>+// push before calling Resume() on the device (and > starting playback) > >>+// and MINIMUM_AUDIO_PUSHDOWN determines how much PCM data we push > >>+// down during steady state playback. It is also important that the > >>+// granularity be less then or equal to > MINIMUM_AUDIO_PUSHDOWN/2. If > >>+// not, underflows could result because only 1 block will be in the > >>+// audio device at any given time. Currently > >>MINIMUM_AUDIO_GRANULARITY > >>+// is not used. In CHXAudioPlayer::Setup() hardcodes this: > >>+// > >>+// m_ulGranularity = MAXIMUM_AUDIO_GRANULARITY; > >>+// > >>+// The CHECK_AUDIO_INTERVAL define tells the audio session > how often > >>+// to check how much data we have pushed down in the audio device. > >>+// for min heap builds it is more important to check often > because we > >>+// have very few blocks pushed down at any one time. The value for > >>+// this define is a percentage (0-100) of the granularity in > >>+// milliseconds. IE, 40 means 40% of whatever granulatiry > is in use. > >>+// > >>+#ifdef HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES > >>+# define MINIMUM_AUDIO_GRANULARITY 50 > >>+# define MAXIMUM_AUDIO_GRANULARITY MINIMUM_AUDIO_GRANULARITY > >>+# define MINIMUM_AUDIO_PUSHDOWN 100 > >>+# define MINIMUM_AUDIO_STARTUP_PUSHDOWN MINIMUM_AUDIO_PUSHDOWN > >>+# define CHECK_AUDIO_INTERVAL 40 > >>+#else > >>+# define MINIMUM_AUDIO_GRANULARITY 50 > >>+# define MAXIMUM_AUDIO_GRANULARITY 100 > >>+# define MINIMUM_AUDIO_PUSHDOWN 1000 > >>+# define MINIMUM_AUDIO_STARTUP_PUSHDOWN 100 > >>+# define CHECK_AUDIO_INTERVAL 90 > >>+#endif > >> > >>The second thing to do was to re-do our logic on how we > calculate the > >>amount of audio pushdown, given the above defines. The new > logic makes > >>sure that we are conservative with regards to block count > and that all > >>the calculated and defined values make sense together. The > changes are > >>to UpdateMinimumPushdown() but the diffs are hard to read, > here is the > >>new version: > >> > >>void CHXAudioSession::UpdateMinimumPushdown() > >>{ > >> //This is called whenever the granularity or audio pushdown > >> //changes. In this method we need to make sure that the > >> //granularity is results in at least 2 blocks being the min > >> //pushdown. If we are left with only one block, it can > be hard to > >> //prevent underflow in the audio device. You don't have to > >> //increase the amount of PCM pushdown, just decrease the > >> //granularity. > >> if( m_ulGranularity ) > >> { > >> //Basically, integer versions of 'ceil' function. > >> m_ulMinBlocksTobeQueued = > >>(m_ulMinimumPushdown+m_ulGranularity-1)/m_ulGranularity; > >> m_ulMinBlocksTobeQueuedAtStart = > >>(m_ulMinimumStartupPushdown+m_ulGranularity-1)/m_ulGranularity; > >> > >>#if defined(HELIX_FEATURE_PREFERENCES) > >> HXBOOL bRestore = FALSE; > >> ReadPrefBOOL( m_pPreferences, > >>"RestoreMinimumPushdown", bRestore ); > >> if( bRestore) > >> { > >> m_ulMinBlocksTobeQueuedAtStart = > m_ulMinBlocksTobeQueued; > >> } > >>#endif > >> > >> //Invarients to ensure glitch free audio playback. > >> HX_ASSERT( m_ulGranularity <= m_ulMinimumPushdown/2 ); > >> HX_ASSERT( m_ulMinBlocksTobeQueued>1 ); > >> HX_ASSERT( m_ulMinBlocksTobeQueued >= > >>m_ulMinBlocksTobeQueuedAtStart ); > >> HX_ASSERT( m_ulMinimumPushdown >= > >>m_ulMinimumStartupPushdown ); > >> } > >>} > >> > >> > >>Next, we had to fix the problem with each platform > >>calculating the number of > >>blocks remaining to play differently. One implementation > >>might return values > >>1 greater or 1 less then another. This is a problem for the > >>core when the total > >>pushdown was just 1 or 2 blocks, we could run into underflow > >>pretty easily. > >>Even if I did go and fix each platform, it is possible that > >>new platforms > >>would not be correct or that old ones would get changed > >>again. This is mostly > >>because it is hard to tell if you are doing it correctly in > >>normal operations. > >>It takes a MIN_HEAP build and some testing to figure it out. > >>However, one thing > >>each platform's audio code *must* do correctly is return a > >>smooth accurate > >>time-line. If they don't it is very obvious. So, I have opted > >>to use that > >>information instead of relying on the buggy > >>NumberOfBlocksRemainingToPlay() > >>method. This was already being done for audio code that > >>returned FALSE from > >>IsWaveOutDevice(). Currently, this only includes the > >>DirectSound driver being > >>used on Window's player builds. This change results in a lot > >>cleaner code > >>and some image size reduction. It also moves the calculation > >>of audio pushdown > >>to a single spot in the code base. A new method, > >>GetBlocksRemainingToPlay(): > >> > >>ULONG32 CHXAudioSession::GetBlocksRemainingToPlay() > >>{ > >> ULONG32 ulRetVal = 0; > >> ULONG32 ulBlocksPlayed = 0; > >> ULONG32 ulCurTime = 0; > >> if( m_pAudioDev->GetCurrentAudioTime(ulCurTime) == HXR_OK ) > >> { > >> ulBlocksPlayed = (ULONG32)(ulCurTime/m_dGranularity+.5); > >> if( m_ulBlocksWritten>ulBlocksPlayed ) > >> { > >> ulRetVal = m_ulBlocksWritten-ulBlocksPlayed; > >> } > >> } > >> return ulRetVal; > >>} > >> > >> > >>So that this code: > >> > >> > >>- if ( (!m_bReplacedDev) && > >>(((CHXAudioDevice*)m_pAudioDev)->IsWaveOutDevice()) ) > >>- { > >>- m_uNumToBePlayed = uNumBlocks = > >>((CHXAudioDevice*)m_pAudioDev)->NumberOfBlocksRemainingToPlay(); > >>- > >>- > >>- > >>- /* Now that m_ulMinimumPushdown can be set by > >>the user, it is possible > >>- * for MIN_BLOCKS_TOBEQUEUED to be 0. > >>- */ > >>- if (uNumBlocks == 0 || > >>- uNumBlocks < m_ulMinBlocksTobeQueued) > >>- { > >>- bPlay = TRUE; > >>- } > >>- } > >>- else > >>- { > >>- ULONG32 ulCurTime = 0; > >>- if (m_pAudioDev->GetCurrentAudioTime(ulCurTime) > >>== HXR_OK) > >>- { > >>- UINT32 ulNumBlocksPlayed = (UINT32) > >>((double) ulCurTime / m_dGranularity); > >>- if (m_ulBlocksWritten > ulNumBlocksPlayed) > >>- { > >>- m_uNumToBePlayed = uNumBlocks = (UINT16) > >>(m_ulBlocksWritten - ulNumBlocksPlayed); > >>- } > >>- > >>- /* Now that m_ulMinimumPushdown can be set > >>by the user, it is possible > >>- * for MIN_BLOCKS_TOBEQUEUED to be 0. > >>- */ > >>- if (uNumBlocks == 0 || > >>- uNumBlocks < m_ulMinBlocksTobeQueued) > >>- { > >>- bPlay = TRUE; > >>- } > >>- } > >>- } > >>- HXLOGL4(HXLOG_ADEV, > >>"CHXAudioSession[%p]::CheckToPlayMoreAudio(): block count = > >>%lu (min to queue = %lu); play = '%s'", this, uNumBlocks, > >>m_ulMinBlocksTobeQueued, bPlay ? "true" : "false"); > >>- > >> > >>simply becomes: > >> > >>+ m_uNumToBePushed = uNumBlocks = GetBlocksRemainingToPlay(); > >>+ bPlay = (uNumBlocks<m_ulMinBlocksTobeQueued) ? > TRUE : FALSE; > >>+ HXLOGL4( HXLOG_ADEV, > >>+ > >>"CHXAudioSession[%p]::CheckToPlayMoreAudio(): block count = %lu", > >>+ this, > >>+ uNumBlocks); > >> > >> > >>The rest of the changes are just general clean changes that > should not > >>have any affect except on readability. > >> > >>A few things left to do: > >> > >>o CHXAudioDevice::NumberOfBlocksRemainingToPlay is not longer > >>used by the core. > >> So, we could go through and remove it to reduce image size > >>in some of the > >> platform audio code (assuming it isn't used internally by > >>the platform). > >>o Same with IsWaveOutDevice(). We no longer use it. > >>o Granularities were originally designed to be set > >>programmatically, but > >> they have been hardcoded historically. We might look into > >>the usefulness of > >> removing the hardcoded value and letting it change for > >>each clip depending > >> on the audio pushdown set by the renderer. This would be > >>required to get > >> audio pushdown values less then 100ms (which is about our > >>lowest pushdown > >> we can do right now without audio glitches). This would > >>also require more > >> testing. > >> > >> > >>Files Modified > >>============== > >> client/audiosvc/hxaudply.cpp > >> audio/device/pub/hxaudev.h > >> client/audiosvc/hxaudses.cpp > >> client/audiosvc/pub/hxaudses.h > >> > >> > >>Branch(s) > >>========= > >>HEAD, 150Cay. > >> > >> > >>Image Size and Heap Use impact > >>============================== > >>Small reduction in image size, no heap changes. > >> > >> > >>Platforms and Profiles Affected > >>=============================== > >>All platforms, all profiles. > >> > >> > >>Distribution Libraries affected > >>=============================== > >>None. > >> > >> > >>Platforms and Profiles Build Verified > >>===================================== > >>Windows min heap. Linux/all-defines/min-heap. > >> > >> > >>Platforms and Profiles Functionality verified > >>============================================= > >>Windows min heap. Linux/all-defines/min-heap. > >> > >> > >>--greg. > >> > >> > >> > >>Index: hxaudply.cpp > >>=================================================================== > >>RCS file: /cvsroot/client/audiosvc/hxaudply.cpp,v > >>retrieving revision 1.36.2.6 > >>diff -u -w -r1.36.2.6 hxaudply.cpp > >>--- hxaudply.cpp 3 May 2005 22:19:26 -0000 1.36.2.6 > >>+++ hxaudply.cpp 16 Aug 2005 19:37:04 -0000 > >>@@ -97,8 +97,7 @@ > >> #include "hxprefutil.h" > >> #endif /* HELIX_FEATURE_PREFERENCES */ > >> > >>-#define MINIMUM_AUDIO_GRANULARITY 50 > >>-#define MAXIMUM_AUDIO_GRANULARITY 100 > >>+ > >> #define MAX_WAIT_AT_SAME_TIME > >>(MAXIMUM_AUDIO_GRANULARITY+50) > >> > >> CHXAudioPlayer::CHXAudioPlayer( CHXAudioSession* owner ) > >> > >> > >>Index: pub/hxaudev.h > >>=================================================================== > >>RCS file: /cvsroot/audio/device/pub/hxaudev.h,v > >>retrieving revision 1.11.6.1 > >>diff -u -w -r1.11.6.1 hxaudev.h > >>--- pub/hxaudev.hernalCl5 May 2005 09:19:33 -0000 1.11.6.1 > >>+++ pub/hxaudev.h 16 Aug 2005 19:30:19 -0000 > >>@@ -59,11 +59,6 @@String("BEFORE CALL TO:Register\r\n"); > >> # define kUSound 4 > >> #endif > >> return HXR_OK; > >>-#ifdef HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES > >>-#define MINIMUM_AUDIO_PUSHDOWN 100RUE; > >>-#else } > >>-#define MINIMUM_AUDIO_PUSHDOWN 1000 > >>-#endifOutputDebugString("BEFORE CALL TO:CreateWindow\r\n"); > >> // Now create an instance of the window > >> > >> > >>Index: hxaudses.cpp > >>=================================================================== > >>RCS file: /cvsroot/client/audiosvc/hxaudses.cpp,v > >>retrieving revision 1.52.2.11 > >>diff -u -w -r1.52.2.11 hxaudses.cpp > >>--- hxaudses.cpp 9 Jun 2005 17:03:19 -0000 1.52.2.11 > >>+++ hxaudses.cpp 16 Aug 2005 20:27:47 -0000 > >>@@ -66,13 +66,9 @@ > >> #include <fcntl.h> > >> #include <sys/types.h> > >> #include <sys/stat.h> > >>- > >> #if defined (_WINDOWS) || defined (_WIN32) > >>- > >> #include <io.h> > >>- > >> #endif > >>- > >> #endif > >> > >> //#include "racodec.h" > >>@@ -125,15 +121,6 @@ > >> static const char HX_THIS_FILE[] = __FILE__; > >> #endif > >> > >>-#if defined(HELIX_FEATURE_MIN_HEAP) > >>-#define MINIMUM_AUDIO_STARTUP_PUSHDOWN 200 //ms > >>-#define CHECK_AUDIO_INTERVAL 40 //% > >>-#else > >>-#define MINIMUM_AUDIO_STARTUP_PUSHDOWN 100 //ms > >>-#define CHECK_AUDIO_INTERVAL 90 //% > >>-#endif > >>- > >>- > >> #define SOME_INSANELY_LARGE_VALUE 3600000 /* 1 hour */ > >> > >> #ifdef _WIN32 > >>@@ -643,20 +630,18 @@ > >> { > >> ReadPrefUINT32(m_pPreferences, > >>"MinimumAudioPushdown", m_ulMinimumPushdown); > >> ReadPrefUINT32(m_pPreferences, > >>"MinimumAudioStartupInitalPushdown", m_ulMinimumStartupPushdown); > >>+ ReadPrefUINT32(m_pPreferences, "CheckAudioPct", > >>m_nPercentage); > >>+ } > >>+#endif /* HELIX_FEATURE_PREFERENCES */ > >> > >> if (m_ulMinimumStartupPushdown > m_ulMinimumPushdown) > >> { > >> m_ulMinimumPushdown = m_ulMinimumStartupPushdown; > >> } > >> HXLOGL3(HXLOG_ADEV, "CHXAudioSession[%p]::Init(): > >>min audio push = %lu; min startup = %lu ", this, > >>m_ulMinimumPushdown, m_ulMinimumStartupPushdown); > >>- } > >>- > >>- ReadPrefUINT32(m_pPreferences, "CheckAudioPct", m_nPercentage); > >> HXLOGL2(HXLOG_ADEV, "Setting callback granulatiry > >>percentage to %d", m_nPercentage ); > >> > >> > >>-#endif /* HELIX_FEATURE_PREFERENCES */ > >>- > >> // Create a device volume interface. > >> if ( !theErr ) > >> { > >>@@ -2942,7 +2927,9 @@ > >> m_ulMinimumPushdown = ulMinimumPushdown; > >> UpdateMinimumPushdown(); > >> > >>- HXLOGL3(HXLOG_ADEV, > >>"CHXAudioSession[%p]::SetAudioPushdown(): push down = %lu", > >>this, ulMinimumPushdown); > >>+ HXLOGL3(HXLOG_ADEV, > >>+ "CHXAudioSession[%p]::SetAudioPushdown(): push > >>down = %lu", > >>+ this, ulMinimumPushdown); > >> return HXR_OK; > >> } > >> > >>@@ -2972,38 +2959,38 @@ > >> CHXAudioSession::GetCurrentAudioDevicePushdown(REF(UINT32) > >>/*OUT*/ ulAudioPusheddown) > >> { > >> HX_RESULT rc = HXR_OK; > >>- UINT16 uNumBlocks = 0; > >>- UINT32 ulNumBlocksPlayed = 0; > >>- UINT32 ulCurTime = 0; > >> > >> ulAudioPusheddown = 0; > >> > >>- if (m_bToBeReOpened || !m_pAudioDev) > >>+ if( !m_bToBeReOpened && m_pAudioDev ) > >> { > >>- goto cleanup; > >>+ ulAudioPusheddown = > >>(UINT32)(GetBlocksRemainingToPlay() * m_dGranularity); > >> } > >> > >>- if ( (!m_bReplacedDev) && > >>(((CHXAudioDevice*)m_pAudioDev)->IsWaveOutDevice()) ) > >>- { > >>- uNumBlocks = > >>((CHXAudioDevice*)m_pAudioDev)->NumberOfBlocksRemainingToPlay(); > >>+ return rc; > >> } > >>- else > >>+ > >>+// We no longer use > >>CHXAudioDevice::NumberOfBlocksRemainingToPlay() to > >>+// determine how much data is left in the audio device. > Not only did > >>+// we have the problem of differences on how it was > >>calculated between > >>+// different platforms but each platform already has to give > >>back very > >>+// accurate timeline information. Since we keep track of how many > >>+// blocks we have written, we just use that and the > current playback > >>+// time to determine how much data is down in the device. > >>+ULONG32 CHXAudioSession::GetBlocksRemainingToPlay() > >> { > >>+ ULONG32 ulRetVal = 0; > >>+ ULONG32 ulBlocksPlayed = 0; > >>+ ULONG32 ulCurTime = 0; > >> if (m_pAudioDev->GetCurrentAudioTime(ulCurTime) == HXR_OK) > >> { > >>- ulNumBlocksPlayed = (UINT32) ((double) ulCurTime > >>/ m_dGranularity); > >>- if (m_ulBlocksWritten > ulNumBlocksPlayed) > >>+ ulBlocksPlayed = (ULONG32)(ulCurTime/m_dGranularity+.5); > >>+ if( m_ulBlocksWritten>ulBlocksPlayed ) > >> { > >>- uNumBlocks = (UINT16) (m_ulBlocksWritten - > >>ulNumBlocksPlayed); > >>+ ulRetVal = m_ulBlocksWritten-ulBlocksPlayed; > >> } > >> } > >>- } > >>- > >>- ulAudioPusheddown = (UINT32)(uNumBlocks * m_dGranularity); > >>- > >>-cleanup: > >>- > >>- return rc; > >>+ return ulRetVal; > >> } > >> > >> > >>/************************************************************* > >>*********** > >>@@ -3129,39 +3116,35 @@ > >> return theErr; > >> } > >> > >>-void > >>-CHXAudioSession::UpdateMinimumPushdown() > >>+void CHXAudioSession::UpdateMinimumPushdown() > >> { > >>+ //This is called whenever the granularity or audio pushdown > >>+ //changes. In this method we need to make sure that the > >>+ //granularity is results in at least 2 blocks being the min > >>+ //pushdown. If we are left with only one block, it can > be hard to > >>+ //prevent underflow in the audio device. You don't have to > >>+ //increase the amount of PCM pushdown, just decrease the > >>+ //granularity. > >> if (m_ulGranularity) > >> { > >>- m_ulMinBlocksTobeQueued = (UINT32) > >>(m_ulMinimumPushdown*1.0/m_ulGranularity); > >>- if ((m_ulMinBlocksTobeQueued == 0) || > >>- (m_ulMinBlocksTobeQueued*m_ulGranularity < > >>m_ulMinimumPushdown)) > >>- { > >>- m_ulMinBlocksTobeQueued++; > >>- } > >>- > >>- if ((m_ulMinBlocksTobeQueued * m_ulGranularity) >= > >>m_ulMinimumStartupPushdown) > >>- { > >>- m_ulMinBlocksTobeQueuedAtStart = (UINT32) > >>(m_ulMinimumStartupPushdown*1.0/m_ulGranularity); > >>- } > >>- else > >>- { > >>- m_ulMinBlocksTobeQueuedAtStart = > m_ulMinBlocksTobeQueued; > >>- } > >>+ //Basically, integer versions of 'ceil' function. > >>+ m_ulMinBlocksTobeQueued = > >>(m_ulMinimumPushdown+m_ulGranularity-1)/m_ulGranularity; > >>+ m_ulMinBlocksTobeQueuedAtStart = > >>(m_ulMinimumStartupPushdown+m_ulGranularity-1)/m_ulGranularity; > >> > >> #if defined(HELIX_FEATURE_PREFERENCES) > >>- IHXBuffer* pBuffer = NULL; > >>- if (m_pPreferences && > >>- > >>m_pPreferences->ReadPref("RestoreMinimumPushdown", pBuffer) > >>== HXR_OK && > >>- pBuffer && > >>- ::atoi((char*) pBuffer->GetBuffer()) == 1) > >>+ HXBOOL bRestore = FALSE; > >>+ ReadPrefBOOL( m_pPreferences, > >>"RestoreMinimumPushdown", bRestore ); > >>+ if( bRestore) > >> { > >> m_ulMinBlocksTobeQueuedAtStart = > >>m_ulMinBlocksTobeQueued; > >> } > >>+#endif > >> > >>- HX_RELEASE(pBuffer); > >>-#endif /* HELIX_FEATURE_PREFERENCES */ > >>+ //Invarients to ensure glitch free audio playback. > >>+ HX_ASSERT( m_ulGranularity <= m_ulMinimumPushdown/2 ); > >>+ HX_ASSERT( m_ulMinBlocksTobeQueued>1 ); > >>+ HX_ASSERT( m_ulMinBlocksTobeQueued >= > >>m_ulMinBlocksTobeQueuedAtStart ); > >>+ HX_ASSERT( m_ulMinimumPushdown >= > >>m_ulMinimumStartupPushdown ); > >> } > >> } > >> > >>@@ -3527,65 +3510,17 @@ > >> } > >> else > >> { > >>- if ( (!m_bReplacedDev) && > >>(((CHXAudioDevice*)m_pAudioDev)->IsWaveOutDevice()) ) > >>- { > >>- m_uNumToBePlayed = uNumBlocks = > >>((CHXAudioDevice*)m_pAudioDev)->NumberOfBlocksRemainingToPlay(); > >>- > >>- > >>- > >>- /* Now that m_ulMinimumPushdown can be set by > >>the user, it is possible > >>- * for MIN_BLOCKS_TOBEQUEUED to be 0. > >>- */ > >>- if (uNumBlocks == 0 || > >>- uNumBlocks < m_ulMinBlocksTobeQueued) > >>- { > >>- bPlay = TRUE; > >>- } > >>- } > >>- else > >>- { > >>- ULONG32 ulCurTime = 0; > >>- if (m_pAudioDev->GetCurrentAudioTime(ulCurTime) > >>== HXR_OK) > >>- { > >>- UINT32 ulNumBlocksPlayed = (UINT32) > >>((double) ulCurTime / m_dGranularity); > >>- if (m_ulBlocksWritten > ulNumBlocksPlayed) > >>- { > >>- m_uNumToBePlayed = uNumBlocks = (UINT16) > >>(m_ulBlocksWritten - ulNumBlocksPlayed); > >>- } > >>- > >>- /* Now that m_ulMinimumPushdown can be set > >>by the user, it is possible > >>- * for MIN_BLOCKS_TOBEQUEUED to be 0. > >>- */ > >>- if (uNumBlocks == 0 || > >>- uNumBlocks < m_ulMinBlocksTobeQueued) > >>- { > >>- bPlay = TRUE; > >>- } > >>- } > >>- } > >>- HXLOGL4(HXLOG_ADEV, > >>"CHXAudioSession[%p]::CheckToPlayMoreAudio(): block count = > >>%lu (min to queue = %lu); play = '%s'", this, uNumBlocks, > >>m_ulMinBlocksTobeQueued, bPlay ? "true" : "false"); > >>- > >>+ m_uNumToBePushed = uNumBlocks = GetBlocksRemainingToPlay(); > >>+ bPlay = (uNumBlocks<m_ulMinBlocksTobeQueued) ? > TRUE : FALSE; > >>+ HXLOGL4( HXLOG_ADEV, > >>+ > >>"CHXAudioSession[%p]::CheckToPlayMoreAudio(): block count = %lu", > >>+ this, > >>+ uNumBlocks); > >> } > >> > >> if (bPlay) > >> { > >> HX_ASSERT(!m_pAudioDev || m_ulMinBlocksTobeQueued > > >>uNumBlocks); > >>- /* Currently we break transcoding feature of > jukwbox because: > >>- * - overriden audio device plays much faster than realtime > >>- * - mp3 datatype does not implement drynotification > >>interface. > >>- * - we therefore play silence instead of halting > >>the timeline > >>- * when we run out of data. > >>- * > >>- * Patch: revert back to old behavior: i.e. push only one > >>- * block at a time for replaced audio device > >>- * > >>- * correct fix: We should fix mp3 renderer to > >>support drynotification > >>- * > >>- * XXXRA > >>- * > >>- * Update Removing this hack for replaced devices > >>since MP3 renderer > >>- * now supports dry notification. -- RA 07/18/01: > >>- */ > >> if (m_pAudioDev && m_ulMinBlocksTobeQueued > uNumBlocks) > >> { > >> uNumBlocks = (UINT16) m_ulMinBlocksTobeQueued - > >>uNumBlocks; > >>@@ -4138,7 +4073,7 @@ > >> HXLOGL2( "IsRebufferRequired: num: %d start: %lu > >>numblk()=%d", > >> m_uNumToBePlayed, > >> m_ulMinBlocksTobeQueuedAtStart, > >>- > >>((CHXAudioDevice*)m_pAudioDev)->NumberOfBlocksRemainingToPlay()); > >>+ GetBlocksRemainingToPlay()); > >> } > >> > >> return bRetVal; > >>Index: pub/hxaudses.h > >>=================================================================== > >>RCS file: /cvsroot/client/audiosvc/pub/hxaudses.h,v > >>retrieving revision 1.18.6.2 > >>diff -u -w -r1.18.6.2 hxaudses.h > >>--- pub/hxaudses.h 5 May 2005 09:33:29 -0000 1.18.6.2 > >>+++ pub/hxaudses.h 16 Aug 2005 20:27:47 -0000 > >>@@ -63,6 +63,52 @@ > >> # define TLW_CLOSE 3 > >> # define TLW_TIMESYNC 4 > >> > >>+ > >>+// These defines control how much audio PCM data we push > >>down into the > >>+// audio device. MINIMUM_AUDIO_STARTUP_PUSHDOWN determines > >>how much we > >>+// push before calling Resume() on the device (and > starting playback) > >>+// and MINIMUM_AUDIO_PUSHDOWN determines how much PCM data we push > >>+// down during steady state playback. It is also important that the > >>+// granularity be less then or equal to > MINIMUM_AUDIO_PUSHDOWN/2. If > >>+// not, underflows could result because only 1 block will be in the > >>+// audio device at any given time. Currently > >>MINIMUM_AUDIO_GRANULARITY > >>+// is not used. In CHXAudioPlayer::Setup() hardcodes this: > >>+// > >>+// m_ulGranularity = MAXIMUM_AUDIO_GRANULARITY; > >>+// > >>+// The CHECK_AUDIO_INTERVAL define tells the audio session > how often > >>+// to check how much data we have pushed down in the audio device. > >>+// for min heap builds it is more important to check often > because we > >>+// have very few blocks pushed down at any one time. The value for > >>+// this define is a percentage (0-100) of the granularity in > >>+// milliseconds. IE, 40 means 40% of whatever granulatiry > is in use. > >>+// > >>+#ifdef HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES > >>+# define MINIMUM_AUDIO_GRANULARITY 50 > >>+# define MAXIMUM_AUDIO_GRANULARITY MINIMUM_AUDIO_GRANULARITY > >>+# define MINIMUM_AUDIO_PUSHDOWN 100 > >>+# define MINIMUM_AUDIO_STARTUP_PUSHDOWN MINIMUM_AUDIO_PUSHDOWN > >>+# define CHECK_AUDIO_INTERVAL 40 > >>+#else > >>+# define MINIMUM_AUDIO_GRANULARITY 50 > >>+# define MAXIMUM_AUDIO_GRANULARITY 100 > >>+# define MINIMUM_AUDIO_PUSHDOWN 1000 > >>+# define MINIMUM_AUDIO_STARTUP_PUSHDOWN 100 > >>+# define CHECK_AUDIO_INTERVAL 90 > >>+#endif > >>+ > >> > >> > >>@@ -349,9 +395,7 @@ > >> */ > >> virtual HX_RESULT CreateAudioPlayer(CHXAudioPlayer** > >>ppAudioPlayer); > >> HX_RESULT _CreateAudioPlayer(CHXAudioPlayer** > >>ppAudioPlayer); > >>- > >> HX_RESULT CloseAudioPlayer( CHXAudioPlayer* > >>pAudioPlayer); > >>- > >> void Close(void); > >> > >> /* The session object determines the audio device format based > >>@@ -362,7 +406,6 @@ > >> /* Open is called to open the audio device. > >> */ > >> HX_RESULT OpenAudio (void); > >>- > >> HX_RESULT OpenDevice (void); > >> > >> /* PlayAudio is called by Audio Player object. > >>@@ -383,8 +426,7 @@ > >> > >> /* Seek is called by Audio Player object. > >> */ > >>- HX_RESULT Seek ( > >>- CHXAudioPlayer* pPlayerToExclude, > >>+ HX_RESULT Seek ( CHXAudioPlayer* pPlayerToExclude, > >> const UINT32 ulSeekTime > >> ); > >> > >>@@ -518,9 +560,10 @@ > >> friend class CHXAudioSession::HXDeviceSetupCallback; > >> protected: > >> ~CHXAudioSession(void); > >>- > >> void _ConstructIfNeeded(); > >> > >>+ ULONG32 GetBlocksRemainingToPlay(); > >>+ > >> private: > >> > >> #ifdef _MACINTOSH > >>@@ -606,8 +649,7 @@ > >> /* CheckAudioFormat Interface is called by audio player to > >> * check resample audio format with audio device format. > >> */ > >>- HX_RESULT CheckAudioFormat( > >>- HXAudioFormat* pAudioFormat ); > >>+ HX_RESULT CheckAudioFormat( HXAudioFormat* pAudioFormat ); > >> > >> /* Create the playback buffer. > >> */ > >>@@ -619,8 +661,7 @@ > >> > >> > >> /* Write audio data to post mix hooks. */ > >>- HX_RESULT ProcessPostMixHooks( > >>- CHXAudioPlayer* pPlayer, > >>+ HX_RESULT ProcessPostMixHooks( CHXAudioPlayer* pPlayer, > >> IHXBuffer*& pInBuffer, > >> BOOL* bDisableWrite, > >> UINT32 ulBufTime, > >>@@ -631,7 +672,6 @@ > >> > >> /* Convert 16-bit buffer to 8-bit */ > >> void ConvertToEight(void); > >>- > >> BOOL IsAudioOnlyTrue(void); > >> > >> UINT32 AnchorDeviceTime(UINT32 ulCurTime); > >> > >> > >>_______________________________________________ > >>Audio-dev mailing list > >>[email protected] > >>http://lists.helixcommunity.org/mailman/listinfo/audio-dev > >> > > > > > > > _______________________________________________ Audio-dev mailing list [email protected] http://lists.helixcommunity.org/mailman/listinfo/audio-dev
