* waveout.c : Windows waveOut plugin for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: waveout.c,v 1.2 2002/08/10 18:17:06 gbazin Exp $
+ * $Id: waveout.c,v 1.11 2002/11/15 16:27:10 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
#include <vlc/aout.h>
#include "aout_internal.h"
+#include <windows.h>
#include <mmsystem.h>
-#define FRAME_SIZE 2048 /* The size is in samples, not in bytes */
+#define FRAME_SIZE 1024 /* The size is in samples, not in bytes */
+#define FRAMES_NUM 4
+
+/*****************************************************************************
+ * Useful macros
+ *****************************************************************************/
+#ifndef WAVE_FORMAT_IEEE_FLOAT
+# define WAVE_FORMAT_IEEE_FLOAT 0x0003
+#endif
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
-
-static int SetFormat ( aout_instance_t * );
-static void Play ( aout_instance_t *, aout_buffer_t * );
+static void Play ( aout_instance_t * );
/* local functions */
static int OpenWaveOut ( aout_instance_t *p_aout, int i_format,
WAVEFORMATEX waveformat; /* audio format */
- WAVEHDR waveheader[2];
+ WAVEHDR waveheader[FRAMES_NUM];
int i_buffer_size;
static int Open( vlc_object_t *p_this )
{
aout_instance_t *p_aout = (aout_instance_t *)p_this;
+ int i_nb_channels, i;
/* Allocate structure */
p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->output.p_sys == NULL )
{
msg_Err( p_aout, "out of memory" );
- return 1;
+ return VLC_EGENERIC;
}
- p_aout->output.pf_setformat = SetFormat;
p_aout->output.pf_play = Play;
+ aout_VolumeSoftInit( p_aout );
- /* calculate the frame size in bytes */
- p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * sizeof(s16)
- * p_aout->output.p_sys->waveformat.nChannels;
- /* Allocate silence buffer */
- p_aout->output.p_sys->p_silence_buffer =
- calloc( p_aout->output.p_sys->i_buffer_size, 1 );
- if( p_aout->output.p_sys->p_silence_buffer == NULL )
+ i_nb_channels = aout_FormatNbChannels( &p_aout->output.output );
+ if ( i_nb_channels >= 2 )
{
- msg_Err( p_aout, "out of memory" );
- return 1;
+ i_nb_channels = 2;
+ p_aout->output.output.i_physical_channels =
+ AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+ }
+ else
+ {
+ i_nb_channels = 1;
+ p_aout->output.output.i_physical_channels =
+ AOUT_CHAN_CENTER;
}
/* We need to open the device with default values to be sure it is
* available */
- return OpenWaveOut( p_aout, WAVE_FORMAT_PCM, 2, 44100 );
-}
+ p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2');
+ if ( OpenWaveOut( p_aout, WAVE_FORMAT_IEEE_FLOAT, i_nb_channels,
+ p_aout->output.output.i_rate ) )
+ {
+ msg_Err( p_aout, "Audio device doesn't allow WAVE_FORMAT_IEEE_FLOAT" );
-/*****************************************************************************
- * SetFormat: reset the audio device and sets its format
- *****************************************************************************
- * This functions set a new audio format.
- * For this we need to close the current device and create another
- * one with the desired format.
- *****************************************************************************/
-static int SetFormat( aout_instance_t *p_aout )
-{
- msg_Dbg( p_aout, "SetFormat" );
+ p_aout->output.output.i_format = VLC_FOURCC('s','1','6','l');
+ if ( OpenWaveOut( p_aout, WAVE_FORMAT_PCM, i_nb_channels,
+ p_aout->output.output.i_rate ) )
+ {
+ msg_Err( p_aout, "cannot open waveout audio device" );
+ return VLC_EGENERIC;
+ }
+ }
waveOutReset( p_aout->output.p_sys->h_waveout );
- p_aout->output.output.i_format = AOUT_FMT_S16_NE;
+ /* Calculate the frame size in bytes */
p_aout->output.i_nb_samples = FRAME_SIZE;
-
- /* Check if the format has changed */
- if( (p_aout->output.p_sys->waveformat.nChannels !=
- p_aout->output.output.i_channels) ||
- (p_aout->output.p_sys->waveformat.nSamplesPerSec !=
- p_aout->output.output.i_rate) )
+ aout_FormatPrepare( &p_aout->output.output );
+ p_aout->output.p_sys->i_buffer_size = FRAME_SIZE *
+ p_aout->output.output.i_bytes_per_frame;
+ /* Allocate silence buffer */
+ p_aout->output.p_sys->p_silence_buffer =
+ calloc( p_aout->output.p_sys->i_buffer_size, 1 );
+ if( p_aout->output.p_sys->p_silence_buffer == NULL )
{
- if( waveOutClose( p_aout->output.p_sys->h_waveout ) !=
- MMSYSERR_NOERROR )
- {
- msg_Err( p_aout, "waveOutClose failed" );
- }
-
- /* calculate the frame size in bytes */
- p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * sizeof(s16)
- * p_aout->output.output.i_channels;
-
- /* take care of silence buffer */
- free( p_aout->output.p_sys->p_silence_buffer );
- p_aout->output.p_sys->p_silence_buffer =
- calloc( p_aout->output.p_sys->i_buffer_size, 1 );
- if( p_aout->output.p_sys->p_silence_buffer == NULL )
- {
- msg_Err( p_aout, "out of memory" );
- return 1;
- }
-
- if( OpenWaveOut( p_aout, WAVE_FORMAT_PCM,
- p_aout->output.output.i_channels,
- p_aout->output.output.i_rate ) )
- return 1;
+ msg_Err( p_aout, "out of memory" );
+ return 1;
}
/* We need to kick off the playback in order to have the callback properly
* working */
- PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout,
- &p_aout->output.p_sys->waveheader[0], NULL );
- PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout,
- &p_aout->output.p_sys->waveheader[1], NULL );
-
+ for( i = 0; i < FRAMES_NUM; i++ )
+ {
+ PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout,
+ &p_aout->output.p_sys->waveheader[i], NULL );
+ }
return 0;
}
* 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, aout_buffer_t *p_buffer )
+static void Play( aout_instance_t *p_aout )
{
- aout_FifoPush( p_aout, &p_aout->output.fifo, p_buffer );
}
/*****************************************************************************
aout_instance_t *p_aout = (aout_instance_t *)p_this;
/* Before calling waveOutClose we must reset the device */
- waveOutReset( p_aout->output.p_sys->h_waveout );
+ p_aout->b_die = VLC_TRUE;
+ //Hmmm, waveOutReset never seems to return... why ???
+ //waveOutReset( p_aout->output.p_sys->h_waveout );
+
+ /* Wait for the waveout buffers to be freed */
+ while( !(p_aout->output.p_sys->waveheader[0].dwFlags & WHDR_DONE) ||
+ !(p_aout->output.p_sys->waveheader[1].dwFlags & WHDR_DONE) )
+ {
+ msleep( 1000 );
+ }
/* Close the device */
if( waveOutClose( p_aout->output.p_sys->h_waveout ) != MMSYSERR_NOERROR )
/* Free silence buffer */
free( p_aout->output.p_sys->p_silence_buffer );
- if( p_aout->output.p_sys != NULL )
- {
- free( p_aout->output.p_sys );
- p_aout->output.p_sys = NULL;
- }
+ free( p_aout->output.p_sys );
}
/*****************************************************************************
p_aout->output.p_sys->waveformat.wFormatTag = i_format;
p_aout->output.p_sys->waveformat.nChannels = i_channels;
p_aout->output.p_sys->waveformat.nSamplesPerSec = i_rate;
- p_aout->output.p_sys->waveformat.wBitsPerSample = 16;
+
+ switch( i_format )
+ {
+ case WAVE_FORMAT_PCM:
+ p_aout->output.p_sys->waveformat.wBitsPerSample = 16;
+ break;
+ case WAVE_FORMAT_IEEE_FLOAT:
+ p_aout->output.p_sys->waveformat.wBitsPerSample = sizeof(float) * 8;
+ break;
+ }
+
p_aout->output.p_sys->waveformat.nBlockAlign =
p_aout->output.p_sys->waveformat.wBitsPerSample / 8 * i_channels;
p_aout->output.p_sys->waveformat.nAvgBytesPerSec =
DWORD _p_aout,
DWORD dwParam1, DWORD dwParam2 )
{
- aout_instance_t * p_aout = (aout_instance_t *)_p_aout;
+ aout_instance_t *p_aout = (aout_instance_t *)_p_aout;
WAVEHDR *p_waveheader = (WAVEHDR *)dwParam1;
- aout_buffer_t * p_buffer;
+ aout_buffer_t *p_buffer;
if( uMsg != WOM_DONE ) return;
if( p_waveheader->dwUser )
aout_BufferFree( (aout_buffer_t *)p_waveheader->dwUser );
- /* FIXME : take into account WaveOut latency instead of mdate() */
- p_buffer = aout_OutputNextBuffer( p_aout, mdate() );
+ if( p_aout->b_die ) return;
+
+ /* Take into account WaveOut latency ( 1 FRAME ) */
+ p_buffer = aout_OutputNextBuffer( p_aout,
+ mdate() + 1000000 / p_aout->output.output.i_rate * FRAME_SIZE,
+ VLC_FALSE );
PlayWaveOut( p_aout, h_waveout, p_waveheader, p_buffer );
}