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

Reply via email to