rolling back r1822 and r1815 to pa_linux_alsa.c . will recommit on alsa_hw_endian_subdevice branch
This commit is contained in:
parent
4ae4fa0ef9
commit
ebd20865db
1 changed files with 176 additions and 915 deletions
|
|
@ -7,7 +7,6 @@
|
||||||
* Copyright (c) 2002 Joshua Haberman <joshua@haberman.com>
|
* Copyright (c) 2002 Joshua Haberman <joshua@haberman.com>
|
||||||
* Copyright (c) 2005-2009 Arve Knudsen <arve.knudsen@gmail.com>
|
* Copyright (c) 2005-2009 Arve Knudsen <arve.knudsen@gmail.com>
|
||||||
* Copyright (c) 2008 Kevin Kofler <kevin.kofler@chello.at>
|
* Copyright (c) 2008 Kevin Kofler <kevin.kofler@chello.at>
|
||||||
* Copyright (c) 2011 Dmitry Kostjuchenko <dmitrykos@neutroncode.com>
|
|
||||||
*
|
*
|
||||||
* Based on the Open Source API proposed by Ross Bencina
|
* Based on the Open Source API proposed by Ross Bencina
|
||||||
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
|
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
|
||||||
|
|
@ -80,7 +79,7 @@
|
||||||
|
|
||||||
#include "pa_linux_alsa.h"
|
#include "pa_linux_alsa.h"
|
||||||
|
|
||||||
/* Add missing define (for compatibility with older ALSA versions). */
|
/* Add missing define (for compatibility with older ALSA versions) */
|
||||||
#ifndef SND_PCM_TSTAMP_ENABLE
|
#ifndef SND_PCM_TSTAMP_ENABLE
|
||||||
#define SND_PCM_TSTAMP_ENABLE SND_PCM_TSTAMP_MMAP
|
#define SND_PCM_TSTAMP_ENABLE SND_PCM_TSTAMP_MMAP
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -88,12 +87,6 @@
|
||||||
/* Combine version elements into a single (unsigned) integer */
|
/* Combine version elements into a single (unsigned) integer */
|
||||||
#define ALSA_VERSION_INT(major, minor, subminor) ((major << 16) | (minor << 8) | subminor)
|
#define ALSA_VERSION_INT(major, minor, subminor) ((major << 16) | (minor << 8) | subminor)
|
||||||
|
|
||||||
/* Specifies that hardware audio sample needs byte-swapping into platfom native value representation. */
|
|
||||||
#define paSwapEndian ((PaSampleFormat) 0x40000000) /**< @see PaSampleFormat */
|
|
||||||
|
|
||||||
/* Remove paSwapEndian and paNonInterleaved flags to get pure format value. */
|
|
||||||
#define PA_ALSA_TO_FORMAT(X) ((X) & ~(paSwapEndian|paNonInterleaved))
|
|
||||||
|
|
||||||
/* Defines Alsa function types and pointers to these functions. */
|
/* Defines Alsa function types and pointers to these functions. */
|
||||||
#define _PA_DEFINE_FUNC(x) typedef typeof(x) x##_ft; static x##_ft *alsa_##x = 0
|
#define _PA_DEFINE_FUNC(x) typedef typeof(x) x##_ft; static x##_ft *alsa_##x = 0
|
||||||
|
|
||||||
|
|
@ -197,9 +190,6 @@ _PA_DEFINE_FUNC(snd_pcm_info_set_subdevice);
|
||||||
_PA_DEFINE_FUNC(snd_pcm_info_set_stream);
|
_PA_DEFINE_FUNC(snd_pcm_info_set_stream);
|
||||||
_PA_DEFINE_FUNC(snd_pcm_info_get_name);
|
_PA_DEFINE_FUNC(snd_pcm_info_get_name);
|
||||||
_PA_DEFINE_FUNC(snd_pcm_info_get_card);
|
_PA_DEFINE_FUNC(snd_pcm_info_get_card);
|
||||||
_PA_DEFINE_FUNC(snd_pcm_info_get_subdevices_count);
|
|
||||||
_PA_DEFINE_FUNC(snd_pcm_info_get_subdevice_name);
|
|
||||||
_PA_DEFINE_FUNC(snd_pcm_info_get_subdevices_avail);
|
|
||||||
#define alsa_snd_pcm_info_alloca(ptr) __alsa_snd_alloca(ptr, snd_pcm_info)
|
#define alsa_snd_pcm_info_alloca(ptr) __alsa_snd_alloca(ptr, snd_pcm_info)
|
||||||
|
|
||||||
_PA_DEFINE_FUNC(snd_ctl_pcm_next_device);
|
_PA_DEFINE_FUNC(snd_ctl_pcm_next_device);
|
||||||
|
|
@ -479,9 +469,6 @@ _PA_LOAD_FUNC(snd_pcm_info_set_subdevice);
|
||||||
_PA_LOAD_FUNC(snd_pcm_info_set_stream);
|
_PA_LOAD_FUNC(snd_pcm_info_set_stream);
|
||||||
_PA_LOAD_FUNC(snd_pcm_info_get_name);
|
_PA_LOAD_FUNC(snd_pcm_info_get_name);
|
||||||
_PA_LOAD_FUNC(snd_pcm_info_get_card);
|
_PA_LOAD_FUNC(snd_pcm_info_get_card);
|
||||||
_PA_LOAD_FUNC(snd_pcm_info_get_subdevices_count);
|
|
||||||
_PA_LOAD_FUNC(snd_pcm_info_get_subdevice_name);
|
|
||||||
_PA_LOAD_FUNC(snd_pcm_info_get_subdevices_avail);
|
|
||||||
|
|
||||||
_PA_LOAD_FUNC(snd_ctl_pcm_next_device);
|
_PA_LOAD_FUNC(snd_ctl_pcm_next_device);
|
||||||
_PA_LOAD_FUNC(snd_ctl_pcm_info);
|
_PA_LOAD_FUNC(snd_ctl_pcm_info);
|
||||||
|
|
@ -738,9 +725,6 @@ static const PaAlsaDeviceInfo *GetDeviceInfo( const PaUtilHostApiRepresentation
|
||||||
return (const PaAlsaDeviceInfo *)hostApi->deviceInfos[device];
|
return (const PaAlsaDeviceInfo *)hostApi->deviceInfos[device];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CheckAndReplaceConverterForSwapEndian(PaAlsaStream *stream, PaSampleFormat hostInputSampleFormat,
|
|
||||||
PaSampleFormat hostOutputSampleFormat);
|
|
||||||
|
|
||||||
/** Uncommented because AlsaErrorHandler is unused for anything good yet. If AlsaErrorHandler is
|
/** Uncommented because AlsaErrorHandler is unused for anything good yet. If AlsaErrorHandler is
|
||||||
to be used, do not forget to register this callback in PaAlsa_Initialize, and unregister in Terminate.
|
to be used, do not forget to register this callback in PaAlsa_Initialize, and unregister in Terminate.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1213,6 +1197,7 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi )
|
||||||
snd_pcm_info_t *pcmInfo;
|
snd_pcm_info_t *pcmInfo;
|
||||||
int res;
|
int res;
|
||||||
int blocking = SND_PCM_NONBLOCK;
|
int blocking = SND_PCM_NONBLOCK;
|
||||||
|
char alsaCardName[50];
|
||||||
#ifdef PA_ENABLE_DEBUG_OUTPUT
|
#ifdef PA_ENABLE_DEBUG_OUTPUT
|
||||||
PaTime startTime = PaUtil_GetTime();
|
PaTime startTime = PaUtil_GetTime();
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1237,106 +1222,65 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi )
|
||||||
alsa_snd_pcm_info_alloca( &pcmInfo );
|
alsa_snd_pcm_info_alloca( &pcmInfo );
|
||||||
while( alsa_snd_card_next( &cardIdx ) == 0 && cardIdx >= 0 )
|
while( alsa_snd_card_next( &cardIdx ) == 0 && cardIdx >= 0 )
|
||||||
{
|
{
|
||||||
char alsaCardNameId[64] = { 0 };
|
|
||||||
char *cardName;
|
char *cardName;
|
||||||
int devIdx = -1;
|
int devIdx = -1;
|
||||||
snd_ctl_t *ctl;
|
snd_ctl_t *ctl;
|
||||||
|
char buf[50];
|
||||||
|
|
||||||
/* Make card name */
|
snprintf( alsaCardName, sizeof (alsaCardName), "hw:%d", cardIdx );
|
||||||
snprintf( alsaCardNameId, sizeof (alsaCardNameId)-1, "hw:%d", cardIdx );
|
|
||||||
|
|
||||||
/* Try opening card */
|
/* Acquire name of card */
|
||||||
if( alsa_snd_ctl_open( &ctl, alsaCardNameId, 0 ) < 0 )
|
if( alsa_snd_ctl_open( &ctl, alsaCardName, 0 ) < 0 )
|
||||||
{
|
{
|
||||||
/* Unable to open card :( */
|
/* Unable to open card :( */
|
||||||
PA_DEBUG(( "%s: Unable to open device %s\n", __FUNCTION__, alsaCardNameId ));
|
PA_DEBUG(( "%s: Unable to open device %s\n", __FUNCTION__, alsaCardName ));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
alsa_snd_ctl_card_info( ctl, cardInfo );
|
alsa_snd_ctl_card_info( ctl, cardInfo );
|
||||||
|
|
||||||
PA_ENSURE( PaAlsa_StrDup( alsaApi, &cardName, alsa_snd_ctl_card_info_get_name( cardInfo )) );
|
PA_ENSURE( PaAlsa_StrDup( alsaApi, &cardName, alsa_snd_ctl_card_info_get_name( cardInfo )) );
|
||||||
|
|
||||||
PA_DEBUG(( "%s: Open card: id[%s] name[%s]\n", __FUNCTION__, alsaCardNameId, cardName ));
|
|
||||||
|
|
||||||
/* Iterate devices */
|
|
||||||
while( alsa_snd_ctl_pcm_next_device( ctl, &devIdx ) == 0 && devIdx >= 0 )
|
while( alsa_snd_ctl_pcm_next_device( ctl, &devIdx ) == 0 && devIdx >= 0 )
|
||||||
{
|
{
|
||||||
char *alsaDeviceName, *deviceName;
|
char *alsaDeviceName, *deviceName;
|
||||||
size_t len;
|
size_t len;
|
||||||
int hasPlayback = 0, hasCapture = 0;
|
int hasPlayback = 0, hasCapture = 0;
|
||||||
int subDevIdx, subDevCount = 1;
|
snprintf( buf, sizeof (buf), "hw:%d,%d", cardIdx, devIdx );
|
||||||
|
|
||||||
PA_DEBUG(( "%s: - idx = %d:\n", __FUNCTION__, devIdx ));
|
/* Obtain info about this particular device */
|
||||||
|
|
||||||
/* Make this device current */
|
|
||||||
alsa_snd_pcm_info_set_device( pcmInfo, devIdx );
|
alsa_snd_pcm_info_set_device( pcmInfo, devIdx );
|
||||||
|
alsa_snd_pcm_info_set_subdevice( pcmInfo, 0 );
|
||||||
/* Iterate sub-devices */
|
|
||||||
for( subDevIdx = 0; subDevIdx < subDevCount; ++subDevIdx )
|
|
||||||
{
|
|
||||||
char buf[64] = { 0 };
|
|
||||||
|
|
||||||
/* Make this sub-device current */
|
|
||||||
alsa_snd_pcm_info_set_subdevice( pcmInfo, subDevIdx );
|
|
||||||
|
|
||||||
/* Test for Capture capability */
|
|
||||||
alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_CAPTURE );
|
alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_CAPTURE );
|
||||||
if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )
|
if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )
|
||||||
{
|
{
|
||||||
hasCapture = 1;
|
hasCapture = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test for Playback capability */
|
|
||||||
alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_PLAYBACK );
|
alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_PLAYBACK );
|
||||||
if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )
|
if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )
|
||||||
{
|
{
|
||||||
hasPlayback = 1;
|
hasPlayback = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If neither supported, such device is stub or failed */
|
|
||||||
if( !hasPlayback && !hasCapture )
|
if( !hasPlayback && !hasCapture )
|
||||||
{
|
{
|
||||||
|
/* Error */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get sub-device count */
|
/* The length of the string written by snprintf plus terminating 0 */
|
||||||
if( subDevIdx == 0 )
|
len = snprintf( NULL, 0, "%s: %s (%s)", cardName, alsa_snd_pcm_info_get_name( pcmInfo ), buf ) + 1;
|
||||||
{
|
PA_UNLESS( deviceName = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ),
|
||||||
subDevCount = alsa_snd_pcm_info_get_subdevices_count( pcmInfo );
|
paInsufficientMemory );
|
||||||
PA_DEBUG(( "%s: sub-devices: %d/%d\n", __FUNCTION__, alsa_snd_pcm_info_get_subdevices_avail( pcmInfo ), subDevCount));
|
snprintf( deviceName, len, "%s: %s (%s)", cardName,
|
||||||
}
|
alsa_snd_pcm_info_get_name( pcmInfo ), buf );
|
||||||
|
|
||||||
PA_DEBUG(( "%s: - sub: %d\n", __FUNCTION__, subDevIdx ));
|
|
||||||
if( hasCapture ) PA_DEBUG(( "%s: - cap: CAPTURE\n", __FUNCTION__ ));
|
|
||||||
if( hasPlayback ) PA_DEBUG(( "%s: - cap: PLAYBACK\n", __FUNCTION__ ));
|
|
||||||
|
|
||||||
/* Make name Id */
|
|
||||||
snprintf( buf, sizeof(buf)-1, ( subDevCount > 1 ? "hw:%d,%d,%d" : "hw:%d,%d" ), cardIdx, devIdx, subDevIdx );
|
|
||||||
|
|
||||||
/* Make name */
|
|
||||||
if( subDevCount <= 1 )
|
|
||||||
{
|
|
||||||
const char *snd_deviceName = alsa_snd_pcm_info_get_name( pcmInfo );
|
|
||||||
|
|
||||||
len = snprintf( NULL, 0, "%s: %s (%s)", cardName, snd_deviceName, buf ) + 1;
|
|
||||||
PA_UNLESS( deviceName = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ), paInsufficientMemory );
|
|
||||||
snprintf( deviceName, len, "%s: %s (%s)", cardName, snd_deviceName, buf );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char *snd_deviceName = alsa_snd_pcm_info_get_name( pcmInfo );
|
|
||||||
const char *snd_subDeviceName = alsa_snd_pcm_info_get_subdevice_name( pcmInfo );
|
|
||||||
|
|
||||||
len = snprintf( NULL, 0, "%s: %s (%s) {%s}", cardName, snd_deviceName, buf, snd_subDeviceName ) + 1;
|
|
||||||
PA_UNLESS( deviceName = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ), paInsufficientMemory );
|
|
||||||
snprintf( deviceName, len, "%s: %s (%s) {%s}", cardName, snd_deviceName, buf, snd_subDeviceName );
|
|
||||||
}
|
|
||||||
|
|
||||||
++numDeviceNames;
|
++numDeviceNames;
|
||||||
if( !hwDevInfos || numDeviceNames > maxDeviceNames )
|
if( !hwDevInfos || numDeviceNames > maxDeviceNames )
|
||||||
{
|
{
|
||||||
maxDeviceNames *= 2;
|
maxDeviceNames *= 2;
|
||||||
PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ), paInsufficientMemory );
|
PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ),
|
||||||
|
paInsufficientMemory );
|
||||||
}
|
}
|
||||||
|
|
||||||
PA_ENSURE( PaAlsa_StrDup( alsaApi, &alsaDeviceName, buf ) );
|
PA_ENSURE( PaAlsa_StrDup( alsaApi, &alsaDeviceName, buf ) );
|
||||||
|
|
@ -1346,9 +1290,6 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi )
|
||||||
hwDevInfos[ numDeviceNames - 1 ].isPlug = 0;
|
hwDevInfos[ numDeviceNames - 1 ].isPlug = 0;
|
||||||
hwDevInfos[ numDeviceNames - 1 ].hasPlayback = hasPlayback;
|
hwDevInfos[ numDeviceNames - 1 ].hasPlayback = hasPlayback;
|
||||||
hwDevInfos[ numDeviceNames - 1 ].hasCapture = hasCapture;
|
hwDevInfos[ numDeviceNames - 1 ].hasCapture = hasCapture;
|
||||||
|
|
||||||
PA_DEBUG(( "%s: Registered device: id[%s] name[%s]\n", __FUNCTION__, alsaDeviceName, deviceName ));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
alsa_snd_ctl_close( ctl );
|
alsa_snd_ctl_close( ctl );
|
||||||
}
|
}
|
||||||
|
|
@ -1393,17 +1334,19 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi )
|
||||||
}
|
}
|
||||||
PA_DEBUG(( "%s: Found plugin [%s] of type [%s]\n", __FUNCTION__, idStr, tpStr ));
|
PA_DEBUG(( "%s: Found plugin [%s] of type [%s]\n", __FUNCTION__, idStr, tpStr ));
|
||||||
|
|
||||||
PA_UNLESS( alsaDeviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations, strlen(idStr) + 6 ), paInsufficientMemory );
|
PA_UNLESS( alsaDeviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations,
|
||||||
|
strlen(idStr) + 6 ), paInsufficientMemory );
|
||||||
strcpy( alsaDeviceName, idStr );
|
strcpy( alsaDeviceName, idStr );
|
||||||
|
PA_UNLESS( deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations,
|
||||||
PA_UNLESS( deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations, strlen(idStr) + 1 ), paInsufficientMemory );
|
strlen(idStr) + 1 ), paInsufficientMemory );
|
||||||
strcpy( deviceName, idStr );
|
strcpy( deviceName, idStr );
|
||||||
|
|
||||||
++numDeviceNames;
|
++numDeviceNames;
|
||||||
if( !hwDevInfos || numDeviceNames > maxDeviceNames )
|
if( !hwDevInfos || numDeviceNames > maxDeviceNames )
|
||||||
{
|
{
|
||||||
maxDeviceNames *= 2;
|
maxDeviceNames *= 2;
|
||||||
PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ), paInsufficientMemory );
|
PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ),
|
||||||
|
paInsufficientMemory );
|
||||||
}
|
}
|
||||||
|
|
||||||
predefined = FindDeviceName( alsaDeviceName );
|
predefined = FindDeviceName( alsaDeviceName );
|
||||||
|
|
@ -1428,10 +1371,12 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi )
|
||||||
PA_DEBUG(( "%s: Iterating over ALSA plugins failed: %s\n", __FUNCTION__, alsa_snd_strerror( res ) ));
|
PA_DEBUG(( "%s: Iterating over ALSA plugins failed: %s\n", __FUNCTION__, alsa_snd_strerror( res ) ));
|
||||||
|
|
||||||
/* allocate deviceInfo memory based on the number of devices */
|
/* allocate deviceInfo memory based on the number of devices */
|
||||||
PA_UNLESS( baseApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( alsaApi->allocations, sizeof(PaDeviceInfo*) * (numDeviceNames) ), paInsufficientMemory );
|
PA_UNLESS( baseApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
|
||||||
|
alsaApi->allocations, sizeof(PaDeviceInfo*) * (numDeviceNames) ), paInsufficientMemory );
|
||||||
|
|
||||||
/* allocate all device info structs in a contiguous block */
|
/* allocate all device info structs in a contiguous block */
|
||||||
PA_UNLESS( deviceInfoArray = (PaAlsaDeviceInfo*)PaUtil_GroupAllocateMemory( alsaApi->allocations, sizeof(PaAlsaDeviceInfo) * numDeviceNames ), paInsufficientMemory );
|
PA_UNLESS( deviceInfoArray = (PaAlsaDeviceInfo*)PaUtil_GroupAllocateMemory(
|
||||||
|
alsaApi->allocations, sizeof(PaAlsaDeviceInfo) * numDeviceNames ), paInsufficientMemory );
|
||||||
|
|
||||||
/* Loop over list of cards, filling in info. If a device is deemed unavailable (can't get name),
|
/* Loop over list of cards, filling in info. If a device is deemed unavailable (can't get name),
|
||||||
* it's ignored.
|
* it's ignored.
|
||||||
|
|
@ -1534,11 +1479,13 @@ static PaSampleFormat GetAvailableFormats( snd_pcm_t *pcm )
|
||||||
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S32 ) >= 0)
|
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S32 ) >= 0)
|
||||||
available |= paInt32;
|
available |= paInt32;
|
||||||
|
|
||||||
|
#ifdef PA_LITTLE_ENDIAN
|
||||||
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) >= 0)
|
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) >= 0)
|
||||||
available |= paInt24;
|
available |= paInt24;
|
||||||
else
|
#elif defined PA_BIG_ENDIAN
|
||||||
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) >= 0)
|
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) >= 0)
|
||||||
available |= paInt24;
|
available |= paInt24;
|
||||||
|
#endif
|
||||||
|
|
||||||
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S16 ) >= 0)
|
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S16 ) >= 0)
|
||||||
available |= paInt16;
|
available |= paInt16;
|
||||||
|
|
@ -1552,34 +1499,6 @@ static PaSampleFormat GetAvailableFormats( snd_pcm_t *pcm )
|
||||||
return available;
|
return available;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if format is available in native endianness, if not apply paSwapEndian flag for futher
|
|
||||||
processing by Alsa swapping converters.
|
|
||||||
*/
|
|
||||||
static void CheckAndApplyEndianSwapToFormat( PaSampleFormat *format, snd_pcm_t *pcm )
|
|
||||||
{
|
|
||||||
snd_pcm_hw_params_t *hwParams;
|
|
||||||
alsa_snd_pcm_hw_params_alloca( &hwParams );
|
|
||||||
|
|
||||||
alsa_snd_pcm_hw_params_any( pcm, hwParams );
|
|
||||||
|
|
||||||
if( *format & paInt24 )
|
|
||||||
{
|
|
||||||
#ifdef PA_LITTLE_ENDIAN
|
|
||||||
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) < 0 )
|
|
||||||
{
|
|
||||||
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) >= 0 )
|
|
||||||
*format |= paSwapEndian;
|
|
||||||
}
|
|
||||||
#elif defined PA_BIG_ENDIAN
|
|
||||||
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) < 0 )
|
|
||||||
{
|
|
||||||
if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) >= 0 )
|
|
||||||
*format |= paSwapEndian;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Output to console all formats supported by device */
|
/* Output to console all formats supported by device */
|
||||||
static void LogAllAvailableFormats( snd_pcm_t *pcm )
|
static void LogAllAvailableFormats( snd_pcm_t *pcm )
|
||||||
{
|
{
|
||||||
|
|
@ -1704,7 +1623,7 @@ static void LogAllAvailableFormats( snd_pcm_t *pcm )
|
||||||
|
|
||||||
static snd_pcm_format_t Pa2AlsaFormat( PaSampleFormat paFormat )
|
static snd_pcm_format_t Pa2AlsaFormat( PaSampleFormat paFormat )
|
||||||
{
|
{
|
||||||
switch( PA_ALSA_TO_FORMAT(paFormat) )
|
switch( paFormat )
|
||||||
{
|
{
|
||||||
case paFloat32:
|
case paFloat32:
|
||||||
return SND_PCM_FORMAT_FLOAT;
|
return SND_PCM_FORMAT_FLOAT;
|
||||||
|
|
@ -1714,10 +1633,11 @@ static snd_pcm_format_t Pa2AlsaFormat( PaSampleFormat paFormat )
|
||||||
|
|
||||||
case paInt24:
|
case paInt24:
|
||||||
#ifdef PA_LITTLE_ENDIAN
|
#ifdef PA_LITTLE_ENDIAN
|
||||||
return ( paFormat & paSwapEndian ? SND_PCM_FORMAT_S24_3BE : SND_PCM_FORMAT_S24_3LE );
|
return SND_PCM_FORMAT_S24_3LE;
|
||||||
#elif defined PA_BIG_ENDIAN
|
#elif defined PA_BIG_ENDIAN
|
||||||
return ( paFormat & paSwapEndian ? SND_PCM_FORMAT_S24_3LE : SND_PCM_FORMAT_S24_3BE );
|
return SND_PCM_FORMAT_S24_3BE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case paInt32:
|
case paInt32:
|
||||||
return SND_PCM_FORMAT_S32;
|
return SND_PCM_FORMAT_S32;
|
||||||
|
|
||||||
|
|
@ -1820,10 +1740,7 @@ static PaError TestParameters( const PaUtilHostApiRepresentation *hostApi, const
|
||||||
|
|
||||||
/* See if we can find a best possible match */
|
/* See if we can find a best possible match */
|
||||||
availableFormats = GetAvailableFormats( pcm );
|
availableFormats = GetAvailableFormats( pcm );
|
||||||
PA_ENSURE( hostFormat = PaUtil_SelectClosestAvailableFormat( PA_ALSA_TO_FORMAT(availableFormats), parameters->sampleFormat ) );
|
PA_ENSURE( hostFormat = PaUtil_SelectClosestAvailableFormat( availableFormats, parameters->sampleFormat ) );
|
||||||
|
|
||||||
/* Append endiannes conversion flag */
|
|
||||||
CheckAndApplyEndianSwapToFormat( &hostFormat, pcm );
|
|
||||||
|
|
||||||
/* Some specific hardware (reported: Audio8 DJ) can fail with assertion during this step. */
|
/* Some specific hardware (reported: Audio8 DJ) can fail with assertion during this step. */
|
||||||
ENSURE_( alsa_snd_pcm_hw_params_set_format( pcm, hwParams, Pa2AlsaFormat( hostFormat ) ), paUnanticipatedHostError );
|
ENSURE_( alsa_snd_pcm_hw_params_set_format( pcm, hwParams, Pa2AlsaFormat( hostFormat ) ), paUnanticipatedHostError );
|
||||||
|
|
@ -1912,7 +1829,6 @@ error:
|
||||||
static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, PaAlsaHostApiRepresentation *alsaApi,
|
static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, PaAlsaHostApiRepresentation *alsaApi,
|
||||||
const PaStreamParameters *params, StreamDirection streamDir, int callbackMode )
|
const PaStreamParameters *params, StreamDirection streamDir, int callbackMode )
|
||||||
{
|
{
|
||||||
PaSampleFormat availableFormats;
|
|
||||||
PaError result = paNoError;
|
PaError result = paNoError;
|
||||||
PaSampleFormat userSampleFormat = params->sampleFormat, hostSampleFormat = paNoError;
|
PaSampleFormat userSampleFormat = params->sampleFormat, hostSampleFormat = paNoError;
|
||||||
assert( params->channelCount > 0 );
|
assert( params->channelCount > 0 );
|
||||||
|
|
@ -1943,12 +1859,7 @@ static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, Pa
|
||||||
PA_ENSURE( AlsaOpen( &alsaApi->baseHostApiRep, params, streamDir, &self->pcm ) );
|
PA_ENSURE( AlsaOpen( &alsaApi->baseHostApiRep, params, streamDir, &self->pcm ) );
|
||||||
self->nfds = alsa_snd_pcm_poll_descriptors_count( self->pcm );
|
self->nfds = alsa_snd_pcm_poll_descriptors_count( self->pcm );
|
||||||
|
|
||||||
/* Get host sample format */
|
PA_ENSURE( hostSampleFormat = PaUtil_SelectClosestAvailableFormat( GetAvailableFormats( self->pcm ), userSampleFormat ) );
|
||||||
availableFormats = GetAvailableFormats( self->pcm );
|
|
||||||
PA_ENSURE( hostSampleFormat = PaUtil_SelectClosestAvailableFormat( PA_ALSA_TO_FORMAT(availableFormats), userSampleFormat ) );
|
|
||||||
|
|
||||||
/* Append endiannes conversion flag */
|
|
||||||
CheckAndApplyEndianSwapToFormat( &hostSampleFormat, self->pcm );
|
|
||||||
|
|
||||||
self->hostSampleFormat = hostSampleFormat;
|
self->hostSampleFormat = hostSampleFormat;
|
||||||
self->nativeFormat = Pa2AlsaFormat( hostSampleFormat );
|
self->nativeFormat = Pa2AlsaFormat( hostSampleFormat );
|
||||||
|
|
@ -2884,16 +2795,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||||
hostOutputSampleFormat = stream->playback.hostSampleFormat | (!stream->playback.hostInterleaved ? paNonInterleaved : 0);
|
hostOutputSampleFormat = stream->playback.hostSampleFormat | (!stream->playback.hostInterleaved ? paNonInterleaved : 0);
|
||||||
|
|
||||||
PA_ENSURE( PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
|
PA_ENSURE( PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
|
||||||
numInputChannels, inputSampleFormat, (hostInputSampleFormat & ~paSwapEndian),
|
numInputChannels, inputSampleFormat, hostInputSampleFormat,
|
||||||
numOutputChannels, outputSampleFormat, (hostOutputSampleFormat & ~paSwapEndian),
|
numOutputChannels, outputSampleFormat, hostOutputSampleFormat,
|
||||||
sampleRate, streamFlags, framesPerBuffer, stream->maxFramesPerHostBuffer,
|
sampleRate, streamFlags, framesPerBuffer, stream->maxFramesPerHostBuffer,
|
||||||
hostBufferSizeMode, callback, userData ) );
|
hostBufferSizeMode, callback, userData ) );
|
||||||
|
|
||||||
/* Some drivers may work only in Big-Endian format (like Audio4DJ), check it and replace
|
|
||||||
original converter with our specific with swapping capability.
|
|
||||||
*/
|
|
||||||
CheckAndReplaceConverterForSwapEndian(stream, hostInputSampleFormat, hostOutputSampleFormat);
|
|
||||||
|
|
||||||
/* Ok, buffer processor is initialized, now we can deduce it's latency */
|
/* Ok, buffer processor is initialized, now we can deduce it's latency */
|
||||||
if( numInputChannels > 0 )
|
if( numInputChannels > 0 )
|
||||||
stream->streamRepresentation.streamInfo.inputLatency = inputLatency + (PaTime)(
|
stream->streamRepresentation.streamInfo.inputLatency = inputLatency + (PaTime)(
|
||||||
|
|
@ -4685,648 +4591,3 @@ PaError PaAlsa_SetRetriesBusy( int retries )
|
||||||
busyRetries_ = retries;
|
busyRetries_ = retries;
|
||||||
return paNoError;
|
return paNoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* CONVERTERS (Swapping SRC/DST) */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#define PA_CLIP_( val, min, max )\
|
|
||||||
{ val = ((val) < (min)) ? (min) : (((val) > (max)) ? (max) : (val)); }
|
|
||||||
|
|
||||||
static const double const_1_div_2147483648_ = 1.0 / 2147483648.0; /* 32 bit multiplier */
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Copy_24_To_24_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
unsigned char *src = (unsigned char*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
dest[2] = src[0];
|
|
||||||
dest[1] = src[1];
|
|
||||||
dest[0] = src[2];
|
|
||||||
|
|
||||||
src += sourceStride * 3;
|
|
||||||
dest += destinationStride * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void UInt8_To_Int24_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
unsigned char *src = (unsigned char*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
(void) ditherGenerator; /* unused parameters */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
dest[2] = 0;
|
|
||||||
dest[1] = 0;
|
|
||||||
dest[0] = (unsigned char)(*src - 128);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(*src - 128);
|
|
||||||
dest[1] = 0;
|
|
||||||
dest[0] = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
src += sourceStride;
|
|
||||||
dest += destinationStride * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int8_To_Int24_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
signed char *src = (signed char*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
(void)ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
dest[2] = 0;
|
|
||||||
dest[1] = 0;
|
|
||||||
dest[0] = (*src);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
dest[2] = (*src);
|
|
||||||
dest[1] = 0;
|
|
||||||
dest[0] = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
src += sourceStride;
|
|
||||||
dest += destinationStride * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int16_To_Int24_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
PaInt16 *src = (PaInt16*) sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
PaInt16 temp;
|
|
||||||
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
temp = *src;
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
dest[2] = 0;
|
|
||||||
dest[1] = (unsigned char)(temp);
|
|
||||||
dest[0] = (unsigned char)(temp >> 8);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(temp >> 8);
|
|
||||||
dest[1] = (unsigned char)(temp);
|
|
||||||
dest[0] = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
src += sourceStride;
|
|
||||||
dest += destinationStride * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int32_To_Int24_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
PaInt32 *src = (PaInt32*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
/* REVIEW */
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(*src >> 8);
|
|
||||||
dest[1] = (unsigned char)(*src >> 16);
|
|
||||||
dest[0] = (unsigned char)(*src >> 24);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(*src >> 24);
|
|
||||||
dest[1] = (unsigned char)(*src >> 16);
|
|
||||||
dest[0] = (unsigned char)(*src >> 8);
|
|
||||||
#endif
|
|
||||||
src += sourceStride;
|
|
||||||
dest += destinationStride * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Float32_To_Int24_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
float *src = (float*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
PaInt32 temp;
|
|
||||||
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
/* convert to 32 bit and drop the low 8 bits */
|
|
||||||
double scaled = (double)(*src) * 2147483647.0;
|
|
||||||
temp = (PaInt32) scaled;
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(temp >> 8);
|
|
||||||
dest[1] = (unsigned char)(temp >> 16);
|
|
||||||
dest[0] = (unsigned char)(temp >> 24);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(temp >> 24);
|
|
||||||
dest[1] = (unsigned char)(temp >> 16);
|
|
||||||
dest[0] = (unsigned char)(temp >> 8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
src += sourceStride;
|
|
||||||
dest += destinationStride * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Float32_To_Int24_Dither_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
float *src = (float*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
PaInt32 temp;
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
/* convert to 32 bit and drop the low 8 bits */
|
|
||||||
|
|
||||||
double dither = PaUtil_GenerateFloatTriangularDither( ditherGenerator );
|
|
||||||
/* use smaller scaler to prevent overflow when we add the dither */
|
|
||||||
double dithered = ((double)*src * (2147483646.0)) + dither;
|
|
||||||
|
|
||||||
temp = (PaInt32) dithered;
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(temp >> 8);
|
|
||||||
dest[1] = (unsigned char)(temp >> 16);
|
|
||||||
dest[0] = (unsigned char)(temp >> 24);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(temp >> 24);
|
|
||||||
dest[1] = (unsigned char)(temp >> 16);
|
|
||||||
dest[0] = (unsigned char)(temp >> 8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
src += sourceStride;
|
|
||||||
dest += destinationStride * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Float32_To_Int24_Clip_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
float *src = (float*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
PaInt32 temp;
|
|
||||||
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
/* convert to 32 bit and drop the low 8 bits */
|
|
||||||
double scaled = *src * 0x7FFFFFFF;
|
|
||||||
PA_CLIP_( scaled, -2147483648., 2147483647. );
|
|
||||||
temp = (PaInt32) scaled;
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(temp >> 8);
|
|
||||||
dest[1] = (unsigned char)(temp >> 16);
|
|
||||||
dest[0] = (unsigned char)(temp >> 24);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(temp >> 24);
|
|
||||||
dest[1] = (unsigned char)(temp >> 16);
|
|
||||||
dest[0] = (unsigned char)(temp >> 8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
src += sourceStride;
|
|
||||||
dest += destinationStride * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Float32_To_Int24_DitherClip_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
float *src = (float*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
PaInt32 temp;
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
/* convert to 32 bit and drop the low 8 bits */
|
|
||||||
|
|
||||||
double dither = PaUtil_GenerateFloatTriangularDither( ditherGenerator );
|
|
||||||
/* use smaller scaler to prevent overflow when we add the dither */
|
|
||||||
double dithered = ((double)*src * (2147483646.0)) + dither;
|
|
||||||
PA_CLIP_( dithered, -2147483648., 2147483647. );
|
|
||||||
|
|
||||||
temp = (PaInt32) dithered;
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(temp >> 8);
|
|
||||||
dest[1] = (unsigned char)(temp >> 16);
|
|
||||||
dest[0] = (unsigned char)(temp >> 24);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
dest[2] = (unsigned char)(temp >> 24);
|
|
||||||
dest[1] = (unsigned char)(temp >> 16);
|
|
||||||
dest[0] = (unsigned char)(temp >> 8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
src += sourceStride;
|
|
||||||
dest += destinationStride * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int24_To_Float32_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
unsigned char *src = (unsigned char*)sourceBuffer;
|
|
||||||
float *dest = (float*)destinationBuffer;
|
|
||||||
PaInt32 temp;
|
|
||||||
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
temp = (((PaInt32)src[2]) << 8);
|
|
||||||
temp = temp | (((PaInt32)src[1]) << 16);
|
|
||||||
temp = temp | (((PaInt32)src[0]) << 24);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
temp = (((PaInt32)src[2]) << 24);
|
|
||||||
temp = temp | (((PaInt32)src[1]) << 16);
|
|
||||||
temp = temp | (((PaInt32)src[0]) << 8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*dest = (float) ((double)temp * const_1_div_2147483648_);
|
|
||||||
|
|
||||||
src += sourceStride * 3;
|
|
||||||
dest += destinationStride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int24_To_Int32_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
unsigned char *src = (unsigned char*)sourceBuffer;
|
|
||||||
PaInt32 *dest = (PaInt32*) destinationBuffer;
|
|
||||||
PaInt32 temp;
|
|
||||||
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
temp = (((PaInt32)src[2]) << 8);
|
|
||||||
temp = temp | (((PaInt32)src[1]) << 16);
|
|
||||||
temp = temp | (((PaInt32)src[0]) << 24);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
temp = (((PaInt32)src[2]) << 24);
|
|
||||||
temp = temp | (((PaInt32)src[1]) << 16);
|
|
||||||
temp = temp | (((PaInt32)src[0]) << 8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*dest = temp;
|
|
||||||
|
|
||||||
src += sourceStride * 3;
|
|
||||||
dest += destinationStride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int24_To_Int16_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
unsigned char *src = (unsigned char*)sourceBuffer;
|
|
||||||
PaInt16 *dest = (PaInt16*)destinationBuffer;
|
|
||||||
|
|
||||||
PaInt16 temp;
|
|
||||||
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
/* src[2] is discarded */
|
|
||||||
temp = (((PaInt16)src[1]));
|
|
||||||
temp = temp | (PaInt16)(((PaInt16)src[0]) << 8);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
/* src[0] is discarded */
|
|
||||||
temp = (PaInt16)(((PaInt16)src[2]) << 8);
|
|
||||||
temp = temp | (((PaInt16)src[1]));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*dest = temp;
|
|
||||||
|
|
||||||
src += sourceStride * 3;
|
|
||||||
dest += destinationStride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int24_To_Int16_Dither_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
unsigned char *src = (unsigned char*)sourceBuffer;
|
|
||||||
PaInt16 *dest = (PaInt16*)destinationBuffer;
|
|
||||||
|
|
||||||
PaInt32 temp, dither;
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
temp = (((PaInt32)src[2]) << 8);
|
|
||||||
temp = temp | (((PaInt32)src[1]) << 16);
|
|
||||||
temp = temp | (((PaInt32)src[0]) << 24);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
temp = (((PaInt32)src[2]) << 24);
|
|
||||||
temp = temp | (((PaInt32)src[1]) << 16);
|
|
||||||
temp = temp | (((PaInt32)src[0]) << 8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* REVIEW */
|
|
||||||
dither = PaUtil_Generate16BitTriangularDither( ditherGenerator );
|
|
||||||
*dest = (PaInt16) (((temp >> 1) + dither) >> 15);
|
|
||||||
|
|
||||||
src += sourceStride * 3;
|
|
||||||
dest += destinationStride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int24_To_Int8_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
unsigned char *src = (unsigned char*)sourceBuffer;
|
|
||||||
signed char *dest = (signed char*)destinationBuffer;
|
|
||||||
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
/* src[0] is discarded */
|
|
||||||
/* src[1] is discarded */
|
|
||||||
*dest = src[0];
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
/* src[2] is discarded */
|
|
||||||
/* src[1] is discarded */
|
|
||||||
*dest = src[2];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
src += sourceStride * 3;
|
|
||||||
dest += destinationStride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int24_To_Int8_Dither_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
unsigned char *src = (unsigned char*)sourceBuffer;
|
|
||||||
signed char *dest = (signed char*)destinationBuffer;
|
|
||||||
|
|
||||||
PaInt32 temp, dither;
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
temp = (((PaInt32)src[2]) << 8);
|
|
||||||
temp = temp | (((PaInt32)src[1]) << 16);
|
|
||||||
temp = temp | (((PaInt32)src[0]) << 24);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
temp = (((PaInt32)src[2]) << 24);
|
|
||||||
temp = temp | (((PaInt32)src[1]) << 16);
|
|
||||||
temp = temp | (((PaInt32)src[0]) << 8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* REVIEW */
|
|
||||||
dither = PaUtil_Generate16BitTriangularDither( ditherGenerator );
|
|
||||||
*dest = (signed char) (((temp >> 1) + dither) >> 23);
|
|
||||||
|
|
||||||
src += sourceStride * 3;
|
|
||||||
dest += destinationStride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void Int24_To_UInt8_Swap(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
unsigned char *src = (unsigned char*)sourceBuffer;
|
|
||||||
unsigned char *dest = (unsigned char*)destinationBuffer;
|
|
||||||
|
|
||||||
(void) ditherGenerator; /* unused parameter */
|
|
||||||
|
|
||||||
while( count-- )
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(PA_LITTLE_ENDIAN)
|
|
||||||
/* src[0] is discarded */
|
|
||||||
/* src[1] is discarded */
|
|
||||||
*dest = (unsigned char)(src[0] + 128);
|
|
||||||
#elif defined(PA_BIG_ENDIAN)
|
|
||||||
*dest = (unsigned char)(src[2] + 128);
|
|
||||||
/* src[1] is discarded */
|
|
||||||
/* src[2] is discarded */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
src += sourceStride * 3;
|
|
||||||
dest += destinationStride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static void X_To_X_Stub(
|
|
||||||
void *destinationBuffer, signed int destinationStride,
|
|
||||||
void *sourceBuffer, signed int sourceStride,
|
|
||||||
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
|
|
||||||
{
|
|
||||||
(void) destinationBuffer; /* unused parameters */
|
|
||||||
(void) destinationStride; /* unused parameters */
|
|
||||||
(void) sourceBuffer; /* unused parameters */
|
|
||||||
(void) sourceStride; /* unused parameters */
|
|
||||||
(void) count; /* unused parameters */
|
|
||||||
(void) ditherGenerator; /* unused parameters */
|
|
||||||
/* IMPLEMENT ME */
|
|
||||||
|
|
||||||
assert(0 && "input/output format needs additional swapping converter");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
static PaUtilConverterTable paAlsaSwapConverters = {
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int32; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int32_Dither; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int32_Clip; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int32_DitherClip; */
|
|
||||||
|
|
||||||
Float32_To_Int24_Swap, /* PaUtilConverter *Float32_To_Int24; */
|
|
||||||
Float32_To_Int24_Dither_Swap, /* PaUtilConverter *Float32_To_Int24_Dither; */
|
|
||||||
Float32_To_Int24_Clip_Swap, /* PaUtilConverter *Float32_To_Int24_Clip; */
|
|
||||||
Float32_To_Int24_DitherClip_Swap, /* PaUtilConverter *Float32_To_Int24_DitherClip; */
|
|
||||||
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int16; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int16_Dither; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int16_Clip; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int16_DitherClip; */
|
|
||||||
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int8; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int8_Dither; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int8_Clip; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_Int8_DitherClip; */
|
|
||||||
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_UInt8; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_UInt8_Dither; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_UInt8_Clip; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Float32_To_UInt8_DitherClip; */
|
|
||||||
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int32_To_Float32; */
|
|
||||||
Int32_To_Int24_Swap, /* PaUtilConverter *Int32_To_Int24; */
|
|
||||||
X_To_X_Stub,/*TO-DO*//* PaUtilConverter *Int32_To_Int24_Dither; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int32_To_Int16; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int32_To_Int16_Dither; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int32_To_Int8; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int32_To_Int8_Dither; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int32_To_UInt8; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int32_To_UInt8_Dither; */
|
|
||||||
|
|
||||||
Int24_To_Float32_Swap, /* PaUtilConverter *Int24_To_Float32; */
|
|
||||||
Int24_To_Int32_Swap, /* PaUtilConverter *Int24_To_Int32; */
|
|
||||||
Int24_To_Int16_Swap, /* PaUtilConverter *Int24_To_Int16; */
|
|
||||||
Int24_To_Int16_Dither_Swap, /* PaUtilConverter *Int24_To_Int16_Dither; */
|
|
||||||
Int24_To_Int8_Swap, /* PaUtilConverter *Int24_To_Int8; */
|
|
||||||
Int24_To_Int8_Dither_Swap, /* PaUtilConverter *Int24_To_Int8_Dither; */
|
|
||||||
Int24_To_UInt8_Swap, /* PaUtilConverter *Int24_To_UInt8; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int24_To_UInt8_Dither; */
|
|
||||||
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int16_To_Float32; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int16_To_Int32; */
|
|
||||||
Int16_To_Int24_Swap, /* PaUtilConverter *Int16_To_Int24; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int16_To_Int8; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int16_To_Int8_Dither; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int16_To_UInt8; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int16_To_UInt8_Dither; */
|
|
||||||
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int8_To_Float32; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int8_To_Int32; */
|
|
||||||
Int8_To_Int24_Swap, /* PaUtilConverter *Int8_To_Int24 */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int8_To_Int16; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Int8_To_UInt8; */
|
|
||||||
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *UInt8_To_Float32; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *UInt8_To_Int32; */
|
|
||||||
UInt8_To_Int24_Swap, /* PaUtilConverter *UInt8_To_Int24; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *UInt8_To_Int16; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *UInt8_To_Int8; */
|
|
||||||
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Copy_8_To_8; */
|
|
||||||
X_To_X_Stub, /* PaUtilConverter *Copy_16_To_16; */
|
|
||||||
Copy_24_To_24_Swap, /* PaUtilConverter *Copy_24_To_24; */
|
|
||||||
X_To_X_Stub /* PaUtilConverter *Copy_32_To_32; */
|
|
||||||
};
|
|
||||||
void CheckAndReplaceConverterForSwapEndian(PaAlsaStream *stream, PaSampleFormat hostInputSampleFormat,
|
|
||||||
PaSampleFormat hostOutputSampleFormat)
|
|
||||||
{
|
|
||||||
PaUtilConverter **cv_org = (PaUtilConverter **)&paConverters,
|
|
||||||
**cv_swp = (PaUtilConverter **)&paAlsaSwapConverters;
|
|
||||||
|
|
||||||
int i, i_max = sizeof(PaUtilConverterTable)/sizeof(PaUtilConverter *);
|
|
||||||
|
|
||||||
if (hostInputSampleFormat & paSwapEndian)
|
|
||||||
{
|
|
||||||
for (i = 0; i < i_max; ++i)
|
|
||||||
{
|
|
||||||
if (cv_org[i] == stream->bufferProcessor.inputConverter)
|
|
||||||
{
|
|
||||||
stream->bufferProcessor.inputConverter = cv_swp[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hostOutputSampleFormat & paSwapEndian)
|
|
||||||
{
|
|
||||||
for (i = 0; i < i_max; ++i)
|
|
||||||
{
|
|
||||||
if (cv_org[i] == stream->bufferProcessor.outputConverter)
|
|
||||||
{
|
|
||||||
stream->bufferProcessor.outputConverter = cv_swp[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue