home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2004 September / maximum-cd-2004-09.iso / Software / Extras / nbeep03.exe / Source / audio.cpp next >
Encoding:
C/C++ Source or Header  |  2002-03-02  |  4.6 KB  |  201 lines

  1. #include <windows.h>
  2. #include <dsound.h>
  3.  
  4. #define BUFFER_SIZE 16384
  5.  
  6. static IDirectSound *g_ds;
  7. static IDirectSoundBuffer *primary, *second;
  8. static HANDLE g_wave_thread;
  9. static volatile int g_wave_quit;
  10. static int needstart=0,write_pos=0;
  11.  
  12. static DWORD WINAPI _threadproc(LPVOID p);
  13.  
  14. extern void generate_samples(short *buf, int samplelength);
  15.  
  16. char *audioOpen(HWND hwnd)
  17. {
  18.   unsigned long len1,len2;
  19.   void *pt1,*pt2;
  20.   DSBUFFERDESC pd={sizeof(pd),};
  21.   WAVEFORMATEX wfx;
  22.   LPGUID lpguid=NULL;
  23.   DWORD id;
  24.  
  25.   if (DirectSoundCreate(lpguid, &g_ds, NULL) != DS_OK) 
  26.   {
  27.     return "Could not create DirectSound object";
  28.   }
  29.  
  30.   if (g_ds->SetCooperativeLevel(hwnd, DSSCL_PRIORITY) != DS_OK) 
  31.   {
  32.     g_ds->Release();
  33.     return "Could not set cooperative level";
  34.   }
  35.  
  36.   if (1) // create primary buffer
  37.   {
  38.     pd.dwFlags = DSBCAPS_PRIMARYBUFFER;
  39.     if (g_ds->CreateSoundBuffer(&pd, &primary, NULL) != DS_OK) 
  40.     {
  41.       g_ds->Release();
  42.       primary = second = (LPDIRECTSOUNDBUFFER)NULL;
  43.       return "Could not create primary buffer";
  44.     }
  45.  
  46.     wfx.wFormatTag = WAVE_FORMAT_PCM;
  47.     wfx.cbSize = 0;
  48.     wfx.nChannels = 2;
  49.     wfx.nSamplesPerSec = 44100;
  50.     wfx.wBitsPerSample = 16;
  51.     wfx.nBlockAlign = (wfx.wBitsPerSample/8)*2;
  52.     wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
  53.  
  54.  
  55.     if (primary->SetFormat(&wfx) != DS_OK) 
  56.     {
  57.       primary->Release();
  58.       g_ds->Release();
  59.       primary = second = (LPDIRECTSOUNDBUFFER)NULL;
  60.       return "Could not set output format";
  61.     }
  62.   }
  63.   else primary=NULL;
  64.  
  65.   wfx.wFormatTag = WAVE_FORMAT_PCM;
  66.   wfx.cbSize = 0;
  67.  
  68.   wfx.nChannels = 1;
  69.   wfx.nSamplesPerSec = 44100;
  70.   wfx.nAvgBytesPerSec = 2 * 44100 * 1;
  71.   wfx.wBitsPerSample = 16;
  72.   wfx.nBlockAlign = 2;
  73.  
  74.   pd.dwFlags = DSBCAPS_GLOBALFOCUS |
  75.                DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS;
  76.   pd.dwBufferBytes = BUFFER_SIZE;
  77.   pd.lpwfxFormat = &wfx;
  78.  
  79.   if (g_ds->CreateSoundBuffer(&pd, &second, NULL) != DS_OK) 
  80.   {
  81.     if (primary) primary->Release();
  82.     g_ds->Release();
  83.     primary = second = (LPDIRECTSOUNDBUFFER)NULL;
  84.     return "Could not create secondary buffer";
  85.   }
  86.  
  87.   if (second->Lock(0,BUFFER_SIZE, &pt1, &len1, &pt2, &len2, 0) == DS_OK) 
  88.     {
  89.       int wrote1=0,wrote2=0;
  90.         wrote1=len1;
  91.     memset(pt1,0,wrote1);
  92.         if (pt2)
  93.         {
  94.             wrote2=len2;
  95.             memset(pt2,0,wrote2);
  96.         }
  97.         second->Unlock(pt1, wrote1, pt2, wrote2);
  98.     }
  99.  
  100.   if (primary && 1) // start primary
  101.   {
  102.     int n=10;
  103.     HRESULT res=0;
  104.     while (n--)
  105.     {
  106.       res=primary->Play(0, 0, DSBPLAY_LOOPING);
  107.       if (res == DS_OK) break;
  108.       if (res == DSERR_BUFFERLOST)
  109.       {
  110.         primary->Restore();
  111.         Sleep(50);
  112.       }
  113.     }
  114.     if (res != DS_OK) 
  115.     {
  116.       second->Release();
  117.       primary->Release();
  118.       g_ds->Release();
  119.       primary = second = (LPDIRECTSOUNDBUFFER)NULL;
  120.       return "Could not start primary buffer";
  121.     }
  122.   }
  123.  
  124.   needstart=0;
  125.   g_wave_quit=0;
  126.     g_wave_thread=CreateThread(NULL,0,_threadproc,NULL,0,&id);
  127.   if (!g_wave_thread)
  128.   {
  129.     g_ds->Release();
  130.   }
  131.   SetThreadPriority(g_wave_thread,THREAD_PRIORITY_HIGHEST);
  132.   return 0;
  133. }
  134.  
  135. void audioClose()
  136. {
  137.   if (!g_wave_thread) return;
  138.   g_wave_quit=1;
  139.  
  140.   WaitForSingleObject(g_wave_thread,INFINITE);
  141.   CloseHandle(g_wave_thread);
  142.   g_wave_thread=0;
  143.   if (primary) primary->Release();
  144.   if (second) second->Release();
  145.   g_ds->Release();
  146.   g_ds=0;
  147. }
  148.  
  149. static DWORD WINAPI _threadproc(LPVOID p)
  150. {
  151.   while (!g_wave_quit)
  152.   {
  153.     int wrote_bytes=0;
  154.         void *pt1, *pt2;
  155.         int len;
  156.     unsigned long len2, len1;
  157.     DWORD pp=0;
  158.     if (needstart == -1) IDirectSoundBuffer_GetCurrentPosition(second,&pp,NULL);
  159.     else pp=BUFFER_SIZE;
  160.  
  161.     len = pp-write_pos;
  162.     if (len < 0) len += BUFFER_SIZE;
  163.  
  164.     if (len > 2)
  165.     {
  166.       HRESULT res;
  167.       len&=~1;
  168.       res=second->Lock(write_pos,len, &pt1, &len1, &pt2, &len2, 0);
  169.       if (res == DS_OK) 
  170.             {
  171.         len1 &= ~1;
  172.         len2 &= ~1;
  173.         
  174.         generate_samples((short*)pt1,len1/2);
  175.         write_pos+=len1;
  176.                 if (pt2)
  177.                 {
  178.           generate_samples((short*)pt2,len2/2);
  179.           write_pos+=len2;
  180.                 }
  181.                 second->Unlock(pt1, len1, pt2, len2);
  182.             }
  183.       else if (res == DSERR_BUFFERLOST)
  184.       {
  185.         second->Restore();
  186.       }
  187.       if (write_pos >= BUFFER_SIZE) write_pos-=BUFFER_SIZE;
  188.     }
  189.  
  190.     if (needstart > -1)
  191.     {
  192.       switch (second->Play(0, 0, DSBPLAY_LOOPING))
  193.       {
  194.         case DS_OK: needstart=-1; break;
  195.         case DSERR_BUFFERLOST: second->Restore(); break;
  196.       }
  197.     }
  198.     Sleep(20);
  199.   }
  200.   return 0;
  201. }