source: trunk/src/dsound/OS2PrimBuff.cpp@ 3831

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

Updated and slightly fixed DSOUND

File size: 16.6 KB
Line 
1/*
2 * DirectSound Primary Buffer
3 *
4 * Copyright 1999-2000 Kevin Langman
5 *
6 * Project Odin Software License can be found in LICENSE.TXT
7 *
8 *
9 */
10
11
12/* NOTES:
13
14 Here is how the buffers, GetPosition and Locking works:
15 Dart is allocated many little buffers. These buffers are filled
16 when dart has finished playing one of the buffer, from a 32kb buffer
17 that the Win32 program can write to. The GetPosition function will
18 determine what buffer is being played, and return the offset to the
19 end of this buffer.
20
21 The Lock function will call the GetCurrentPosition function to determine
22 where the end of the currently playing buffer is and allow the Win32
23 program to lock between that location and 15ms from there
24 (15ms should be past the next buffer).
25
26*/
27
28#define INCL_DOSMISC
29#include <os2win.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34#define INITGUID
35#include <dsound.h>
36
37//#include "DSound.h"
38#include "OS2DSound.h"
39#include "OS2SndBuffer.h"
40#include "OS2PrimBuff.h"
41#include "OS23DListener.h"
42
43#include "dart.h"
44
45#undef THIS
46#define THIS VOID*This
47
48#undef THIS_
49#define THIS_ VOID*This,
50
51//******************************************************************************
52//******************************************************************************
53OS2PrimBuff::OS2PrimBuff(OS2IDirectSound *DSound, const DSBUFFERDESC *lpDSBufferDesc )
54{
55 LONG rc;
56
57 lpVtbl = &Vtbl;
58 Vtbl.AddRef = PrimBufAddRef;
59 Vtbl.Release = PrimBufRelease;
60 Vtbl.QueryInterface = PrimBufQueryInterface;
61 Vtbl.GetCaps = PrimBufGetCaps;
62 Vtbl.GetFormat = PrimBufGetFormat;
63 Vtbl.GetVolume = PrimBufGetVolume;
64 Vtbl.GetStatus = PrimBufGetStatus;
65 Vtbl.GetCurrentPosition = PrimBufGetCurrentPosition;
66 Vtbl.GetPan = PrimBufGetPan;
67 Vtbl.GetFrequency = PrimBufGetFrequency;
68 Vtbl.Initialize = PrimBufInitialize;
69 Vtbl.Restore = PrimBufRestore;
70 Vtbl.SetFormat = PrimBufSetFormat;
71 Vtbl.SetVolume = PrimBufSetVolume;
72 Vtbl.SetCurrentPosition = PrimBufSetCurrentPosition;
73 Vtbl.SetPan = PrimBufSetPan;
74 Vtbl.SetFrequency = PrimBufSetFrequency;
75 Vtbl.Lock = PrimBufLock;
76 Vtbl.Unlock = PrimBufUnlock;
77 Vtbl.Stop = PrimBufStop;
78 Vtbl.Play = PrimBufPlay;
79
80 dprintf(("DSOUND-PrimBuff: Constructor"));
81
82 parentDS = DSound;
83 fPlaying = FALSE;
84 playpos = 0;
85 fPrimary = TRUE;
86 Referenced = 0;
87 listener = NULL;
88
89 lpfxFormat = (WAVEFORMATEX *)malloc(/*bufferdesc.lpwfxFormat->cbSize +*/ sizeof(WAVEFORMATEX));
90 lpfxFormat->wBitsPerSample = bps = 16;
91 lpfxFormat->nChannels = channels = 2;
92 lpfxFormat->nSamplesPerSec = rate = 22500;
93
94 bufferdesc.dwBufferBytes = BUFFER_SIZE;
95
96 lastError = Dart_Open_Device(&usDeviceID, &vpMixBuffer, &vpMixSetup,
97 &vpBuffParms, (PVOID*)&lpBuffer );
98
99 if (lastError == DS_OK)
100 primary = this;
101}
102
103//******************************************************************************
104//******************************************************************************
105OS2PrimBuff::~OS2PrimBuff()
106{
107 dprintf(("DSOUND-PrimBuff: Destructor"));
108
109 if (fPlaying)
110 Dart_Stop(usDeviceID);
111
112 lastError = Dart_Close_Device(usDeviceID, vpMixBuffer, vpMixSetup,
113 vpBuffParms );
114
115 dprintf(("DSOUND-PrimBuff: Freeing Memory"));
116 free(lpfxFormat);
117 //free( *vpMixBuffer );
118 //free( *vpMixSetup );
119 //free( *vpBuffParms );
120 //free( vpGenericParms );
121
122 dprintf(("DSOUND-PrimBuff: Destructor Complete"));
123
124 primary = NULL;
125}
126
127//******************************************************************************
128//******************************************************************************
129HRESULT WIN32API PrimBufQueryInterface(THIS, REFIID riid, LPVOID * ppvObj)
130{
131 dprintf(("DSOUND-PrimBuff: QueryInterface"));
132
133 if (This == NULL) {
134 return DSERR_INVALIDPARAM;
135 }
136 *ppvObj = NULL;
137
138 if (IsEqualGUID(riid, IID_IDirectSoundBuffer)) {
139 *ppvObj = This;
140 PrimBufAddRef(This);
141 return DS_OK;
142 }
143
144
145 if (IsEqualGUID(riid, IID_IDirectSound3DListener)) {
146 OS2PrimBuff *me = (OS2PrimBuff *)This;
147 OS2IDirectSound3DListener *listener;
148
149 listener = new OS2IDirectSound3DListener(me);
150 *ppvObj = listener;
151 listener->Vtbl.AddRef((IDirectSound3DListener *)listener);
152 return DS_OK;
153 }
154
155 // I guess a Notify object should be creaed for the Primary Buffer also..
156 // Does windows DSound have a notify object for Primary buffer???
157
158 return E_NOINTERFACE;
159}
160
161//******************************************************************************
162//******************************************************************************
163ULONG WIN32API PrimBufAddRef(THIS)
164{
165 OS2PrimBuff *me = (OS2PrimBuff *)This;
166
167 dprintf(("DSOUND-PrimBuff: AddRef %d", me->Referenced+1));
168
169 if (me == NULL) {
170 return DS_OK;
171 }
172 return ++me->Referenced;
173}
174
175//******************************************************************************
176//******************************************************************************
177ULONG WIN32API PrimBufRelease(THIS)
178{
179 OS2PrimBuff *me = (OS2PrimBuff *)This;
180
181 dprintf(("DSOUND-PrimBuff: Release %d", me->Referenced-1));
182
183 if (me == NULL) {
184 return DS_OK;
185 }
186 if (me->Referenced) {
187 me->Referenced--;
188 if (me->Referenced == 0) {
189 delete me;
190 return DS_OK;
191 }
192 else
193 return me->Referenced;
194 }
195 else
196 return DS_OK;
197}
198
199//******************************************************************************
200//******************************************************************************
201HRESULT __stdcall PrimBufGetCaps(THIS_ LPDSBCAPS lpDSCaps )
202{
203 OS2PrimBuff *me = (OS2PrimBuff *)This;
204
205 dprintf(("DSOUND-PrimBuff: GetCaps"));
206 if(me == NULL || lpDSCaps == NULL)
207 {
208 return DSERR_INVALIDPARAM;
209 }
210
211 lpDSCaps->dwFlags = DSBCAPS_PRIMARYBUFFER;
212 lpDSCaps->dwBufferBytes = BUFFER_SIZE;
213 lpDSCaps->dwUnlockTransferRate = 0;
214 lpDSCaps->dwPlayCpuOverhead = 0;
215
216 return DS_OK;
217}
218
219//******************************************************************************
220//******************************************************************************
221HRESULT __stdcall PrimBufGetCurrentPosition(THIS_ LPDWORD lpdwCurrentPlayCursor,LPDWORD lpdwCurrentWriteCursor )
222{
223 OS2PrimBuff *me = (OS2PrimBuff *)This;
224 LONG lDartPos;
225 LONG lBytesPerSec;
226
227 dprintf(("DSOUND-PrimBuff: GetCurrentPosition"));
228
229 if (me == NULL || lpdwCurrentPlayCursor == NULL || lpdwCurrentWriteCursor == NULL) {
230 return DSERR_INVALIDPARAM;
231 }
232
233 if (me->fPlaying == FALSE) {
234 *lpdwCurrentPlayCursor = 0;
235 *lpdwCurrentWriteCursor = 0;
236 return DS_OK;
237 }
238
239
240 Dart_GetPosition( me->usDeviceID, &lDartPos ); // Returns the Playing Buffer * 'Bytes Per Dart Bufer'
241
242 *lpdwCurrentPlayCursor = lDartPos;
243
244 // Calculate the Write Cursor as 15ms from the current play cursor.
245 // NOTE: This may need to be changed to insure that the write cursor is always beyond the
246 // point where the next buffer will read from.
247 *lpdwCurrentWriteCursor = (lDartPos + (me->rate * me->channels * (me->bps/8) * 15 / 1000) ) % BUFFER_SIZE;
248
249 return DS_OK;
250}
251
252
253//******************************************************************************
254//******************************************************************************
255HRESULT __stdcall PrimBufGetFormat(THIS_ LPWAVEFORMATEX lpfxFormat, DWORD dwSizeAllocated , LPDWORD lpdwSizeWritten )
256{
257 OS2PrimBuff *me = (OS2PrimBuff *)This;
258 long copysize;
259
260 dprintf(("DSOUND-PrimBuff: GetFormat"));
261
262 if( me == NULL || lpfxFormat == NULL || dwSizeAllocated == 0)
263 {
264 return DSERR_INVALIDPARAM;
265 }
266
267 copysize = min(dwSizeAllocated, (me->lpfxFormat->cbSize + sizeof(WAVEFORMATEX)));
268 memcpy(lpfxFormat, me->lpfxFormat, copysize);
269
270 if(lpdwSizeWritten)
271 {
272 *lpdwSizeWritten = copysize;
273 }
274 return DS_OK;
275}
276
277//******************************************************************************
278//******************************************************************************
279HRESULT __stdcall PrimBufGetVolume(THIS_ LPLONG )
280{
281 dprintf(("DSOUND-PrimBuff: GetVolume"));
282
283 return DSERR_INVALIDCALL;
284}
285
286//******************************************************************************
287//******************************************************************************
288HRESULT __stdcall PrimBufGetPan(THIS_ LPLONG )
289{
290 dprintf(("DSOUND-PrimBuff: GetPan"));
291
292 return DSERR_INVALIDCALL;
293}
294
295//******************************************************************************
296//******************************************************************************
297HRESULT __stdcall PrimBufGetFrequency(THIS_ LPDWORD )
298{
299 dprintf(("DSOUND-PrimBuff: GetGrequency"));
300
301 return DSERR_INVALIDCALL;
302}
303
304//******************************************************************************
305//******************************************************************************
306HRESULT __stdcall PrimBufGetStatus(THIS_ LPDWORD lpdwStatus )
307{
308 OS2PrimBuff *me = (OS2PrimBuff *)This;
309 dprintf(("DSOUND-PrimBuff: GetStatus"));
310
311 if (me == NULL || lpdwStatus == NULL) {
312 return(DSERR_INVALIDPARAM);
313 }
314
315 *lpdwStatus = DSBSTATUS_LOOPING /*| DSBSTATUS_LOCSOFTWARE*/;
316 if (me->fPlaying == TRUE)
317 *lpdwStatus |= DSBSTATUS_PLAYING;
318
319 return DS_OK;
320}
321
322//******************************************************************************
323//******************************************************************************
324HRESULT __stdcall PrimBufInitialize(THIS_ LPDIRECTSOUND, LPDSBUFFERDESC )
325{
326 OS2PrimBuff *me = (OS2PrimBuff *)This;
327 dprintf(("DSOUND-PrimBuff: Initialize"));
328
329 if (me == NULL) {
330 return DSERR_INVALIDPARAM;
331 }
332 return DSERR_ALREADYINITIALIZED; //todo: for future extensions (dx5/6 ??) ??
333}
334
335//******************************************************************************
336//******************************************************************************
337HRESULT __stdcall PrimBufLock(THIS_ DWORD dwWriteCursor, DWORD dwWriteBytes,
338 LPVOID lplpAudioPtr1, LPDWORD lpdwAudioBytes1,
339 LPVOID lplpAudioPtr2, LPDWORD lpdwAudioBytes2,
340 DWORD dwFlags)
341{
342 OS2PrimBuff *me = (OS2PrimBuff *)This;
343 DWORD dwCurPlayPos, dwCurWritePos;
344 LONG rc;
345
346 dprintf(("DSOUND-PrimBuff: Lock"));
347
348 if (me == NULL || !lplpAudioPtr1 || !lpdwAudioBytes1) {
349 return DSERR_INVALIDPARAM;
350 }
351 //not sure if this is an error, but it's certainly a smart thing to do (cond. == true)
352 if (dwWriteBytes > BUFFER_SIZE) {
353 dprintf(("SoundBufLock: dwWriteBytes > me->bufferdesc.dwBufferBytes"));
354 return DSERR_INVALIDPARAM;
355 }
356
357 if (me->fPlaying == FALSE) {
358 *(DWORD*)lplpAudioPtr1 = (DWORD)(me->lpBuffer);
359 *lpdwAudioBytes1 = dwWriteBytes;
360 if (lplpAudioPtr2 != NULL) {
361 *(DWORD*)lplpAudioPtr2 = NULL;
362 *lpdwAudioBytes2 = 0;
363 }
364 return DS_OK;
365 }
366
367 rc = PrimBufGetCurrentPosition( me, &dwCurPlayPos, &dwCurWritePos );
368 if (rc != DS_OK) {
369 return DSERR_GENERIC;
370 }
371
372 /* Debugging */
373 dprintf(("DSOUND-PrimBuff: CurPlay = %d, CurWrite = %d", dwCurPlayPos, dwCurWritePos));
374
375 if (dwFlags & DSBLOCK_FROMWRITECURSOR) {
376 dprintf(("DSOUND-PrimBuff: Locking FromCursor"));
377 dwWriteCursor = dwCurWritePos;
378 }
379
380 *(DWORD*)lplpAudioPtr1 = (DWORD)(me->lpBuffer + dwWriteCursor);
381
382 if (dwWriteCursor > dwCurPlayPos) {
383 if (dwWriteCursor + dwWriteBytes > BUFFER_SIZE) {
384 *lpdwAudioBytes1 = BUFFER_SIZE - dwWriteCursor;
385 if (lplpAudioPtr2!=NULL) {
386 *(DWORD*)lplpAudioPtr2 = (DWORD)me->lpBuffer;
387 if (dwWriteBytes - *lpdwAudioBytes1 > dwCurPlayPos) {
388 *lpdwAudioBytes2 = dwCurPlayPos;
389 } else {
390 *lpdwAudioBytes2 = dwWriteBytes - *lpdwAudioBytes1;
391 }
392 }
393 } else {
394 *lpdwAudioBytes1 = dwWriteBytes;
395 if (lplpAudioPtr2!=NULL) {
396 *(DWORD*)lplpAudioPtr2 = NULL;
397 *lpdwAudioBytes2 = 0;
398 }
399 }
400 } else { // The WriteCursor is behind of the PlayCursor
401 if (lplpAudioPtr2!=NULL) {
402 *(DWORD*)lplpAudioPtr2 = NULL;
403 *lpdwAudioBytes2 = 0;
404 }
405 if (dwWriteCursor + dwWriteBytes > dwCurPlayPos) {
406 *lpdwAudioBytes1 = dwWriteCursor - dwCurPlayPos;
407 } else {
408 *lpdwAudioBytes1 = dwWriteBytes;
409 }
410 }
411
412 return DS_OK;
413}
414
415//******************************************************************************
416//******************************************************************************
417HRESULT __stdcall PrimBufPlay(THIS_ DWORD dwRes1,DWORD dwRes2,DWORD dwFlags )
418{
419 long rc;
420 OS2PrimBuff *me = (OS2PrimBuff *)This;
421
422 if (me == NULL || !(dwFlags & DSBPLAY_LOOPING) ) {
423 return DSERR_INVALIDPARAM;
424 }
425
426 if (me->fPlaying)
427 return DS_OK;
428
429 dprintf(("DSOUND-PrimBuff: Play"));
430
431 rc = Dart_Play(me->usDeviceID, me->vpMixSetup, me->vpMixBuffer, me->fPlaying);
432 me->fPlaying = TRUE;
433 return rc;
434}
435
436//******************************************************************************
437//******************************************************************************
438HRESULT __stdcall PrimBufSetCurrentPosition(THIS_ DWORD )
439{
440 dprintf(("DSOUND-PrimBuff: SetCurrentPosition"));
441
442 return DSERR_INVALIDCALL;
443}
444
445//******************************************************************************
446//******************************************************************************
447HRESULT __stdcall PrimBufSetFormat(THIS_ LPWAVEFORMATEX lpfxFormat )
448{
449 dprintf(("DSOUND-PrimBuff: SetFormat"));
450 OS2PrimBuff *me = (OS2PrimBuff *)This;
451
452 if (me == NULL || lpfxFormat == NULL) {
453 return DSERR_INVALIDPARAM;
454 }
455
456 /* Note: the software mixer doesn't really support mono output but */
457 /* we can safely mix in stereo anyway */
458 if (lpfxFormat->nChannels == 1) {
459 if (me->parentDS->GetCoopLevel() != DSSCL_WRITEPRIMARY)
460 lpfxFormat->nChannels = 2;
461 }
462
463 memcpy( me->lpfxFormat, lpfxFormat, sizeof(WAVEFORMATEX) );
464
465 me->bps = lpfxFormat->wBitsPerSample;
466 me->rate = lpfxFormat->nSamplesPerSec;
467 me->channels = lpfxFormat->nChannels;
468
469 dprintf(("DSOUND-PrimBuff: BPS = %d, Rate = %d, Ch = %d", me->bps, me->rate, me->channels));
470
471 Dart_SetFormat(&me->usDeviceID, me->vpMixSetup, me->vpBuffParms, &me->vpMixBuffer, me->bps, me->rate, me->channels);
472
473 return DS_OK;
474}
475
476//******************************************************************************
477//******************************************************************************
478HRESULT __stdcall PrimBufSetVolume(THIS_ LONG )
479{
480 dprintf(("DSOUND-PrimBuff: SetVolume"));
481
482 return DSERR_CONTROLUNAVAIL;
483}
484
485//******************************************************************************
486//******************************************************************************
487HRESULT __stdcall PrimBufSetPan(THIS_ LONG )
488{
489 dprintf(("DSOUND-PrimBuff: SetPan"));
490
491 return DSERR_CONTROLUNAVAIL;
492}
493
494//******************************************************************************
495//******************************************************************************
496HRESULT __stdcall PrimBufSetFrequency(THIS_ DWORD )
497{
498 dprintf(("DSOUND-PrimBuff: SetFrequency"));
499
500 return DSERR_CONTROLUNAVAIL;
501}
502
503//******************************************************************************
504//******************************************************************************
505HRESULT __stdcall PrimBufStop(THIS )
506{
507 OS2PrimBuff *me = (OS2PrimBuff *)This;
508 dprintf(("DSOUND-PrimBuff: Stop"));
509
510 if (me == NULL) {
511 return DSERR_INVALIDPARAM;
512 }
513
514 if (!me->fPlaying)
515 return DS_OK;
516
517 me->fPlaying = FALSE;
518
519 return Dart_Stop(me->usDeviceID);
520}
521
522//******************************************************************************
523//******************************************************************************
524HRESULT __stdcall PrimBufUnlock(THIS_ LPVOID,DWORD,LPVOID,DWORD )
525{
526 // I don't think we really need any code here..
527
528 dprintf(("DSOUND-PrimBuff: Unlock"));
529
530 return DS_OK;
531}
532
533//******************************************************************************
534//******************************************************************************
535HRESULT __stdcall PrimBufRestore(THIS )
536{
537 // This maybe a good place to re-aquire the device if some other process
538 // has taken the audio focus, but before we do that we need to determine
539 // if we have lost the device and set the falg in the GetStatus method!
540
541 dprintf(("DSOUND-PrimBuff: Restore"));
542
543 return DS_OK;
544}
545
546
Note: See TracBrowser for help on using the repository browser.