home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 43 / Mac Magazin and MacEasy Magazine CD - Issue 43.iso / Software / Multimedia / Sound / PlayerPRO 4.6 Dev.Kit / MADH Library 4.6 / MADLibrary Source / DirectSound.c < prev    next >
Encoding:
Text File  |  1998-02-12  |  12.2 KB  |  417 lines  |  [TEXT/CWIE]

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 4.6 - DRIVER SOURCE CODE -
  4. //
  5. //    Library Version 4.6
  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:         rosset@dial.eunet.ch or 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.     if( WinMADDriver->DriverSettings.outPutMode == MonoOutPut) pcmwf.nChannels = 1;
  113.     else pcmwf.nChannels = 2;
  114.     pcmwf.nSamplesPerSec        = WinMADDriver->DriverSettings.outPutRate >> 16L;
  115.     pcmwf.wBitsPerSample        = WinMADDriver->DriverSettings.outPutBits;
  116.     pcmwf.nBlockAlign            = pcmwf.nChannels * (pcmwf.wBitsPerSample/8);
  117.     pcmwf.nAvgBytesPerSec        = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
  118.     
  119.     // Set up DSBUFFERDESC structure.
  120.     memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
  121.     dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  122.     dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;    //;    //DSBCAPS_GLOBALFOCUS;    //;
  123.     dsbdesc.dwBufferBytes = 0; // Buffer size is determined
  124.                                // by sound hardware.
  125.     dsbdesc.lpwfxFormat = NULL; // Must be NULL for primary buffers.
  126.     // Obtain write-primary cooperative level.
  127.     hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, hwnd, DSSCL_PRIORITY);
  128.     if(DS_OK == hr)
  129.     {
  130.         // Succeeded! Try to create buffer.
  131.         hr = lpDirectSound->lpVtbl->CreateSoundBuffer(lpDirectSound,
  132.             &dsbdesc, lplpDsb, NULL);
  133.         if(DS_OK == hr) {
  134.             // Succeeded! Set primary buffer to desired format.
  135.             hr = (*lplpDsb)->lpVtbl->SetFormat(*lplpDsb, &pcmwf);
  136.             (*lplpDsb)->lpVtbl->Play(*lplpDsb,0,0,DSBPLAY_LOOPING);
  137.             return TRUE;
  138.         }
  139.         //DEBUG else debugger( TranslateDSError( hr));
  140.     }
  141.     // If we got here, then we failed SetCooperativeLevel.
  142.     // CreateSoundBuffer, or SetFormat.
  143.     *lplpDsb = NULL;
  144.     return FALSE;
  145. }
  146.  
  147. AppDetermineHardwareCaps(LPDIRECTSOUND lpDirectSound)
  148. {
  149.     DSCAPS dscaps;
  150.     HRESULT hr;
  151.     dscaps.dwSize = sizeof(DSCAPS);
  152.     hr = lpDirectSound->lpVtbl->GetCaps(lpDirectSound, &dscaps);
  153.     if(DS_OK == hr)
  154.     {
  155.         printf( "dwFlags = %ld", dscaps.dwFlags);
  156.         
  157.     //DEBUG    if( dscaps.dwFlags & DSBCAPS_GLOBALFOCUS)    debugger("global");
  158.     //DEBUG    if( dscaps.dwFlags & DSBCAPS_STICKYFOCUS)    debugger("sticky");
  159.       //DEBUG    if( dscaps.dwFlags & DSBCAPS_PRIMARYBUFFER)    debugger("DSBCAPS_PRIMARYBUFFER");
  160.             
  161.         // Succeeded, now parse DSCAPS structure.
  162.         
  163.        /*  printf("Hardware Buffers:      %i\n",dscaps.dwSize);
  164.          printf("Hardware Memory:       %i\n",dscaps.dwMinSecondarySampleRate);
  165.          printf("Hardware Free Memory:  %i\n",dscaps.dwFreeHwMemBytes);
  166.          printf( "Byebye");*/
  167.     }
  168.     // .
  169.     // .
  170.     // .
  171. }
  172.  
  173. BOOL WriteDataToBuffer(
  174.     LPDIRECTSOUNDBUFFER lpDsb,
  175.     DWORD dwOffset,
  176.     LPBYTE lpbSoundData,
  177.     DWORD dwSoundBytes)
  178. {
  179.     LPVOID lpvPtr1;
  180.     DWORD dwBytes1;
  181.     LPVOID lpvPtr2;
  182.     DWORD dwBytes2;
  183.     HRESULT hr;
  184.     
  185.     //    lpDirectSound->lpVtbl->SetCooperativeLevel( lpDirectSound, hwnd, DSSCL_EXCLUSIVE);
  186.         
  187.     // Obtain write pointer.
  188.     hr = lpDsb->lpVtbl->Lock(lpDsb, dwOffset, dwSoundBytes, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
  189.  
  190.     // If we got DSERR_BUFFERLOST, restore and retry lock.
  191.     if(DSERR_BUFFERLOST == hr) {
  192.         lpDsb->lpVtbl->Restore(lpDsb);
  193.         hr = lpDsb->lpVtbl->Lock(lpDsb, dwOffset, dwSoundBytes, &lpvPtr1,
  194.              &dwBytes1, &lpvPtr2, &dwBytes2, 0);
  195.     }
  196.     if(DS_OK == hr) {
  197.         // Write to pointers.
  198.         CopyMemory(lpvPtr1, lpbSoundData, dwBytes1);
  199.         if(NULL != lpvPtr2) {
  200.             CopyMemory(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2);
  201.         }
  202.         // Release the data back to DirectSound.
  203.         hr = lpDsb->lpVtbl->Unlock(lpDsb, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
  204.         if(DS_OK == hr) {
  205.             // Success!
  206.             return TRUE;
  207.         }
  208.     }
  209.     
  210. //        lpDirectSound->lpVtbl->SetCooperativeLevel( lpDirectSound, hwnd, DSSCL_NORMAL);
  211.     
  212.     // If we got here, then we failed Lock, Unlock, or Restore.
  213.     return FALSE;
  214. }
  215.  
  216. BOOL LoadSamp(LPDIRECTSOUND lpDirectSound,
  217.               LPDIRECTSOUNDBUFFER *lplpDsb,
  218.               LPBYTE samp, UINT length, UINT flags, MADDriverRec *WinMADDriver)
  219. {
  220.     DSBUFFERDESC dsbdesc;
  221.     HRESULT hr;
  222.     WAVEFORMATEX pcmwf;
  223.  
  224.     // Set up wave format structure.
  225.     memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
  226.     pcmwf.wFormatTag            = WAVE_FORMAT_PCM;
  227.     if( WinMADDriver->DriverSettings.outPutMode == MonoOutPut) pcmwf.nChannels = 1;
  228.     else pcmwf.nChannels = 2;
  229.     pcmwf.nSamplesPerSec        = WinMADDriver->DriverSettings.outPutRate >> 16L;
  230.     pcmwf.wBitsPerSample        = WinMADDriver->DriverSettings.outPutBits;
  231.     pcmwf.nBlockAlign            = pcmwf.nChannels * (pcmwf.wBitsPerSample/8);
  232.     pcmwf.nAvgBytesPerSec        = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
  233.     
  234.     // Set up DSBUFFERDESC structure.
  235.     memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
  236.     dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  237. //    dsbdesc.dwFlags =    DSBCAPS_STATIC | DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;    //;    //;    // | flags;    //DSBCAPS_STATIC | DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY| DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2|flags;
  238.   
  239. //      dsbdesc.dwFlags =    DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY|flags;
  240.       
  241.       dsbdesc.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GLOBALFOCUS;
  242.     dsbdesc.dwBufferBytes = length;
  243.     dsbdesc.dwReserved = 0;
  244.     dsbdesc.lpwfxFormat = &pcmwf;
  245.     hr = lpDirectSound->lpVtbl->CreateSoundBuffer(lpDirectSound, &dsbdesc, lplpDsb, NULL);
  246.     if(hr == DS_OK)
  247.     {
  248. //        lpDirectSound->lpVtbl->SetCooperativeLevel(
  249. //                lpDirectSound,hwnd, DSSCL_EXCLUSIVE);
  250.         // Succeeded! Valid interface is in *lplpDsb.
  251.   //      WriteDataToBuffer(*lplpDsb, 0, samp,length);
  252. //        lpDirectSound->lpVtbl->SetCooperativeLevel(
  253. //                lpDirectSound,hwnd, DSSCL_NORMAL);
  254.     }
  255.     else
  256.     {
  257.         //DEBUG debugger( TranslateDSError( hr));
  258.         
  259.       *lplpDsb=NULL;
  260.       return 0;
  261.     }
  262.     return 1;
  263. }
  264.  
  265. static void CALLBACK TimeProc(
  266.      UINT  IDEvent,            /* identifies timer event */
  267.      UINT  uReserved,        /* not used */
  268.      DWORD  dwUser,            /* application-defined instance data */
  269.      DWORD  dwReserved1,    /* not used */
  270.      DWORD  dwReserved2        /* not used */
  271. )
  272. {
  273.     DWORD         pos, posp, i;
  274.     static volatile int timersema=0;
  275.  
  276.     /* use semaphore to prevent entering the mixing routines twice.. do we need this ? */
  277.  
  278.     if(++timersema==1)
  279.     {
  280.         MADDriverRec    *WinMADDriver = (MADDriverRec*) dwUser;
  281.         
  282.         WinMADDriver->lpSwSamp->lpVtbl->GetCurrentPosition( WinMADDriver->lpSwSamp, &pos, &posp);
  283.         
  284.         if(pos > WIN95BUFFERSIZE/2 && OnOff == true)
  285.         {
  286.             OnOff = false;
  287.             
  288.             if( !DirectSave( currentBuf, 0L, WinMADDriver))
  289.             {
  290.                 switch( WinMADDriver->DriverSettings.outPutBits)
  291.                 {
  292.                     case 8:
  293.                         for( i = 0; i < WIN95BUFFERSIZE/2; i++) currentBuf[ i] = 0x80;
  294.                     break;
  295.                     
  296.                     case 16:
  297.                         for( i = 0; i < WIN95BUFFERSIZE/2; i++) currentBuf[ i] = 0;
  298.                     break;
  299.                 }
  300.             }
  301.             
  302.             if( !WriteDataToBuffer( WinMADDriver->lpSwSamp, 0, (unsigned char*) currentBuf, WIN95BUFFERSIZE/2))
  303.             {
  304.                 //DEBUG     debugger("ERR");
  305.             }
  306.         }
  307.         else if( OnOff == false && (pos < WIN95BUFFERSIZE/2))
  308.         {
  309.             OnOff = true;
  310.             
  311.             if( !DirectSave( currentBuf + WIN95BUFFERSIZE/2, 0L, WinMADDriver))
  312.             {
  313.                 switch( WinMADDriver->DriverSettings.outPutBits)
  314.                 {
  315.                     case 8:
  316.                         for( i = WIN95BUFFERSIZE/2; i < WIN95BUFFERSIZE; i++) currentBuf[ i] = 0x80;
  317.                     break;
  318.                     
  319.                     case 16:
  320.                         for( i = WIN95BUFFERSIZE/2; i < WIN95BUFFERSIZE; i++) currentBuf[ i] = 0;
  321.                     break;
  322.                 }
  323.             }
  324.             
  325.             if( !WriteDataToBuffer( WinMADDriver->lpSwSamp, WIN95BUFFERSIZE/2, (unsigned char*) (currentBuf + WIN95BUFFERSIZE/2), WIN95BUFFERSIZE/2))
  326.             {
  327.                 //DEBUG     debugger("ERR");
  328.             }
  329.         }
  330.         
  331.         if( WIN95BUFFERSIZE - pos > 1700)    WinMADDriver->OscilloWavePtr = currentBuf + pos;
  332.         else WinMADDriver->OscilloWavePtr = currentBuf;
  333.     }
  334.     timersema--;
  335. }
  336.  
  337.  
  338. Boolean DirectSoundInit( MADDriverRec* WinMADDriver)
  339. {
  340.     OnOff                    = false;
  341.     
  342.     WIN95BUFFERSIZE = WinMADDriver->BufSize;
  343.     WIN95BUFFERSIZE *= 2L;                                // double buffer system
  344.     
  345.     currentBuf         = calloc( WIN95BUFFERSIZE, 1);
  346.     
  347.     hwnd = GetForegroundWindow();    //GetForegroundWindow();
  348.     if( !hwnd) return false;
  349.     
  350.     if(DS_OK == DirectSoundCreate(NULL, &WinMADDriver->lpDirectSound, NULL))
  351.     {
  352.         if( !AppCreateWritePrimaryBuffer( WinMADDriver->lpDirectSound, &WinMADDriver->lpDirectSoundBuffer, hwnd, WinMADDriver))
  353.         {
  354.             WinMADDriver->lpDirectSound = 0L;
  355.             return false;
  356.         }
  357.         if( !WinMADDriver->lpDirectSoundBuffer) return false;
  358.         
  359.         // Creation succeeded.
  360.         WinMADDriver->lpDirectSound->lpVtbl->SetCooperativeLevel(WinMADDriver->lpDirectSound, hwnd, DSSCL_NORMAL);
  361.         
  362.         WinMADDriver->lpSwSamp = 0L;
  363.         if( !LoadSamp(WinMADDriver->lpDirectSound, &WinMADDriver->lpSwSamp, 0L, WIN95BUFFERSIZE, DSBCAPS_LOCSOFTWARE, WinMADDriver))
  364.         {
  365.             //DEBUG debugger( "Error 2\n");        //DSBCAPS_LOCSOFTWARE
  366.             WinMADDriver->lpDirectSound = 0L;
  367.             return false;
  368.         }
  369.         
  370.         if( !WinMADDriver->lpSwSamp) return false;
  371.         
  372.         WinMADDriver->lpSwSamp->lpVtbl->Play(WinMADDriver->lpSwSamp, 0, 0, DSBPLAY_LOOPING);
  373.         
  374.         ///////////
  375.         
  376.         timeBeginPeriod(20);      /* set the minimum resolution */
  377.         
  378.         /*  Set up the callback event.  The callback function
  379.          *  MUST be in a FIXED CODE DLL!!! -> not in Win95
  380.          */
  381.          
  382.         // debugger( "timeSetEvent\n");
  383.          
  384.         gwID = timeSetEvent(      40,                                                   /* how often                 */
  385.                                                       40,                               /* timer resolution          */
  386.                                                       TimeProc,                          /* callback function         */
  387.                                                       (unsigned long) WinMADDriver,        /* info to pass to callback  */
  388.                                                       TIME_PERIODIC);                     /* oneshot or periodic?      */
  389.         
  390.         if( gwID == 0) return false;
  391.         else return true;
  392.     }
  393.     
  394.     WinMADDriver->lpDirectSound = 0L;
  395.     
  396.     return false;
  397. }
  398.  
  399. void DirectSoundClose( MADDriverRec* WinMADDriver)
  400. {
  401.     if( WinMADDriver->lpDirectSound)
  402.     {
  403.         /* stop the timer */
  404.         timeKillEvent( gwID);
  405.         timeEndPeriod( 20);
  406.         
  407.         WinMADDriver->lpSwSamp->lpVtbl->Stop( WinMADDriver->lpSwSamp);
  408.         WinMADDriver->lpSwSamp->lpVtbl->Release( WinMADDriver->lpSwSamp);
  409.         WinMADDriver->lpSwSamp = 0L;
  410.         
  411.         WinMADDriver->lpDirectSoundBuffer->lpVtbl->Stop(WinMADDriver->lpDirectSoundBuffer);
  412.           WinMADDriver->lpDirectSoundBuffer->lpVtbl->Release(WinMADDriver->lpDirectSoundBuffer);
  413.   
  414.         WinMADDriver->lpDirectSound->lpVtbl->Release( WinMADDriver->lpDirectSound);
  415.         WinMADDriver->lpDirectSound = NULL;
  416.     }
  417. }