comparison libao2/ao_dsound.c @ 13640:a7d080bc610f

ao dsound improvements patch by Florian Dietrich <flodt8 at yahoo.de>
author faust3
date Thu, 14 Oct 2004 13:03:03 +0000
parents 70d8f1975fc8
children b7322244e53c
comparison
equal deleted inserted replaced
13639:12028d59e650 13640:a7d080bc610f
23 23
24 24
25 #include <stdio.h> 25 #include <stdio.h>
26 #include <stdlib.h> 26 #include <stdlib.h>
27 #include <windows.h> 27 #include <windows.h>
28 #include <mmsystem.h> 28 #define DIRECTSOUND_VERSION 0x0600
29 #include <dsound.h> 29 #include <dsound.h>
30 30
31 #include "afmt.h" 31 #include "afmt.h"
32 #include "audio_out.h" 32 #include "audio_out.h"
33 #include "audio_out_internal.h" 33 #include "audio_out_internal.h"
106 SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY 106 SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY
107 }; 107 };
108 108
109 static HINSTANCE hdsound_dll = NULL; ///handle to the dll 109 static HINSTANCE hdsound_dll = NULL; ///handle to the dll
110 static LPDIRECTSOUND hds = NULL; ///direct sound object 110 static LPDIRECTSOUND hds = NULL; ///direct sound object
111 static LPDIRECTSOUNDBUFFER hdsbuf = NULL; ///direct sound buffer 111 static LPDIRECTSOUNDBUFFER hdspribuf = NULL; ///primary direct sound buffer
112 static LPDIRECTSOUNDBUFFER hdsbuf = NULL; ///secondary direct sound buffer (stream buffer)
112 static int buffer_size = 0; ///size in bytes of the direct sound buffer 113 static int buffer_size = 0; ///size in bytes of the direct sound buffer
113 static int write_offset = 0; ///offset of the write cursor in the direct sound buffer 114 static int write_offset = 0; ///offset of the write cursor in the direct sound buffer
114 static int min_free_space = 4096; ///if the free space is below this value get_space() will return 0 115 static int min_free_space = 4096; ///if the free space is below this value get_space() will return 0
115
116 #define BUFFERSIZE 32767 /// in samples - at 48khz 0.6 sec buffer, gets multiplied with nBlockAlign
117 116
118 /***************************************************************************************/ 117 /***************************************************************************************/
119 118
120 /** 119 /**
121 \brief output error message 120 \brief output error message
232 { 231 {
233 if (hdsbuf) { 232 if (hdsbuf) {
234 IDirectSoundBuffer_Release(hdsbuf); 233 IDirectSoundBuffer_Release(hdsbuf);
235 hdsbuf = NULL; 234 hdsbuf = NULL;
236 } 235 }
236 if (hdspribuf) {
237 IDirectSoundBuffer_Release(hdspribuf);
238 hdspribuf = NULL;
239 }
237 } 240 }
238 241
239 /** 242 /**
240 \brief fill sound buffer 243 \brief fill sound buffer
241 \param data pointer to the sound data to copy 244 \param data pointer to the sound data to copy
247 HRESULT res; 250 HRESULT res;
248 LPVOID lpvPtr1; 251 LPVOID lpvPtr1;
249 DWORD dwBytes1; 252 DWORD dwBytes1;
250 LPVOID lpvPtr2; 253 LPVOID lpvPtr2;
251 DWORD dwBytes2; 254 DWORD dwBytes2;
255
256 DWORD play_offset;
257 int space;
258
259 // make sure we have enough space to write data
260 IDirectSoundBuffer_GetCurrentPosition(hdsbuf,&play_offset,NULL);
261 space=buffer_size-(write_offset-play_offset);
262 if(space > buffer_size)space -= buffer_size; // write_offset < play_offset
263 if(space < len) len = space;
252 264
253 // Lock the buffer 265 // Lock the buffer
254 res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0); 266 res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
255 // If the buffer was lost, restore and retry lock. 267 // If the buffer was lost, restore and retry lock.
256 if (DSERR_BUFFERLOST == res) 268 if (DSERR_BUFFERLOST == res)
264 { 276 {
265 // Write to pointers. 277 // Write to pointers.
266 memcpy(lpvPtr1,data,dwBytes1); 278 memcpy(lpvPtr1,data,dwBytes1);
267 if (NULL != lpvPtr2 )memcpy(lpvPtr2,data+dwBytes1,dwBytes2); 279 if (NULL != lpvPtr2 )memcpy(lpvPtr2,data+dwBytes1,dwBytes2);
268 write_offset+=dwBytes1+dwBytes2; 280 write_offset+=dwBytes1+dwBytes2;
269 if(write_offset>=buffer_size)write_offset-=buffer_size; 281 if(write_offset>=buffer_size)write_offset=dwBytes2;
270 282
271 // Release the data back to DirectSound. 283 // Release the data back to DirectSound.
272 res = IDirectSoundBuffer_Unlock(hdsbuf,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2); 284 res = IDirectSoundBuffer_Unlock(hdsbuf,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2);
273 if (SUCCEEDED(res)) 285 if (SUCCEEDED(res))
274 { 286 {
326 static int init(int rate, int channels, int format, int flags) 338 static int init(int rate, int channels, int format, int flags)
327 { 339 {
328 int res; 340 int res;
329 if (!InitDirectSound()) return 0; 341 if (!InitDirectSound()) return 0;
330 342
331 // ok, now create the primary buffer 343 // ok, now create the buffers
332 WAVEFORMATEXTENSIBLE wformat; 344 WAVEFORMATEXTENSIBLE wformat;
345 DSBUFFERDESC dsbpridesc;
333 DSBUFFERDESC dsbdesc; 346 DSBUFFERDESC dsbdesc;
334 347
335 //fill global ao_data 348 //fill global ao_data
336 ao_data.channels = channels; 349 ao_data.channels = channels;
337 ao_data.samplerate = rate; 350 ao_data.samplerate = rate;
338 ao_data.format = format; 351 ao_data.format = format;
339 ao_data.bps = channels * rate * (audio_out_format_bits(format)>>3); 352 ao_data.bps = channels * rate * (audio_out_format_bits(format)>>3);
340 if(ao_data.buffersize==-1) 353 if(ao_data.buffersize==-1) ao_data.buffersize = ao_data.bps; // space for 1 sec
341 {
342 ao_data.buffersize = audio_out_format_bits(format) >> 3;
343 ao_data.buffersize *= channels;
344 ao_data.buffersize *= BUFFERSIZE;
345 }
346 mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Samplerate:%iHz Channels:%i Format:%s\n", rate, channels, audio_out_format_name(format)); 354 mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Samplerate:%iHz Channels:%i Format:%s\n", rate, channels, audio_out_format_name(format));
347 mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Buffersize:%d bytes (%d msec)\n", ao_data.buffersize, BUFFERSIZE * 1000 / rate); 355 mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Buffersize:%d bytes (%d msec)\n", ao_data.buffersize, ao_data.buffersize / ao_data.bps * 1000);
348 356
349 //fill waveformatex 357 //fill waveformatex
350 ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE)); 358 ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE));
351 wformat.Format.cbSize = (channels > 2) ? sizeof(WAVEFORMATEXTENSIBLE) : 0; 359 wformat.Format.cbSize = (channels > 2) ? sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) : 0;
352 wformat.Format.nChannels = channels; 360 wformat.Format.nChannels = channels;
353 wformat.Format.nSamplesPerSec = rate; 361 wformat.Format.nSamplesPerSec = rate;
354 if (format == AFMT_AC3) { 362 if (format == AFMT_AC3) {
355 wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; 363 wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
356 wformat.Format.wBitsPerSample = 16; 364 wformat.Format.wBitsPerSample = 16;
359 wformat.Format.wFormatTag = (channels > 2) ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM; 367 wformat.Format.wFormatTag = (channels > 2) ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM;
360 wformat.Format.wBitsPerSample = audio_out_format_bits(format); 368 wformat.Format.wBitsPerSample = audio_out_format_bits(format);
361 wformat.Format.nBlockAlign = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3); 369 wformat.Format.nBlockAlign = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3);
362 } 370 }
363 371
364 // fill in the direct sound buffer descriptor 372 // fill in primary sound buffer descriptor
373 memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC));
374 dsbpridesc.dwSize = sizeof(DSBUFFERDESC);
375 dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
376 dsbpridesc.dwBufferBytes = 0;
377 dsbpridesc.lpwfxFormat = NULL;
378
379
380 // fill in the secondary sound buffer (=stream buffer) descriptor
365 memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); 381 memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
366 dsbdesc.dwSize = sizeof(DSBUFFERDESC); 382 dsbdesc.dwSize = sizeof(DSBUFFERDESC);
367 dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */ 383 dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */
368 | DSBCAPS_GLOBALFOCUS /** Allows background playing */ 384 | DSBCAPS_GLOBALFOCUS /** Allows background playing */
369 | DSBCAPS_CTRLVOLUME; /** volume control enabled */ 385 | DSBCAPS_CTRLVOLUME; /** volume control enabled */
370 386
371 if (channels > 2) { 387 if (channels > 2) {
372 wformat.dwChannelMask = channel_mask[channels - 3]; 388 wformat.dwChannelMask = channel_mask[channels - 3];
373 wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 389 wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
374 wformat.Samples.wValidBitsPerSample = audio_out_format_bits(format); 390 wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample;
375 // Needed for 5.1 on emu101k - shit soundblaster 391 // Needed for 5.1 on emu101k - shit soundblaster
376 dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE; 392 dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE;
377 } 393 }
378 wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign; 394 wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign;
379 395
380 dsbdesc.dwBufferBytes = wformat.Format.nBlockAlign * BUFFERSIZE; 396 dsbdesc.dwBufferBytes = ao_data.buffersize;
381 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat; 397 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat;
382 buffer_size = dsbdesc.dwBufferBytes; 398 buffer_size = dsbdesc.dwBufferBytes;
383 ao_data.outburst = wformat.Format.nBlockAlign * 512; 399 ao_data.outburst = wformat.Format.nBlockAlign * 512;
384 400
385 // now create the sound buffer 401 // create primary buffer and set its format
402
403 res = IDirectSound_CreateSoundBuffer( hds, &dsbpridesc, &hdspribuf, NULL );
404 if ( res != DS_OK ) {
405 UninitDirectSound();
406 mp_msg(MSGT_AO, MSGL_ERR,"ao_dsound: cannot create primary buffer (%s)\n", dserr2str(res));
407 return 0;
408 }
409 res = IDirectSoundBuffer_SetFormat( hdspribuf, (WAVEFORMATEX *)&wformat );
410 if ( res != DS_OK ) mp_msg(MSGT_AO, MSGL_WARN,"ao_dsound: cannot set primary buffer format (%s), using standard setting (bad quality)", dserr2str(res));
411
412 // now create the stream buffer
386 413
387 res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL); 414 res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
388 if (res != DS_OK) { 415 if (res != DS_OK) {
389 if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) { 416 if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) {
390 // Try without DSBCAPS_LOCHARDWARE 417 // Try without DSBCAPS_LOCHARDWARE
391 dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE; 418 dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
392 res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL); 419 res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
393 } 420 }
394 if (res != DS_OK) { 421 if (res != DS_OK) {
395 UninitDirectSound(); 422 UninitDirectSound();
396 mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot create secondary buffer (%s)\n", dserr2str(res)); 423 mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot create secondary (stream)buffer (%s)\n", dserr2str(res));
397 return 0; 424 return 0;
398 } 425 }
399 } 426 }
400 mp_msg(MSGT_AO, MSGL_V, "ao_dsound: secondary buffer created\n"); 427 mp_msg(MSGT_AO, MSGL_V, "ao_dsound: secondary (stream)buffer created\n");
401 return 1; 428 return 1;
402 } 429 }
403 430
404 431
405 432