* directx.c: Windows DirectX audio output method
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: directx.c,v 1.21 2003/06/11 18:20:38 gbazin Exp $
+ * $Id: directx.c,v 1.22 2003/07/11 23:14:03 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
#include <dsound.h>
#define FRAME_SIZE 2048 /* The size is in samples, not in bytes */
-#define FRAMES_NUM 4
+#define FRAMES_NUM 8
/* frame buffer status */
#define FRAME_QUEUED 0
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
| DSBCAPS_CTRLPOSITIONNOTIFY /* We need notification */
- | DSBCAPS_GLOBALFOCUS; /* Allows background playing */
+ | DSBCAPS_GLOBALFOCUS /* Allows background playing */
+ | DSBCAPS_LOCHARDWARE; /* Needed for 5.1 on emu101k */
dsbdesc.dwBufferBytes = FRAMES_NUM * i_bytes_per_frame; /* buffer size */
dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&waveformat;
p_aout->output.p_sys->p_dsobject, &dsbdesc,
&p_aout->output.p_sys->p_dsbuffer, NULL) )
{
- return VLC_EGENERIC;
+ /* Try without DSBCAPS_LOCHARDWARE */
+ dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
+ if FAILED( IDirectSound_CreateSoundBuffer(
+ p_aout->output.p_sys->p_dsobject, &dsbdesc,
+ &p_aout->output.p_sys->p_dsbuffer, NULL) )
+ {
+ return VLC_EGENERIC;
+ }
+ if( !b_probe ) msg_Dbg( p_aout, "couldn't use hardware sound buffer" );
}
/* Stop here if we were just probing */
int i_channels, int i_nb_channels, int i_rate,
vlc_bool_t b_probe )
{
- if( CreateDSBuffer( p_aout, VLC_FOURCC('f','l','3','2'),
+ /* Float32 audio samples are not supported for 5.1 output on the emu101k */
+
+ if( i_nb_channels > 2 ||
+ CreateDSBuffer( p_aout, VLC_FOURCC('f','l','3','2'),
i_channels, i_nb_channels, i_rate,
FRAME_SIZE * 4 * i_nb_channels, b_probe )
!= VLC_SUCCESS )
* waveout.c : Windows waveOut plugin for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: waveout.c,v 1.25 2003/05/21 15:54:08 gbazin Exp $
+ * $Id: waveout.c,v 1.26 2003/07/11 23:14:03 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
#include <mmsystem.h>
#define FRAME_SIZE 1024 /* The size is in samples, not in bytes */
-#define FRAMES_NUM 4
+#define FRAMES_NUM 8
/*****************************************************************************
* Useful macros
static void Close ( vlc_object_t * );
static void Play ( aout_instance_t * );
+/*****************************************************************************
+ * notification_thread_t: waveOut event thread
+ *****************************************************************************/
+typedef struct notification_thread_t
+{
+ VLC_COMMON_MEMBERS
+ aout_instance_t *p_aout;
+
+} notification_thread_t;
+
/* local functions */
static void Probe ( aout_instance_t * );
static int OpenWaveOut ( aout_instance_t *, int, int, int, int, vlc_bool_t );
aout_buffer_t * );
static void CALLBACK WaveOutCallback ( HWAVEOUT, UINT, DWORD, DWORD, DWORD );
+static void WaveOutThread( notification_thread_t * );
static void InterleaveFloat32( float *, int *, int );
static void InterleaveS16( int16_t *, int *, int );
WAVEHDR waveheader[FRAMES_NUM];
+ notification_thread_t *p_notif; /* WaveOutThread id */
+ HANDLE event;
+
int i_buffer_size;
byte_t *p_silence_buffer; /* buffer we use to play silence */
memset( p_aout->output.p_sys->p_silence_buffer, 0,
p_aout->output.p_sys->i_buffer_size );
+ /* Now we need to setup our waveOut play notification structure */
+ p_aout->output.p_sys->p_notif =
+ vlc_object_create( p_aout, sizeof(notification_thread_t) );
+ p_aout->output.p_sys->p_notif->p_aout = p_aout;
+ p_aout->output.p_sys->event = CreateEvent( NULL, FALSE, FALSE, NULL );
+
+ /* Then launch the notification thread */
+ if( vlc_thread_create( p_aout->output.p_sys->p_notif,
+ "waveOut Notification Thread", WaveOutThread,
+ VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
+ {
+ msg_Err( p_aout, "cannot create WaveOutThread" );
+ }
+
/* We need to kick off the playback in order to have the callback properly
* working */
for( i = 0; i < FRAMES_NUM; i++ )
* This doesn't actually play the buffer. This just stores the buffer so it
* can be played by the callback thread.
*****************************************************************************/
-static void Play( aout_instance_t *p_aout )
+static void Play( aout_instance_t *_p_aout )
{
}
/* Before calling waveOutClose we must reset the device */
p_aout->b_die = VLC_TRUE;
+ /* wake up the audio thread */
+ SetEvent( p_aout->output.p_sys->event );
+ vlc_thread_join( p_aout->output.p_sys->p_notif );
+ CloseHandle( p_aout->output.p_sys->event );
+
/* Wait for the waveout buffers to be freed */
while( VLC_TRUE )
{
{
aout_instance_t *p_aout = (aout_instance_t *)_p_aout;
WAVEHDR *p_waveheader = (WAVEHDR *)dwParam1;
- aout_buffer_t *p_buffer = NULL;
- vlc_bool_t b_sleek;
int i, i_queued_frames = 0;
if( uMsg != WOM_DONE ) return;
if( p_aout->b_die ) return;
- /* We don't want any resampling when using S/PDIF */
- b_sleek = p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i');
-
/* Find out the current latency */
for( i = 0; i < FRAMES_NUM; i++ )
{
}
}
- /* Try to fill in as many frame buffers as possible */
- for( i = 0; i < FRAMES_NUM; i++ )
- {
- /* Check if frame buf is available */
- if( p_aout->output.p_sys->waveheader[i].dwFlags & WHDR_DONE )
- {
- /* Take into account the latency */
- p_buffer = aout_OutputNextBuffer( p_aout,
- mdate() + 1000000 * i_queued_frames /
- p_aout->output.output.i_rate * p_aout->output.i_nb_samples,
- b_sleek );
-
- if( !p_buffer && i_queued_frames )
- {
- /* We aren't late so no need to play a blank sample */
- return;
- }
-
- /* Do the channel reordering here */
- if( p_buffer && p_aout->output.p_sys->b_chan_reorder )
- {
- if( p_aout->output.output.i_format ==
- VLC_FOURCC('s','1','6','l') )
- InterleaveS16( (int16_t *)p_buffer->p_buffer,
- p_aout->output.p_sys->pi_chan_table,
- aout_FormatNbChannels( &p_aout->output.output ) );
- else
- InterleaveFloat32( (float *)p_buffer->p_buffer,
- p_aout->output.p_sys->pi_chan_table,
- aout_FormatNbChannels( &p_aout->output.output ) );
- }
-
- PlayWaveOut( p_aout, h_waveout,
- &p_aout->output.p_sys->waveheader[i] , p_buffer );
-
- i_queued_frames++;
- }
- }
+ /* Don't wake up the thread too much */
+ if( i_queued_frames < FRAMES_NUM / 2 )
+ SetEvent( p_aout->output.p_sys->event );
}
/*****************************************************************************
i_nb_channels * sizeof(int16_t) );
}
}
+
+/*****************************************************************************
+ * WaveOutThread: this thread will capture play notification events.
+ *****************************************************************************
+ * We use this thread to feed new audio samples to the sound card because
+ * we are not authorized to use waveOutWrite() directly in the waveout
+ * callback.
+ *****************************************************************************/
+static void WaveOutThread( notification_thread_t *p_notif )
+{
+ aout_instance_t *p_aout = p_notif->p_aout;
+ aout_buffer_t *p_buffer = NULL;
+ vlc_bool_t b_sleek;
+ int i, i_queued_frames;
+
+ /* We don't want any resampling when using S/PDIF */
+ b_sleek = p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i');
+
+ while( 1 )
+ {
+ WaitForSingleObject( p_aout->output.p_sys->event, INFINITE );
+ if( p_aout->b_die ) return;
+
+ /* Find out the current latency */
+ i_queued_frames = 0;
+ for( i = 0; i < FRAMES_NUM; i++ )
+ {
+ /* Check if frame buf is available */
+ if( !(p_aout->output.p_sys->waveheader[i].dwFlags & WHDR_DONE) )
+ {
+ i_queued_frames++;
+ }
+ }
+
+ /* Try to fill in as many frame buffers as possible */
+ for( i = 0; i < FRAMES_NUM; i++ )
+ {
+ /* Check if frame buf is available */
+ if( p_aout->output.p_sys->waveheader[i].dwFlags & WHDR_DONE )
+ {
+ /* Take into account the latency */
+ p_buffer = aout_OutputNextBuffer( p_aout,
+ mdate() + 1000000 * i_queued_frames /
+ p_aout->output.output.i_rate * p_aout->output.i_nb_samples,
+ b_sleek );
+
+ if( !p_buffer && i_queued_frames )
+ {
+ /* We aren't late so no need to play a blank sample */
+ break;
+ }
+
+ /* Do the channel reordering here */
+ if( p_buffer && p_aout->output.p_sys->b_chan_reorder )
+ {
+ if( p_aout->output.output.i_format ==
+ VLC_FOURCC('s','1','6','l') )
+ InterleaveS16( (int16_t *)p_buffer->p_buffer,
+ p_aout->output.p_sys->pi_chan_table,
+ aout_FormatNbChannels( &p_aout->output.output ) );
+ else
+ InterleaveFloat32( (float *)p_buffer->p_buffer,
+ p_aout->output.p_sys->pi_chan_table,
+ aout_FormatNbChannels( &p_aout->output.output ) );
+ }
+
+ PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout,
+ &p_aout->output.p_sys->waveheader[i] , p_buffer );
+
+ i_queued_frames++;
+ }
+ }
+ }
+}