home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / directx2 / sdk / samples / dsstream / dstrtime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-28  |  12.1 KB  |  301 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:               Dstrtime.c
  6.  *  Content:    This source file contains a Multimedia Timer Callback
  7.  *             procedure which is used by the DirectSound Stream Sample
  8.  *             application to update the playback buffer at regular intervals
  9.  *
  10.  ***************************************************************************/
  11. #define WIN32_LEAN_AND_MEAN
  12. #include <windows.h>
  13. #include <windowsx.h>
  14. #include <mmsystem.h>
  15. #include <dsound.h>
  16. #include <commctrl.h>
  17. #include <commdlg.h>
  18. #include <memory.h>
  19. #include <cderr.h>
  20.  
  21. #include "dsstream.h"
  22.  
  23. extern HWND  hWndMain; 
  24. extern char  szDebug[];
  25. extern WAVEINFOCA wiWave;
  26.  
  27. LONG lInTimer = FALSE;
  28.  
  29. void CALLBACK TimeFunc( UINT uTimerID, UINT uMsg, DWORD dwUser,
  30.                                                         DWORD dw1, DWORD dw2 )
  31.     {
  32.     LPBYTE      lpWrite1, lpWrite2, lpTemp;
  33.     DWORD       dwLen1, dwLen2, dwPlay, dwWrite, dwPlayedLength;
  34.     DWORD       dwLeftToRead;
  35.     int         nChkErr;
  36.     UINT        uChkErr;
  37.  
  38.     if (InterlockedExchange(&lInTimer, TRUE)) return;
  39.  
  40.     /* Get and print the current position of the play cursor */
  41.     wiWave.lpDSBStreamBuffer->lpVtbl->GetCurrentPosition( 
  42.                     wiWave.lpDSBStreamBuffer, &dwPlay, &dwWrite );
  43.     
  44.     /* If the play cursor is at the same spot as the last call, there are two
  45.      * possibilities.  The first is that we were called extremely late and
  46.      * happened to land on an integer number of complete buffer cycles.  This
  47.      * is not very likely.  The other is that the play cursor didn't move.
  48.      * Since we're oversampling, this is very likely.  In this case, we should
  49.      * bail.
  50.      */
  51.  
  52.     if( dwPlay == wiWave.dwNextWriteOffset )
  53.         {
  54. #ifdef DEBUG
  55.         PostMessage( hWndMain, WM_DSSTREAM_DEBUG,
  56.                 MAKEWPARAM( DEBUGF_SKIP, 0 ), 0 );
  57. #endif
  58.         InterlockedExchange(&lInTimer, FALSE);
  59.         return;
  60.         }
  61.  
  62. #ifdef DEBUG
  63.     PostMessage( hWndMain, WM_DSSTREAM_DEBUG,
  64.                 MAKEWPARAM( DEBUGF_PLAYPOSITION, 0 ), dwPlay );
  65. #endif
  66.  
  67. #ifdef DEBUG
  68.     PostMessage( hWndMain, WM_DSSTREAM_DEBUG,
  69.                     MAKEWPARAM( DEBUGF_WRITEPOSITION, 0 ),
  70.                     wiWave.dwNextWriteOffset );
  71. #endif
  72.  
  73.     /* Have we found the end of the file and passed the buffer end? */
  74.     if( wiWave.bFoundEnd && !wiWave.dwBytesRemaining )
  75.         {
  76.         if( !wiWave.bDonePlaying )
  77.             {
  78.             wiWave.bDonePlaying = TRUE;
  79.             PostMessage( hWndMain, WM_DSSTREAM_DONE, (WPARAM)0, (LPARAM)0 );
  80.             }
  81.         InterlockedExchange(&lInTimer, FALSE);
  82.         return;
  83.         }
  84.  
  85.     if( dwPlay < wiWave.dwNextWriteOffset )
  86.         {
  87.         /* Calculate how many writeable bytes there are behind the play cursor */
  88.         dwPlayedLength = (dwPlay + wiWave.dwBufferSize - wiWave.dwNextWriteOffset);
  89.         }
  90.     else
  91.         {
  92.         /* Calculate how many writeable bytes there are behind the play cursor */
  93.         dwPlayedLength = (dwPlay - wiWave.dwNextWriteOffset);
  94.         }
  95.  
  96.     wiWave.dwProgress += dwPlayedLength;
  97.  
  98.     PostMessage( hWndMain, WM_DSSTREAM_PROGRESS, 0L, wiWave.dwProgress );
  99.  
  100.  
  101.     /*
  102.      *  If wiWave.bFoundEnd == TRUE, then we've finished reading in the file,
  103.      * but we need to wait until the buffer's play cursor passes the point we
  104.      * were at when we found out we were done reading.
  105.      */
  106.     if( wiWave.bFoundEnd && wiWave.dwBytesRemaining )
  107.         {
  108.         // Decrement the count of how many bytes we have to wait for before
  109.         // we can kill the timer procedure safely
  110.         if( dwPlayedLength > wiWave.dwBytesRemaining )
  111.             wiWave.dwBytesRemaining = 0;
  112.         else
  113.             wiWave.dwBytesRemaining -= dwPlayedLength;
  114.  
  115.         if( wiWave.lpDSBStreamBuffer->lpVtbl->Lock( wiWave.lpDSBStreamBuffer,
  116.                                                 wiWave.dwNextWriteOffset,
  117.                                                 dwPlayedLength,
  118.                                                 &((LPVOID)lpWrite1), &dwLen1,
  119.                                                 &((LPVOID)lpWrite2), &dwLen2,
  120.                                                 0 ) != 0 )
  121.             {
  122.             OutputDebugString( "TimeFunc() could not lock DirectSoundBuffer" );
  123.             InterlockedExchange(&lInTimer, FALSE);
  124.             return;
  125.             }
  126.  
  127.         /* Silence out both parts of the locked buffer */
  128.         memset( lpWrite1, wiWave.pwfx->wBitsPerSample == 8 ? 128 : 0, dwLen1 );
  129.  
  130.         if( lpWrite2 && dwLen2 )
  131.             memset( lpWrite2,
  132.                     wiWave.pwfx->wBitsPerSample == 8 ? 128 : 0,
  133.                     dwLen2 );
  134.  
  135.         wiWave.lpDSBStreamBuffer->lpVtbl->Unlock( wiWave.lpDSBStreamBuffer,
  136.                                                     (LPVOID)lpWrite1, dwLen1,
  137.                                                     (LPVOID)lpWrite2, dwLen2 );
  138.     /*
  139.      * This code is stolen from the end of the routine -- we need to keep
  140.      * zeroing out buffer segments while we're waiting for the play cursor to
  141.      * catch up to the end of the WAVE data.
  142.      */
  143.         wiWave.dwNextWriteOffset += dwPlayedLength;
  144.         if( wiWave.dwNextWriteOffset >= wiWave.dwBufferSize )
  145.             wiWave.dwNextWriteOffset -= wiWave.dwBufferSize;
  146.  
  147. #ifdef DEBUG
  148.     PostMessage( hWndMain, WM_DSSTREAM_DEBUG,
  149.                     MAKEWPARAM( DEBUGF_NEXTWRITE, 0 ),
  150.                     wiWave.dwNextWriteOffset );
  151. #endif
  152.         InterlockedExchange(&lInTimer, FALSE);
  153.         return;
  154.         }
  155.  
  156.     /* Lock a segment of memory that is behind the play cursor */
  157.     if( wiWave.lpDSBStreamBuffer->lpVtbl->Lock( wiWave.lpDSBStreamBuffer,
  158.                                             wiWave.dwNextWriteOffset,
  159.                                             dwPlayedLength,
  160.                                             &((LPVOID)lpWrite1), &dwLen1,
  161.                                             &((LPVOID)lpWrite2), &dwLen2,
  162.                                             0 ) != 0 )
  163.         {
  164.         OutputDebugString( "TimeFunc() could not lock DirectSoundBuffer" );
  165.         InterlockedExchange(&lInTimer, FALSE);
  166.         return;
  167.         }
  168.         
  169.     if( dwLen1 && !wiWave.bDonePlaying )
  170.         {
  171.         nChkErr = WaveReadFile( wiWave.hmmio, (UINT)dwLen1, lpWrite1,
  172.                                 &wiWave.mmck, &uChkErr );
  173.         if( uChkErr < (UINT)dwLen1 )
  174.             {
  175.             if( !wiWave.bLoopFile )
  176.                 {
  177.                 /* Zero out the rest of this block */
  178.                 if( wiWave.pwfx->wBitsPerSample == 8 )
  179.                     memset( lpWrite1+uChkErr, 128, ((UINT)dwLen1-uChkErr));
  180.                 else if( wiWave.pwfx->wBitsPerSample == 16 )
  181.                     memset( lpWrite1+uChkErr, 0, ((UINT)dwLen1-uChkErr));
  182.  
  183. /* Enable play completion detection code at the beginning of the next call */
  184.  
  185.                 wiWave.bFoundEnd = TRUE;
  186.                 if( dwPlay > wiWave.dwNextWriteOffset )
  187.                     wiWave.dwBytesRemaining = (wiWave.dwNextWriteOffset
  188.                                             + wiWave.dwBufferSize - dwPlay);
  189.                 else
  190.                     wiWave.dwBytesRemaining = (wiWave.dwNextWriteOffset
  191.                                             - dwPlay);
  192.                 }
  193.              else
  194.                 {
  195.                 lpTemp = lpWrite1;
  196.                 dwLeftToRead = dwLen1;
  197.                 do
  198.                     {
  199.                     /* Continue decrementing our count and moving our temp
  200.                      * pointer forward until we've read the file enough times
  201.                      * to fill the buffer.  NOTE: It's probably not efficient
  202.                      * to bother with the overhead of streaming a file that's
  203.                      * not at least as large as the buffer... */
  204.                     lpTemp += uChkErr;
  205.                     dwLeftToRead -= uChkErr;
  206.                     nChkErr = WaveStartDataRead( &wiWave.hmmio,
  207.                                                     &wiWave.mmck,
  208.                                                     &wiWave.mmckInRIFF );
  209.                     nChkErr = WaveReadFile( wiWave.hmmio, (UINT)dwLeftToRead,
  210.                                             lpTemp,
  211.                                             &wiWave.mmck, &uChkErr );
  212.                     } while( uChkErr < dwLeftToRead );
  213.                 }
  214.             }
  215.         }
  216.     /*
  217.     * The bDonePlaying flag is set by the caller if the user stops playback
  218.     * before the end of the WAVE file is encountered.  It tells us to cut this
  219.     * racket out and play nothing in case it takes the caller a couple
  220.     * interrupts to shut off the timer.
  221.     */
  222.     else if( dwLen1 && wiWave.bDonePlaying )
  223.         {
  224.         // Set the appropriate silence value
  225.         _fmemset( lpWrite1,
  226.                     wiWave.pwfx->wBitsPerSample == 8 ? 128 : 0,
  227.                     dwLen1);
  228.         }
  229.  
  230.     if( dwLen2 && !wiWave.bDonePlaying )
  231.         {
  232.         nChkErr = WaveReadFile( wiWave.hmmio, (UINT)dwLen2, lpWrite2,
  233.                                 &wiWave.mmck, &uChkErr );
  234.         if( uChkErr < (UINT)dwLen2 )
  235.             {
  236.             if( !wiWave.bLoopFile )
  237.                 {
  238.                 /* Zero out the rest of this block */
  239.                 if( wiWave.pwfx->wBitsPerSample == 8 )
  240.                     memset( lpWrite2+uChkErr, 128, ((UINT)dwLen2-uChkErr));
  241.                 else if( wiWave.pwfx->wBitsPerSample == 16 )
  242.                     memset( lpWrite2+uChkErr, 0, ((UINT)dwLen2-uChkErr));
  243.                 /* Enable play completion detection code at the beginning
  244.                  * of the next call
  245.                  */
  246.                 wiWave.bFoundEnd = TRUE;
  247.                 if( dwPlay > wiWave.dwNextWriteOffset )
  248.                     wiWave.dwBytesRemaining = (wiWave.dwNextWriteOffset
  249.                                             + wiWave.dwBufferSize - dwPlay);
  250.                 else
  251.                     wiWave.dwBytesRemaining = (wiWave.dwNextWriteOffset
  252.                                             - dwPlay);
  253.                 }
  254.             else
  255.                 {
  256.                 lpTemp = lpWrite2;
  257.                 dwLeftToRead = dwLen2;
  258.                 do
  259.                     {
  260.                     /* Continue decrementing our count and moving our temp
  261.                      * pointer forward until we've read the file enough times
  262.                      * to fill the buffer.  NOTE: It's probably not efficient
  263.                      * to bother with the overhead of streaming a file that's
  264.                      * not at least as large as the buffer... */
  265.                     lpTemp += uChkErr;
  266.                     dwLeftToRead -= uChkErr;
  267.                     nChkErr = WaveStartDataRead( &wiWave.hmmio,
  268.                                                     &wiWave.mmck,
  269.                                                     &wiWave.mmckInRIFF );
  270.                     nChkErr = WaveReadFile( wiWave.hmmio, (UINT)dwLeftToRead,
  271.                                             lpTemp,
  272.                                             &wiWave.mmck, &uChkErr );
  273.                     } while( uChkErr < dwLeftToRead );
  274.                 }
  275.             }
  276.         }
  277.     else if( lpWrite2 && dwLen2 && wiWave.bDonePlaying )
  278.         {
  279.         // Set the appropriate silence value
  280.         _fmemset( lpWrite2,
  281.                     wiWave.pwfx->wBitsPerSample == 8 ? 128 : 0,
  282.                     dwLen2 );
  283.         }
  284.  
  285.     wiWave.lpDSBStreamBuffer->lpVtbl->Unlock( wiWave.lpDSBStreamBuffer,
  286.                                                 (LPVOID)lpWrite1, dwLen1,
  287.                                                 (LPVOID)lpWrite2, dwLen2 );
  288.  
  289.     wiWave.dwNextWriteOffset += dwPlayedLength;
  290.     if( wiWave.dwNextWriteOffset >= wiWave.dwBufferSize )
  291.         wiWave.dwNextWriteOffset -= wiWave.dwBufferSize;
  292.  
  293. #ifdef DEBUG
  294.     PostMessage( hWndMain, WM_DSSTREAM_DEBUG,
  295.                     MAKEWPARAM( DEBUGF_NEXTWRITE, 0 ),
  296.                     wiWave.dwNextWriteOffset );
  297. #endif
  298.     InterlockedExchange(&lInTimer, FALSE);
  299.     return;
  300.     }
  301.