source: trunk/src/dsound/new/dart.cpp@ 3035

Last change on this file since 3035 was 3035, checked in by mike, 25 years ago

Fixed sound latency

File size: 12.2 KB
Line 
1/*
2 * Kevin Langman
3 *
4 * The Dart functions are here to avoid the conficts with the
5 * the OS/2 mcios2.h, meerror.h, os2medef.h and mmsystem.h
6 *
7 */
8
9#define INCL_DOS
10#define INCL_OS2MM
11#include <os2wrap.h>
12#include <os2mewrap.h>
13
14#include <stdlib.h>
15#include <string.h>
16
17#define DART_DSOUND
18#include "dart.h"
19#include "dsmixer.h"
20
21#include <misc.h>
22
23static MCI_MIXSETUP_PARMS *MixSetup_Global;
24static MCI_MIX_BUFFER *pMixBuffs;
25static long lLastBuff;
26static char *pDSoundBuff;
27
28USHORT usDeviceID; /* Amp Mixer device id */
29MCI_MIX_BUFFER MixBuffers[NUM_DART_BUFFS]; /* Device buffers */
30MCI_MIXSETUP_PARMS MixSetupParms; /* Mixer parameters */
31MCI_BUFFER_PARMS BufferParms; /* Device buffer parms */
32
33
34#define ULONG_LOWD(ul) (*(USHORT *)((ULONG *)(&ul))) /* Low Word */
35
36//******************************************************************************
37//******************************************************************************
38LONG APIENTRY OS2_Dart_Update(ULONG ulStatus,PMCI_MIX_BUFFER pBuffer,ULONG ulFlags)
39{
40 //MCI_STATUS_PARMS Status;
41 ULONG rc;
42
43 if ((ulFlags == MIX_WRITE_COMPLETE) ||
44 ((ulFlags == (MIX_WRITE_COMPLETE | MIX_STREAM_ERROR))&&
45 (ulStatus == ERROR_DEVICE_UNDERRUN)))
46 {
47 lLastBuff++;
48 if (lLastBuff == NUM_DART_BUFFS)
49 lLastBuff = 0;
50
51 /* Now mix sound from all playing secondary SoundBuffers into the primary buffer */
52 MixCallback(BUFFER_SIZE/NUM_DART_BUFFS);
53
54 /* Fill The next buff from the DSound Buffer */
55 memcpy( pMixBuffs[lLastBuff].pBuffer, &pDSoundBuff[lLastBuff*(BUFFER_SIZE/NUM_DART_BUFFS)], BUFFER_SIZE/NUM_DART_BUFFS );
56
57 /* Send the NEXT Buffer to Dart for playing! */
58 rc = MixSetup_Global->pmixWrite(MixSetup_Global->ulMixHandle, &pMixBuffs[lLastBuff], 1 );
59 //dprintf(("DSOUND-DART: Playing Next Buffer %d", rc));
60 }
61
62 return TRUE;
63}
64
65
66long Dart_Open_Device(USHORT *pusDeviceID, void **vpMixBuffer, void **vpMixSetup,
67 void **vpBuffParms, void **ppvBuffer)
68{
69
70 MCI_AMP_OPEN_PARMS AmpOpenParms;
71 //MCI_WAVE_SET_PARMS WaveSetParms;
72 ULONG rc;
73 short device = 0;
74
75 dprintf(("DSOUND-DART: Dart_Open_Device"));
76
77 *vpMixBuffer = &MixBuffers;
78 *vpMixSetup = &MixSetupParms;
79 *vpBuffParms = &BufferParms;
80
81 pMixBuffs = &MixBuffers[0];
82 lLastBuff = 0;
83
84 /* Is there a way to avoid the use of the MixSetup_Global ????? */
85 MixSetup_Global = &MixSetupParms;
86 /****************************************************************/
87
88 // If the DSOUND_DEVICE is set then use that number as the device for DART.
89 // this will allow people with many sound cards to use the card of their choice
90 // for an instance of a DSOUND enabled app!
91 if (getenv("DSOUND_DEVICE") != NULL) {
92 device = atoi(getenv("DSOUND_DEVICE"));
93 }
94
95 /* Open the AmpMix Device and start processing the buffer! */
96 memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
97 AmpOpenParms.usDeviceID = 0;
98 AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
99
100 rc = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE_ID, (PVOID)&AmpOpenParms, 0);
101 if (rc != MCIERR_SUCCESS) {
102 dprintf(("DSOUND-DART: MCI_OPEN %d", rc));
103 return DSERR_GENERIC;
104 }
105 *pusDeviceID = AmpOpenParms.usDeviceID;
106 usDeviceID = AmpOpenParms.usDeviceID;
107
108 /* setup playback parameters */
109 memset(&MixSetupParms, 0, sizeof(MCI_MIXSETUP_PARMS));
110 MixSetupParms.ulBitsPerSample = 16;
111 MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
112 MixSetupParms.ulSamplesPerSec = 22500;
113 MixSetupParms.ulChannels = 2;
114 MixSetupParms.ulFormatMode = MCI_PLAY;
115 MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
116 MixSetupParms.pmixEvent = OS2_Dart_Update;
117
118 rc = mciSendCommand(usDeviceID, MCI_MIXSETUP, MCI_WAIT | MCI_MIXSETUP_INIT,
119 (PVOID)&MixSetupParms, 0);
120 if (rc != MCIERR_SUCCESS) {
121 dprintf(("DSOUND-DART: MCI_MIXSETUP (Constructor) %d", rc));
122 return DSERR_GENERIC;
123 }
124
125 /* Create the Audio Buffer */
126 // OK... Since DSound only uses 1 buffer and uses the GetPosition API to
127 // figure out where it can and can't write, I have emulating this by
128 // using 16 1kb buffers and do locking by tracking what buffer is currently
129 // playing. This maybe less CPU friendly then other methods but it's the best
130 // my little brain could come up with!!
131
132 MixSetupParms.ulBufferSize = BUFFER_SIZE/NUM_DART_BUFFS;
133
134// BufferParms->ulStructLength = sizeof(MCI_BUFFER_PARMS);
135 BufferParms.ulNumBuffers = NUM_DART_BUFFS;
136 BufferParms.ulBufferSize = MixSetupParms.ulBufferSize;
137 BufferParms.pBufList = MixBuffers;
138
139 rc = mciSendCommand(usDeviceID, MCI_BUFFER, MCI_WAIT | MCI_ALLOCATE_MEMORY,
140 (PVOID)&BufferParms, 0);
141 if ( ULONG_LOWD(rc) != MCIERR_SUCCESS ) {
142 dprintf(("DSOUND-DART: MCI_BUFFER (Alloc) %d", rc));
143 mciSendCommand(*pusDeviceID, MCI_CLOSE, MCI_WAIT, NULL, 0);
144 return DSERR_OUTOFMEMORY;
145 }
146
147 /* Clear the Buffer */
148 // Todo: I don't know if Dart expects Signed or Unsigned data... This will
149 // ok until I look in to this... Also it may be that Dart uses signed for
150 // 8bit data and unsigned for 16it.. Anyhow the worst that can happen by setting
151 // the buffer to 0 is a click on Dart_Play and a Clink when real sound is written
152 // to the buffer!
153 for (device = 0; device < NUM_DART_BUFFS; device++) {
154 memset(MixBuffers[device].pBuffer, 0, BUFFER_SIZE/NUM_DART_BUFFS);
155 }
156
157 // Allocate memory for the DSound "Holder" buffer.
158 // TODO: Move this to the Constructor for OS2PrimBuff
159 // so that the Deconstructor can be used to free the memory!
160 *(char**)ppvBuffer = (char*)malloc(BUFFER_SIZE);
161 if (*ppvBuffer == NULL) {
162 return DSERR_OUTOFMEMORY;
163 }
164 pDSoundBuff = (char*)(*ppvBuffer);
165
166 dprintf(("DSOUND-DART: Dart_Open_Device Exiting"));
167
168 return DS_OK;
169}
170
171long Dart_Close_Device(USHORT usDeviceID, void *vpMixBuffer, void *vpMixSetup,
172 void *vpBuffParms )
173{
174 MCI_MIX_BUFFER *MixBuffer;
175 MCI_MIXSETUP_PARMS *MixSetup;
176 MCI_BUFFER_PARMS *BufferParms;
177
178 dprintf(("DSOUND-DART: Dart_Close_Device"));
179
180 MixBuffer = (MCI_MIX_BUFFER*)vpMixBuffer;
181 MixSetup = (MCI_MIXSETUP_PARMS*)vpMixSetup;
182 BufferParms = (MCI_BUFFER_PARMS*)vpBuffParms;
183
184 if (MixBuffer->pBuffer) {
185 mciSendCommand(usDeviceID,MCI_BUFFER,MCI_WAIT|MCI_DEALLOCATE_MEMORY, BufferParms,0);
186 MixBuffer->pBuffer=NULL;
187 }
188 if (usDeviceID) {
189 mciSendCommand(usDeviceID,MCI_CLOSE,MCI_WAIT, NULL, 0);
190 usDeviceID=0;
191 }
192
193 dprintf(("DSOUND-DART: Dart_Close_Device returning DS_OK"));
194 return DS_OK;
195}
196
197
198long Dart_GetPosition(USHORT usDeviceID, LONG *pulPosition)
199{
200 dprintf(("DSOUND-DART: Dart_GetPosition"));
201
202 *pulPosition = (lLastBuff * (BUFFER_SIZE/NUM_DART_BUFFS)) + (BUFFER_SIZE/NUM_DART_BUFFS);
203 if (*pulPosition > BUFFER_SIZE)
204 *pulPosition = 0;
205
206 dprintf(("DSOUND-DART: Returning %d", *pulPosition));
207
208 return DS_OK;
209}
210
211long Dart_SetFormat(USHORT *pusDeviceID, void *vpMixSetup, void *vpBufferParms, void *vpMixBuffer, LONG lBPS, LONG lSPS, LONG lChannels )
212{
213 ULONG rc;
214 MCI_MIXSETUP_PARMS *MixSetup;
215 MCI_BUFFER_PARMS *BufferParms;
216 MCI_MIX_BUFFER *MixBuffer;
217 MCI_AMP_OPEN_PARMS AmpOpenParms;
218 short device = 0;
219
220 MixSetup = (MCI_MIXSETUP_PARMS*)vpMixSetup;
221 BufferParms = (MCI_BUFFER_PARMS*)vpBufferParms;
222 MixBuffer = (MCI_MIX_BUFFER*)vpMixBuffer;
223
224 dprintf(("DSOUND-DART: Dart_SetFormat"));
225
226 // If the DSOUND_DEVICE is set then use that number as the device for DART.
227 // this will allow people with many sound cards to use the card of there choice
228 // for an instance of a DSOUND enabled app!
229 if (getenv("DSOUND_DEVICE") != NULL) {
230 device = atoi(getenv( "DSOUND_DEVICE" ));
231 }
232
233 /* Dealloc to avoid the 5511 error */
234 rc = mciSendCommand(*pusDeviceID, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY,
235 BufferParms, 0);
236 if (rc != MCIERR_SUCCESS) {
237 dprintf(("DSOUND-DART: MCI_DEALLOCATE_MEMORY (SetFormat) %d", rc));
238 return DSERR_GENERIC;
239 }
240
241 rc = mciSendCommand(*pusDeviceID, MCI_CLOSE, MCI_WAIT, NULL, 0);
242 if (rc != MCIERR_SUCCESS) {
243 dprintf(("DSOUND-DART: MCI_CLOSE (SetFormat) %d", rc));
244 return(DSERR_GENERIC);
245 }
246
247 /* Reopen the MixAmp Device and start processing the buffer! */
248 memset(&AmpOpenParms,0,sizeof(MCI_AMP_OPEN_PARMS));
249 AmpOpenParms.usDeviceID = 0;
250 AmpOpenParms.pszDeviceType = (PSZ)MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, (USHORT)device);
251
252 rc = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE_ID, (PVOID)&AmpOpenParms, 0);
253 if (rc != MCIERR_SUCCESS) {
254 dprintf(("DSOUND-DART: MCI_OPEN %d", rc));
255 return DSERR_GENERIC;
256 }
257 *pusDeviceID = AmpOpenParms.usDeviceID;
258
259 /* setup playback parameters */
260 memset(MixSetup, 0, sizeof(MCI_MIXSETUP_PARMS));
261 MixSetup->ulBitsPerSample = lBPS;
262 MixSetup->ulFormatTag = MCI_WAVE_FORMAT_PCM;
263 MixSetup->ulSamplesPerSec = lSPS;
264 MixSetup->ulChannels = lChannels;
265 MixSetup->ulFormatMode = MCI_PLAY;
266 MixSetup->ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
267 MixSetup->pmixEvent = OS2_Dart_Update;
268
269 rc = mciSendCommand(*pusDeviceID, MCI_MIXSETUP, MCI_WAIT | MCI_MIXSETUP_INIT,
270 (PVOID)MixSetup, 0);
271 if (rc != MCIERR_SUCCESS) {
272 dprintf(("DSOUND-DART: MCI_MIXSETUP (SetFormat) %d", rc));
273 return DSERR_GENERIC;
274 }
275
276 memset(BufferParms, 0, sizeof(MCI_BUFFER_PARMS));
277 memset(MixBuffer, 0, sizeof(MCI_MIX_BUFFER) * NUM_DART_BUFFS);
278 BufferParms->ulStructLength = sizeof(MCI_BUFFER_PARMS);
279 BufferParms->ulNumBuffers = NUM_DART_BUFFS;
280 BufferParms->ulBufferSize = BUFFER_SIZE/NUM_DART_BUFFS;
281 BufferParms->pBufList = MixBuffer;
282 MixBuffer->pBuffer = NULL;
283
284 rc = mciSendCommand(*pusDeviceID, MCI_BUFFER, MCI_WAIT | MCI_ALLOCATE_MEMORY,
285 (PVOID)BufferParms, 0);
286 if (rc != MCIERR_SUCCESS) {
287 dprintf(("DSOUND-DART: MCI_BUFFER_ALLOCATE_MEMORY (SetFormat) %d", rc));
288 mciSendCommand(*pusDeviceID, MCI_CLOSE, MCI_WAIT, NULL, 0);
289 memset(MixBuffer, 0, sizeof(MCI_MIX_BUFFER) * NUM_DART_BUFFS);
290 return DSERR_OUTOFMEMORY;
291 }
292
293 /* Clear the Buffer */
294 // Todo: I don't know if Dart expects Signed or Unsigned data... This will
295 // ok until I look in to this... Also it may be that Dart uses signed for
296 // 8bit data and unsigned for 16it.. Anyhow the worst that can happen by setting
297 // the buffer to 0 is a click on Dart_Play and a Clink when real sound is written
298 // to the buffer!
299 for (int i=0; i<NUM_DART_BUFFS; i++) {
300 memset(MixBuffer[i].pBuffer, 0, BUFFER_SIZE/NUM_DART_BUFFS);
301 }
302
303 return DS_OK;
304}
305
306
307long Dart_Stop(USHORT usDeviceID)
308{
309 ULONG rc;
310
311 dprintf(("DSOUND-DART: Dart_Stop"));
312
313// rc = mciSendCommand(usDeviceID, MCI_PAUSE, MCI_WAIT, NULL, 0);
314 rc = mciSendCommand(usDeviceID, MCI_STOP, MCI_WAIT, NULL, 0);
315 if (rc != MCIERR_SUCCESS) {
316 dprintf(("DSOUND-DART: MCI_PAUSE %d", rc));
317 return DSERR_GENERIC;
318 }
319 return DS_OK;
320}
321
322long Dart_Play(USHORT usDeviceID, void *vpMixSetup, void *vpMixBuffer, long playing)
323{
324 ULONG rc;
325 MCI_MIXSETUP_PARMS *MixSetup;
326 MCI_MIX_BUFFER *MixBuffer;
327
328 MixSetup = (MCI_MIXSETUP_PARMS*)vpMixSetup;
329 MixBuffer = (MCI_MIX_BUFFER*)vpMixBuffer;
330
331 dprintf(("DSOUND-DART: Dart_Play"));
332
333 if (playing == TRUE) {
334 rc = mciSendCommand(usDeviceID, MCI_RESUME, MCI_WAIT, NULL, 0);
335 if (rc != MCIERR_SUCCESS) {
336 dprintf(("DSOUND-DART: MCI_RESUME %d", rc));
337 return DSERR_GENERIC;
338 }
339 } else { //if (playing==FALSE)
340 dprintf(("DSOUND-DART: Playback started!!!!"));
341
342 /* Mix the first buffer before playing */
343 MixCallback(BUFFER_SIZE/NUM_DART_BUFFS);
344 memcpy(pMixBuffs[lLastBuff].pBuffer, &pDSoundBuff[lLastBuff*(BUFFER_SIZE/NUM_DART_BUFFS)], BUFFER_SIZE/NUM_DART_BUFFS);
345
346 USHORT sel = RestoreOS2FS();
347 /* Note: the call to pmixWrite trashes the FS selector, we have to save */
348 /* and then restore FS!!! Otherwise exception handling will be broken. */
349 MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle, MixBuffers, 2);
350 SetFS(sel);
351 }
352
353 return DS_OK;
354}
Note: See TracBrowser for help on using the repository browser.