diff --git a/alsa_driver.c b/alsa_driver.c index 67c3627..bbcc1ac 100644 --- a/alsa_driver.c +++ b/alsa_driver.c @@ -149,8 +149,13 @@ alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) } else { driver->channel_copy = memcpy_fake; } - - driver->write_via_copy = sample_move_d16_sS; + + if (driver->dither) { + printf("Rectangular dithering at 16 bits\n"); + driver->write_via_copy = sample_move_dither_rect_d16_sS; + } else { + driver->write_via_copy = sample_move_d16_sS; + } driver->read_via_copy = sample_move_dS_s16; break; @@ -1243,7 +1248,8 @@ alsa_driver_new (char *name, char *alsa_device, nframes_t rate, int hw_monitoring, int capturing, - int playing) + int playing, + int dither) { int err; @@ -1289,6 +1295,8 @@ alsa_driver_new (char *name, char *alsa_device, driver->playback_nfds = 0; driver->capture_nfds = 0; + driver->dither = dither; + pthread_mutex_init (&driver->clock_sync_lock, 0); driver->clock_sync_listeners = 0; @@ -1454,6 +1462,7 @@ driver_initialize (int argc, char **argv) int hw_monitoring = FALSE; int capture = FALSE; int playback = FALSE; + int dither = FALSE; int i; /* grrrr ... getopt() cannot be called in more than one "loop" @@ -1500,6 +1509,10 @@ driver_initialize (int argc, char **argv) case 'H': hw_monitoring = 1; break; + + case 'z': + dither = TRUE; + break; default: alsa_usage (); @@ -1519,7 +1532,8 @@ driver_initialize (int argc, char **argv) } return alsa_driver_new ("alsa_pcm", pcm_name, frames_per_interrupt, - user_nperiods, srate, hw_monitoring, capture, playback); + user_nperiods, srate, hw_monitoring, capture, + playback, dither); } void diff --git a/configure.in b/configure.in index 24ca9db..64c081e 100644 --- a/configure.in +++ b/configure.in @@ -4,8 +4,8 @@ AC_INIT(client.c) AC_CONFIG_AUX_DIR(.) JACK_MAJOR_VERSION=0 -JACK_MINOR_VERSION=15 -JACK_MICRO_VERSION=6 +JACK_MINOR_VERSION=16 +JACK_MICRO_VERSION=0 BETA= diff --git a/engine.c b/engine.c index f7b25f8..8714480 100644 --- a/engine.c +++ b/engine.c @@ -1675,9 +1675,9 @@ jack_rechain_graph (jack_engine_t *engine, int take_lock) if (subgraph_client == NULL) { - /* start a new subgraph. the engine will start the chain - by writing to the nth FIFO. - */ + /* start a new subgraph. the engine will start the chain + by writing to the nth FIFO. + */ subgraph_client = client; subgraph_client->subgraph_start_fd = jack_get_fifo_fd (engine, n); diff --git a/jack/alsa_driver.h b/jack/alsa_driver.h index c5fddcc..80385b6 100644 --- a/jack/alsa_driver.h +++ b/jack/alsa_driver.h @@ -102,6 +102,8 @@ typedef struct { WriteCopyFunction write_via_copy; CopyCopyFunction channel_copy; + int dither; + SampleClockMode clock_mode; GSList *clock_sync_listeners; pthread_mutex_t clock_sync_lock; diff --git a/jack/memops.h b/jack/memops.h index c388f50..3c5cd3e 100644 --- a/jack/memops.h +++ b/jack/memops.h @@ -26,9 +26,12 @@ void sample_move_d32u24_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip); void sample_move_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip); +void sample_move_dither_rect_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip); + void sample_move_dS_s32u24 (sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); void sample_move_dS_s16 (sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); + void sample_merge_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip); void sample_merge_d32u24_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip); @@ -63,11 +66,3 @@ void merge_memcpy_d16_s16 (char *dst, char *src, unsigned long src_by void merge_memcpy_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); #endif /* __jack_memops_h__ */ - - - - - - - - diff --git a/memops.c b/memops.c index e221533..a7fafd1 100644 --- a/memops.c +++ b/memops.c @@ -30,6 +30,13 @@ #define SAMPLE_MAX_24BIT 8388608.0f #define SAMPLE_MAX_16BIT 32767.0f +/* Round float to int (can't go in memops.h otherwise it gets multiply + defined) */ +inline int f_round(float f) { + f += (3<<22); + return *((int*)&f) - 0x4b400000; +} + /* XXX we could use rint(), but for now we'll accept whatever default floating-point => int conversion the compiler provides. */ @@ -80,7 +87,30 @@ void sample_move_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsi dst += dst_skip; src++; } -} +} + +void sample_move_dither_rect_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip) + +{ + sample_t val; + int tmp; + + while (nsamples--) { + val = *src * (float)SAMPLE_MAX_16BIT; + val -= (float)rand() / (float)RAND_MAX; + /* swh: This could be some inline asm on x86 */ + tmp = f_round(val); + if (tmp > SHRT_MAX) { + *((short *)dst) = SHRT_MAX; + } else if (tmp < SHRT_MIN) { + *((short *)dst) = SHRT_MIN; + } else { + *((short *) dst) = (short)tmp; + } + dst += dst_skip; + src++; + } +} void sample_move_dS_s16 (sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip)