5c9cc0c1b26910b587aab82a1a9dec7c7f12f70b
[picodrive.git] / platform / win32 / GenaDrive / DSound.cpp
1 \r
2 #include "app.h"\r
3 \r
4 #ifndef _XBOX\r
5 #pragma warning (disable:4201)\r
6 #include <mmsystem.h>\r
7 #include <dsound.h>\r
8 #endif\r
9 \r
10 static IDirectSound *DSound=NULL;\r
11 static IDirectSoundBuffer *LoopBuffer=NULL;\r
12 static int LoopLen=0,LoopWrite=0; // Next position in loop to write\r
13 \r
14 short *DSoundNext=NULL; // Buffer for next sound data to put in loop\r
15 \r
16 static int LoopBlank()\r
17 {\r
18   void *mema=NULL,*memb=NULL;\r
19   DWORD sizea=0,sizeb=0;\r
20 \r
21   LoopBuffer->Lock(0,LoopLen<<2, &mema,&sizea, &memb,&sizeb, 0);\r
22   \r
23   if (mema) memset(mema,0,sizea);\r
24 \r
25   LoopBuffer->Unlock(mema,sizea, memb,sizeb);\r
26 \r
27   return 0;\r
28 }\r
29 \r
30 int DSoundInit()\r
31 {\r
32   DSBUFFERDESC dsbd;\r
33   WAVEFORMATEX wfx;\r
34 \r
35   memset(&dsbd,0,sizeof(dsbd));\r
36   memset(&wfx,0,sizeof(wfx));\r
37 \r
38   // Make wave format:\r
39   wfx.wFormatTag=WAVE_FORMAT_PCM;\r
40   wfx.nChannels=(unsigned short)((PicoOpt&8) ? 2 : 1); // Stereo/mono\r
41   wfx.nSamplesPerSec=PsndRate;\r
42   wfx.wBitsPerSample=16;\r
43 \r
44   wfx.nBlockAlign=(WORD)((wfx.nChannels*wfx.wBitsPerSample)>>3);\r
45   wfx.nAvgBytesPerSec=wfx.nBlockAlign*wfx.nSamplesPerSec;\r
46 \r
47   // Make buffer for the next seg to put into the loop:\r
48   DSoundNext=(short *)malloc(PsndLen<<2); if (DSoundNext==NULL) return 1;\r
49   memset(DSoundNext,0,PsndLen<<2);\r
50 \r
51   // Create the DirectSound interface:\r
52   DirectSoundCreate(NULL,&DSound,NULL);\r
53   if (DSound==NULL) return 1;\r
54 \r
55   LoopLen=PsndLen<<1; // 2 segs\r
56 \r
57 #ifndef _XBOX\r
58   LoopLen<<=1; // 4 segs\r
59   DSound->SetCooperativeLevel(FrameWnd,DSSCL_PRIORITY);\r
60   dsbd.dwFlags=DSBCAPS_GLOBALFOCUS;  // Play in background\r
61 #endif\r
62 \r
63   // Create the looping buffer:\r
64   dsbd.dwSize=sizeof(dsbd);\r
65   dsbd.dwBufferBytes=LoopLen<<wfx.nChannels; // 16bit stereo?\r
66   dsbd.lpwfxFormat=&wfx;\r
67 \r
68   DSound->CreateSoundBuffer(&dsbd,&LoopBuffer,NULL);\r
69   if (LoopBuffer==NULL) return 1;\r
70 \r
71   LoopBlank();\r
72   LoopBuffer->Play(0,0,DSBPLAY_LOOPING);\r
73   return 0;\r
74 }\r
75 \r
76 void DSoundExit()\r
77 {\r
78   if (LoopBuffer) LoopBuffer->Stop();\r
79   RELEASE(LoopBuffer)\r
80   RELEASE(DSound)\r
81   free(DSoundNext); DSoundNext=NULL;\r
82 }\r
83 \r
84 static int WriteSeg()\r
85 {\r
86   void *mema=NULL,*memb=NULL;\r
87   DWORD sizea=0,sizeb=0;\r
88 \r
89   // Lock the segment at 'LoopWrite' and copy the next segment in\r
90   LoopBuffer->Lock(LoopWrite<<((PicoOpt&8) ? 2 : 1),PsndLen<<((PicoOpt&8) ? 2 : 1), &mema,&sizea, &memb,&sizeb, 0);\r
91   \r
92   if (mema) memcpy(mema,DSoundNext,sizea);\r
93 \r
94   LoopBuffer->Unlock(mema,sizea, memb,0);\r
95 \r
96   return 0;\r
97 }\r
98 \r
99 int DSoundUpdate()\r
100 {\r
101   DWORD play=0;\r
102   int pos=0;\r
103 \r
104   if (LoopBuffer==NULL) return -1;\r
105 \r
106   LoopBuffer->GetCurrentPosition(&play,NULL);\r
107   pos=play>>((PicoOpt&8) ? 2 : 1);\r
108 \r
109   // 'LoopWrite' is the next seg in the loop that we want to write\r
110   // First check that the sound 'play' pointer has moved out of it:\r
111   if (pos>=LoopWrite && pos<LoopWrite+PsndLen) return 1; // No, it hasn't\r
112 \r
113   WriteSeg();\r
114 \r
115   // Advance LoopWrite to next seg:\r
116   LoopWrite+=PsndLen; if (LoopWrite+PsndLen>LoopLen) LoopWrite=0;\r
117 \r
118   return 0;\r
119 }\r
120 \r
121 void DSoundMute()\r
122 {\r
123   if (LoopBuffer==NULL) return;\r
124   LoopBuffer->Stop();\r
125 }\r
126 \r
127 void DSoundUnMute()\r
128 {\r
129   if (LoopBuffer==NULL) return;\r
130   LoopBuffer->Play(0,0,DSBPLAY_LOOPING);\r
131 }\r