Mercurial > mplayer.hg
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 |