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); | |||