home *** CD-ROM | disk | FTP | other *** search
/ Amiga Dream 59 / CDDream59.ISO / BeOs / Sound / Intel / PPBeDevKit.ZIP / PLAYERPR.TAR / PlayerPRO / Source / Win-DirectSound.c < prev    next >
C/C++ Source or Header  |  1998-12-27  |  13KB  |  415 lines

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 5.0 - DRIVER SOURCE CODE -
  4. //
  5. //    Library Version 5.0
  6. //
  7. //    To use with MAD Library for Mac: Symantec, CodeWarrior and MPW
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //
  14. //    COPYRIGHT ANTOINE ROSSET 1996, 1997, 1998
  15. //
  16. //    Thank you for your interest in PlayerPRO !
  17. //
  18. //    FAX:                (+41 22) 346 11 97
  19. //    PHONE:             (+41 79) 203 74 62
  20. //    Internet:     RossetAntoine@bluewin.ch
  21. //
  22. /********************                        ***********************/
  23.  
  24. #include "RDriver.h"
  25. #include "RDriverInt.h"
  26. #include "OBJBASE.h"
  27.  
  28. #include <cguid.h>
  29.  
  30. //#define DEBUG
  31.  
  32. static UINT gwID;
  33. static HWND hwnd;
  34.  
  35. /*static LPDIRECTSOUND lpDirectSound;
  36. static LPDIRECTSOUNDBUFFER lpDirectSoundBuffer;
  37. static LPDIRECTSOUNDBUFFER lpSwSamp;*/
  38.  
  39. static     Ptr                     currentBuf;
  40. static     Boolean                    OnOff;
  41. static     long                    WIN95BUFFERSIZE;
  42.  
  43. char *TranslateDSError( HRESULT hr )
  44.     {
  45.     switch( hr )
  46.     {
  47.     case DSERR_ALLOCATED:
  48.         return "DSERR_ALLOCATED";
  49.  
  50.     case DSERR_CONTROLUNAVAIL:
  51.         return "DSERR_CONTROLUNAVAIL";
  52.  
  53.     case DSERR_INVALIDPARAM:
  54.         return "DSERR_INVALIDPARAM";
  55.  
  56.     case DSERR_INVALIDCALL:
  57.         return "DSERR_INVALIDCALL";
  58.  
  59.     case DSERR_GENERIC:
  60.         return "DSERR_GENERIC";
  61.  
  62.     case DSERR_PRIOLEVELNEEDED:
  63.         return "DSERR_PRIOLEVELNEEDED";
  64.  
  65.     case DSERR_OUTOFMEMORY:
  66.         return "DSERR_OUTOFMEMORY";
  67.  
  68.     case DSERR_BADFORMAT:
  69.         return "DSERR_BADFORMAT";
  70.  
  71.     case DSERR_UNSUPPORTED:
  72.         return "DSERR_UNSUPPORTED";
  73.  
  74.     case DSERR_NODRIVER:
  75.         return "DSERR_NODRIVER";
  76.  
  77.     case DSERR_ALREADYINITIALIZED:
  78.         return "DSERR_ALREADYINITIALIZED";
  79.  
  80.     case DSERR_NOAGGREGATION:
  81.         return "DSERR_NOAGGREGATION";
  82.  
  83.     case DSERR_BUFFERLOST:
  84.         return "DSERR_BUFFERLOST";
  85.  
  86.     case DSERR_OTHERAPPHASPRIO:
  87.         return "DSERR_OTHERAPPHASPRIO";
  88.  
  89.     case DSERR_UNINITIALIZED:
  90.         return "DSERR_UNINITIALIZED";
  91.  
  92.     default:
  93.         return "Unknown HRESULT";
  94.     }
  95.     }
  96.  
  97.  
  98. BOOL AppCreateWritePrimaryBuffer(
  99.     LPDIRECTSOUND lpDirectSound,
  100.     LPDIRECTSOUNDBUFFER *lplpDsb,
  101.     HWND hwnd,
  102.     MADDriverRec    *WinMADDriver)
  103. {
  104.     DSBUFFERDESC dsbdesc;
  105.     HRESULT hr;
  106.     WAVEFORMATEX pcmwf;
  107.  
  108.     // Set up wave format structure.
  109.     memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
  110.     pcmwf.wFormatTag         = WAVE_FORMAT_PCM;
  111.     
  112.     pcmwf.nChannels = 2;
  113.     pcmwf.nSamplesPerSec        = WinMADDriver->DriverSettings.outPutRate >> 16L;
  114.     pcmwf.wBitsPerSample        = WinMADDriver->DriverSettings.outPutBits;
  115.     pcmwf.nBlockAlign            = pcmwf.nChannels * (pcmwf.wBitsPerSample/8);
  116.     pcmwf.nAvgBytesPerSec        = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
  117.     
  118.     // Set up DSBUFFERDESC structure.
  119.     memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
  120.     dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  121.     dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;    //;    //DSBCAPS_GLOBALFOCUS;    //;
  122.     dsbdesc.dwBufferBytes = 0; // Buffer size is determined
  123.                                // by sound hardware.
  124.     dsbdesc.lpwfxFormat = NULL; // Must be NULL for primary buffers.
  125.     // Obtain write-primary cooperative level.
  126.     hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hwnd, DSSCL_PRIORITY);
  127.     if(DS_OK == hr)
  128.     {
  129.         // Succeeded! Try to create buffer.
  130.         hr = lpDirectSound->lpVtbl->CreateSoundBuffer(lpDirectSound,
  131.             &dsbdesc, lplpDsb, NULL);
  132.         if(DS_OK == hr) {
  133.             // Succeeded! Set primary buffer to desired format.
  134.             hr = (*lplpDsb)->lpVtbl->SetFormat(*lplpDsb, &pcmwf);
  135.             (*lplpDsb)->lpVtbl->Play(*lplpDsb,0,0,DSBPLAY_LOOPING);
  136.             return TRUE;
  137.         }
  138.         //DEBUG else debugger( TranslateDSError( hr));
  139.     }
  140.     // If we got here, then we failed SetCooperativeLevel.
  141.     // CreateSoundBuffer, or SetFormat.
  142.     *lplpDsb = NULL;
  143.     return FALSE;
  144. }
  145.  
  146. AppDetermineHardwareCaps(LPDIRECTSOUND lpDirectSound)
  147. {
  148.     DSCAPS dscaps;
  149.     HRESULT hr;
  150.     dscaps.dwSize = sizeof(DSCAPS);
  151.     hr = lpDirectSound->lpVtbl->GetCaps(lpDirectSound, &dscaps);
  152.     if(DS_OK == hr)
  153.     {
  154.         printf( "dwFlags = %ld", dscaps.dwFlags);
  155.         
  156.     //DEBUG    if( dscaps.dwFlags & DSBCAPS_GLOBALFOCUS)    debugger("global");
  157.     //DEBUG    if( dscaps.dwFlags & DSBCAPS_STICKYFOCUS)    debugger("sticky");
  158.       //DEBUG    if( dscaps.dwFlags & DSBCAPS_PRIMARYBUFFER)    debugger("DSBCAPS_PRIMARYBUFFER");
  159.             
  160.         // Succeeded, now parse DSCAPS structure.
  161.         
  162.        /*  printf("Hardware Buffers:      %i\n",dscaps.dwSize);
  163.          printf("Hardware Memory:       %i\n",dscaps.dwMinSecondarySampleRate);
  164.          printf("Hardware Free Memory:  %i\n",dscaps.dwFreeHwMemBytes);
  165.          printf( "Byebye");*/
  166.     }
  167.     // .
  168.     // .
  169.     // .
  170. }
  171.  
  172. BOOL WriteDataToBuffer(
  173.     LPDIRECTSOUNDBUFFER lpDsb,
  174.     DWORD dwOffset,
  175.     LPBYTE lpbSoundData,
  176.     DWORD dwSoundBytes)
  177. {
  178.     LPVOID lpvPtr1;
  179.     DWORD dwBytes1;
  180.     LPVOID lpvPtr2;
  181.     DWORD dwBytes2;
  182.     HRESULT hr;
  183.     
  184.     //    lpDirectSound->lpVtbl->SetCooperativeLevel( lpDirectSound, hwnd, DSSCL_EXCLUSIVE);
  185.         
  186.     // Obtain write pointer.
  187.     hr = lpDsb->lpVtbl->Lock(lpDsb, dwOffset, dwSoundBytes, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
  188.  
  189.     // If we got DSERR_BUFFERLOST, restore and retry lock.
  190.     if(DSERR_BUFFERLOST == hr) {
  191.         lpDsb->lpVtbl->Restore(lpDsb);
  192.         hr = lpDsb->lpVtbl->Lock(lpDsb, dwOffset, dwSoundBytes, &lpvPtr1,
  193.              &dwBytes1, &lpvPtr2, &dwBytes2, 0);
  194.     }
  195.     if(DS_OK == hr) {
  196.         // Write to pointers.
  197.         CopyMemory(lpvPtr1, lpbSoundData, dwBytes1);
  198.         if(NULL != lpvPtr2) {
  199.             CopyMemory(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2);
  200.         }
  201.         // Release the data back to DirectSound.
  202.         hr = lpDsb->lpVtbl->Unlock(lpDsb, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
  203.         if(DS_OK == hr) {
  204.             // Success!
  205.             return TRUE;
  206.         }
  207.     }
  208.     
  209. //        lpDirectSound->lpVtbl->SetCooperativeLevel( lpDirectSound, hwnd, DSSCL_NORMAL);
  210.     
  211.     // If we got here, then we failed Lock, Unlock, or Restore.
  212.     return FALSE;
  213. }
  214.  
  215. BOOL LoadSamp(LPDIRECTSOUND lpDirectSound,
  216.               LPDIRECTSOUNDBUFFER *lplpDsb,
  217.               LPBYTE samp, UINT length, UINT flags, MADDriverRec *WinMADDriver)
  218. {
  219.     DSBUFFERDESC dsbdesc;
  220.     HRESULT hr;
  221.     WAVEFORMATEX pcmwf;
  222.  
  223.     // Set up wave format structure.
  224.     memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
  225.     pcmwf.wFormatTag            = WAVE_FORMAT_PCM;
  226.     pcmwf.nChannels = 2;
  227.     pcmwf.nSamplesPerSec        = WinMADDriver->DriverSettings.outPutRate >> 16L;
  228.     pcmwf.wBitsPerSample        = WinMADDriver->DriverSettings.outPutBits;
  229.     pcmwf.nBlockAlign            = pcmwf.nChannels * (pcmwf.wBitsPerSample/8);
  230.     pcmwf.nAvgBytesPerSec        = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
  231.     
  232.     // Set up DSBUFFERDESC structure.
  233.     memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
  234.     dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  235. //    dsbdesc.dwFlags =    DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;    //;    //;    // | flags;    //DSBCAPS_STATIC | DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY| DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2|flags;
  236.   
  237. //      dsbdesc.dwFlags =    DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY|flags;
  238.       
  239.       dsbdesc.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GLOBALFOCUS;
  240.     dsbdesc.dwBufferBytes = length;
  241.     dsbdesc.dwReserved = 0;
  242.     dsbdesc.lpwfxFormat = &pcmwf;
  243.     hr = lpDirectSound->lpVtbl->CreateSoundBuffer(lpDirectSound, &dsbdesc, lplpDsb, NULL);
  244.     if(hr == DS_OK)
  245.     {
  246. //        lpDirectSound->lpVtbl->SetCooperativeLevel(
  247. //                lpDirectSound,hwnd, DSSCL_EXCLUSIVE);
  248.         // Succeeded! Valid interface is in *lplpDsb.
  249.   //      WriteDataToBuffer(*lplpDsb, 0, samp,length);
  250. //        lpDirectSound->lpVtbl->SetCooperativeLevel(
  251. //                lpDirectSound,hwnd, DSSCL_NORMAL);
  252.     }
  253.     else
  254.     {
  255.         //DEBUG debugger( TranslateDSError( hr));
  256.         
  257.       *lplpDsb=NULL;
  258.       return 0;
  259.     }
  260.     return 1;
  261. }
  262.  
  263. static void CALLBACK TimeProc(
  264.      UINT  IDEvent,            /* identifies timer event */
  265.      UINT  uReserved,        /* not used */
  266.      DWORD  dwUser,            /* application-defined instance data */
  267.      DWORD  dwReserved1,    /* not used */
  268.      DWORD  dwReserved2        /* not used */
  269. )
  270. {
  271.     DWORD         pos, posp, i;
  272.     static volatile int timersema=0;
  273.  
  274.     /* use semaphore to prevent entering the mixing routines twice.. do we need this ? */
  275.  
  276.     if(++timersema==1)
  277.     {
  278.         MADDriverRec    *WinMADDriver = (MADDriverRec*) dwUser;
  279.         
  280.         WinMADDriver->lpSwSamp->lpVtbl->GetCurrentPosition( WinMADDriver->lpSwSamp, &pos, &posp);
  281.         
  282.         if(pos > WIN95BUFFERSIZE/2 && OnOff == true)
  283.         {
  284.             OnOff = false;
  285.             
  286.             if( !DirectSave( currentBuf, 0L, WinMADDriver))
  287.             {
  288.                 switch( WinMADDriver->DriverSettings.outPutBits)
  289.                 {
  290.                     case 8:
  291.                         for( i = 0; i < WIN95BUFFERSIZE/2; i++) currentBuf[ i] = 0x80;
  292.                     break;
  293.                     
  294.                     case 16:
  295.                         for( i = 0; i < WIN95BUFFERSIZE/2; i++) currentBuf[ i] = 0;
  296.                     break;
  297.                 }
  298.             }
  299.             
  300.             if( !WriteDataToBuffer( WinMADDriver->lpSwSamp, 0, (unsigned char*) currentBuf, WIN95BUFFERSIZE/2))
  301.             {
  302.                 //DEBUG     debugger("ERR");
  303.             }
  304.         }
  305.         else if( OnOff == false && (pos < WIN95BUFFERSIZE/2))
  306.         {
  307.             OnOff = true;
  308.             
  309.             if( !DirectSave( currentBuf + WIN95BUFFERSIZE/2, 0L, WinMADDriver))
  310.             {
  311.                 switch( WinMADDriver->DriverSettings.outPutBits)
  312.                 {
  313.                     case 8:
  314.                         for( i = WIN95BUFFERSIZE/2; i < WIN95BUFFERSIZE; i++) currentBuf[ i] = 0x80;
  315.                     break;
  316.                     
  317.                     case 16:
  318.                         for( i = WIN95BUFFERSIZE/2; i < WIN95BUFFERSIZE; i++) currentBuf[ i] = 0;
  319.                     break;
  320.                 }
  321.             }
  322.             
  323.             if( !WriteDataToBuffer( WinMADDriver->lpSwSamp, WIN95BUFFERSIZE/2, (unsigned char*) (currentBuf + WIN95BUFFERSIZE/2), WIN95BUFFERSIZE/2))
  324.             {
  325.                 //DEBUG     debugger("ERR");
  326.             }
  327.         }
  328.         
  329.         if( WIN95BUFFERSIZE - pos > 1700)    WinMADDriver->OscilloWavePtr = currentBuf + pos;
  330.         else WinMADDriver->OscilloWavePtr = currentBuf;
  331.     }
  332.     timersema--;
  333. }
  334.  
  335.  
  336. Boolean DirectSoundInit( MADDriverRec* WinMADDriver)
  337. {
  338.     OnOff                    = false;
  339.     
  340.     WIN95BUFFERSIZE = WinMADDriver->BufSize;
  341.     WIN95BUFFERSIZE *= 2L;                                // double buffer system
  342.     
  343.     currentBuf         = calloc( WIN95BUFFERSIZE, 1);
  344.     
  345.     hwnd = GetForegroundWindow();    //GetForegroundWindow();
  346.     if( !hwnd) return false;
  347.     
  348.     if(DS_OK == DirectSoundCreate(NULL, &WinMADDriver->lpDirectSound, NULL))
  349.     {
  350.         if( !AppCreateWritePrimaryBuffer( WinMADDriver->lpDirectSound, &WinMADDriver->lpDirectSoundBuffer, hwnd, WinMADDriver))
  351.         {
  352.             WinMADDriver->lpDirectSound = 0L;
  353.             return false;
  354.         }
  355.         if( !WinMADDriver->lpDirectSoundBuffer) return false;
  356.         
  357.         // Creation succeeded.
  358.         WinMADDriver->lpDirectSound->lpVtbl->SetCooperativeLevel(WinMADDriver->lpDirectSound, hwnd, DSSCL_NORMAL);
  359.         
  360.         WinMADDriver->lpSwSamp = 0L;
  361.         if( !LoadSamp(WinMADDriver->lpDirectSound, &WinMADDriver->lpSwSamp, 0L, WIN95BUFFERSIZE, DSBCAPS_LOCSOFTWARE, WinMADDriver))
  362.         {
  363.             //DEBUG debugger( "Error 2\n");        //DSBCAPS_LOCSOFTWARE
  364.             WinMADDriver->lpDirectSound = 0L;
  365.             return false;
  366.         }
  367.         
  368.         if( !WinMADDriver->lpSwSamp) return false;
  369.         
  370.         WinMADDriver->lpSwSamp->lpVtbl->Play(WinMADDriver->lpSwSamp, 0, 0, DSBPLAY_LOOPING);
  371.         
  372.         ///////////
  373.         
  374.         timeBeginPeriod(20);      /* set the minimum resolution */
  375.         
  376.         /*  Set up the callback event.  The callback function
  377.          *  MUST be in a FIXED CODE DLL!!! -> not in Win95
  378.          */
  379.          
  380.         // debugger( "timeSetEvent\n");
  381.          
  382.         gwID = timeSetEvent(      40,                                                   /* how often                 */
  383.                                                       40,                               /* timer resolution          */
  384.                                                       TimeProc,                          /* callback function         */
  385.                                                       (unsigned long) WinMADDriver,        /* info to pass to callback  */
  386.                                                       TIME_PERIODIC);                     /* oneshot or periodic?      */
  387.         
  388.         if( gwID == 0) return false;
  389.         else return true;
  390.     }
  391.     
  392.     WinMADDriver->lpDirectSound = 0L;
  393.     
  394.     return false;
  395. }
  396.  
  397. void DirectSoundClose( MADDriverRec* WinMADDriver)
  398. {
  399.     if( WinMADDriver->lpDirectSound)
  400.     {
  401.         /* stop the timer */
  402.         timeKillEvent( gwID);
  403.         timeEndPeriod( 20);
  404.         
  405.         WinMADDriver->lpSwSamp->lpVtbl->Stop( WinMADDriver->lpSwSamp);
  406.         WinMADDriver->lpSwSamp->lpVtbl->Release( WinMADDriver->lpSwSamp);
  407.         WinMADDriver->lpSwSamp = 0L;
  408.         
  409.         WinMADDriver->lpDirectSoundBuffer->lpVtbl->Stop(WinMADDriver->lpDirectSoundBuffer);
  410.           WinMADDriver->lpDirectSoundBuffer->lpVtbl->Release(WinMADDriver->lpDirectSoundBuffer);
  411.   
  412.         WinMADDriver->lpDirectSound->lpVtbl->Release( WinMADDriver->lpDirectSound);
  413.         WinMADDriver->lpDirectSound = NULL;
  414.     }
  415. }