git-svn-id: svn+ssh://jackaudio.org/trunk/jack@602 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
@@ -15,7 +15,7 @@ dnl changes are made | |||
dnl --- | |||
JACK_MAJOR_VERSION=0 | |||
JACK_MINOR_VERSION=93 | |||
JACK_MICRO_VERSION=5 | |||
JACK_MICRO_VERSION=6 | |||
dnl --- | |||
dnl HOWTO: updating the jack protocal version | |||
@@ -243,6 +243,35 @@ alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) | |||
} | |||
break; | |||
case 3: | |||
if (driver->playback_interleaved) { | |||
driver->channel_copy = memcpy_interleave_d24_s24; | |||
} else { | |||
driver->channel_copy = memcpy_fake; | |||
} | |||
switch (driver->dither) { | |||
case Rectangular: | |||
printf("Rectangular dithering at 16 bits\n"); | |||
driver->write_via_copy = sample_move_dither_rect_d24u24_sS; | |||
break; | |||
case Triangular: | |||
printf("Triangular dithering at 16 bits\n"); | |||
driver->write_via_copy = sample_move_dither_tri_d24u24_sS; | |||
break; | |||
case Shaped: | |||
printf("Noise-shaped dithering at 16 bits\n"); | |||
driver->write_via_copy = sample_move_dither_shaped_d24u24_sS; | |||
break; | |||
default: | |||
driver->write_via_copy = sample_move_d24u24_sS; | |||
break; | |||
} | |||
break; | |||
case 4: | |||
if (driver->playback_interleaved) { | |||
driver->channel_copy = memcpy_interleave_d32_s32; | |||
@@ -280,6 +309,9 @@ alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) | |||
case 2: | |||
driver->read_via_copy = sample_move_dS_s16; | |||
break; | |||
case 3: | |||
driver->read_via_copy = sample_move_dS_s24u24; | |||
break; | |||
case 4: | |||
driver->read_via_copy = sample_move_dS_s32u24; | |||
break; | |||
@@ -294,8 +326,17 @@ alsa_driver_configure_stream (alsa_driver_t *driver, char *device_name, | |||
snd_pcm_sw_params_t *sw_params, | |||
unsigned long *nchns,unsigned long sample_width) | |||
{ | |||
int err; | |||
int err, format; | |||
snd_pcm_uframes_t stop_th; | |||
static struct { | |||
char Name[16]; | |||
snd_pcm_format_t format; | |||
} formats[] = { | |||
{"32bit", SND_PCM_FORMAT_S32}, | |||
{"24bit", SND_PCM_FORMAT_S24_3}, | |||
{"16bit", SND_PCM_FORMAT_S16}, | |||
}; | |||
#define NOFORMATS (sizeof(formats)/sizeof(formats[0])) | |||
if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) { | |||
jack_error ("ALSA: no playback configurations available (%s)", | |||
@@ -323,44 +364,25 @@ alsa_driver_configure_stream (alsa_driver_t *driver, char *device_name, | |||
return -1; | |||
} | |||
} | |||
if (sample_width == 4) { | |||
if ((err = snd_pcm_hw_params_set_format ( | |||
handle, hw_params, SND_PCM_FORMAT_S32)) < 0) { | |||
jack_error("Couldn't open %s for 32bit samples " | |||
"trying 16bit instead", device_name); | |||
if ((err = snd_pcm_hw_params_set_format ( | |||
handle, hw_params, SND_PCM_FORMAT_S16)) | |||
< 0) { | |||
jack_error ("Sorry. The audio interface \"%s\"" | |||
"doesn't support either of the two" | |||
" hardware sample formats that " | |||
"JACK can use.", | |||
device_name); | |||
return -1; | |||
} | |||
} | |||
} else { | |||
if ((err = snd_pcm_hw_params_set_format ( | |||
handle, hw_params, SND_PCM_FORMAT_S16)) < 0) { | |||
jack_error("Couldn't open %s for 16bit samples trying" | |||
" 32bit instead",device_name); | |||
if ((err = snd_pcm_hw_params_set_format ( | |||
handle, hw_params, SND_PCM_FORMAT_S32)) | |||
< 0) { | |||
format = sample_width == 4 ? 0 : NOFORMATS - 1; | |||
while (1) { | |||
if ((err = snd_pcm_hw_params_set_format (handle, hw_params, formats[format].format)) < 0) { | |||
int failed_format = format; | |||
if (sample_width == 4 ? format++ < NOFORMATS - 1 : format-- > 0) { | |||
jack_error ("Couldn't open %s for %s samples" | |||
" trying %s instead", device_name, formats[failed_format].Name, formats[format].Name); | |||
} else { | |||
jack_error ("Sorry. The audio interface \"%s\"" | |||
"doesn't support either of the two" | |||
" hardware sample formats that " | |||
"JACK can use.", | |||
" doesn't support any of the" | |||
" hardware sample formats that" | |||
" JACK's alsa-driver can use.", | |||
device_name); | |||
return -1; | |||
} | |||
} | |||
} | |||
} else | |||
break; | |||
} | |||
if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params, | |||
driver->frame_rate, 0)) | |||
@@ -674,6 +696,7 @@ alsa_driver_set_parameters (alsa_driver_t *driver, | |||
if (driver->playback_handle) { | |||
switch (driver->playback_sample_format) { | |||
case SND_PCM_FORMAT_S32_LE: | |||
case SND_PCM_FORMAT_S24_3: | |||
case SND_PCM_FORMAT_S16_LE: | |||
case SND_PCM_FORMAT_S32_BE: | |||
case SND_PCM_FORMAT_S16_BE: | |||
@@ -689,6 +712,7 @@ alsa_driver_set_parameters (alsa_driver_t *driver, | |||
if (driver->capture_handle) { | |||
switch (driver->capture_sample_format) { | |||
case SND_PCM_FORMAT_S32_LE: | |||
case SND_PCM_FORMAT_S24_3: | |||
case SND_PCM_FORMAT_S16_LE: | |||
case SND_PCM_FORMAT_S32_BE: | |||
case SND_PCM_FORMAT_S16_BE: | |||
@@ -25,6 +25,14 @@ | |||
#define ALSA_PCM_OLD_SW_PARAMS_API | |||
#include <alsa/asoundlib.h> | |||
#if __BYTE_ORDER == __LITTLE_ENDIAN | |||
#define SND_PCM_FORMAT_S24_3 SND_PCM_FORMAT_S24_3LE | |||
#elif __BYTE_ORDER == __BIG_ENDIAN | |||
#define SND_PCM_FORMAT_S24_3 SND_PCM_FORMAT_S24_3BE | |||
#endif | |||
#include <jack/types.h> | |||
#include <jack/hardware.h> | |||
#include <jack/driver.h> | |||
@@ -181,6 +181,163 @@ void sample_move_dither_shaped_d32u24_sS (char *dst, jack_default_audio_sample_ | |||
state->idx = idx; | |||
} | |||
void sample_move_d24u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) | |||
{ | |||
long long y; | |||
while (nsamples--) { | |||
y = (long long)(*src * SAMPLE_MAX_24BIT); | |||
if (y > (INT_MAX >> 8 )) { | |||
y = (INT_MAX >> 8); | |||
} else if (y < (INT_MIN >> 8 )) { | |||
y = (INT_MIN >> 8 ); | |||
} | |||
#if __BYTE_ORDER == __LITTLE_ENDIAN | |||
memcpy (dst, &y, 3); | |||
#elif __BYTE_ORDER == __BIG_ENDIAN | |||
memcpy (dst, (char *)&y + 5, 3); | |||
#endif | |||
dst += dst_skip; | |||
src++; | |||
} | |||
} | |||
void sample_move_dS_s24u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) | |||
{ | |||
/* ALERT: signed sign-extension portability !!! */ | |||
while (nsamples--) { | |||
int x; | |||
#if __BYTE_ORDER == __LITTLE_ENDIAN | |||
memcpy((char*)&x + 1, src, 3); | |||
#elif __BYTE_ORDER == __BIG_ENDIAN | |||
memcpy(&x, src, 3); | |||
#endif | |||
x >>= 8; | |||
*dst = x / SAMPLE_MAX_24BIT; | |||
dst++; | |||
src += src_skip; | |||
} | |||
} | |||
void sample_move_dither_rect_d24u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) | |||
{ | |||
/* ALERT: signed sign-extension portability !!! */ | |||
jack_default_audio_sample_t x; | |||
long long y; | |||
while (nsamples--) { | |||
x = *src * SAMPLE_MAX_16BIT; | |||
x -= (float)fast_rand() / (float)INT_MAX; | |||
y = (long long)f_round(x); | |||
y <<= 8; | |||
if (y > (INT_MAX >> 8)) { | |||
y = (INT_MAX >> 8); | |||
} else if (y < (INT_MIN >> 8)) { | |||
y = (INT_MIN >> 8); | |||
} | |||
#if __BYTE_ORDER == __LITTLE_ENDIAN | |||
memcpy (dst, &y, 3); | |||
#elif __BYTE_ORDER == __BIG_ENDIAN | |||
memcpy (dst, (char *)&y + 5, 3); | |||
#endif | |||
dst += dst_skip; | |||
src++; | |||
} | |||
} | |||
void sample_move_dither_tri_d24u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) | |||
{ | |||
jack_default_audio_sample_t x; | |||
float r; | |||
float rm1 = state->rm1; | |||
long long y; | |||
while (nsamples--) { | |||
x = *src * (float)SAMPLE_MAX_16BIT; | |||
r = 2.0f * (float)fast_rand() / (float)INT_MAX - 1.0f; | |||
x += r - rm1; | |||
rm1 = r; | |||
y = (long long)f_round(x); | |||
y <<= 8; | |||
if (y > (INT_MAX >> 8)) { | |||
y = (INT_MAX >> 8); | |||
} else if (y < (INT_MIN >> 8)) { | |||
y = (INT_MIN >> 8); | |||
} | |||
#if __BYTE_ORDER == __LITTLE_ENDIAN | |||
memcpy (dst, &y, 3); | |||
#elif __BYTE_ORDER == __BIG_ENDIAN | |||
memcpy (dst, (char *)&y + 5, 3); | |||
#endif | |||
dst += dst_skip; | |||
src++; | |||
} | |||
state->rm1 = rm1; | |||
} | |||
void sample_move_dither_shaped_d24u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) | |||
{ | |||
jack_default_audio_sample_t x; | |||
jack_default_audio_sample_t xe; /* the innput sample - filtered error */ | |||
jack_default_audio_sample_t xp; /* x' */ | |||
float r; | |||
float rm1 = state->rm1; | |||
unsigned int idx = state->idx; | |||
long long y; | |||
while (nsamples--) { | |||
x = *src * (float)SAMPLE_MAX_16BIT; | |||
r = 2.0f * (float)fast_rand() / (float)INT_MAX - 1.0f; | |||
/* Filter the error with Lipshitz's minimally audible FIR: | |||
[2.033 -2.165 1.959 -1.590 0.6149] */ | |||
xe = x | |||
- state->e[idx] * 2.033f | |||
+ state->e[(idx - 1) & DITHER_BUF_MASK] * 2.165f | |||
- state->e[(idx - 2) & DITHER_BUF_MASK] * 1.959f | |||
+ state->e[(idx - 3) & DITHER_BUF_MASK] * 1.590f | |||
- state->e[(idx - 4) & DITHER_BUF_MASK] * 0.6149f; | |||
xp = xe + r - rm1; | |||
rm1 = r; | |||
/* This could be some inline asm on x86 */ | |||
y = (long long)f_round(xp); | |||
/* Intrinsic z^-1 delay */ | |||
idx = (idx + 1) & DITHER_BUF_MASK; | |||
state->e[idx] = y - xe; | |||
y <<= 8; | |||
if (y > (INT_MAX >> 8)) { | |||
y = (INT_MAX >> 8); | |||
} else if (y < (INT_MIN >> 8)) { | |||
y = (INT_MIN >> 8); | |||
} | |||
#if __BYTE_ORDER == __LITTLE_ENDIAN | |||
memcpy (dst, &y, 3); | |||
#elif __BYTE_ORDER == __BIG_ENDIAN | |||
memcpy (dst, (char *)&y + 5, 3); | |||
#endif | |||
dst += dst_skip; | |||
src++; | |||
} | |||
state->rm1 = rm1; | |||
state->idx = idx; | |||
} | |||
void sample_move_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) | |||
{ | |||
@@ -368,6 +525,13 @@ void memset_interleave (char *dst, char val, unsigned long bytes, | |||
bytes -= 4; | |||
} | |||
break; | |||
default: | |||
while (bytes) { | |||
memset(dst, val, unit_bytes); | |||
dst += skip_bytes; | |||
bytes -= unit_bytes; | |||
} | |||
break; | |||
} | |||
} | |||
@@ -434,6 +598,19 @@ merge_memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, | |||
} | |||
} | |||
void | |||
merge_memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
{ | |||
while (src_bytes) { | |||
int acc = (*(int *)dst & 0xFFFFFF) + (*(int *)src & 0xFFFFFF); | |||
memcpy(dst, &acc, 3); | |||
dst += dst_skip_bytes; | |||
src += src_skip_bytes; | |||
src_bytes -= 3; | |||
} | |||
} | |||
void | |||
memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
@@ -446,6 +623,19 @@ memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, | |||
} | |||
} | |||
void | |||
memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
{ | |||
while (src_bytes) { | |||
memcpy(dst, src, 3); | |||
dst += dst_skip_bytes; | |||
src += src_skip_bytes; | |||
src_bytes -= 3; | |||
} | |||
} | |||
void | |||
memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
@@ -42,16 +42,21 @@ typedef struct { | |||
void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_d24u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dither_rect_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dither_tri_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dither_shaped_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dither_rect_d24u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dither_tri_d24u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dither_shaped_d24u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dither_rect_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dither_tri_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dither_shaped_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||
void sample_move_dS_s24u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||
void sample_move_dS_s16 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||
void sample_merge_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||
@@ -79,9 +84,11 @@ void memset_interleave (char *dst, char val, unsigned long bytes, | |||
void memcpy_fake (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); | |||
void memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||
void memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||
void memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||
void merge_memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||
void merge_memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||
void merge_memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||
void merge_memcpy_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); | |||