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