bugfix for SIMPLE_WRITE_SOUND
[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)+64); 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 //  if (memb) memcpy(memb,DSoundNext+sizea,sizeb);\r
94   if (sizeb != 0) dprintf2("sizeb is not 0! (%i)\n", sizeb);\r
95 \r
96   LoopBuffer->Unlock(mema,sizea, memb,0);\r
97 \r
98   return 0;\r
99 }\r
100 \r
101 int DSoundUpdate()\r
102 {\r
103   DWORD play=0;\r
104   int pos=0;\r
105 \r
106   if (LoopBuffer==NULL) return -1;\r
107 \r
108   LoopBuffer->GetCurrentPosition(&play,NULL);\r
109   pos=play>>((PicoOpt&8) ? 2 : 1);\r
110 \r
111   // 'LoopWrite' is the next seg in the loop that we want to write\r
112   // First check that the sound 'play' pointer has moved out of it:\r
113   if (pos>=LoopWrite && pos<LoopWrite+PsndLen) return 1; // No, it hasn't\r
114 \r
115   WriteSeg();\r
116 \r
117   // Advance LoopWrite to next seg:\r
118   LoopWrite+=PsndLen; if (LoopWrite+PsndLen>LoopLen) LoopWrite=0;\r
119 \r
120   return 0;\r
121 }\r
122 \r
123 void DSoundMute()\r
124 {\r
125   if (LoopBuffer==NULL) return;\r
126   LoopBuffer->Stop();\r
127 }\r
128 \r
129 void DSoundUnMute()\r
130 {\r
131   if (LoopBuffer==NULL) return;\r
132   LoopBuffer->Play(0,0,DSBPLAY_LOOPING);\r
133 }\r