home *** CD-ROM | disk | FTP | other *** search
- #include <windows.h>
- #include <dsound.h>
-
- #define BUFFER_SIZE 16384
-
- static IDirectSound *g_ds;
- static IDirectSoundBuffer *primary, *second;
- static HANDLE g_wave_thread;
- static volatile int g_wave_quit;
- static int needstart=0,write_pos=0;
-
- static DWORD WINAPI _threadproc(LPVOID p);
-
- extern void generate_samples(short *buf, int samplelength);
-
- char *audioOpen(HWND hwnd)
- {
- unsigned long len1,len2;
- void *pt1,*pt2;
- DSBUFFERDESC pd={sizeof(pd),};
- WAVEFORMATEX wfx;
- LPGUID lpguid=NULL;
- DWORD id;
-
- if (DirectSoundCreate(lpguid, &g_ds, NULL) != DS_OK)
- {
- return "Could not create DirectSound object";
- }
-
- if (g_ds->SetCooperativeLevel(hwnd, DSSCL_PRIORITY) != DS_OK)
- {
- g_ds->Release();
- return "Could not set cooperative level";
- }
-
- if (1) // create primary buffer
- {
- pd.dwFlags = DSBCAPS_PRIMARYBUFFER;
- if (g_ds->CreateSoundBuffer(&pd, &primary, NULL) != DS_OK)
- {
- g_ds->Release();
- primary = second = (LPDIRECTSOUNDBUFFER)NULL;
- return "Could not create primary buffer";
- }
-
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.cbSize = 0;
- wfx.nChannels = 2;
- wfx.nSamplesPerSec = 44100;
- wfx.wBitsPerSample = 16;
- wfx.nBlockAlign = (wfx.wBitsPerSample/8)*2;
- wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
-
-
- if (primary->SetFormat(&wfx) != DS_OK)
- {
- primary->Release();
- g_ds->Release();
- primary = second = (LPDIRECTSOUNDBUFFER)NULL;
- return "Could not set output format";
- }
- }
- else primary=NULL;
-
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.cbSize = 0;
-
- wfx.nChannels = 1;
- wfx.nSamplesPerSec = 44100;
- wfx.nAvgBytesPerSec = 2 * 44100 * 1;
- wfx.wBitsPerSample = 16;
- wfx.nBlockAlign = 2;
-
- pd.dwFlags = DSBCAPS_GLOBALFOCUS |
- DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS;
- pd.dwBufferBytes = BUFFER_SIZE;
- pd.lpwfxFormat = &wfx;
-
- if (g_ds->CreateSoundBuffer(&pd, &second, NULL) != DS_OK)
- {
- if (primary) primary->Release();
- g_ds->Release();
- primary = second = (LPDIRECTSOUNDBUFFER)NULL;
- return "Could not create secondary buffer";
- }
-
- if (second->Lock(0,BUFFER_SIZE, &pt1, &len1, &pt2, &len2, 0) == DS_OK)
- {
- int wrote1=0,wrote2=0;
- wrote1=len1;
- memset(pt1,0,wrote1);
- if (pt2)
- {
- wrote2=len2;
- memset(pt2,0,wrote2);
- }
- second->Unlock(pt1, wrote1, pt2, wrote2);
- }
-
- if (primary && 1) // start primary
- {
- int n=10;
- HRESULT res=0;
- while (n--)
- {
- res=primary->Play(0, 0, DSBPLAY_LOOPING);
- if (res == DS_OK) break;
- if (res == DSERR_BUFFERLOST)
- {
- primary->Restore();
- Sleep(50);
- }
- }
- if (res != DS_OK)
- {
- second->Release();
- primary->Release();
- g_ds->Release();
- primary = second = (LPDIRECTSOUNDBUFFER)NULL;
- return "Could not start primary buffer";
- }
- }
-
- needstart=0;
- g_wave_quit=0;
- g_wave_thread=CreateThread(NULL,0,_threadproc,NULL,0,&id);
- if (!g_wave_thread)
- {
- g_ds->Release();
- }
- SetThreadPriority(g_wave_thread,THREAD_PRIORITY_HIGHEST);
- return 0;
- }
-
- void audioClose()
- {
- if (!g_wave_thread) return;
- g_wave_quit=1;
-
- WaitForSingleObject(g_wave_thread,INFINITE);
- CloseHandle(g_wave_thread);
- g_wave_thread=0;
- if (primary) primary->Release();
- if (second) second->Release();
- g_ds->Release();
- g_ds=0;
- }
-
- static DWORD WINAPI _threadproc(LPVOID p)
- {
- while (!g_wave_quit)
- {
- int wrote_bytes=0;
- void *pt1, *pt2;
- int len;
- unsigned long len2, len1;
- DWORD pp=0;
- if (needstart == -1) IDirectSoundBuffer_GetCurrentPosition(second,&pp,NULL);
- else pp=BUFFER_SIZE;
-
- len = pp-write_pos;
- if (len < 0) len += BUFFER_SIZE;
-
- if (len > 2)
- {
- HRESULT res;
- len&=~1;
- res=second->Lock(write_pos,len, &pt1, &len1, &pt2, &len2, 0);
- if (res == DS_OK)
- {
- len1 &= ~1;
- len2 &= ~1;
-
- generate_samples((short*)pt1,len1/2);
- write_pos+=len1;
- if (pt2)
- {
- generate_samples((short*)pt2,len2/2);
- write_pos+=len2;
- }
- second->Unlock(pt1, len1, pt2, len2);
- }
- else if (res == DSERR_BUFFERLOST)
- {
- second->Restore();
- }
- if (write_pos >= BUFFER_SIZE) write_pos-=BUFFER_SIZE;
- }
-
- if (needstart > -1)
- {
- switch (second->Play(0, 0, DSBPLAY_LOOPING))
- {
- case DS_OK: needstart=-1; break;
- case DSERR_BUFFERLOST: second->Restore(); break;
- }
- }
- Sleep(20);
- }
- return 0;
- }