-- initial support for ac3+wma spdif passthrough for pa_win_wmme. see flags
in pa_win_wmme.h. flags currently work for OpenStream but are ignored for
IsFormatSupported
-- wmme host api: take account of paWinMmeWaveFormatDolbyAc3Spdif and
paWinMmeWaveFormatWmaSpdif flags in Pa_IsFormatSupported
-- added patest_wmme_ac3.cp test for wmme ac3 spdif passthrough
-- minor code logic cleanup
-- always disable wmme clip and dither if an spdif passthrough wave format
is requested
-- added notes to pa_test_ac3.c that the test stream file must include the
correct spdif preamble on every ac3 frame
-- fixed bug in asio blocking i/o stream initialization which would cause
crash (bad ptr). enabled timeout code in read/writestream. patch from sven
fischer
-- fixed inputBufferAdcTime calculation for AdaptingInputOnlyProcess. patch
from Yann.
-- fixed a bug in WAVEFORMATEX casts, and warnings on sprintf
-- added pragma to autolink libwinmm with msvc to get timeGetTime symbol
when only using ASIO. thanks Yann
-- fix for half duplex and build issues from Toni Wilen.
-- Apply Kevin Kofler's non-mmap patch
-- Clarify hostapi ordering somewhat
-- Add PA ALSA extension to allow setting number of retries when busy
-- Fix latency calculation in PA ALSA
http://code.google.com/p/sipxtapi/source/detail?r=1372
Added:
/trunk/sipXmediaLib/contrib/portaudio_v19/test/patest_wmme_ac3.c
Modified:
/trunk/sipXmediaLib/contrib/portaudio_v19/include/pa_linux_alsa.h
/trunk/sipXmediaLib/contrib/portaudio_v19/include/pa_win_waveformat.h
/trunk/sipXmediaLib/contrib/portaudio_v19/include/pa_win_wmme.h
/trunk/sipXmediaLib/contrib/portaudio_v19/src/common/pa_process.c
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/alsa/pa_linux_alsa.c
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/asio/pa_asio.cpp
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/dsound/pa_win_ds.c
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/wasapi/pa_win_wasapi.cpp
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/wdmks/pa_win_wdmks.c
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/wmme/pa_win_wmme.c
/trunk/sipXmediaLib/contrib/portaudio_v19/src/os/unix/pa_unix_hostapis.c
/trunk/sipXmediaLib/contrib/portaudio_v19/src/os/win/pa_win_util.c
/trunk/sipXmediaLib/contrib/portaudio_v19/src/os/win/pa_win_waveformat.c
=======================================
--- /dev/null
+++ /trunk/sipXmediaLib/contrib/portaudio_v19/test/patest_wmme_ac3.c Fri
Jan 22 12:18:54 2010
@@ -0,0 +1,217 @@
+/*
+ * $Id: $
+ * Portable Audio I/O Library
+ * Windows MME ac3 sound output test
+ *
+ * Copyright (c) 2009 Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#include <windows.h> /* required when using pa_win_wmme.h */
+#include <mmsystem.h> /* required when using pa_win_wmme.h */
+
+#include "portaudio.h"
+#include "pa_win_wmme.h"
+
+#define NUM_SECONDS (20)
+#define SAMPLE_RATE (48000)
+#define FRAMES_PER_BUFFER (64)
+
+#ifndef M_PI
+#define M_PI (3.14159265)
+#endif
+
+#define TABLE_SIZE (100)
+
+#define CHANNEL_COUNT (2)
+
+
+
+typedef struct
+{
+ short *buffer;
+ int bufferSampleCount;
+ int playbackIndex;
+}
+paTestData;
+
+/* This routine will be called by the PortAudio engine when audio is
needed.
+** It may called at interrupt level on some machines so don't do anything
+** that could mess up the system like calling malloc() or free().
+*/
+static int patestCallback( const void *inputBuffer, void *outputBuffer,
+ unsigned long framesPerBuffer,
+ const PaStreamCallbackTimeInfo* timeInfo,
+ PaStreamCallbackFlags statusFlags,
+ void *userData )
+{
+ paTestData *data = (paTestData*)userData;
+ short *out = (short*)outputBuffer;
+ unsigned long i,j;
+
+ (void) timeInfo; /* Prevent unused variable warnings. */
+ (void) statusFlags;
+ (void) inputBuffer;
+
+ /* stream out contents of data->buffer looping at end */
+
+ for( i=0; i<framesPerBuffer; i++ )
+ {
+ for( j = 0; j < CHANNEL_COUNT; ++j ){
+ *out++ = data->buffer[ data->playbackIndex++ ];
+
+ if( data->playbackIndex >= data->bufferSampleCount )
+ data->playbackIndex = 0; /* loop at end of buffer */
+ }
+ }
+
+ return paContinue;
+}
+
+/*******************************************************************/
+int main(int argc, char* argv[])
+{
+ PaStreamParameters outputParameters;
+ PaWinMmeStreamInfo wmmeStreamInfo;
+ PaStream *stream;
+ PaError err;
+ paTestData data;
+ int i;
+ int deviceIndex;
+ FILE *fp;
+ const char *fileName = "c:\\test_48k.ac3.spdif";
+ data.buffer = NULL;
+
+ printf("usage: patest_wmme_ac3 fileName [paDeviceIndex]\n");
+ printf("**IMPORTANT*** The provided file must include the spdif
preamble at the start of every AC-3 frame. Using a normal ac3 file won't
work."
+ printf("PortAudio Test: output a raw spdif ac3 stream. SR = %d,
BufSize = %d, Chans = %d\n",
+ SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);
+
+
+ if( argc >= 2 )
+ fileName = argv[1];
+
+ printf( "reading spdif ac3 raw stream file %s\n", fileName );
+
+ fp = fopen( fileName, "rb" );
+ if( !fp ){
+ fprintf( stderr, "error opening spdif ac3 file.\n" );
+ return -1;
+ }
+ /* get file size */
+ fseek( fp, 0, SEEK_END );
+ data.bufferSampleCount = ftell( fp ) / sizeof(short);
+ fseek( fp, 0, SEEK_SET );
+
+ /* allocate buffer, read the whole file into memory */
+ data.buffer = (short*)malloc( data.bufferSampleCount * sizeof(short) );
+ if( !data.buffer ){
+ fprintf( stderr, "error allocating buffer.\n" );
+ return -1;
+ }
+
+ fread( data.buffer, sizeof(short), data.bufferSampleCount, fp );
+ fclose( fp );
+
+ data.playbackIndex = 0;
+
+ err = Pa_Initialize();
+ if( err != paNoError ) goto error;
+
+ deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME )
)->defaultOutputDevice;
+ if( argc >= 3 ){
+ sscanf( argv[1], "%d", &deviceIndex );
+ }
+
+ printf( "using device id %d (%s)\n", deviceIndex,
Pa_GetDeviceInfo(deviceIndex)->name );
+
+
+ outputParameters.device = deviceIndex;
+ outputParameters.channelCount = CHANNEL_COUNT;
+ outputParameters.sampleFormat = paInt16; /* IMPORTANT must use paInt16
for WMME AC3 */
+ outputParameters.suggestedLatency = Pa_GetDeviceInfo(
outputParameters.device )->defaultLowOutputLatency;
+ outputParameters.hostApiSpecificStreamInfo = NULL;
+
+ wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);
+ wmmeStreamInfo.hostApiType = paMME;
+ wmmeStreamInfo.version = 1;
+ wmmeStreamInfo.flags = paWinMmeWaveFormatDolbyAc3Spdif;
+ outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;
+
+
+ if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) ==
paFormatIsSupported ){
+ printf( "Pa_IsFormatSupported reports device will support %d
channels.\n", CHANNEL_COUNT );
+ }else{
+ printf( "Pa_IsFormatSupported reports device will not support %d
channels.\n", CHANNEL_COUNT );
+ }
+
+ err = Pa_OpenStream(
+ &stream,
+ NULL, /* no input */
+ &outputParameters,
+ SAMPLE_RATE,
+ FRAMES_PER_BUFFER,
+ 0,
+ patestCallback,
+ &data );
+ if( err != paNoError ) goto error;
+
+ err = Pa_StartStream( stream );
+ if( err != paNoError ) goto error;
+
+ printf("Play for %d seconds.\n", NUM_SECONDS );
+ Pa_Sleep( NUM_SECONDS * 1000 );
+
+ err = Pa_StopStream( stream );
+ if( err != paNoError ) goto error;
+
+ err = Pa_CloseStream( stream );
+ if( err != paNoError ) goto error;
+
+ Pa_Terminate();
+ free( data.buffer );
+ printf("Test finished.\n");
+
+ return err;
+error:
+ Pa_Terminate();
+ free( data.buffer );
+
+ fprintf( stderr, "An error occured while using the portaudio stream\n"
);
+ fprintf( stderr, "Error number: %d\n", err );
+ fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
+ return err;
+}
+
=======================================
--- /trunk/sipXmediaLib/contrib/portaudio_v19/include/pa_linux_alsa.h Wed
Oct 22 11:32:45 2008
+++ /trunk/sipXmediaLib/contrib/portaudio_v19/include/pa_linux_alsa.h Fri
Jan 22 12:18:54 2010
@@ -87,6 +87,11 @@
*/
PaError PaAlsa_SetNumPeriods( int numPeriods );
+/** Set the maximum number of times to retry opening busy device (sleeping
for a
+ * short interval inbetween).
+ */
+PaError PaAlsa_SetRetriesBusy( int retries );
+
#ifdef __cplusplus
}
#endif
=======================================
--- /trunk/sipXmediaLib/contrib/portaudio_v19/include/pa_win_waveformat.h
Wed Oct 22 11:32:45 2008
+++ /trunk/sipXmediaLib/contrib/portaudio_v19/include/pa_win_waveformat.h
Fri Jan 22 12:18:54 2010
@@ -157,16 +157,34 @@
#define PAWIN_INDEXOF_DWCHANNELMASK (PAWIN_SIZEOF_WAVEFORMATEX+2)
#define PAWIN_INDEXOF_SUBFORMAT (PAWIN_SIZEOF_WAVEFORMATEX+6)
+
+/*
+ Valid values to pass for the waveFormatTag
PaWin_InitializeWaveFormatEx and
+ PaWin_InitializeWaveFormatExtensible functions below. These must match
+ the standard Windows WAVE_FORMAT_* values.
+*/
+#define PAWIN_WAVE_FORMAT_PCM (1)
+#define PAWIN_WAVE_FORMAT_IEEE_FLOAT (3)
+#define PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF (0x0092)
+#define PAWIN_WAVE_FORMAT_WMA_SPDIF (0x0164)
+
+
+/*
+ returns PAWIN_WAVE_FORMAT_PCM or PAWIN_WAVE_FORMAT_IEEE_FLOAT
+ depending on the sampleFormat parameter.
+*/
+int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat );
+
/*
Use the following two functions to initialize the waveformat structure.
*/
void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat,
- int numChannels, PaSampleFormat sampleFormat, double sampleRate );
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double
sampleRate );
void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
- int numChannels, PaSampleFormat sampleFormat, double sampleRate,
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double
sampleRate,
PaWinWaveFormatChannelMask channelMask );
=======================================
--- /trunk/sipXmediaLib/contrib/portaudio_v19/include/pa_win_wmme.h Wed Oct
22 11:32:45 2008
+++ /trunk/sipXmediaLib/contrib/portaudio_v19/include/pa_win_wmme.h Fri Jan
22 12:18:54 2010
@@ -53,6 +53,10 @@
#endif /* __cplusplus */
+/* The following are flags which can be set in
+ PaWinMmeStreamInfo's flags field.
+*/
+
#define paWinMmeUseLowLevelLatencyParameters (0x01)
#define paWinMmeUseMultipleDevices (0x02) /* use mme
specific multiple device feature */
#define paWinMmeUseChannelMask (0x04)
@@ -64,6 +68,11 @@
*/
#define paWinMmeDontThrottleOverloadedProcessingThread (0x08)
+/* Flags for non-PCM spdif passthrough.
+*/
+#define paWinMmeWaveFormatDolbyAc3Spdif (0x10)
+#define paWinMmeWaveFormatWmaSpdif (0x20)
+
typedef struct PaWinMmeDeviceAndChannelCount{
PaDeviceIndex device;
=======================================
--- /trunk/sipXmediaLib/contrib/portaudio_v19/src/common/pa_process.c Wed
Oct 22 11:32:45 2008
+++ /trunk/sipXmediaLib/contrib/portaudio_v19/src/common/pa_process.c Fri
Jan 22 12:18:54 2010
@@ -997,7 +997,7 @@
bp->framesPerUserBuffer, bp->timeInfo,
bp->callbackStatusFlags, bp->userData );
- bp->timeInfo->inputBufferAdcTime += frameCount *
bp->samplePeriod;
+ bp->timeInfo->inputBufferAdcTime +=
bp->framesPerUserBuffer * bp->samplePeriod;
}
bp->framesInTempInputBuffer = 0;
=======================================
---
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/alsa/pa_linux_alsa.c
Wed Oct 22 11:32:45 2008
+++
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/alsa/pa_linux_alsa.c
Fri Jan 22 12:18:54 2010
@@ -5,7 +5,8 @@
* ALSA implementation by Joshua Haberman and Arve Knudsen
*
* Copyright (c) 2002 Joshua Haberman <jos...@haberman.com>
- * Copyright (c) 2005-2007 Arve Knudsen <aknu...@broadpark.no>
+ * Copyright (c) 2005-2009 Arve Knudsen <arve.k...@gmail.com>
+ * Copyright (c) 2008 Kevin Kofler <kevin....@chello.at>
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
@@ -99,6 +100,7 @@
static int aErr_; /* Used with ENSURE_ */
static int numPeriods_ = 4;
+static int busyRetries_ = 100;
int PaAlsa_SetNumPeriods( int numPeriods )
{
@@ -118,6 +120,8 @@
unsigned long framesPerBuffer;
int numUserChannels, numHostChannels;
int userInterleaved, hostInterleaved;
+ int canMmap;
+ void *nonMmapBuffer;
PaDeviceIndex device; /* Keep the device index */
snd_pcm_t *pcm;
@@ -321,7 +325,7 @@
* and a suitable result returned. The device is closed before returning.
*/
static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection
mode, int openBlocking,
- PaAlsaDeviceInfo* devInfo, int* canMmap )
+ PaAlsaDeviceInfo* devInfo )
{
PaError result = paNoError;
snd_pcm_hw_params_t *hwParams;
@@ -354,9 +358,6 @@
snd_pcm_hw_params_alloca( &hwParams );
snd_pcm_hw_params_any( pcm, hwParams );
- *canMmap = snd_pcm_hw_params_test_access( pcm, hwParams,
SND_PCM_ACCESS_MMAP_INTERLEAVED ) >= 0 ||
- snd_pcm_hw_params_test_access( pcm, hwParams,
SND_PCM_ACCESS_MMAP_NONINTERLEAVED ) >= 0;
-
if( defaultSr >= 0 )
{
/* Could be that the device opened in one mode supports
samplerates that the other mode wont have,
@@ -539,7 +540,7 @@
**/
static int OpenPcm( snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t
stream, int mode, int waitOnBusy )
{
- int tries = 0, maxTries = waitOnBusy ? 100 : 0;
+ int tries = 0, maxTries = waitOnBusy ? busyRetries_ : 0;
int ret = snd_pcm_open( pcmp, name, stream, mode );
for( tries = 0; tries < maxTries && -EBUSY == ret; ++tries )
{
@@ -566,7 +567,6 @@
PaError result = 0;
PaDeviceInfo *baseDeviceInfo = &devInfo->baseDeviceInfo;
snd_pcm_t *pcm;
- int canMmap = -1;
PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep;
/* Zero fields */
@@ -580,8 +580,7 @@
OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_CAPTURE,
blocking, 0 )
>= 0 )
{
- if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In,
blocking, devInfo,
- &canMmap ) != paNoError )
+ if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In,
blocking, devInfo ) != paNoError )
{
/* Error */
PA_DEBUG(("%s: Failed groping %s for capture\n", __FUNCTION__,
deviceName->alsaName));
@@ -594,20 +593,13 @@
OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_PLAYBACK,
blocking, 0 )
>= 0 )
{
- if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out,
blocking, devInfo,
- &canMmap ) != paNoError )
+ if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out,
blocking, devInfo ) != paNoError )
{
/* Error */
PA_DEBUG(("%s: Failed groping %s for playback\n",
__FUNCTION__, deviceName->alsaName));
goto end;
}
}
-
- if( 0 == canMmap )
- {
- PA_DEBUG(("%s: Device %s doesn't support mmap\n", __FUNCTION__,
deviceName->alsaName));
- goto end;
- }
baseDeviceInfo->structVersion = 2;
baseDeviceInfo->hostApi = alsaApi->hostApiIndex;
@@ -1197,6 +1189,8 @@
self->hostInterleaved = self->userInterleaved = !(userSampleFormat &
paNonInterleaved);
self->numUserChannels = params->channelCount;
self->streamDir = streamDir;
+ self->canMmap = 0;
+ self->nonMmapBuffer = NULL;
if( !callbackMode && !self->userInterleaved )
{
@@ -1239,6 +1233,7 @@
PaError result = paNoError;
snd_pcm_access_t accessMode, alternateAccessMode;
+ snd_pcm_access_t rwAccessMode, alternateRwAccessMode;
int dir = 0;
snd_pcm_t *pcm = self->pcm;
double sr = *sampleRate;
@@ -1258,32 +1253,40 @@
if( self->userInterleaved )
{
accessMode = SND_PCM_ACCESS_MMAP_INTERLEAVED;
+ rwAccessMode = SND_PCM_ACCESS_RW_INTERLEAVED;
alternateAccessMode = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
+ alternateRwAccessMode = SND_PCM_ACCESS_RW_NONINTERLEAVED;
}
else
{
accessMode = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
+ rwAccessMode = SND_PCM_ACCESS_RW_NONINTERLEAVED;
alternateAccessMode = SND_PCM_ACCESS_MMAP_INTERLEAVED;
+ alternateRwAccessMode = SND_PCM_ACCESS_RW_INTERLEAVED;
}
/* If requested access mode fails, try alternate mode */
+ self->canMmap = 1;
if( snd_pcm_hw_params_set_access( pcm, hwParams, accessMode ) < 0 )
{
- int err = 0;
- if( (err = snd_pcm_hw_params_set_access( pcm, hwParams,
alternateAccessMode )) < 0)
- {
- result = paUnanticipatedHostError;
- if( -EINVAL == err )
- {
- PaUtil_SetLastHostErrorInfo( paALSA, err, "PA ALSA
requires that a device supports mmap access" );
- }
- else
- {
- PaUtil_SetLastHostErrorInfo( paALSA, err, snd_strerror(
err ) );
- }
- goto error;
- }
- /* Flip mode */
- self->hostInterleaved = !self->userInterleaved;
+ if( snd_pcm_hw_params_set_access( pcm, hwParams, rwAccessMode ) >=
0 )
+ self->canMmap = 0;
+ else
+ {
+ if( snd_pcm_hw_params_set_access( pcm, hwParams,
alternateAccessMode ) < 0 )
+ {
+ int err = 0;
+ if( (err = snd_pcm_hw_params_set_access( pcm, hwParams,
alternateRwAccessMode )) >= 0)
+ self->canMmap = 0;
+ else
+ {
+ result = paUnanticipatedHostError;
+ PaUtil_SetLastHostErrorInfo( paALSA, err,
snd_strerror( err ) );
+ goto error;
+ }
+ }
+ /* Flip mode */
+ self->hostInterleaved = !self->userInterleaved;
+ }
}
ENSURE_( snd_pcm_hw_params_set_format( pcm, hwParams,
self->nativeFormat ), paUnanticipatedHostError );
@@ -1361,7 +1364,7 @@
ENSURE_( snd_pcm_sw_params_set_avail_min( self->pcm, swParams,
self->framesPerBuffer ), paUnanticipatedHostError );
ENSURE_( snd_pcm_sw_params_set_xfer_align( self->pcm, swParams, 1 ),
paUnanticipatedHostError );
- ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams,
SND_PCM_TSTAMP_MMAP ), paUnanticipatedHostError );
+ ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams,
SND_PCM_TSTAMP_ENABLE ), paUnanticipatedHostError );
/* Set the parameters! */
ENSURE_( snd_pcm_sw_params( self->pcm, swParams ),
paUnanticipatedHostError );
@@ -1588,6 +1591,10 @@
framesPerHostBuffer = bufferSize / numPeriods;
}
}
+
+ /* non-mmap mode needs a reasonably-sized buffer or it'll stutter */
+ if( !self->canMmap && framesPerHostBuffer < 2048 )
+ framesPerHostBuffer = 2048;
assert( framesPerHostBuffer > 0 );
{
@@ -1831,12 +1838,13 @@
PA_UNLESS( framesPerHostBuffer != 0, paInternalError );
self->maxFramesPerHostBuffer = framesPerHostBuffer;
- if( !accurate )
+ if( !self->playback.canMmap || !accurate )
{
/* Don't know the exact size per host buffer */
*hostBufferSizeMode = paUtilBoundedHostBufferSize;
/* Raise upper bound */
- ++self->maxFramesPerHostBuffer;
+ if( !accurate )
+ ++self->maxFramesPerHostBuffer;
}
error:
@@ -1995,11 +2003,11 @@
/* Ok, buffer processor is initialized, now we can deduce it's latency
*/
if( numInputChannels > 0 )
- stream->streamRepresentation.streamInfo.inputLatency =
inputLatency + PaUtil_GetBufferProcessorInputLatency(
- &stream->bufferProcessor );
+ stream->streamRepresentation.streamInfo.inputLatency =
inputLatency + (PaTime)(
+ PaUtil_GetBufferProcessorInputLatency(
&stream->bufferProcessor ) / sampleRate);
if( numOutputChannels > 0 )
- stream->streamRepresentation.streamInfo.outputLatency =
outputLatency + PaUtil_GetBufferProcessorOutputLatency(
- &stream->bufferProcessor );
+ stream->streamRepresentation.streamInfo.outputLatency =
outputLatency + (PaTime)(
+ PaUtil_GetBufferProcessorOutputLatency(
&stream->bufferProcessor ) / sampleRate);
*s = (PaStream*)stream;
@@ -2059,9 +2067,11 @@
{
/* Buffer isn't primed, so prepare and silence */
ENSURE_( snd_pcm_prepare( stream->playback.pcm ),
paUnanticipatedHostError );
- SilenceBuffer( stream );
- }
- ENSURE_( snd_pcm_start( stream->playback.pcm ),
paUnanticipatedHostError );
+ if( stream->playback.canMmap )
+ SilenceBuffer( stream );
+ }
+ if( stream->playback.canMmap )
+ ENSURE_( snd_pcm_start( stream->playback.pcm ),
paUnanticipatedHostError );
}
else
ENSURE_( snd_pcm_prepare( stream->playback.pcm ),
paUnanticipatedHostError );
@@ -2390,6 +2400,7 @@
snd_pcm_status_t *st;
PaTime now = PaUtil_GetTime();
snd_timestamp_t t;
+ int errplayback = 0, errcapture = 0;
snd_pcm_status_alloca( &st );
@@ -2400,6 +2411,7 @@
{
snd_pcm_status_get_trigger_tstamp( st, &t );
self->underrun = now * 1000 - ((PaTime) t.tv_sec * 1000 +
(PaTime) t.tv_usec / 1000);
+ errplayback = snd_pcm_recover( self->playback.pcm, -EPIPE, 0 );
}
}
if( self->capture.pcm )
@@ -2409,10 +2421,12 @@
{
snd_pcm_status_get_trigger_tstamp( st, &t );
self->overrun = now * 1000 - ((PaTime) t.tv_sec * 1000 +
(PaTime) t.tv_usec / 1000);
+ errcapture = snd_pcm_recover( self->capture.pcm, -EPIPE, 0 );
}
}
- PA_ENSURE( AlsaRestart( self ) );
+ if( errplayback || errcapture )
+ PA_ENSURE( AlsaRestart( self ) );
end:
return result;
@@ -2563,7 +2577,7 @@
static PaError PaAlsaStreamComponent_EndProcessing( PaAlsaStreamComponent
*self, unsigned long numFrames, int *xrun )
{
PaError result = paNoError;
- int res;
+ int res = 0;
/* @concern FullDuplex It is possible that only one direction is
marked ready after polling, and processed
* afterwards
@@ -2571,7 +2585,34 @@
if( !self->ready )
goto end;
- res = snd_pcm_mmap_commit( self->pcm, self->offset, numFrames );
+ if( !self->canMmap && StreamDirection_Out == self->streamDir )
+ {
+ /* Play sound */
+ if( self->hostInterleaved )
+ res = snd_pcm_writei( self->pcm, self->nonMmapBuffer,
numFrames );
+ else
+ {
+ void *bufs[self->numHostChannels];
+ int bufsize = snd_pcm_format_size( self->nativeFormat,
self->framesPerBuffer + 1 );
+ unsigned char *buffer = self->nonMmapBuffer;
+ int i;
+ for( i = 0; i < self->numHostChannels; ++i )
+ {
+ bufs[i] = buffer;
+ buffer += bufsize;
+ }
+ res = snd_pcm_writen( self->pcm, bufs, numFrames );
+ }
+ }
+
+ if( self->canMmap )
+ res = snd_pcm_mmap_commit( self->pcm, self->offset, numFrames );
+ else
+ {
+ free( self->nonMmapBuffer );
+ self->nonMmapBuffer = NULL;
+ }
+
if( res == -EPIPE || res == -ESTRPIPE )
{
*xrun = 1;
@@ -2611,7 +2652,7 @@
if( self->hostInterleaved )
{
int swidth = snd_pcm_format_size( self->nativeFormat, 1 );
- unsigned char *buffer = ExtractAddress( self->channelAreas,
self->offset );
+ unsigned char *buffer = self->canMmap ? ExtractAddress(
self->channelAreas, self->offset ) : self->nonMmapBuffer;
/* Start after the last user channel */
p = buffer + self->numUserChannels * swidth;
@@ -2991,13 +3032,23 @@
goto end;
}
- ENSURE_( snd_pcm_mmap_begin( self->pcm, &areas, &self->offset,
numFrames ), paUnanticipatedHostError );
+ if( self->canMmap )
+ {
+ ENSURE_( snd_pcm_mmap_begin( self->pcm, &areas, &self->offset,
numFrames ), paUnanticipatedHostError );
+ /* @concern ChannelAdaption Buffer address is recorded so we can
do some channel adaption later */
+ self->channelAreas = (snd_pcm_channel_area_t *)areas;
+ }
+ else
+ {
+ free( self->nonMmapBuffer );
+ self->nonMmapBuffer = calloc( self->numHostChannels,
snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 ) );
+ }
if( self->hostInterleaved )
{
int swidth = snd_pcm_format_size( self->nativeFormat, 1 );
- p = buffer = ExtractAddress( areas, self->offset );
+ p = buffer = self->canMmap ? ExtractAddress( areas, self->offset
) : self->nonMmapBuffer;
for( i = 0; i < self->numUserChannels; ++i )
{
/* We're setting the channels up to userChannels, but the
stride will be hostChannels samples */
@@ -3007,16 +3058,52 @@
}
else
{
- for( i = 0; i < self->numUserChannels; ++i )
- {
- area = areas + i;
- buffer = ExtractAddress( area, self->offset );
- setChannel( bp, i, buffer, 1 );
+ if( self->canMmap )
+ for( i = 0; i < self->numUserChannels; ++i )
+ {
+ area = areas + i;
+ buffer = ExtractAddress( area, self->offset );
+ setChannel( bp, i, buffer, 1 );
+ }
+ else
+ {
+ int bufsize = snd_pcm_format_size( self->nativeFormat,
self->framesPerBuffer + 1 );
+ buffer = self->nonMmapBuffer;
+ for( i = 0; i < self->numUserChannels; ++i )
+ {
+ setChannel( bp, i, buffer, 1 );
+ buffer += bufsize;
+ }
}
}
- /* @concern ChannelAdaption Buffer address is recorded so we can do
some channel adaption later */
- self->channelAreas = (snd_pcm_channel_area_t *)areas;
+ if( !self->canMmap && StreamDirection_In == self->streamDir )
+ {
+ /* Read sound */
+ int res;
+ if( self->hostInterleaved )
+ res = snd_pcm_readi( self->pcm, self->nonMmapBuffer,
*numFrames );
+ else
+ {
+ void *bufs[self->numHostChannels];
+ int bufsize = snd_pcm_format_size( self->nativeFormat,
self->framesPerBuffer + 1 );
+ unsigned char *buffer = self->nonMmapBuffer;
+ int i;
+ for( i = 0; i < self->numHostChannels; ++i )
+ {
+ bufs[i] = buffer;
+ buffer += bufsize;
+ }
+ res = snd_pcm_readn( self->pcm, bufs, *numFrames );
+ }
+ if( res == -EPIPE || res == -ESTRPIPE )
+ {
+ *xrun = 1;
+ *numFrames = 0;
+ free( self->nonMmapBuffer );
+ self->nonMmapBuffer = NULL;
+ }
+ }
end:
error:
@@ -3584,3 +3671,9 @@
error:
return result;
}
+
+PaError PaAlsa_SetRetriesBusy( int retries )
+{
+ busyRetries_ = retries;
+ return paNoError;
+}
=======================================
--- /trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/asio/pa_asio.cpp
Fri Jan 22 11:51:35 2010
+++ /trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/asio/pa_asio.cpp
Fri Jan 22 12:18:54 2010
@@ -2055,7 +2055,7 @@
{
/* Blocking i/o is implemented by running callback mode, using a
special blocking i/o callback. */
streamCallback = BlockingIoPaCallback; /* Setup PA to use the ASIO
blocking i/o callback. */
- userData = &stream; /* The callback user data will be
the PA ASIO stream. */
+ userData = &theAsioStream; /* The callback user data
will be the PA ASIO stream. */
PaUtil_InitializeStreamRepresentation(
&stream->streamRepresentation,
&asioHostApi->blockingStreamInterface, streamCallback, userData );
}
@@ -3470,11 +3470,8 @@
/* If block processing has stopped, abort! */
if( blockingState->stopFlag ) { return result =
paStreamIsStopped; }
- /* if a timeout is encountered, continue, perhaps we
should give up eventually */
- continue;
- /* To give up eventually, we may increase the time out
- period and return an error if it fails anyway. */
- /* retrun result = paTimedOut; */
+ /* If a timeout is encountered, give up eventually. */
+ return result = paTimedOut;
}
}
/* Now, the ring buffer contains the required amount of data
@@ -3644,11 +3641,9 @@
/* If block processing has stopped, abort! */
if( blockingState->stopFlag ) { return result =
paStreamIsStopped; }
- /* if a timeout is encountered, continue, perhaps we
should give up eventually */
- continue;
- /* To give up eventually, we may increase the time out
- period and return an error if it fails anyway. */
- /* retrun result = paTimedOut; */
+
+ /* If a timeout is encountered, give up eventually. */
+ return result = paTimedOut;
}
}
/* Now, the ring buffer contains the required amount of free
=======================================
---
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/dsound/pa_win_ds.c
Wed Oct 22 11:32:45 2008
+++
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/dsound/pa_win_ds.c
Fri Jan 22 12:18:54 2010
@@ -1403,12 +1403,14 @@
// first try WAVEFORMATEXTENSIBLE. if this fails, fall back to
WAVEFORMATEX
PaWin_InitializeWaveFormatExtensible( &waveFormat, nChannels,
- sampleFormat, nFrameRate, channelMask );
+ sampleFormat, PaWin_SampleFormatToLinearWaveFormatTag(
sampleFormat ),
+ nFrameRate, channelMask );
if( IDirectSoundCapture_CreateCaptureBuffer(
stream->pDirectSoundCapture,
&captureDesc, &stream->pDirectSoundInputBuffer, NULL) !=
DS_OK )
{
- PaWin_InitializeWaveFormatEx( &waveFormat, nChannels,
sampleFormat, nFrameRate );
+ PaWin_InitializeWaveFormatEx( &waveFormat, nChannels, sampleFormat,
+ PaWin_SampleFormatToLinearWaveFormatTag( sampleFormat ),
nFrameRate );
if ((result = IDirectSoundCapture_CreateCaptureBuffer(
stream->pDirectSoundCapture,
&captureDesc, &stream->pDirectSoundInputBuffer,
NULL)) != DS_OK) return result;
@@ -1479,11 +1481,13 @@
// first try WAVEFORMATEXTENSIBLE. if this fails, fall back to
WAVEFORMATEX
PaWin_InitializeWaveFormatExtensible( &waveFormat, nChannels,
- sampleFormat, nFrameRate, channelMask );
+ sampleFormat, PaWin_SampleFormatToLinearWaveFormatTag(
sampleFormat ),
+ nFrameRate, channelMask );
if( IDirectSoundBuffer_SetFormat( pPrimaryBuffer,
(WAVEFORMATEX*)&waveFormat) != DS_OK )
{
- PaWin_InitializeWaveFormatEx( &waveFormat, nChannels,
sampleFormat, nFrameRate );
+ PaWin_InitializeWaveFormatEx( &waveFormat, nChannels, sampleFormat,
+ PaWin_SampleFormatToLinearWaveFormatTag( sampleFormat ),
nFrameRate );
if((result = IDirectSoundBuffer_SetFormat( pPrimaryBuffer,
(WAVEFORMATEX*)&waveFormat)) != DS_OK) return result;
}
=======================================
---
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/wasapi/pa_win_wasapi.cpp
Fri Jan 22 11:51:35 2010
+++
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/wasapi/pa_win_wasapi.cpp
Fri Jan 22 12:18:54 2010
@@ -518,7 +518,7 @@
if (value.pwszVal)
wcstombs(deviceName, value.pwszVal,MAX_STR_LEN-1); //todo proper
size
else{
- sprintf(deviceName,"baddev%d",i);
+ _snprintf_s(deviceName,MAX_STR_LEN-1,MAX_STR_LEN-1,"baddev%d",i);
}
deviceInfo->name = deviceName;
@@ -956,9 +956,9 @@
HRESULT hResult=!S_OK;
if (*shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE)
- hResult =
myClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,(WAVEFORMATEX*)outWavex,NULL);
+ hResult =
myClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,&outWavex->Format,NULL);
else
- hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,
(WAVEFORMATEX*)&outWavex,&sharedClosestMatch);
+ hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,
&outWavex->Format,&sharedClosestMatch);
if (hResult == S_OK)
answer = paFormatIsSupported;
@@ -990,9 +990,9 @@
WAVEFORMATEXTENSIBLE ext;
wasapiFillWFEXT(&ext,BestToWorst[i],sampleRate,params->channelCount);
if (*shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE)
- hResult =
myClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,(WAVEFORMATEX*)&ext,NULL);
+ hResult =
myClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,&ext.Format,NULL);
else
- hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,
(WAVEFORMATEX*)&ext,&sharedClosestMatch);
+ hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,
&ext.Format,&sharedClosestMatch);
if (hResult == S_OK){
memcpy(outWavex,&ext,sizeof(WAVEFORMATEXTENSIBLE));
@@ -1015,9 +1015,9 @@
pcm16WaveFormat.cbSize = 0;
if (*shareMode == AUDCLNT_SHAREMODE_EXCLUSIVE)
- hResult =
myClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,(WAVEFORMATEX*)&pcm16WaveFormat,NULL);
+ hResult =
myClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,&pcm16WaveFormat,NULL);
else
- hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,
(WAVEFORMATEX*)&pcm16WaveFormat,&sharedClosestMatch);
+ hResult = myClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED,
&pcm16WaveFormat,&sharedClosestMatch);
if (hResult == S_OK){
memcpy(outWavex,&pcm16WaveFormat,sizeof(WAVEFORMATEX));
=======================================
---
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/wdmks/pa_win_wdmks.c
Fri Jan 22 11:51:35 2010
+++
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/wdmks/pa_win_wdmks.c
Fri Jan 22 12:18:54 2010
@@ -77,7 +77,7 @@
#include <windows.h>
#include <winioctl.h>
-
+#include <process.h>
#ifdef __GNUC__
#undef PA_LOGE_
@@ -121,24 +121,16 @@
#endif
#ifdef _MSC_VER
+ #define NOMMIDS
#define DYNAMIC_GUID(data) {data}
- #define _INC_MMREG
#define _NTRTL_ /* Turn off default definition of DEFINE_GUIDEX */
#undef DEFINE_GUID
#define DEFINE_GUID(n,data) EXTERN_C const GUID n = {data}
#define DEFINE_GUID_THUNK(n,data) DEFINE_GUID(n,data)
#define DEFINE_GUIDEX(n) DEFINE_GUID_THUNK(n, STATIC_##n)
- #if !defined( DEFINE_WAVEFORMATEX_GUID )
- #define DEFINE_WAVEFORMATEX_GUID(x) (USHORT)(x), 0x0000, 0x0010,
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
- #endif
- #define WAVE_FORMAT_ADPCM 0x0002
- #define WAVE_FORMAT_IEEE_FLOAT 0x0003
- #define WAVE_FORMAT_ALAW 0x0006
- #define WAVE_FORMAT_MULAW 0x0007
- #define WAVE_FORMAT_MPEG 0x0050
- #define WAVE_FORMAT_DRM 0x0009
#endif
+#include <mmreg.h>
#include <ks.h>
#include <ksmedia.h>
#include <tchar.h>
@@ -2924,11 +2916,26 @@
PaUtil_SetInputChannel(&stream->bufferProcessor,i,((unsigned
char*)(stream->packets[inbuf].Header.Data))+(i*stream->inputSampleSize),stream->deviceInputChannels);
}
}
- /* Only call the EndBufferProcessing function is the total
input frames == total output frames */
- if((stream->bufferProcessor.hostInputFrameCount[0] +
stream->bufferProcessor.hostInputFrameCount[1]) ==
- (stream->bufferProcessor.hostOutputFrameCount[0] +
stream->bufferProcessor.hostOutputFrameCount[1]) )
+
+ if (stream->recordingPin && stream->playbackPin) /* full
duplex */
+ {
+ /* Only call the EndBufferProcessing function when the
total input frames == total output frames */
+
+ if((stream->bufferProcessor.hostInputFrameCount[0] +
stream->bufferProcessor.hostInputFrameCount[1]) ==
+ (stream->bufferProcessor.hostOutputFrameCount[0] +
stream->bufferProcessor.hostOutputFrameCount[1]) )
+ {
+ framesProcessed =
PaUtil_EndBufferProcessing(&stream->bufferProcessor,&cbResult);
+ }
+ else
+ {
+ framesProcessed = 0;
+ }
+ }
+ else
+ {
framesProcessed =
PaUtil_EndBufferProcessing(&stream->bufferProcessor,&cbResult);
- else framesProcessed = 0;
+ }
+
if( doChannelCopy )
{
/* Copy the first output channel to the other channels */
=======================================
---
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/wmme/pa_win_wmme.c
Fri Jan 22 11:51:35 2010
+++
/trunk/sipXmediaLib/contrib/portaudio_v19/src/hostapi/wmme/pa_win_wmme.c
Fri Jan 22 12:18:54 2010
@@ -471,6 +471,21 @@
return hostApi->winMmeDeviceIds[ device ];
}
+
+
+static int SampleFormatAndWinWmmeSpecificFlagsToLinearWaveFormatTag(
PaSampleFormat sampleFormat, unsigned long winMmeSpecificFlags )
+{
+ int waveFormatTag = 0;
+
+ if( winMmeSpecificFlags & paWinMmeWaveFormatDolbyAc3Spdif )
+ waveFormatTag = PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF;
+ else if( winMmeSpecificFlags & paWinMmeWaveFormatWmaSpdif )
+ waveFormatTag = PAWIN_WAVE_FORMAT_WMA_SPDIF;
+ else
+ waveFormatTag = PaWin_SampleFormatToLinearWaveFormatTag(
sampleFormat );
+
+ return waveFormatTag;
+}
static PaError QueryInputWaveFormatEx( int deviceId, WAVEFORMATEX
*waveFormatEx )
@@ -527,43 +542,55 @@
static PaError QueryFormatSupported( PaDeviceInfo *deviceInfo,
PaError (*waveFormatExQueryFunction)(int, WAVEFORMATEX*),
- int winMmeDeviceId, int channels, double sampleRate )
+ int winMmeDeviceId, int channels, double sampleRate, unsigned long
winMmeSpecificFlags )
{
PaWinMmeDeviceInfo *winMmeDeviceInfo = (PaWinMmeDeviceInfo*)deviceInfo;
PaWinWaveFormat waveFormat;
-
- if( sampleRate == 11025.0
- && ( (channels == 1 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_1M16))
- || (channels == 2 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_1S16)) ) ){
-
- return paNoError;
- }
-
- if( sampleRate == 22050.0
- && ( (channels == 1 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_2M16))
- || (channels == 2 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_2S16)) ) ){
-
- return paNoError;
- }
-
- if( sampleRate == 44100.0
- && ( (channels == 1 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_4M16))
- || (channels == 2 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_4S16)) ) ){
-
- return paNoError;
- }
+ PaSampleFormat sampleFormat;
+ int waveFormatTag;
+
+ /* @todo at the moment we only query with 16 bit sample format and
directout speaker config*/
+
+ sampleFormat = paInt16;
+ waveFormatTag =
SampleFormatAndWinWmmeSpecificFlagsToLinearWaveFormatTag( sampleFormat,
winMmeSpecificFlags );
+
+ if( waveFormatTag == PaWin_SampleFormatToLinearWaveFormatTag( paInt16
) ){
+
+ /* attempt bypass querying the device for linear formats */
+
+ if( sampleRate == 11025.0
+ && ( (channels == 1 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_1M16))
+ || (channels == 2 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_1S16)) ) ){
+
+ return paNoError;
+ }
+
+ if( sampleRate == 22050.0
+ && ( (channels == 1 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_2M16))
+ || (channels == 2 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_2S16)) ) ){
+
+ return paNoError;
+ }
+
+ if( sampleRate == 44100.0
+ && ( (channels == 1 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_4M16))
+ || (channels == 2 && (winMmeDeviceInfo->dwFormats &
WAVE_FORMAT_4S16)) ) ){
+
+ return paNoError;
+ }
+ }
+
/* first, attempt to query the device using WAVEFORMATEXTENSIBLE,
if this fails we fall back to WAVEFORMATEX */
- /* @todo at the moment we only query with 16 bit sample format and
directout speaker config*/
- PaWin_InitializeWaveFormatExtensible( &waveFormat, channels,
- paInt16, sampleRate, PAWIN_SPEAKER_DIRECTOUT );
+ PaWin_InitializeWaveFormatExtensible( &waveFormat, channels,
sampleFormat, waveFormatTag,
+ sampleRate, PAWIN_SPEAKER_DIRECTOUT );
if( waveFormatExQueryFunction( winMmeDeviceId,
(WAVEFORMATEX*)&waveFormat ) == paNoError )
return paNoError;
- PaWin_InitializeWaveFormatEx( &waveFormat, channels, paInt16,
sampleRate );
+ PaWin_InitializeWaveFormatEx( &waveFormat, channels, sampleFormat,
waveFormatTag, sampleRate );
return waveFormatExQueryFunction( winMmeDeviceId,
(WAVEFORMATEX*)&waveFormat );
}
@@ -585,7 +612,7 @@
for( i=0; i < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++i )
{
double sampleRate = defaultSampleRateSearchOrder_[ i ];
- PaError paerror = QueryFormatSupported( deviceInfo,
waveFormatExQueryFunction, winMmeDeviceId, maxChannels, sampleRate );
+ PaError paerror = QueryFormatSupported( deviceInfo,
waveFormatExQueryFunction, winMmeDeviceId, maxChannels, sampleRate, 0 );
if( paerror == paNoError )
{
deviceInfo->defaultSampleRate = sampleRate;
@@ -1198,7 +1225,9 @@
/* test for valid sample rate, see comment above */
winMmeInputDeviceId = LocalDeviceIndexToWinMmeDeviceId(
winMmeHostApi, inputStreamInfo->devices[i].device );
- paerror = QueryFormatSupported( inputDeviceInfo,
QueryInputWaveFormatEx, winMmeInputDeviceId,
inputStreamInfo->devices[i].channelCount, sampleRate );
+ paerror = QueryFormatSupported( inputDeviceInfo,
QueryInputWaveFormatEx,
+ winMmeInputDeviceId,
inputStreamInfo->devices[i].channelCount, sampleRate,
+ ((inputStreamInfo) ? inputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1220,7 +1249,9 @@
/* test for valid sample rate, see comment above */
winMmeInputDeviceId = LocalDeviceIndexToWinMmeDeviceId(
winMmeHostApi, inputParameters->device );
- paerror = QueryFormatSupported( inputDeviceInfo,
QueryInputWaveFormatEx, winMmeInputDeviceId, inputChannelCount, sampleRate
);
+ paerror = QueryFormatSupported( inputDeviceInfo,
QueryInputWaveFormatEx,
+ winMmeInputDeviceId, inputChannelCount, sampleRate,
+ ((inputStreamInfo) ? inputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1258,7 +1289,9 @@
/* test for valid sample rate, see comment above */
winMmeOutputDeviceId = LocalDeviceIndexToWinMmeDeviceId(
winMmeHostApi, outputStreamInfo->devices[i].device );
- paerror = QueryFormatSupported( outputDeviceInfo,
QueryOutputWaveFormatEx, winMmeOutputDeviceId,
outputStreamInfo->devices[i].channelCount, sampleRate );
+ paerror = QueryFormatSupported( outputDeviceInfo,
QueryOutputWaveFormatEx,
+ winMmeOutputDeviceId,
outputStreamInfo->devices[i].channelCount, sampleRate,
+ ((outputStreamInfo) ? outputStreamInfo->flags : 0)
);
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1280,7 +1313,9 @@
/* test for valid sample rate, see comment above */
winMmeOutputDeviceId = LocalDeviceIndexToWinMmeDeviceId(
winMmeHostApi, outputParameters->device );
- paerror = QueryFormatSupported( outputDeviceInfo,
QueryOutputWaveFormatEx, winMmeOutputDeviceId, outputChannelCount,
sampleRate );
+ paerror = QueryFormatSupported( outputDeviceInfo,
QueryOutputWaveFormatEx,
+ winMmeOutputDeviceId, outputChannelCount, sampleRate,
+ ((outputStreamInfo) ? outputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1703,6 +1738,7 @@
static void InitializeSingleDirectionHandlesAndBuffers(
PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers );
static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation
*winMmeHostApi,
PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
+ unsigned long winMmeSpecificFlags,
unsigned long bytesPerHostSample,
double sampleRate, PaWinMmeDeviceAndChannelCount *devices,
unsigned int deviceCount, PaWinWaveFormatChannelMask channelMask,
int isInput );
@@ -1727,6 +1763,7 @@
static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation
*winMmeHostApi,
PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
+ unsigned long winMmeSpecificFlags,
unsigned long bytesPerHostSample,
double sampleRate, PaWinMmeDeviceAndChannelCount *devices,
unsigned int deviceCount, PaWinWaveFormatChannelMask channelMask,
int isInput )
@@ -1734,6 +1771,8 @@
PaError result;
MMRESULT mmresult;
signed int i, j;
+ PaSampleFormat sampleFormat;
+ int waveFormatTag;
/* for error cleanup we expect that
InitializeSingleDirectionHandlesAndBuffers()
has already been called to zero some fields */
@@ -1760,6 +1799,10 @@
else
((HWAVEOUT*)handlesAndBuffers->waveHandles)[i] = 0;
}
+
+ /* @todo at the moment we only use 16 bit sample format */
+ sampleFormat = paInt16;
+ waveFormatTag =
SampleFormatAndWinWmmeSpecificFlagsToLinearWaveFormatTag( sampleFormat,
winMmeSpecificFlags );
for( i = 0; i < (signed int)deviceCount; ++i )
{
@@ -1776,16 +1819,16 @@
/* first, attempt to open the device using
WAVEFORMATEXTENSIBLE,
if this fails we fall back to WAVEFORMATEX */
- /* @todo at the moment we only use 16 bit sample format */
PaWin_InitializeWaveFormatExtensible( &waveFormat,
devices[i].channelCount,
- paInt16, sampleRate, channelMask );
+ sampleFormat, waveFormatTag, sampleRate,
channelMask );
}
else
{
/* retry with WAVEFORMATEX */
- PaWin_InitializeWaveFormatEx( &waveFormat,
devices[i].channelCount, paInt16, sampleRate );
+ PaWin_InitializeWaveFormatEx( &waveFormat,
devices[i].channelCount,
+ sampleFormat, waveFormatTag, sampleRate );
}
/* REVIEW: consider not firing an event for input when a full
duplex
@@ -2090,6 +2133,7 @@
static PaError ValidateWinMmeSpecificStreamInfo(
const PaStreamParameters *streamParameters,
const PaWinMmeStreamInfo *streamInfo,
+ unsigned long *winMmeSpecificFlags,
char *throttleProcessingThreadOnOverload,
unsigned long *deviceCount )
{
@@ -2100,6 +2144,8 @@
{
return paIncompatibleHostApiSpecificStreamInfo;
}
+
+ *winMmeSpecificFlags = streamInfo->flags;
if( streamInfo->flags &
paWinMmeDontThrottleOverloadedProcessingThread )
*throttleProcessingThreadOnOverload = 0;
@@ -2244,8 +2290,10 @@
unsigned long hostOutputBufferCount;
unsigned long framesPerBufferProcessorCall;
PaWinMmeDeviceAndChannelCount *inputDevices = 0; /* contains all
devices and channel counts as local host api ids, even when
PaWinMmeUseMultipleDevices is not used */
+ unsigned long winMmeSpecificInputFlags = 0;
unsigned long inputDeviceCount = 0;
PaWinMmeDeviceAndChannelCount *outputDevices = 0;
+ unsigned long winMmeSpecificOutputFlags = 0;
unsigned long outputDeviceCount = 0; /* contains all
devices and channel counts as local host api ids, even when
PaWinMmeUseMultipleDevices is not used */
char throttleProcessingThreadOnOverload = 1;
@@ -2261,6 +2309,7 @@
/* validate input hostApiSpecificStreamInfo */
inputStreamInfo =
(PaWinMmeStreamInfo*)inputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( inputParameters,
inputStreamInfo,
+ &winMmeSpecificInputFlags,
&throttleProcessingThreadOnOverload,
&inputDeviceCount );
if( result != paNoError ) return result;
@@ -2310,6 +2359,7 @@
/* validate output hostApiSpecificStreamInfo */
outputStreamInfo =
(PaWinMmeStreamInfo*)outputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( outputParameters,
outputStreamInfo,
+ &winMmeSpecificOutputFlags,
&throttleProcessingThreadOnOverload,
&outputDeviceCount );
if( result != paNoError ) return result;
@@ -2357,6 +2407,14 @@
/* validate platform specific flags */
if( (streamFlags & paPlatformSpecificFlags) != 0 )
return paInvalidFlag; /* unexpected platform specific flag */
+
+
+ /* always disable clipping and dithering if we are outputting a raw
spdif stream */
+ if( (winMmeSpecificOutputFlags & paWinMmeWaveFormatDolbyAc3Spdif)
+ || (winMmeSpecificOutputFlags & paWinMmeWaveFormatWmaSpdif) ){
+
+ streamFlags = streamFlags | paClipOff | paDitherOff;
+ }
result = CalculateBufferSettings( &framesPerHostInputBuffer,
&hostInputBufferCount,
@@ -2457,6 +2515,7 @@
if( inputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->input,
+ winMmeSpecificInputFlags,
stream->bufferProcessor.bytesPerHostInputSample,
sampleRate,
inputDevices, inputDeviceCount, inputChannelMask, 1 /*
isInput */ );
if( result != paNoError ) goto error;
@@ -2465,6 +2524,7 @@
if( outputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->output,
+ winMmeSpecificOutputFlags,
stream->bufferProcessor.bytesPerHostOutputSample,
sampleRate,
outputDevices, outputDeviceCount, outputChannelMask, 0 /*
isInput */ );
if( result != paNoError ) goto error;
=======================================
---
/trunk/sipXmediaLib/contrib/portaudio_v19/src/os/unix/pa_unix_hostapis.c
Fri Jan 22 11:45:56 2010
+++
/trunk/sipXmediaLib/contrib/portaudio_v19/src/os/unix/pa_unix_hostapis.c
Fri Jan 22 12:18:54 2010
@@ -52,8 +52,7 @@
PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi,
PaHostApiIndex index );
PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi,
PaHostApiIndex index );
-/** Note that ALSA is placed before OSS so that the latter is preferred
over the
- * latter on Linux.
+/** Note that on Linux, ALSA is placed before OSS so that the former is
preferred over the latter.
*/
PaUtilHostApiInitializer *paHostApiInitializers[] =
@@ -68,7 +67,7 @@
PaOSS_Initialize,
#endif
-#else
+#else /* __linux__ */
#ifdef PA_USE_OSS
PaOSS_Initialize,
=======================================
--- /trunk/sipXmediaLib/contrib/portaudio_v19/src/os/win/pa_win_util.c Wed
Oct 22 11:32:45 2008
+++ /trunk/sipXmediaLib/contrib/portaudio_v19/src/os/win/pa_win_util.c Fri
Jan 22 12:18:54 2010
@@ -51,6 +51,10 @@
#include "pa_util.h"
+#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC
version 6 and above */
+#pragma comment( lib, "winmm.lib" )
+#endif
+
/*
Track memory allocations to avoid leaks.
=======================================
---
/trunk/sipXmediaLib/contrib/portaudio_v19/src/os/win/pa_win_waveformat.c
Wed Oct 22 11:32:45 2008
+++
/trunk/sipXmediaLib/contrib/portaudio_v19/src/os/win/pa_win_waveformat.c
Fri Jan 22 12:18:54 2010
@@ -47,30 +47,27 @@
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
#endif
-#if !defined(WAVE_FORMAT_IEEE_FLOAT)
-#define WAVE_FORMAT_IEEE_FLOAT 0x0003
-#endif
-
-static GUID pawin_ksDataFormatSubtypePcm =
+static GUID pawin_ksDataFormatSubtypeGuidBase =
{ (USHORT)(WAVE_FORMAT_PCM), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa,
0x00, 0x38, 0x9b, 0x71 };
-static GUID pawin_ksDataFormatSubtypeIeeeFloat =
- { (USHORT)(WAVE_FORMAT_IEEE_FLOAT), 0x0000, 0x0010, 0x80, 0x00, 0x00,
0xaa, 0x00, 0x38, 0x9b, 0x71 };
-
+
+int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat )
+{
+ if( sampleFormat == paFloat32 )
+ return PAWIN_WAVE_FORMAT_IEEE_FLOAT;
+
+ return PAWIN_WAVE_FORMAT_PCM;
+}
void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat,
- int numChannels, PaSampleFormat sampleFormat, double sampleRate )
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double
sampleRate )
{
WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat;
int bytesPerSample = Pa_GetSampleSize(sampleFormat);
unsigned long bytesPerFrame = numChannels * bytesPerSample;
-
- if( sampleFormat == paFloat32 )
- waveFormatEx->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
- else
- waveFormatEx->wFormatTag = WAVE_FORMAT_PCM;
-
+
+ waveFormatEx->wFormatTag = waveFormatTag;
waveFormatEx->nChannels = (WORD)numChannels;
waveFormatEx->nSamplesPerSec = (DWORD)sampleRate;
waveFormatEx->nAvgBytesPerSec = waveFormatEx->nSamplesPerSec *
bytesPerFrame;
@@ -81,12 +78,13 @@
void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
- int numChannels, PaSampleFormat sampleFormat, double sampleRate,
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double
sampleRate,
PaWinWaveFormatChannelMask channelMask )
{
WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat;
int bytesPerSample = Pa_GetSampleSize(sampleFormat);
unsigned long bytesPerFrame = numChannels * bytesPerSample;
+ GUID guid;
waveFormatEx->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
waveFormatEx->nChannels = (WORD)numChannels;
@@ -100,13 +98,10 @@
waveFormatEx->wBitsPerSample;
*((DWORD*)&waveFormat->fields[PAWIN_INDEXOF_DWCHANNELMASK]) = channelMask;
-
- if( sampleFormat == paFloat32 )
- *((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) =
- pawin_ksDataFormatSubtypeIeeeFloat;
- else
- *((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) =
- pawin_ksDataFormatSubtypePcm;
+
+ guid = pawin_ksDataFormatSubtypeGuidBase;
+ guid.Data1 = (USHORT)waveFormatTag;
+ *((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) = guid;
}