summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_dsound.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-06-04 00:51:07 +0200
committerwm4 <wm4@nowhere>2013-06-04 00:56:28 +0200
commitcee56e8623b18ddf37426ab9204b551925006083 (patch)
tree55182740210915d5d6bdfc0031a41af024be96c4 /audio/out/ao_dsound.c
parent92ae48db0f91fbfcfbb1722fa81c922808f62d5a (diff)
downloadmpv-cee56e8623b18ddf37426ab9204b551925006083.tar.bz2
mpv-cee56e8623b18ddf37426ab9204b551925006083.tar.xz
ao_dsound: uncrustify
Diffstat (limited to 'audio/out/ao_dsound.c')
-rw-r--r--audio/out/ao_dsound.c714
1 files changed, 375 insertions, 339 deletions
diff --git a/audio/out/ao_dsound.c b/audio/out/ao_dsound.c
index f57d7cd96e..95a45a1482 100644
--- a/audio/out/ao_dsound.c
+++ b/audio/out/ao_dsound.c
@@ -47,10 +47,10 @@
static const ao_info_t info =
{
- "Windows DirectSound audio output",
- "dsound",
- "Gabor Szecsi <deje@miki.hu>",
- ""
+ "Windows DirectSound audio output",
+ "dsound",
+ "Gabor Szecsi <deje@miki.hu>",
+ ""
};
LIBAO_EXTERN(dsound)
@@ -62,7 +62,9 @@ LIBAO_EXTERN(dsound)
#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
-static const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x1,0x0000,0x0010, {0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};
+static const GUID KSDATAFORMAT_SUBTYPE_PCM = {
+ 0x1, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+};
#if 0
#define DSSPEAKER_HEADPHONE 0x00000001
@@ -75,15 +77,15 @@ static const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x1,0x0000,0x0010, {0x80,0x00,0x00
#ifndef _WAVEFORMATEXTENSIBLE_
typedef struct {
- WAVEFORMATEX Format;
+ WAVEFORMATEX Format;
union {
WORD wValidBitsPerSample; /* bits of precision */
WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */
WORD wReserved; /* If neither applies, set to zero. */
} Samples;
- DWORD dwChannelMask; /* which channels are */
+ DWORD dwChannelMask; /* which channels are */
/* present in stream */
- GUID SubFormat;
+ GUID SubFormat;
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
#endif
@@ -111,28 +113,28 @@ static int audio_volume;
*/
static char * dserr2str(int err)
{
- switch (err) {
- case DS_OK: return "DS_OK";
- case DS_NO_VIRTUALIZATION: return "DS_NO_VIRTUALIZATION";
- case DSERR_ALLOCATED: return "DS_NO_VIRTUALIZATION";
- case DSERR_CONTROLUNAVAIL: return "DSERR_CONTROLUNAVAIL";
- case DSERR_INVALIDPARAM: return "DSERR_INVALIDPARAM";
- case DSERR_INVALIDCALL: return "DSERR_INVALIDCALL";
- case DSERR_GENERIC: return "DSERR_GENERIC";
- case DSERR_PRIOLEVELNEEDED: return "DSERR_PRIOLEVELNEEDED";
- case DSERR_OUTOFMEMORY: return "DSERR_OUTOFMEMORY";
- case DSERR_BADFORMAT: return "DSERR_BADFORMAT";
- case DSERR_UNSUPPORTED: return "DSERR_UNSUPPORTED";
- case DSERR_NODRIVER: return "DSERR_NODRIVER";
- case DSERR_ALREADYINITIALIZED: return "DSERR_ALREADYINITIALIZED";
- case DSERR_NOAGGREGATION: return "DSERR_NOAGGREGATION";
- case DSERR_BUFFERLOST: return "DSERR_BUFFERLOST";
- case DSERR_OTHERAPPHASPRIO: return "DSERR_OTHERAPPHASPRIO";
- case DSERR_UNINITIALIZED: return "DSERR_UNINITIALIZED";
- case DSERR_NOINTERFACE: return "DSERR_NOINTERFACE";
- case DSERR_ACCESSDENIED: return "DSERR_ACCESSDENIED";
- default: return "unknown";
- }
+ switch (err) {
+ case DS_OK: return "DS_OK";
+ case DS_NO_VIRTUALIZATION: return "DS_NO_VIRTUALIZATION";
+ case DSERR_ALLOCATED: return "DS_NO_VIRTUALIZATION";
+ case DSERR_CONTROLUNAVAIL: return "DSERR_CONTROLUNAVAIL";
+ case DSERR_INVALIDPARAM: return "DSERR_INVALIDPARAM";
+ case DSERR_INVALIDCALL: return "DSERR_INVALIDCALL";
+ case DSERR_GENERIC: return "DSERR_GENERIC";
+ case DSERR_PRIOLEVELNEEDED: return "DSERR_PRIOLEVELNEEDED";
+ case DSERR_OUTOFMEMORY: return "DSERR_OUTOFMEMORY";
+ case DSERR_BADFORMAT: return "DSERR_BADFORMAT";
+ case DSERR_UNSUPPORTED: return "DSERR_UNSUPPORTED";
+ case DSERR_NODRIVER: return "DSERR_NODRIVER";
+ case DSERR_ALREADYINITIALIZED: return "DSERR_ALREADYINITIALIZED";
+ case DSERR_NOAGGREGATION: return "DSERR_NOAGGREGATION";
+ case DSERR_BUFFERLOST: return "DSERR_BUFFERLOST";
+ case DSERR_OTHERAPPHASPRIO: return "DSERR_OTHERAPPHASPRIO";
+ case DSERR_UNINITIALIZED: return "DSERR_UNINITIALIZED";
+ case DSERR_NOINTERFACE: return "DSERR_NOINTERFACE";
+ case DSERR_ACCESSDENIED: return "DSERR_ACCESSDENIED";
+ }
+ return "unknown";
}
/**
@@ -142,15 +144,15 @@ static void UninitDirectSound(void)
{
// finally release the DirectSound object
if (hds) {
- IDirectSound_Release(hds);
- hds = NULL;
+ IDirectSound_Release(hds);
+ hds = NULL;
}
// free DSOUND.DLL
if (hdsound_dll) {
- FreeLibrary(hdsound_dll);
- hdsound_dll = NULL;
+ FreeLibrary(hdsound_dll);
+ hdsound_dll = NULL;
}
- mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound uninitialized\n");
+ mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound uninitialized\n");
}
/**
@@ -158,7 +160,7 @@ static void UninitDirectSound(void)
*/
static void print_help(void)
{
- mp_msg(MSGT_AO, MSGL_FATAL,
+ mp_msg(MSGT_AO, MSGL_FATAL,
"\n-ao dsound commandline help:\n"
"Example: mpv -ao dsound:device=1\n"
" sets 1st device\n"
@@ -172,17 +174,17 @@ static void print_help(void)
\brief enumerate direct sound devices
\return TRUE to continue with the enumeration
*/
-static BOOL CALLBACK DirectSoundEnum(LPGUID guid,LPCSTR desc,LPCSTR module,LPVOID context)
+static BOOL CALLBACK DirectSoundEnum(LPGUID guid, LPCSTR desc, LPCSTR module,
+ LPVOID context)
{
- int* device_index=context;
- mp_msg(MSGT_AO, MSGL_V,"%i %s ",*device_index,desc);
- if(device_num==*device_index){
- mp_msg(MSGT_AO, MSGL_V,"<--");
- if(guid){
- memcpy(&device,guid,sizeof(GUID));
- }
+ int *device_index = context;
+ mp_msg(MSGT_AO, MSGL_V, "%i %s ", *device_index, desc);
+ if (device_num == *device_index) {
+ mp_msg(MSGT_AO, MSGL_V, "<--");
+ if (guid)
+ memcpy(&device, guid, sizeof(GUID));
}
- mp_msg(MSGT_AO, MSGL_V,"\n");
+ mp_msg(MSGT_AO, MSGL_V, "\n");
(*device_index)++;
return TRUE;
}
@@ -194,73 +196,83 @@ static BOOL CALLBACK DirectSoundEnum(LPGUID guid,LPCSTR desc,LPCSTR module,LPVOI
*/
static int InitDirectSound(void)
{
- DSCAPS dscaps;
+ DSCAPS dscaps;
- // initialize directsound
+ // initialize directsound
HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
- HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKA, LPVOID);
- int device_index=0;
- const opt_t subopts[] = {
- {"device", OPT_ARG_INT, &device_num,NULL},
- {NULL}
- };
- if (subopt_parse(ao_subdevice, subopts) != 0) {
- print_help();
- return 0;
- }
-
- hdsound_dll = LoadLibrary("DSOUND.DLL");
- if (hdsound_dll == NULL) {
- mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot load DSOUND.DLL\n");
- return 0;
- }
- OurDirectSoundCreate = (void*)GetProcAddress(hdsound_dll, "DirectSoundCreate");
- OurDirectSoundEnumerate = (void*)GetProcAddress(hdsound_dll, "DirectSoundEnumerateA");
-
- if (OurDirectSoundCreate == NULL || OurDirectSoundEnumerate == NULL) {
- mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: GetProcAddress FAILED\n");
- FreeLibrary(hdsound_dll);
- return 0;
- }
-
- // Enumerate all directsound devices
- mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Output Devices:\n");
- OurDirectSoundEnumerate(DirectSoundEnum,&device_index);
-
- // Create the direct sound object
- if FAILED(OurDirectSoundCreate((device_num)?&device:NULL, &hds, NULL )) {
- mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot create a DirectSound device\n");
- FreeLibrary(hdsound_dll);
- return 0;
- }
-
- /* Set DirectSound Cooperative level, ie what control we want over Windows
- * sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
- * settings of the primary buffer, but also that only the sound of our
- * application will be hearable when it will have the focus.
- * !!! (this is not really working as intended yet because to set the
- * cooperative level you need the window handle of your application, and
- * I don't know of any easy way to get it. Especially since we might play
- * sound without any video, and so what window handle should we use ???
- * The hack for now is to use the Desktop window handle - it seems to be
- * working */
- if (IDirectSound_SetCooperativeLevel(hds, GetDesktopWindow(), DSSCL_EXCLUSIVE)) {
- mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot set direct sound cooperative level\n");
- IDirectSound_Release(hds);
- FreeLibrary(hdsound_dll);
- return 0;
- }
- mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound initialized\n");
-
- memset(&dscaps, 0, sizeof(DSCAPS));
- dscaps.dwSize = sizeof(DSCAPS);
- if (DS_OK == IDirectSound_GetCaps(hds, &dscaps)) {
- if (dscaps.dwFlags & DSCAPS_EMULDRIVER) mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound is emulated, waveOut may give better performance\n");
- } else {
- mp_msg(MSGT_AO, MSGL_V, "ao_dsound: cannot get device capabilities\n");
- }
-
- return 1;
+ HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKA, LPVOID);
+ int device_index = 0;
+ const opt_t subopts[] = {
+ {"device", OPT_ARG_INT, &device_num, NULL},
+ {NULL}
+ };
+ if (subopt_parse(ao_subdevice, subopts) != 0) {
+ print_help();
+ return 0;
+ }
+
+ hdsound_dll = LoadLibrary("DSOUND.DLL");
+ if (hdsound_dll == NULL) {
+ mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot load DSOUND.DLL\n");
+ return 0;
+ }
+ OurDirectSoundCreate = (void *)GetProcAddress(hdsound_dll,
+ "DirectSoundCreate");
+ OurDirectSoundEnumerate = (void *)GetProcAddress(hdsound_dll,
+ "DirectSoundEnumerateA");
+
+ if (OurDirectSoundCreate == NULL || OurDirectSoundEnumerate == NULL) {
+ mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: GetProcAddress FAILED\n");
+ FreeLibrary(hdsound_dll);
+ return 0;
+ }
+
+ // Enumerate all directsound devices
+ mp_msg(MSGT_AO, MSGL_V, "ao_dsound: Output Devices:\n");
+ OurDirectSoundEnumerate(DirectSoundEnum, &device_index);
+
+ // Create the direct sound object
+ if (FAILED(OurDirectSoundCreate((device_num) ? &device : NULL, &hds,
+ NULL)))
+ {
+ mp_msg(MSGT_AO, MSGL_ERR,
+ "ao_dsound: cannot create a DirectSound device\n");
+ FreeLibrary(hdsound_dll);
+ return 0;
+ }
+
+ /* Set DirectSound Cooperative level, ie what control we want over Windows
+ * sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
+ * settings of the primary buffer, but also that only the sound of our
+ * application will be hearable when it will have the focus.
+ * !!! (this is not really working as intended yet because to set the
+ * cooperative level you need the window handle of your application, and
+ * I don't know of any easy way to get it. Especially since we might play
+ * sound without any video, and so what window handle should we use ???
+ * The hack for now is to use the Desktop window handle - it seems to be
+ * working */
+ if (IDirectSound_SetCooperativeLevel(hds, GetDesktopWindow(),
+ DSSCL_EXCLUSIVE))
+ {
+ mp_msg(MSGT_AO, MSGL_ERR,
+ "ao_dsound: cannot set direct sound cooperative level\n");
+ IDirectSound_Release(hds);
+ FreeLibrary(hdsound_dll);
+ return 0;
+ }
+ mp_msg(MSGT_AO, MSGL_V, "ao_dsound: DirectSound initialized\n");
+
+ memset(&dscaps, 0, sizeof(DSCAPS));
+ dscaps.dwSize = sizeof(DSCAPS);
+ if (DS_OK == IDirectSound_GetCaps(hds, &dscaps)) {
+ if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
+ mp_msg(MSGT_AO, MSGL_V,
+ "ao_dsound: DirectSound is emulated, waveOut may give better performance\n");
+ } else {
+ mp_msg(MSGT_AO, MSGL_V, "ao_dsound: cannot get device capabilities\n");
+ }
+
+ return 1;
}
/**
@@ -268,14 +280,14 @@ static int InitDirectSound(void)
*/
static void DestroyBuffer(void)
{
- if (hdsbuf) {
- IDirectSoundBuffer_Release(hdsbuf);
- hdsbuf = NULL;
- }
- if (hdspribuf) {
- IDirectSoundBuffer_Release(hdspribuf);
- hdspribuf = NULL;
- }
+ if (hdsbuf) {
+ IDirectSoundBuffer_Release(hdsbuf);
+ hdsbuf = NULL;
+ }
+ if (hdspribuf) {
+ IDirectSoundBuffer_Release(hdspribuf);
+ hdspribuf = NULL;
+ }
}
/**
@@ -286,57 +298,58 @@ static void DestroyBuffer(void)
*/
static int write_buffer(unsigned char *data, int len)
{
- HRESULT res;
- LPVOID lpvPtr1;
- DWORD dwBytes1;
- LPVOID lpvPtr2;
- DWORD dwBytes2;
-
- underrun_check = 0;
-
- // Lock the buffer
- res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
- // If the buffer was lost, restore and retry lock.
- if (DSERR_BUFFERLOST == res)
- {
- IDirectSoundBuffer_Restore(hdsbuf);
- res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
- }
-
-
- if (SUCCEEDED(res))
- {
- if (!AF_FORMAT_IS_AC3(ao_data.format)) {
+ HRESULT res;
+ LPVOID lpvPtr1;
+ DWORD dwBytes1;
+ LPVOID lpvPtr2;
+ DWORD dwBytes2;
+
+ underrun_check = 0;
+
+ // Lock the buffer
+ res = IDirectSoundBuffer_Lock(hdsbuf, write_offset, len, &lpvPtr1, &dwBytes1,
+ &lpvPtr2, &dwBytes2, 0);
+ // If the buffer was lost, restore and retry lock.
+ if (DSERR_BUFFERLOST == res) {
+ IDirectSoundBuffer_Restore(hdsbuf);
+ res = IDirectSoundBuffer_Lock(hdsbuf, write_offset, len, &lpvPtr1,
+ &dwBytes1, &lpvPtr2, &dwBytes2, 0);
+ }
+
+
+ if (SUCCEEDED(res)) {
+ if (!AF_FORMAT_IS_AC3(ao_data.format)) {
memcpy(lpvPtr1, data, dwBytes1);
if (lpvPtr2 != NULL)
memcpy(lpvPtr2, (char *)data + dwBytes1, dwBytes2);
- write_offset+=dwBytes1+dwBytes2;
- if(write_offset>=buffer_size)
- write_offset=dwBytes2;
- } else {
- // Write to pointers without reordering.
- memcpy(lpvPtr1,data,dwBytes1);
- if (NULL != lpvPtr2 )memcpy(lpvPtr2,data+dwBytes1,dwBytes2);
- write_offset+=dwBytes1+dwBytes2;
- if(write_offset>=buffer_size)write_offset=dwBytes2;
- }
-
- // Release the data back to DirectSound.
- res = IDirectSoundBuffer_Unlock(hdsbuf,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2);
- if (SUCCEEDED(res))
- {
- // Success.
- DWORD status;
- IDirectSoundBuffer_GetStatus(hdsbuf, &status);
- if (!(status & DSBSTATUS_PLAYING)){
- res = IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);
- }
- return dwBytes1+dwBytes2;
+ write_offset += dwBytes1 + dwBytes2;
+ if (write_offset >= buffer_size)
+ write_offset = dwBytes2;
+ } else {
+ // Write to pointers without reordering.
+ memcpy(lpvPtr1, data, dwBytes1);
+ if (NULL != lpvPtr2)
+ memcpy(lpvPtr2, data + dwBytes1, dwBytes2);
+ write_offset += dwBytes1 + dwBytes2;
+ if (write_offset >= buffer_size)
+ write_offset = dwBytes2;
+ }
+
+ // Release the data back to DirectSound.
+ res = IDirectSoundBuffer_Unlock(hdsbuf, lpvPtr1, dwBytes1, lpvPtr2,
+ dwBytes2);
+ if (SUCCEEDED(res)) {
+ // Success.
+ DWORD status;
+ IDirectSoundBuffer_GetStatus(hdsbuf, &status);
+ if (!(status & DSBSTATUS_PLAYING))
+ res = IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);
+ return dwBytes1 + dwBytes2;
+ }
}
- }
- // Lock, Unlock, or Restore failed.
- return 0;
+ // Lock, Unlock, or Restore failed.
+ return 0;
}
/***************************************************************************************/
@@ -349,24 +362,24 @@ static int write_buffer(unsigned char *data, int len)
*/
static int control(int cmd, void *arg)
{
- DWORD volume;
- switch (cmd) {
- case AOCONTROL_GET_VOLUME: {
- ao_control_vol_t* vol = (ao_control_vol_t*)arg;
- vol->left = vol->right = audio_volume;
- return CONTROL_OK;
- }
- case AOCONTROL_SET_VOLUME: {
- ao_control_vol_t* vol = (ao_control_vol_t*)arg;
- volume = audio_volume = vol->right;
- if (volume < 1)
- volume = 1;
- volume = (DWORD)(log10(volume) * 5000.0) - 10000;
- IDirectSoundBuffer_SetVolume(hdsbuf, volume);
- return CONTROL_OK;
- }
- }
- return -1;
+ DWORD volume;
+ switch (cmd) {
+ case AOCONTROL_GET_VOLUME: {
+ ao_control_vol_t *vol = (ao_control_vol_t *)arg;
+ vol->left = vol->right = audio_volume;
+ return CONTROL_OK;
+ }
+ case AOCONTROL_SET_VOLUME: {
+ ao_control_vol_t *vol = (ao_control_vol_t *)arg;
+ volume = audio_volume = vol->right;
+ if (volume < 1)
+ volume = 1;
+ volume = (DWORD)(log10(volume) * 5000.0) - 10000;
+ IDirectSoundBuffer_SetVolume(hdsbuf, volume);
+ return CONTROL_OK;
+ }
+ }
+ return -1;
}
/**
@@ -380,118 +393,138 @@ static int control(int cmd, void *arg)
static int init(int rate, const struct mp_chmap *channels, int format, int flags)
{
int res;
- if (!InitDirectSound()) return 0;
+ if (!InitDirectSound())
+ return 0;
+
+ global_ao->no_persistent_volume = true;
+ audio_volume = 100;
+
+ // ok, now create the buffers
+ WAVEFORMATEXTENSIBLE wformat;
+ DSBUFFERDESC dsbpridesc;
+ DSBUFFERDESC dsbdesc;
+
+ if (AF_FORMAT_IS_AC3(format))
+ format = AF_FORMAT_AC3_NE;
+ else {
+ struct mp_chmap_sel sel = {
+ 0
+ };
+ mp_chmap_sel_add_waveext(&sel);
+ if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
+ return 0;
+ }
+ switch (format) {
+ case AF_FORMAT_AC3_NE:
+ case AF_FORMAT_S24_LE:
+ case AF_FORMAT_S16_LE:
+ case AF_FORMAT_U8:
+ break;
+ default:
+ mp_msg(MSGT_AO, MSGL_V,
+ "ao_dsound: format %s not supported defaulting to Signed 16-bit Little-Endian\n",
+ af_fmt2str_short(format));
+ format = AF_FORMAT_S16_LE;
+ }
+ //fill global ao_data
+ ao_data.samplerate = rate;
+ ao_data.format = format;
+ ao_data.bps = ao_data.channels.num * rate * (af_fmt2bits(format) >> 3);
+ if (ao_data.buffersize == -1)
+ ao_data.buffersize = ao_data.bps; // space for 1 sec
+ mp_msg(MSGT_AO, MSGL_V,
+ "ao_dsound: Samplerate:%iHz Channels:%i Format:%s\n", rate,
+ ao_data.channels.num, af_fmt2str_short(format));
+ mp_msg(MSGT_AO, MSGL_V, "ao_dsound: Buffersize:%d bytes (%d msec)\n",
+ ao_data.buffersize, ao_data.buffersize / ao_data.bps * 1000);
+
+ //fill waveformatex
+ ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE));
+ wformat.Format.cbSize = (ao_data.channels.num > 2)
+ ? sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) : 0;
+ wformat.Format.nChannels = ao_data.channels.num;
+ wformat.Format.nSamplesPerSec = rate;
+ if (AF_FORMAT_IS_AC3(format)) {
+ wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
+ wformat.Format.wBitsPerSample = 16;
+ wformat.Format.nBlockAlign = 4;
+ } else {
+ wformat.Format.wFormatTag = (ao_data.channels.num > 2)
+ ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM;
+ wformat.Format.wBitsPerSample = af_fmt2bits(format);
+ wformat.Format.nBlockAlign = wformat.Format.nChannels *
+ (wformat.Format.wBitsPerSample >> 3);
+ }
- global_ao->no_persistent_volume = true;
- audio_volume = 100;
+ // fill in primary sound buffer descriptor
+ memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC));
+ dsbpridesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
+ dsbpridesc.dwBufferBytes = 0;
+ dsbpridesc.lpwfxFormat = NULL;
+
+ // fill in the secondary sound buffer (=stream buffer) descriptor
+ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */
+ | DSBCAPS_GLOBALFOCUS /** Allows background playing */
+ | DSBCAPS_CTRLVOLUME; /** volume control enabled */
+
+ if (ao_data.channels.num > 2) {
+ wformat.dwChannelMask = mp_chmap_to_waveext(&ao_data.channels);
+ wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+ wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample;
+ // Needed for 5.1 on emu101k - shit soundblaster
+ dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE;
+ }
+ wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec *
+ wformat.Format.nBlockAlign;
+
+ dsbdesc.dwBufferBytes = ao_data.buffersize;
+ dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat;
+ buffer_size = dsbdesc.dwBufferBytes;
+ write_offset = 0;
+ min_free_space = wformat.Format.nBlockAlign;
+ ao_data.outburst = wformat.Format.nBlockAlign * 512;
+
+ // create primary buffer and set its format
+
+ res = IDirectSound_CreateSoundBuffer(hds, &dsbpridesc, &hdspribuf, NULL);
+ if (res != DS_OK) {
+ UninitDirectSound();
+ mp_msg(MSGT_AO, MSGL_ERR,
+ "ao_dsound: cannot create primary buffer (%s)\n",
+ dserr2str(res));
+ return 0;
+ }
+ res = IDirectSoundBuffer_SetFormat(hdspribuf, (WAVEFORMATEX *)&wformat);
+ 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));
+ }
- // ok, now create the buffers
- WAVEFORMATEXTENSIBLE wformat;
- DSBUFFERDESC dsbpridesc;
- DSBUFFERDESC dsbdesc;
+ mp_msg(MSGT_AO, MSGL_V, "ao_dsound: primary buffer created\n");
- if (AF_FORMAT_IS_AC3(format)) {
- format = AF_FORMAT_AC3_NE;
- } else {
- struct mp_chmap_sel sel = {0};
- mp_chmap_sel_add_waveext(&sel);
- if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
- return 0;
+ // now create the stream buffer
+
+ res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
+ if (res != DS_OK) {
+ if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) {
+ // Try without DSBCAPS_LOCHARDWARE
+ dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
+ res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
}
- switch(format){
- case AF_FORMAT_AC3_NE:
- case AF_FORMAT_S24_LE:
- case AF_FORMAT_S16_LE:
- case AF_FORMAT_U8:
- break;
- default:
- mp_msg(MSGT_AO, MSGL_V,"ao_dsound: format %s not supported defaulting to Signed 16-bit Little-Endian\n",af_fmt2str_short(format));
- format=AF_FORMAT_S16_LE;
- }
- //fill global ao_data
- ao_data.samplerate = rate;
- ao_data.format = format;
- ao_data.bps = ao_data.channels.num * rate * (af_fmt2bits(format)>>3);
- if(ao_data.buffersize==-1) ao_data.buffersize = ao_data.bps; // space for 1 sec
- mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Samplerate:%iHz Channels:%i Format:%s\n", rate, ao_data.channels.num, af_fmt2str_short(format));
- mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Buffersize:%d bytes (%d msec)\n", ao_data.buffersize, ao_data.buffersize / ao_data.bps * 1000);
-
- //fill waveformatex
- ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE));
- wformat.Format.cbSize = (ao_data.channels.num > 2) ? sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) : 0;
- wformat.Format.nChannels = ao_data.channels.num;
- wformat.Format.nSamplesPerSec = rate;
- if (AF_FORMAT_IS_AC3(format)) {
- wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
- wformat.Format.wBitsPerSample = 16;
- wformat.Format.nBlockAlign = 4;
- } else {
- wformat.Format.wFormatTag = (ao_data.channels.num > 2) ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM;
- wformat.Format.wBitsPerSample = af_fmt2bits(format);
- wformat.Format.nBlockAlign = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3);
- }
-
- // fill in primary sound buffer descriptor
- memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC));
- dsbpridesc.dwSize = sizeof(DSBUFFERDESC);
- dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
- dsbpridesc.dwBufferBytes = 0;
- dsbpridesc.lpwfxFormat = NULL;
-
-
- // fill in the secondary sound buffer (=stream buffer) descriptor
- memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */
- | DSBCAPS_GLOBALFOCUS /** Allows background playing */
- | DSBCAPS_CTRLVOLUME; /** volume control enabled */
-
- if (ao_data.channels.num > 2) {
- wformat.dwChannelMask = mp_chmap_to_waveext(&ao_data.channels);
- wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample;
- // Needed for 5.1 on emu101k - shit soundblaster
- dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE;
- }
- wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign;
-
- dsbdesc.dwBufferBytes = ao_data.buffersize;
- dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat;
- buffer_size = dsbdesc.dwBufferBytes;
- write_offset = 0;
- min_free_space = wformat.Format.nBlockAlign;
- ao_data.outburst = wformat.Format.nBlockAlign * 512;
-
- // create primary buffer and set its format
-
- res = IDirectSound_CreateSoundBuffer( hds, &dsbpridesc, &hdspribuf, NULL );
- if ( res != DS_OK ) {
- UninitDirectSound();
- mp_msg(MSGT_AO, MSGL_ERR,"ao_dsound: cannot create primary buffer (%s)\n", dserr2str(res));
- return 0;
- }
- res = IDirectSoundBuffer_SetFormat( hdspribuf, (WAVEFORMATEX *)&wformat );
- 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));
-
- mp_msg(MSGT_AO, MSGL_V, "ao_dsound: primary buffer created\n");
-
- // now create the stream buffer
-
- res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
- if (res != DS_OK) {
- if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) {
- // Try without DSBCAPS_LOCHARDWARE
- dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
- res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);
- }
- if (res != DS_OK) {
- UninitDirectSound();
- mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot create secondary (stream)buffer (%s)\n", dserr2str(res));
- return 0;
- }
- }
- mp_msg(MSGT_AO, MSGL_V, "ao_dsound: secondary (stream)buffer created\n");
- return 1;
+ if (res != DS_OK) {
+ UninitDirectSound();
+ mp_msg(MSGT_AO, MSGL_ERR,
+ "ao_dsound: cannot create secondary (stream)buffer (%s)\n",
+ dserr2str(res));
+ return 0;
+ }
+ }
+ mp_msg(MSGT_AO, MSGL_V, "ao_dsound: secondary (stream)buffer created\n");
+ return 1;
}
@@ -501,11 +534,11 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
*/
static void reset(void)
{
- IDirectSoundBuffer_Stop(hdsbuf);
- // reset directsound buffer
- IDirectSoundBuffer_SetCurrentPosition(hdsbuf, 0);
- write_offset=0;
- underrun_check=0;
+ IDirectSoundBuffer_Stop(hdsbuf);
+ // reset directsound buffer
+ IDirectSoundBuffer_SetCurrentPosition(hdsbuf, 0);
+ write_offset = 0;
+ underrun_check = 0;
}
/**
@@ -513,7 +546,7 @@ static void reset(void)
*/
static void audio_pause(void)
{
- IDirectSoundBuffer_Stop(hdsbuf);
+ IDirectSoundBuffer_Stop(hdsbuf);
}
/**
@@ -521,7 +554,7 @@ static void audio_pause(void)
*/
static void audio_resume(void)
{
- IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);
+ IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);
}
/**
@@ -530,51 +563,53 @@ static void audio_resume(void)
*/
static void uninit(int immed)
{
- if (!immed)
- mp_sleep_us(get_delay() * 1000000);
- reset();
+ if (!immed)
+ mp_sleep_us(get_delay() * 1000000);
+ reset();
- DestroyBuffer();
- UninitDirectSound();
+ DestroyBuffer();
+ UninitDirectSound();
}
// return exact number of free (safe to write) bytes
static int check_free_buffer_size(void)
{
- int space;
- DWORD play_offset;
- IDirectSoundBuffer_GetCurrentPosition(hdsbuf,&play_offset,NULL);
- space=buffer_size-(write_offset-play_offset);
- // | | <-- const --> | | |
- // buffer start play_cursor write_cursor write_offset buffer end
- // play_cursor is the actual postion of the play cursor
- // write_cursor is the position after which it is assumed to be save to write data
- // write_offset is the postion where we actually write the data to
- if(space > buffer_size)space -= buffer_size; // write_offset < play_offset
- // Check for buffer underruns. An underrun happens if DirectSound
- // started to play old data beyond the current write_offset. Detect this
- // by checking whether the free space shrinks, even though no data was
- // written (i.e. no write_buffer). Doesn't always work, but the only
- // reason we need this is to deal with the situation when playback ends,
- // and the buffer is only half-filled.
- if (space < underrun_check) {
- // there's no useful data in the buffers
- space = buffer_size;
- reset();
- }
- underrun_check = space;
- return space;
+ int space;
+ DWORD play_offset;
+ IDirectSoundBuffer_GetCurrentPosition(hdsbuf, &play_offset, NULL);
+ space = buffer_size - (write_offset - play_offset);
+ // | | <-- const --> | | |
+ // buffer start play_cursor write_cursor write_offset buffer end
+ // play_cursor is the actual postion of the play cursor
+ // write_cursor is the position after which it is assumed to be save to write data
+ // write_offset is the postion where we actually write the data to
+ if (space > buffer_size)
+ space -= buffer_size; // write_offset < play_offset
+ // Check for buffer underruns. An underrun happens if DirectSound
+ // started to play old data beyond the current write_offset. Detect this
+ // by checking whether the free space shrinks, even though no data was
+ // written (i.e. no write_buffer). Doesn't always work, but the only
+ // reason we need this is to deal with the situation when playback ends,
+ // and the buffer is only half-filled.
+ if (space < underrun_check) {
+ // there's no useful data in the buffers
+ space = buffer_size;
+ reset();
+ }
+ underrun_check = space;
+ return space;
}
/**
-\brief find out how many bytes can be written into the audio buffer without
-\return free space in bytes, has to return 0 if the buffer is almost full
-*/
+ \brief find out how many bytes can be written into the audio buffer without
+ \return free space in bytes, has to return 0 if the buffer is almost full
+ */
static int get_space(void)
{
- int space = check_free_buffer_size();
- if(space < min_free_space)return 0;
- return space-min_free_space;
+ int space = check_free_buffer_size();
+ if (space < min_free_space)
+ return 0;
+ return space - min_free_space;
}
/**
@@ -584,14 +619,15 @@ static int get_space(void)
\param flags currently unused
\return number of played bytes
*/
-static int play(void* data, int len, int flags)
+static int play(void *data, int len, int flags)
{
- int space = check_free_buffer_size();
- if(space < len) len = space;
+ int space = check_free_buffer_size();
+ if (space < len)
+ len = space;
- if (!(flags & AOPLAY_FINAL_CHUNK))
- len = (len / ao_data.outburst) * ao_data.outburst;
- return write_buffer(data, len);
+ if (!(flags & AOPLAY_FINAL_CHUNK))
+ len = (len / ao_data.outburst) * ao_data.outburst;
+ return write_buffer(data, len);
}
/**
@@ -600,6 +636,6 @@ static int play(void* data, int len, int flags)
*/
static float get_delay(void)
{
- int space = check_free_buffer_size();
- return (float)(buffer_size - space) / (float)ao_data.bps;
+ int space = check_free_buffer_size();
+ return (float)(buffer_size - space) / (float)ao_data.bps;
}