Commit 945f2946 authored by Sam Hocevar's avatar Sam Hocevar

  * DirectX plugin by Gildas Bazin <gbazin@netcourrier.com>.

    Notes: o I called it 'directx' instead of 'windx' because it
             made a lot more sense to me.
           o Completely untested. I didn't manage to compile it yet.
           o Code in vout_directx.c will go through a big rewrite when
             vout 4 is finished. Xav is already working on this.
parent e9cc5c05
......@@ -23,6 +23,13 @@ If you intend to debug stuff, you may want to disable optimizations:
--enable-mga --enable-gtk --enable-qt --enable-xvideo --enable-alsa \
--enable-debug
It is also possible to cross-compile for the Win32 platform using mingw32:
make distclean && CC=i586-mingw32msvc-gcc CFLAGS=-I/usr/i586-mingw32msvc \
RANLIB=i586-mingw32msvc-ranlib ./configure --host=i386-mingw32msvc \
--target=i386-mingw32msvc --build=i386-linux --disable-dsp \
--disable-gtk --disable-x11 --disable-xvideo
Building VideoLAN
=================
......
......@@ -11,7 +11,7 @@
#
# All possible plugin directories, needed for make clean
#
PLUGINS_DIR := alsa beos darwin dsp dummy \
PLUGINS_DIR := alsa beos darwin directx dsp dummy \
dvd esd fb ggi glide gtk \
downmix idct imdct \
macosx mga \
......@@ -22,8 +22,9 @@ PLUGINS_DIR := alsa beos darwin dsp dummy \
#
# All possible plugin objects
#
PLUGINS_TARGETS := alsa/alsa beos/beos darwin/darwin dsp/dsp dummy/dummy \
dvd/dvd esd/esd fb/fb ggi/ggi glide/glide gtk/gnome gtk/gtk \
PLUGINS_TARGETS := alsa/alsa beos/beos darwin/darwin directx/directx \
dsp/dsp dummy/dummy dvd/dvd esd/esd fb/fb ggi/ggi \
glide/glide gtk/gnome gtk/gtk \
downmix/downmix downmix/downmixsse downmix/downmix3dn \
idct/idct idct/idctclassic idct/idctmmx idct/idctmmxext \
imdct/imdct imdct/imdct3dn imdct/imdctsse \
......@@ -133,7 +134,7 @@ endif
#
# Generated header
#
H_OBJ = include/modules_builtin.h
H_OBJ = src/misc/modules_builtin.h
#
# Other lists of files
......@@ -176,6 +177,7 @@ distclean: clean
rm -f **/*.o **/*~ *.log
rm -f Makefile.opts
rm -f include/defs.h include/config.h include/modules_builtin.h
rm -f src/misc/modules_builtin.h
rm -f config*status config*cache config*log
rm -f gmon.out core build-stamp
rm -Rf .dep
......
......@@ -73,6 +73,7 @@ LIB_NCURSES = @LIB_NCURSES@
LIB_QT = @LIB_QT@
LIB_TS = @LIB_TS@
LIB_SDL = @LIB_SDL@
LIB_DIRECTX = @LIB_DIRECTX@
LIB_X11 = @LIB_X11@
LIB_XVIDEO = @LIB_XVIDEO@
LIB_YUV = @LIB_YUV@
......
This diff is collapsed.
......@@ -68,13 +68,13 @@ CFLAGS="${CFLAGS} -I/usr/local/include"
dnl Check for pthreads - borrowed from XMMS
PTHREAD_LIBS=error
AC_CHECK_LIB(pthread,pthread_attr_init,PTHREAD_LIBS="-lpthread")
if test "x$PTHREAD_LIBS" = xerror; then
if test "x${PTHREAD_LIBS}" = xerror; then
AC_CHECK_LIB(pthreads,pthread_attr_init,PTHREAD_LIBS="-lpthreads")
fi
if test "x$PTHREAD_LIBS" = xerror; then
if test "x${PTHREAD_LIBS}" = xerror; then
AC_CHECK_LIB(c_r,pthread_attr_init,PTHREAD_LIBS="-lc_r")
fi
if test "x$PTHREAD_LIBS" = xerror; then
if test "x${PTHREAD_LIBS}" = xerror; then
PTHREAD_LIBS=""
AC_CHECK_FUNC(pthread_attr_init)
fi
......@@ -395,6 +395,30 @@ AC_ARG_WITH(sdl,
LIB_SDL="${LIB_SDL} -L/usr/X11R6/lib -lSDL"])
fi
dnl
dnl Windows DirectX module
dnl
AC_ARG_WITH(directx,
[ --with-directx[=name] Windows DirectX support (default enabled)],
[ if test "x$withval" != "xno";
then
PLUGINS="${PLUGINS} directx";
if test "x$withval" != "xyes";
then
LIB_DIRECTX="${LIB_DIRECTX} -L"$withval"/lib -lddraw -ldsound"
INCLUDE="${INCLUDE} -I"$withval"/include"
else
AC_CHECK_HEADERS(directx.h, , [echo "Cannot find DirectX headers !"; exit])
LIB_DIRECTX="${LIB_DIRECTX} -L/usr/lib -lddraw -ldsound"
fi
fi ])
if test "x$withval" = "x";
then
AC_CHECK_HEADERS(directx.h,
[PLUGINS="${PLUGINS} directx"
LIB_DIRECTX="${LIB_DIRECTX} -L/usr/lib -lddraw -ldsound"])
fi
dnl
dnl Glide module
dnl
......@@ -562,6 +586,7 @@ AC_SUBST(LIB_NCURSES)
AC_SUBST(LIB_QT)
AC_SUBST(LIB_TS)
AC_SUBST(LIB_SDL)
AC_SUBST(LIB_DIRECTX)
AC_SUBST(LIB_X11)
AC_SUBST(LIB_XVIDEO)
AC_SUBST(LIB_YUV)
......
###############################################################################
# vlc (VideoLAN Client) DirectX module Makefile
# (c)2001 VideoLAN
###############################################################################
#
# Objects
#
PLUGIN_C = directx.o vout_directx.o aout_directx.o
BUILTIN_C = $(PLUGIN_C:%.o=BUILTIN_%.o)
ALL_OBJ = $(PLUGIN_C) $(BUILTIN_C)
#
# Virtual targets
#
include ../../Makefile.modules
#
# Real targets
#
../../lib/directx.so: $(PLUGIN_C)
$(CC) $(PCFLAGS) -o $@ $^ $(PLCFLAGS) $(LIB_DIRECTX)
../../lib/directx.a: $(BUILTIN_C)
ar r $@ $^
$(RANLIB) $@
/*****************************************************************************
* aout_directx.c: Windows DirectX audio output method
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: aout_directx.c,v 1.1 2001/06/02 01:09:03 sam Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#define MODULE_NAME directx
#include "modules_inner.h"
/* The most important this to do for now is to fix the audio bug we've got
* on startup: the audio will start later than the video (sometimes) and
* is trying to catching up with it.
* At first sight it seems to be a scheduling problem
*/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <errno.h> /* ENOMEM */
#include <fcntl.h> /* open(), O_WRONLY */
#include <string.h> /* strerror() */
#include <unistd.h> /* write(), close() */
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* calloc(), malloc(), free() */
#include "config.h"
#include "common.h" /* boolean_t, byte_t */
#include "threads.h"
#include "mtime.h"
#include "tests.h"
#include "directx.h"
#include "audio_output.h" /* aout_thread_t */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "main.h"
#include "modules.h"
/*****************************************************************************
* aout_sys_t: directx audio output method descriptor
*****************************************************************************
* This structure is part of the audio output thread descriptor.
* It describes the direct sound specific properties of an audio device.
*****************************************************************************/
typedef struct aout_sys_s
{
LPDIRECTSOUND p_dsobject; /* main Direct Sound object */
LPDIRECTSOUNDBUFFER p_dsbuffer_primary; /* the actual sound card buffer
(not used directly) */
LPDIRECTSOUNDBUFFER p_dsbuffer; /* the sound buffer we use (direct sound
* takes care of mixing all the
* secondary buffers into the primary) */
long l_buffer_size; /* secondary sound buffer size */
long l_write_position; /* next write position for the buffer */
boolean_t b_active;
} aout_sys_t;
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static int aout_Probe ( probedata_t *p_data );
static int aout_Open ( aout_thread_t *p_aout );
static int aout_SetFormat ( aout_thread_t *p_aout );
static long aout_GetBufInfo ( aout_thread_t *p_aout, long l_buffer_info );
static void aout_Play ( aout_thread_t *p_aout,
byte_t *buffer, int i_size );
static void aout_Close ( aout_thread_t *p_aout );
/* local function */
static int windx_CreateSecondaryBuffer( aout_thread_t *p_aout );
/*****************************************************************************
* Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much.
*****************************************************************************/
void _M( aout_getfunctions )( function_list_t * p_function_list )
{
p_function_list->pf_probe = aout_Probe;
p_function_list->functions.aout.pf_open = aout_Open;
p_function_list->functions.aout.pf_setformat = aout_SetFormat;
p_function_list->functions.aout.pf_getbufinfo = aout_GetBufInfo;
p_function_list->functions.aout.pf_play = aout_Play;
p_function_list->functions.aout.pf_close = aout_Close;
}
/*****************************************************************************
* aout_Probe: probe the audio device and return a score
*****************************************************************************
* This function tries to probe for a Direct Sound device and returns a
* score to the plugin manager so that it can select the best plugin.
*****************************************************************************/
static int aout_Probe( probedata_t *p_data )
{
/* For now just assume the computer has a sound device */
if( TestMethod( AOUT_METHOD_VAR, "directx" ) )
{
return( 999 );
}
return( 400 );
}
/*****************************************************************************
* aout_Open: open the audio device
*****************************************************************************
* This function opens and setups Direct Sound.
*****************************************************************************/
static int aout_Open( aout_thread_t *p_aout )
{
#if 0
HRESULT dsresult;
DSBUFFERDESC dsbuffer_desc;
WAVEFORMATEX waveformat;
#endif
/* Allocate structure */
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->p_sys == NULL )
{
intf_ErrMsg( "aout error: %s", strerror(ENOMEM) );
return( 1 );
}
/* Initialize some variables */
p_aout->p_sys->p_dsobject = NULL;
p_aout->p_sys->p_dsbuffer_primary = NULL;
p_aout->p_sys->p_dsbuffer = NULL;
p_aout->psz_device = 0;
p_aout->i_format = AOUT_FORMAT_DEFAULT;
p_aout->i_channels = 1 + main_GetIntVariable( AOUT_STEREO_VAR,
AOUT_STEREO_DEFAULT );
p_aout->l_rate = main_GetIntVariable( AOUT_RATE_VAR,
AOUT_RATE_DEFAULT );
/* Create the direct sound object */
if( DirectSoundCreate(NULL, &p_aout->p_sys->p_dsobject, NULL) != DS_OK )
{
intf_WarnMsg( 3, "aout: can't create a direct sound device ");
p_aout->p_sys->p_dsobject = NULL;
return( 1 );
}
/* 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(p_aout->p_sys->p_dsobject,
GetDesktopWindow(),
DSSCL_EXCLUSIVE) )
{
intf_WarnMsg( 3, "aout: can't set direct sound cooperative level ");
}
#if 0
/* Obtain (not create) Direct Sound primary buffer */
memset( &dsbuffer_desc, 0, sizeof(DSBUFFERDESC) );
dsbuffer_desc.dwSize = sizeof(DSBUFFERDESC);
dsbuffer_desc.dwFlags = DSBCAPS_PRIMARYBUFFER;
intf_WarnMsg( 3, "aout: Create direct sound primary buffer ");
dsresult = IDirectSound_CreateSoundBuffer(p_aout->p_sys->p_dsobject,
&dsbuffer_desc,
&p_aout->p_sys->p_dsbuffer_primary,
NULL);
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: can't create direct sound primary buffer ");
IDirectSound_Release( p_aout->p_sys->p_dsobject );
p_aout->p_sys->p_dsobject = NULL;
p_aout->p_sys->p_dsbuffer_primary = NULL;
return( 1 );
}
/* Set Direct Sound primary buffer format because the default value set by
* Windows is usually not the high quality value */
memset(&waveformat, 0, sizeof(WAVEFORMATEX));
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.nChannels = 2;
waveformat.nSamplesPerSec = 44100;
waveformat.wBitsPerSample = 16;
waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 *
waveformat.nChannels;
waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec *
waveformat.nBlockAlign;
dsresult = IDirectSoundBuffer_SetFormat(p_aout->p_sys->p_dsbuffer_primary,
&waveformat);
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: can't set primary buffer format");
}
/* ensure the primary buffer is playing. We won't actually hear anything
* until the secondary buffer is playing */
dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer_primary,
0,
0,
DSBPLAY_LOOPING);
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: can't play direct sound primary buffer ");
IDirectSound_Release( p_aout->p_sys->p_dsbuffer_primary );
IDirectSound_Release( p_aout->p_sys->p_dsobject );
p_aout->p_sys->p_dsobject = NULL;
p_aout->p_sys->p_dsbuffer_primary = NULL;
return( 1 );
}
#endif
/* Now create the buffer that we'll actually use: the secondary buffer */
if( windx_CreateSecondaryBuffer( p_aout ) )
{
intf_WarnMsg( 3, "aout: can't create direct sound secondary buffer ");
#if 0
IDirectSound_Release( p_aout->p_sys->p_dsbuffer_primary );
#endif
IDirectSound_Release( p_aout->p_sys->p_dsobject );
p_aout->p_sys->p_dsobject = NULL;
p_aout->p_sys->p_dsbuffer_primary = NULL;
p_aout->p_sys->p_dsbuffer = NULL;
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* aout_SetFormat: reset the audio device and sets its format
*****************************************************************************
* This functions set a new audio format.
* For this we need to close the current secondary buffer and create another
* one with the desired format.
*****************************************************************************/
static int aout_SetFormat( aout_thread_t *p_aout )
{
HRESULT dsresult;
/* first release the current secondary buffer */
if( p_aout->p_sys->p_dsbuffer != NULL )
{
IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer );
p_aout->p_sys->p_dsbuffer = NULL;
}
/* then create a new secondary buffer */
dsresult = windx_CreateSecondaryBuffer( p_aout );
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: WinDX aout_SetFormat cannot create buffer");
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* aout_GetBufInfo: buffer status query
*****************************************************************************
* returns the number of bytes in the audio buffer compared to the size of
* l_buffer_limit...
*****************************************************************************/
static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
{
long l_play_position, l_notused, l_result;
HRESULT dsresult;
dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
&l_play_position, &l_notused);
if( dsresult == DSERR_BUFFERLOST )
{
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
dsresult = IDirectSoundBuffer_GetCurrentPosition(
p_aout->p_sys->p_dsbuffer,
&l_play_position, &l_notused
);
}
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: WinDX aout_GetBufInfo cannot get current pos");
return( l_buffer_limit );
}
l_result = ((p_aout->p_sys->l_write_position >= l_play_position) ?
(p_aout->p_sys->l_write_position - l_play_position)/2
: (p_aout->p_sys->l_buffer_size - l_play_position
+ p_aout->p_sys->l_write_position)/2 );
intf_WarnMsg( 5, "aout: WinDX aout_GetBufInfo: %li", l_result);
return l_result;
}
/*****************************************************************************
* aout_Play: play a sound buffer
*****************************************************************************
* This function writes a buffer of i_length bytes
*****************************************************************************/
static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
{
VOID *p_write_position, *p_start_buffer;
long l_bytes1, l_bytes2;
long l_play_position, l_notused, l_buffer_free_length;
HRESULT dsresult;
/* We want to copy data to the circular sound buffer, so first we need to
* find out were in the buffer we can write our data */
dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
&l_play_position,
&l_notused);
if( dsresult == DSERR_BUFFERLOST )
{
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
dsresult = IDirectSoundBuffer_GetCurrentPosition(
p_aout->p_sys->p_dsbuffer,
&l_play_position, &l_notused
);
}
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: WinDX aout_Play can'get buffer position");
}
/* check that we are not overflowing the circular buffer (everything should
* be alright but just in case) */
l_buffer_free_length = l_play_position - p_aout->p_sys->l_write_position;
if( l_buffer_free_length <= 0 )
l_buffer_free_length += p_aout->p_sys->l_buffer_size ;
if( i_size > l_buffer_free_length )
{
intf_WarnMsg( 3, "aout: WinDX aout_Play buffer overflow: size %i, free %i !!!", i_size, l_buffer_free_length);
intf_WarnMsg( 3, "aout: WinDX aout_Play buffer overflow: writepos %i, readpos %i !!!", l_play_position, p_aout->p_sys->l_write_position);
/*i_size = l_buffer_free_length;*/
}
/* Before copying anything, we have to lock the buffer */
dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
p_aout->p_sys->l_write_position, /* Offset of lock start */
i_size, /* Number of bytes to lock */
&p_write_position, /* Address of lock start */
&l_bytes1, /* Count of bytes locked before wrap around */
&p_start_buffer, /* Buffer adress (if wrap around) */
&l_bytes2, /* Count of bytes after wrap around */
0); /* Flags */
if( dsresult == DSERR_BUFFERLOST )
{
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
p_aout->p_sys->l_write_position,
i_size,
&p_write_position,
&l_bytes1,
&p_start_buffer,
&l_bytes2,
0);
}
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: WinDX aout_Play can't lock buffer");
return;
}
/* Now do the actual memcopy (two memcpy because the buffer is circular) */
memcpy( p_write_position, buffer, l_bytes1 );
if( p_start_buffer != NULL )
memcpy( p_start_buffer, buffer + l_bytes1, l_bytes2 );
/* Now the data has been copied, unlock the buffer */
IDirectSoundBuffer_Unlock( p_aout->p_sys->p_dsbuffer,
p_write_position, l_bytes1, p_start_buffer, l_bytes2 );
/* Update the write position index of the buffer*/
p_aout->p_sys->l_write_position += i_size;
p_aout->p_sys->l_write_position %= p_aout->p_sys->l_buffer_size;
/* The play function has no effect if the buffer is already playing */
dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
0, /* Unused */
0, /* Unused */
DSBPLAY_LOOPING ); /* Flags */
if( dsresult == DSERR_BUFFERLOST )
{
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
0, /* Unused */
0, /* Unused */
DSBPLAY_LOOPING ); /* Flags */
}
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: WinDX aout_Play can't play buffer");
return;
}
}
/*****************************************************************************
* aout_Close: close the audio device
*****************************************************************************/
static void aout_Close( aout_thread_t *p_aout )
{
/* make sure the buffer isn't playing */
if( p_aout->p_sys->p_dsbuffer != NULL )
{
IDirectSoundBuffer_Stop( p_aout->p_sys->p_dsbuffer );
}
/* first release the secondary buffer */
if( p_aout->p_sys->p_dsbuffer != NULL )
{
IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer );
p_aout->p_sys->p_dsbuffer = NULL;
}
/* then release the primary buffer */
if( p_aout->p_sys->p_dsbuffer_primary != NULL )
{
IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer_primary );
p_aout->p_sys->p_dsbuffer_primary = NULL;
}
/* finally release the DirectSound object */
if( p_aout->p_sys->p_dsobject != NULL )
{
IDirectSound_Release( p_aout->p_sys->p_dsobject );
p_aout->p_sys->p_dsobject = NULL;
}
/* Close the Output. */
if ( p_aout->p_sys != NULL )
{
free( p_aout->p_sys );
p_aout->p_sys = NULL;
}
}
/*****************************************************************************
* windx_CreateSecondaryBuffer
*****************************************************************************
* This function creates the buffer we'll use to play audio.
* In DirectSound there are two kinds of buffers:
* - the primary buffer: which is the actual buffer that the soundcard plays
* - the secondary buffer(s): these buffers are the one actually used by
* applications and DirectSound takes care of mixing them into the primary.
*
* Once you create a secondary buffer, you cannot change its format anymore so
* you have to release the current and create another one.
*****************************************************************************/
static int windx_CreateSecondaryBuffer( aout_thread_t *p_aout )
{
WAVEFORMATEX waveformat;
DSBUFFERDESC dsbdesc;
DSBCAPS dsbcaps;
HRESULT dsresult;
/* First set the buffer format */
memset(&waveformat, 0, sizeof(WAVEFORMATEX));
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.nChannels = p_aout->i_channels;
waveformat.nSamplesPerSec = p_aout->l_rate;
waveformat.wBitsPerSample = 16;
waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 *
waveformat.nChannels;
waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec *
waveformat.nBlockAlign;
/* Then fill in the descriptor */
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GET