f05d47b29699548851a000284b0672debf2ad136
[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<<((PicoOpt&8) ? 2 : 1), &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 //  dprintf2("p %p\n", DSoundNext);\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   DSound=0;\r
83   if (DSoundNext) free(DSoundNext); DSoundNext=NULL;\r
84 }\r
85 \r
86 static int WriteSeg()\r
87 {\r
88   void *mema=NULL,*memb=NULL;\r
89   DWORD sizea=0,sizeb=0;\r
90   int ret;\r
91 \r
92   // Lock the segment at 'LoopWrite' and copy the next segment in\r
93   ret = LoopBuffer->Lock(LoopWrite<<((PicoOpt&8) ? 2 : 1),PsndLen<<((PicoOpt&8) ? 2 : 1), &mema,&sizea, &memb,&sizeb, 0);\r
94   if (ret) dprintf2("LoopBuffer->Lock() failed: %i\n", ret);\r
95 \r
96   if (mema) memcpy(mema,DSoundNext,sizea);\r
97 //  if (memb) memcpy(memb,DSoundNext+sizea,sizeb);\r
98   if (sizeb != 0) dprintf2("sizeb is not 0! (%i)\n", sizeb);\r
99 \r
100   ret = LoopBuffer->Unlock(mema,sizea, memb,0);\r
101   if (ret) dprintf2("LoopBuffer->Unlock() failed: %i\n", ret);\r
102 \r
103   return 0;\r
104 }\r
105 \r
106 static int DSoundFake()\r
107 {\r
108   static int ticks_old = 0;\r
109   int ticks = GetTickCount() * 1000;\r
110   int diff;\r
111 \r
112   diff = ticks - ticks_old;\r
113   if (diff >= 0 && diff < 1000000/60)\r
114   {\r
115     while (diff >= 0 && diff < 1000000/60)\r
116     {\r
117       Sleep(1);\r
118       diff = GetTickCount()*1000 - ticks_old;\r
119     }\r
120     ticks_old = ticks + 1000000/60;\r
121   }\r
122   else\r
123     ticks_old = ticks;\r
124   return 0;\r
125 }\r
126 \r
127 int DSoundUpdate()\r
128 {\r
129   DWORD play=0;\r
130   int pos=0;\r
131 \r
132   if (LoopBuffer==NULL) return DSoundFake();\r
133 \r
134   LoopBuffer->GetCurrentPosition(&play,NULL);\r
135   pos=play>>((PicoOpt&8) ? 2 : 1);\r
136 \r
137   // 'LoopWrite' is the next seg in the loop that we want to write\r
138   // First check that the sound 'play' pointer has moved out of it:\r
139   if (pos>=LoopWrite && pos<LoopWrite+PsndLen) return 1; // No, it hasn't\r
140 \r
141   WriteSeg();\r
142 \r
143   // Advance LoopWrite to next seg:\r
144   LoopWrite+=PsndLen; if (LoopWrite+PsndLen>LoopLen) LoopWrite=0;\r
145 \r
146   return 0;\r
147 }\r
148 \r