* Copyright (c) 2002 Joshua Haberman <joshua@haberman.com>
* Copyright (c) 2005-2009 Arve Knudsen <arve.knudsen@gmail.com>
* 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
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
#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
#define SND_PCM_TSTAMP_ENABLE SND_PCM_TSTAMP_MMAP
#endif
/* Combine version elements into a single (unsigned) integer */
#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. */
#define _PA_DEFINE_FUNC(x) typedef typeof(x) x##_ft; static x##_ft *alsa_##x = 0
_PA_DEFINE_FUNC(snd_pcm_info_set_stream);
_PA_DEFINE_FUNC(snd_pcm_info_get_name);
_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)
_PA_DEFINE_FUNC(snd_ctl_pcm_next_device);
int _PA_LOCAL_IMPL(snd_pcm_hw_params_set_rate_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
{
- int ret;
+ int ret;
- if ((ret = alsa_snd_pcm_hw_params_set_rate(pcm, params, (*val), (*dir))) < 0)
- return ret;
+ if ((ret = alsa_snd_pcm_hw_params_set_rate(pcm, params, (*val), (*dir))) < 0)
+ return ret;
- return 0;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_set_buffer_size_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
{
- int ret;
+ int ret;
- if ((ret = alsa_snd_pcm_hw_params_set_buffer_size(pcm, params, (*val))) < 0)
- return ret;
+ if ((ret = alsa_snd_pcm_hw_params_set_buffer_size(pcm, params, (*val))) < 0)
+ return ret;
- return 0;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_set_period_size_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)
{
- int ret;
+ int ret;
- if ((ret = alsa_snd_pcm_hw_params_set_period_size(pcm, params, (*val), (*dir))) < 0)
- return ret;
+ if ((ret = alsa_snd_pcm_hw_params_set_period_size(pcm, params, (*val), (*dir))) < 0)
+ return ret;
- return 0;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_channels_min) (const snd_pcm_hw_params_t *params, unsigned int *val)
{
- (*val) = 1;
- return 0;
+ (*val) = 1;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_channels_max) (const snd_pcm_hw_params_t *params, unsigned int *val)
{
- (*val) = 2;
- return 0;
+ (*val) = 2;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_periods_min) (const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
{
- (*val) = 2;
- return 0;
+ (*val) = 2;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_periods_max) (const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
{
- (*val) = 8;
- return 0;
+ (*val) = 8;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_period_size_min) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir)
{
- (*frames) = 64;
- return 0;
+ (*frames) = 64;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_period_size_max) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir)
{
- (*frames) = 512;
- return 0;
+ (*frames) = 512;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_buffer_size_max) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val)
{
- int ret;
- int dir = 0;
- snd_pcm_uframes_t pmax = 0;
- unsigned int pcnt = 0;
-
- if ((ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_period_size_max)(params, &pmax, &dir)) < 0)
- return ret;
- if ((ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_periods_max)(params, &pcnt, &dir)) < 0)
- return ret;
-
- (*val) = pmax * pcnt;
- return 0;
+ int ret;
+ int dir = 0;
+ snd_pcm_uframes_t pmax = 0;
+ unsigned int pcnt = 0;
+
+ if ((ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_period_size_max)(params, &pmax, &dir)) < 0)
+ return ret;
+ if ((ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_periods_max)(params, &pcnt, &dir)) < 0)
+ return ret;
+
+ (*val) = pmax * pcnt;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_rate_min) (const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
{
- (*val) = 44100;
- return 0;
+ (*val) = 44100;
+ return 0;
}
int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_rate_max) (const snd_pcm_hw_params_t *params, unsigned int *val, int *dir)
{
- (*val) = 44100;
- return 0;
+ (*val) = 44100;
+ return 0;
}
#endif // PA_ALSA_DYNAMIC
{
#ifdef PA_ALSA_DYNAMIC
- PA_DEBUG(( "%s: loading ALSA library file - %s\n", __FUNCTION__, g_AlsaLibName ));
+ PA_DEBUG(( "%s: loading ALSA library file - %s\n", __FUNCTION__, g_AlsaLibName ));
- dlerror();
+ dlerror();
g_AlsaLib = dlopen(g_AlsaLibName, (RTLD_NOW|RTLD_GLOBAL));
if (g_AlsaLib == NULL)
{
- PA_DEBUG(( "%s: failed dlopen() ALSA library file - %s, error: %s\n", __FUNCTION__, g_AlsaLibName, dlerror() ));
- return 0;
+ PA_DEBUG(( "%s: failed dlopen() ALSA library file - %s, error: %s\n", __FUNCTION__, g_AlsaLibName, dlerror() ));
+ return 0;
}
PA_DEBUG(( "%s: loading ALSA API\n", __FUNCTION__ ));
#define _PA_LOAD_FUNC(x) do { \
- alsa_##x = dlsym(g_AlsaLib, #x); \
- if (alsa_##x == NULL) { \
- PA_DEBUG(( "%s: symbol [%s] not found in - %s, error: %s\n", __FUNCTION__, #x, g_AlsaLibName, dlerror() )); }\
+ alsa_##x = dlsym(g_AlsaLib, #x); \
+ if (alsa_##x == NULL) { \
+ PA_DEBUG(( "%s: symbol [%s] not found in - %s, error: %s\n", __FUNCTION__, #x, g_AlsaLibName, dlerror() )); }\
} while(0)
#else
_PA_LOAD_FUNC(snd_pcm_info_set_stream);
_PA_LOAD_FUNC(snd_pcm_info_get_name);
_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_info);
#undef _PA_LOAD_FUNC
#ifdef PA_ALSA_DYNAMIC
- PA_DEBUG(( "%s: loaded ALSA API - ok\n", __FUNCTION__ ));
+ PA_DEBUG(( "%s: loaded ALSA API - ok\n", __FUNCTION__ ));
#define _PA_VALIDATE_LOAD_REPLACEMENT(x)\
- do {\
- if (alsa_##x == NULL)\
- {\
- alsa_##x = &_PA_LOCAL_IMPL(x);\
- PA_DEBUG(( "%s: replacing [%s] with local implementation\n", __FUNCTION__, #x ));\
- }\
- } while (0)
-
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_rate_near);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_buffer_size_near);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_period_size_near);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_channels_min);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_channels_max);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_periods_min);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_periods_max);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_period_size_min);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_period_size_max);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_buffer_size_max);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_rate_min);
- _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_rate_max);
+ do {\
+ if (alsa_##x == NULL)\
+ {\
+ alsa_##x = &_PA_LOCAL_IMPL(x);\
+ PA_DEBUG(( "%s: replacing [%s] with local implementation\n", __FUNCTION__, #x ));\
+ }\
+ } while (0)
+
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_rate_near);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_buffer_size_near);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_set_period_size_near);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_channels_min);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_channels_max);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_periods_min);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_periods_max);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_period_size_min);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_period_size_max);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_buffer_size_max);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_rate_min);
+ _PA_VALIDATE_LOAD_REPLACEMENT(snd_pcm_hw_params_get_rate_max);
#undef _PA_LOCAL_IMPL
#undef _PA_VALIDATE_LOAD_REPLACEMENT
{
#ifdef PA_ALSA_DYNAMIC
dlclose(g_AlsaLib);
- g_AlsaLib = NULL;
+ g_AlsaLib = NULL;
#endif
}
/* Check return value of ALSA function, and map it to PaError */
#define ENSURE_(expr, code) \
do { \
- int __pa_unsure_error_id;\
+ int __pa_unsure_error_id;\
if( UNLIKELY( (__pa_unsure_error_id = (expr)) < 0 ) ) \
{ \
/* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \
#define ASSERT_CALL_(expr, success) \
do {\
- int __pa_assert_error_id;\
- __pa_assert_error_id = (expr);\
- assert( success == __pa_assert_error_id );\
- } while (0)
+ int __pa_assert_error_id;\
+ __pa_assert_error_id = (expr);\
+ assert( success == __pa_assert_error_id );\
+ } while (0)
static int numPeriods_ = 4;
static int busyRetries_ = 100;
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
to be used, do not forget to register this callback in PaAlsa_Initialize, and unregister in Terminate.
*/
{ "AndroidPlayback_ExtraDockSpeaker_normal", NULL, 0, 1, 0 },
{ "AndroidPlayback_TvOut_normal", NULL, 0, 1, 0 },
- { "AndroidRecord_Microphone", NULL, 0, 0, 1 },
+ { "AndroidRecord_Microphone", NULL, 0, 0, 1 },
{ "AndroidRecord_Earpiece_normal", NULL, 0, 0, 1 },
- { "AndroidRecord_Speaker_normal", NULL, 0, 0, 1 },
+ { "AndroidRecord_Speaker_normal", NULL, 0, 0, 1 },
{ "AndroidRecord_Headset_normal", NULL, 0, 0, 1 },
- { "AndroidRecord_Bluetooth_normal", NULL, 0, 0, 1 },
+ { "AndroidRecord_Bluetooth_normal", NULL, 0, 0, 1 },
{ "AndroidRecord_Speaker_Headset_normal", NULL, 0, 0, 1 },
{ NULL, NULL, 0, 1, 0 }
}
else
{
- if (ret < 0)
- PA_DEBUG(( "%s: Opened device '%s' ptr[%p] - result: [%d:%s]\n", __FUNCTION__, name, *pcmp, ret, alsa_snd_strerror(ret) ));
+ if (ret < 0)
+ PA_DEBUG(( "%s: Opened device '%s' ptr[%p] - result: [%d:%s]\n", __FUNCTION__, name, *pcmp, ret, alsa_snd_strerror(ret) ));
}
return ret;
snd_pcm_t *pcm = NULL;
PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep;
- PA_DEBUG(( "%s: Filling device info for: %s\n", __FUNCTION__, deviceName->name ));
+ PA_DEBUG(( "%s: Filling device info for: %s\n", __FUNCTION__, deviceName->name ));
/* Zero fields */
InitializeDeviceInfo( baseDeviceInfo );
}
baseDeviceInfo->structVersion = 2;
- baseDeviceInfo->hostApi = alsaApi->hostApiIndex;
- baseDeviceInfo->name = deviceName->name;
- devInfo->alsaName = deviceName->alsaName;
- devInfo->isPlug = deviceName->isPlug;
+ baseDeviceInfo->hostApi = alsaApi->hostApiIndex;
+ baseDeviceInfo->name = deviceName->name;
+ devInfo->alsaName = deviceName->alsaName;
+ devInfo->isPlug = deviceName->isPlug;
/* A: Storing pointer to PaAlsaDeviceInfo object as pointer to PaDeviceInfo object.
* Should now be safe to add device info, unless the device supports neither capture nor playback
}
else
{
- PA_DEBUG(( "%s: Skipped device: %s, all channels == 0\n", __FUNCTION__, deviceName->name ));
+ PA_DEBUG(( "%s: Skipped device: %s, all channels == 0\n", __FUNCTION__, deviceName->name ));
}
end:
snd_pcm_info_t *pcmInfo;
int res;
int blocking = SND_PCM_NONBLOCK;
+ char alsaCardName[50];
#ifdef PA_ENABLE_DEBUG_OUTPUT
PaTime startTime = PaUtil_GetTime();
#endif
alsa_snd_pcm_info_alloca( &pcmInfo );
while( alsa_snd_card_next( &cardIdx ) == 0 && cardIdx >= 0 )
{
- char alsaCardNameId[64] = { 0 };
char *cardName;
int devIdx = -1;
snd_ctl_t *ctl;
+ char buf[50];
- /* Make card name */
- snprintf( alsaCardNameId, sizeof (alsaCardNameId)-1, "hw:%d", cardIdx );
+ snprintf( alsaCardName, sizeof (alsaCardName), "hw:%d", cardIdx );
- /* Try opening card */
- if( alsa_snd_ctl_open( &ctl, alsaCardNameId, 0 ) < 0 )
+ /* Acquire name of card */
+ if( alsa_snd_ctl_open( &ctl, alsaCardName, 0 ) < 0 )
{
/* 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;
}
alsa_snd_ctl_card_info( ctl, 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 )
{
char *alsaDeviceName, *deviceName;
size_t len;
int hasPlayback = 0, hasCapture = 0;
- int subDevIdx, subDevCount = 1;
-
- PA_DEBUG(( "%s: - idx = %d:\n", __FUNCTION__, devIdx ));
+ snprintf( buf, sizeof (buf), "hw:%d,%d", cardIdx, devIdx );
- /* Make this device current */
+ /* Obtain info about this particular device */
alsa_snd_pcm_info_set_device( pcmInfo, devIdx );
-
- /* Iterate sub-devices */
- for( subDevIdx = 0; subDevIdx < subDevCount; ++subDevIdx )
+ alsa_snd_pcm_info_set_subdevice( pcmInfo, 0 );
+ alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_CAPTURE );
+ if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )
{
- 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 );
- if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )
- {
- hasCapture = 1;
- }
-
- /* Test for Playback capability */
- alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_PLAYBACK );
- if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )
- {
- hasPlayback = 1;
- }
-
- /* If neither supported, such device is stub or failed */
- if( !hasPlayback && !hasCapture )
- {
- continue;
- }
-
- /* Get sub-device count */
- if( subDevIdx == 0 )
- {
- subDevCount = alsa_snd_pcm_info_get_subdevices_count( pcmInfo );
- PA_DEBUG(( "%s: sub-devices: %d/%d\n", __FUNCTION__, alsa_snd_pcm_info_get_subdevices_avail( pcmInfo ), subDevCount));
- }
-
- 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 );
+ hasCapture = 1;
+ }
- 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 );
+ alsa_snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_PLAYBACK );
+ if( alsa_snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )
+ {
+ hasPlayback = 1;
+ }
- 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 );
- }
+ if( !hasPlayback && !hasCapture )
+ {
+ /* Error */
+ continue;
+ }
- ++numDeviceNames;
- if( !hwDevInfos || numDeviceNames > maxDeviceNames )
- {
- maxDeviceNames *= 2;
- PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ), paInsufficientMemory );
- }
+ /* The length of the string written by snprintf plus terminating 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 ),
+ paInsufficientMemory );
+ snprintf( deviceName, len, "%s: %s (%s)", cardName,
+ alsa_snd_pcm_info_get_name( pcmInfo ), buf );
- PA_ENSURE( PaAlsa_StrDup( alsaApi, &alsaDeviceName, buf ) );
+ ++numDeviceNames;
+ if( !hwDevInfos || numDeviceNames > maxDeviceNames )
+ {
+ maxDeviceNames *= 2;
+ PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ),
+ paInsufficientMemory );
+ }
- hwDevInfos[ numDeviceNames - 1 ].alsaName = alsaDeviceName;
- hwDevInfos[ numDeviceNames - 1 ].name = deviceName;
- hwDevInfos[ numDeviceNames - 1 ].isPlug = 0;
- hwDevInfos[ numDeviceNames - 1 ].hasPlayback = hasPlayback;
- hwDevInfos[ numDeviceNames - 1 ].hasCapture = hasCapture;
+ PA_ENSURE( PaAlsa_StrDup( alsaApi, &alsaDeviceName, buf ) );
- PA_DEBUG(( "%s: Registered device: id[%s] name[%s]\n", __FUNCTION__, alsaDeviceName, deviceName ));
- }
+ hwDevInfos[ numDeviceNames - 1 ].alsaName = alsaDeviceName;
+ hwDevInfos[ numDeviceNames - 1 ].name = deviceName;
+ hwDevInfos[ numDeviceNames - 1 ].isPlug = 0;
+ hwDevInfos[ numDeviceNames - 1 ].hasPlayback = hasPlayback;
+ hwDevInfos[ numDeviceNames - 1 ].hasCapture = hasCapture;
}
alsa_snd_ctl_close( ctl );
}
}
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 );
-
- PA_UNLESS( deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations, strlen(idStr) + 1 ), paInsufficientMemory );
+ PA_UNLESS( deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations,
+ strlen(idStr) + 1 ), paInsufficientMemory );
strcpy( deviceName, idStr );
++numDeviceNames;
if( !hwDevInfos || numDeviceNames > maxDeviceNames )
{
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 );
PA_DEBUG(( "%s: Iterating over ALSA plugins failed: %s\n", __FUNCTION__, alsa_snd_strerror( res ) ));
/* 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 */
- 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),
* it's ignored.
alsa_snd_pcm_hw_params_any( pcm, hwParams );
- if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_FLOAT ) >= 0 )
+ if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_FLOAT ) >= 0)
available |= paFloat32;
- 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;
- if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) >= 0 )
+#ifdef PA_LITTLE_ENDIAN
+ if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) >= 0)
available |= paInt24;
- else
- if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) >= 0 )
+#elif defined PA_BIG_ENDIAN
+ if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) >= 0)
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;
- if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_U8 ) >= 0 )
+ if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_U8 ) >= 0)
available |= paUInt8;
- if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S8 ) >= 0 )
+ if( alsa_snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S8 ) >= 0)
available |= paInt8;
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 */
static void LogAllAvailableFormats( snd_pcm_t *pcm )
{
static snd_pcm_format_t Pa2AlsaFormat( PaSampleFormat paFormat )
{
- switch( PA_ALSA_TO_FORMAT(paFormat) )
+ switch( paFormat )
{
case paFloat32:
return SND_PCM_FORMAT_FLOAT;
case paInt24:
#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
- return ( paFormat & paSwapEndian ? SND_PCM_FORMAT_S24_3LE : SND_PCM_FORMAT_S24_3BE );
+ return SND_PCM_FORMAT_S24_3BE;
#endif
+
case paInt32:
return SND_PCM_FORMAT_S32;
/* See if we can find a best possible match */
availableFormats = GetAvailableFormats( pcm );
- PA_ENSURE( hostFormat = PaUtil_SelectClosestAvailableFormat( PA_ALSA_TO_FORMAT(availableFormats), parameters->sampleFormat ) );
-
- /* Append endiannes conversion flag */
- CheckAndApplyEndianSwapToFormat( &hostFormat, pcm );
+ PA_ENSURE( hostFormat = PaUtil_SelectClosestAvailableFormat( availableFormats, parameters->sampleFormat ) );
/* 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 );
static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, PaAlsaHostApiRepresentation *alsaApi,
const PaStreamParameters *params, StreamDirection streamDir, int callbackMode )
{
- PaSampleFormat availableFormats;
PaError result = paNoError;
PaSampleFormat userSampleFormat = params->sampleFormat, hostSampleFormat = paNoError;
assert( params->channelCount > 0 );
PA_ENSURE( AlsaOpen( &alsaApi->baseHostApiRep, params, streamDir, &self->pcm ) );
self->nfds = alsa_snd_pcm_poll_descriptors_count( self->pcm );
- /* Get host sample format */
- availableFormats = GetAvailableFormats( self->pcm );
- PA_ENSURE( hostSampleFormat = PaUtil_SelectClosestAvailableFormat( PA_ALSA_TO_FORMAT(availableFormats), userSampleFormat ) );
-
- /* Append endiannes conversion flag */
- CheckAndApplyEndianSwapToFormat( &hostSampleFormat, self->pcm );
+ PA_ENSURE( hostSampleFormat = PaUtil_SelectClosestAvailableFormat( GetAvailableFormats( self->pcm ), userSampleFormat ) );
self->hostSampleFormat = hostSampleFormat;
self->nativeFormat = Pa2AlsaFormat( hostSampleFormat );
}
if (alsa_snd_pcm_hw_params_get_buffer_size != NULL)
{
- ENSURE_( alsa_snd_pcm_hw_params_get_buffer_size( hwParams, &self->bufferSize ), paUnanticipatedHostError );
- }
- else
- {
- self->bufferSize = bufSz;
- }
+ ENSURE_( alsa_snd_pcm_hw_params_get_buffer_size( hwParams, &self->bufferSize ), paUnanticipatedHostError );
+ }
+ else
+ {
+ self->bufferSize = bufSz;
+ }
/* Latency in seconds */
*latency = self->bufferSize / sampleRate;
*/
static unsigned long PaAlsa_AlignBackward(unsigned long v, unsigned long align)
{
- return ((v - (align ? v % align : 0)));
+ return ((v - (align ? v % align : 0)));
}
/** Align value in forward direction.
*/
static unsigned long PaAlsa_AlignForward(unsigned long v, unsigned long align)
{
- unsigned long remainder = (align ? (v % align) : 0);
- return (remainder != 0 ? v + (align - remainder) : v);
+ unsigned long remainder = (align ? (v % align) : 0);
+ return (remainder != 0 ? v + (align - remainder) : v);
}
/** Get size of host buffer maintained from the number of user frames, sample rate and suggested latency. Minimum double buffering
*/
static unsigned long PaAlsa_GetFramesPerHostBuffer(unsigned long userFramesPerBuffer, PaTime suggestedLatency, double sampleRate)
{
- unsigned long frames = userFramesPerBuffer + PA_MAX( userFramesPerBuffer, (unsigned long)(suggestedLatency * sampleRate) );
- return frames;
+ unsigned long frames = userFramesPerBuffer + PA_MAX( userFramesPerBuffer, (unsigned long)(suggestedLatency * sampleRate) );
+ return frames;
}
/** Determine size per host buffer.
#endif
- {
+ {
unsigned numPeriods = numPeriods_, maxPeriods = 0, minPeriods = numPeriods_;
/* It may be that the device only supports 2 periods for instance */
framesPerHostBuffer = 2048;
#endif
PA_DEBUG(( "%s: suggested host buffer period = %lu \n", __FUNCTION__, framesPerHostBuffer ));
- }
+ }
{
/* Get min/max period sizes and adjust our chosen */
framesPerHostBuffer = ((minmax_diff == 2) ? max - 1 : max);
}
- PA_DEBUG(( "%s: device period minimum = %lu\n", __FUNCTION__, min ));
- PA_DEBUG(( "%s: device period maximum = %lu\n", __FUNCTION__, max ));
- PA_DEBUG(( "%s: host buffer period = %lu\n", __FUNCTION__, framesPerHostBuffer ));
- PA_DEBUG(( "%s: host buffer period latency = %f\n", __FUNCTION__, (double)(framesPerHostBuffer / sampleRate) ));
+ PA_DEBUG(( "%s: device period minimum = %lu\n", __FUNCTION__, min ));
+ PA_DEBUG(( "%s: device period maximum = %lu\n", __FUNCTION__, max ));
+ PA_DEBUG(( "%s: host buffer period = %lu\n", __FUNCTION__, framesPerHostBuffer ));
+ PA_DEBUG(( "%s: host buffer period latency = %f\n", __FUNCTION__, (double)(framesPerHostBuffer / sampleRate) ));
/* Try setting period size */
dir = 0;
hostOutputSampleFormat = stream->playback.hostSampleFormat | (!stream->playback.hostInterleaved ? paNonInterleaved : 0);
PA_ENSURE( PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
- numInputChannels, inputSampleFormat, (hostInputSampleFormat & ~paSwapEndian),
- numOutputChannels, outputSampleFormat, (hostOutputSampleFormat & ~paSwapEndian),
+ numInputChannels, inputSampleFormat, hostInputSampleFormat,
+ numOutputChannels, outputSampleFormat, hostOutputSampleFormat,
sampleRate, streamFlags, framesPerBuffer, stream->maxFramesPerHostBuffer,
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 */
if( numInputChannels > 0 )
stream->streamRepresentation.streamInfo.inputLatency = inputLatency + (PaTime)(
/* not else ! */
if (timeouts >= 2048) /* audio device not working, shall return error to notify waiters */
{
- *framesAvail = 0; /* no frames available for processing */
- xrun = 1; /* try recovering device */
+ *framesAvail = 0; /* no frames available for processing */
+ xrun = 1; /* try recovering device */
PA_DEBUG(( "%s: poll timed out\n", __FUNCTION__, timeouts ));
goto end;/*PA_ENSURE( paTimedOut );*/
int xrun = 0;
#ifdef PTHREAD_CANCELED
- pthread_testcancel();
+ pthread_testcancel();
#endif
/* @concern StreamStop if the main thread has requested a stop and the stream has not been effectively
busyRetries_ = retries;
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;
- }
- }
- }
-}