git-svn-id: svn+ssh://jackaudio.org/trunk/jack@145 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
| @@ -54,6 +54,11 @@ alsa_driver_release_channel_dependent_memory (alsa_driver_t *driver) | |||||
| free (driver->silent); | free (driver->silent); | ||||
| driver->silent = 0; | driver->silent = 0; | ||||
| } | } | ||||
| if (driver->dither_state) { | |||||
| free (driver->dither_state); | |||||
| driver->dither_state = 0; | |||||
| } | |||||
| } | } | ||||
| static int | static int | ||||
| @@ -150,12 +155,27 @@ alsa_driver_setup_io_function_pointers (alsa_driver_t *driver) | |||||
| driver->channel_copy = memcpy_fake; | driver->channel_copy = memcpy_fake; | ||||
| } | } | ||||
| if (driver->dither) { | |||||
| switch (driver->dither) { | |||||
| case Rectangular: | |||||
| printf("Rectangular dithering at 16 bits\n"); | printf("Rectangular dithering at 16 bits\n"); | ||||
| driver->write_via_copy = sample_move_dither_rect_d16_sS; | driver->write_via_copy = sample_move_dither_rect_d16_sS; | ||||
| } else { | |||||
| break; | |||||
| case Triangular: | |||||
| printf("Triangular dithering at 16 bits\n"); | |||||
| driver->write_via_copy = sample_move_dither_tri_d16_sS; | |||||
| break; | |||||
| case Shaped: | |||||
| printf("Noise-shaped dithering at 16 bits\n"); | |||||
| driver->write_via_copy = sample_move_dither_shaped_d16_sS; | |||||
| break; | |||||
| default: | |||||
| driver->write_via_copy = sample_move_d16_sS; | driver->write_via_copy = sample_move_d16_sS; | ||||
| break; | |||||
| } | } | ||||
| driver->read_via_copy = sample_move_dS_s16; | driver->read_via_copy = sample_move_dS_s16; | ||||
| break; | break; | ||||
| @@ -463,6 +483,8 @@ alsa_driver_set_parameters (alsa_driver_t *driver, nframes_t frames_per_cycle, n | |||||
| for (chn = 0; chn < driver->playback_nchannels; chn++) { | for (chn = 0; chn < driver->playback_nchannels; chn++) { | ||||
| driver->channel_done_bits |= (1<<chn); | driver->channel_done_bits |= (1<<chn); | ||||
| } | } | ||||
| driver->dither_state = (dither_state_t *) calloc ( driver->playback_nchannels, sizeof (dither_state_t)); | |||||
| } | } | ||||
| if (driver->capture_handle) { | if (driver->capture_handle) { | ||||
| @@ -995,14 +1017,17 @@ alsa_driver_process (alsa_driver_t *driver, nframes_t nframes) | |||||
| /* now move data from ports to channels */ | /* now move data from ports to channels */ | ||||
| for (chn = 0, node = driver->playback_ports; node; node = g_slist_next (node), chn++) { | for (chn = 0, node = driver->playback_ports; node; node = g_slist_next (node), chn++) { | ||||
| sample_t *buf; | |||||
| jack_port_t *port = (jack_port_t *) node->data; | jack_port_t *port = (jack_port_t *) node->data; | ||||
| if (!jack_port_connected (port)) { | if (!jack_port_connected (port)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| buf = jack_port_get_buffer (port, contiguous); | |||||
| alsa_driver_write_to_channel (driver, chn, jack_port_get_buffer (port, contiguous), contiguous); | |||||
| alsa_driver_write_to_channel (driver, chn, buf, contiguous); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1256,7 +1281,7 @@ alsa_driver_new (char *name, char *alsa_device, | |||||
| int hw_monitoring, | int hw_monitoring, | ||||
| int capturing, | int capturing, | ||||
| int playing, | int playing, | ||||
| int dither) | |||||
| DitherAlgorithm dither) | |||||
| { | { | ||||
| int err; | int err; | ||||
| @@ -1456,6 +1481,7 @@ alsa PCM driver args: | |||||
| -D (duplex, default: yes) | -D (duplex, default: yes) | ||||
| -C (capture, default: duplex) | -C (capture, default: duplex) | ||||
| -P (playback, default: duplex) | -P (playback, default: duplex) | ||||
| -z[r|t|s|-] (dither, rect|tri|shaped|off, default: off) | |||||
| "); | "); | ||||
| } | } | ||||
| @@ -1469,7 +1495,7 @@ driver_initialize (int argc, char **argv) | |||||
| int hw_monitoring = FALSE; | int hw_monitoring = FALSE; | ||||
| int capture = FALSE; | int capture = FALSE; | ||||
| int playback = FALSE; | int playback = FALSE; | ||||
| int dither = FALSE; | |||||
| DitherAlgorithm dither = None; | |||||
| int i; | int i; | ||||
| /* grrrr ... getopt() cannot be called in more than one "loop" | /* grrrr ... getopt() cannot be called in more than one "loop" | ||||
| @@ -1518,7 +1544,24 @@ driver_initialize (int argc, char **argv) | |||||
| break; | break; | ||||
| case 'z': | case 'z': | ||||
| dither = TRUE; | |||||
| switch (argv[i][2]) { | |||||
| case '-': | |||||
| dither = None; | |||||
| break; | |||||
| case 'r': | |||||
| dither = Rectangular; | |||||
| break; | |||||
| case 's': | |||||
| dither = Shaped; | |||||
| break; | |||||
| case 't': | |||||
| default: | |||||
| dither = Triangular; | |||||
| break; | |||||
| } | |||||
| break; | break; | ||||
| default: | default: | ||||
| @@ -1203,6 +1203,9 @@ jack_port_get_buffer (jack_port_t *port, nframes_t nframes) | |||||
| the buffer of the connected (output) port. | the buffer of the connected (output) port. | ||||
| */ | */ | ||||
| printf ("get buffer for port %s is at offset %d\n", port->shared->name, | |||||
| ((jack_port_t *) node->data)->shared->offset); | |||||
| return jack_port_buffer (((jack_port_t *) node->data)); | return jack_port_buffer (((jack_port_t *) node->data)); | ||||
| } | } | ||||
| @@ -1597,7 +1600,7 @@ jack_audio_port_mixdown (jack_port_t *port, nframes_t nframes) | |||||
| node = port->connections; | node = port->connections; | ||||
| input = (jack_port_t *) node->data; | input = (jack_port_t *) node->data; | ||||
| buffer = jack_port_buffer (port); | buffer = jack_port_buffer (port); | ||||
| memcpy (buffer, jack_port_buffer (input), sizeof (sample_t) * nframes); | memcpy (buffer, jack_port_buffer (input), sizeof (sample_t) * nframes); | ||||
| for (node = g_slist_next (node); node; node = g_slist_next (node)) { | for (node = g_slist_next (node); node; node = g_slist_next (node)) { | ||||
| @@ -4,7 +4,7 @@ AC_INIT(client.c) | |||||
| AC_CONFIG_AUX_DIR(.) | AC_CONFIG_AUX_DIR(.) | ||||
| JACK_MAJOR_VERSION=0 | JACK_MAJOR_VERSION=0 | ||||
| JACK_MINOR_VERSION=19 | |||||
| JACK_MINOR_VERSION=20 | |||||
| JACK_MICRO_VERSION=0 | JACK_MICRO_VERSION=0 | ||||
| BETA= | BETA= | ||||
| @@ -31,7 +31,7 @@ JACK_OPT_CFLAGS="-D_REENTRANT -O6 -Wall -fomit-frame-pointer -ffast-math -fstren | |||||
| AC_ARG_ENABLE(optimize, | AC_ARG_ENABLE(optimize, | ||||
| [ --enable-optimize ask the compiler for its best optimizations.], | [ --enable-optimize ask the compiler for its best optimizations.], | ||||
| [ if test "x$enable_optimize" != "xno" ; then JACK_CFLAGS="$JACK_OPT_CFLAGS" ; fi ]) | |||||
| [ if test "x$enable_optimize" != "xno" ; then CFLAGS="$JACK_OPT_CFLAGS" ; fi ]) | |||||
| AC_SUBST(JACK_CFLAGS) | AC_SUBST(JACK_CFLAGS) | ||||
| @@ -520,48 +520,6 @@ jack_process (jack_engine_t *engine, nframes_t nframes) | |||||
| return engine->process_errors > 0; | return engine->process_errors > 0; | ||||
| } | } | ||||
| static void * | |||||
| jack_cleanup_clients (void *arg) | |||||
| { | |||||
| jack_engine_t *engine = (jack_engine_t *) arg; | |||||
| jack_client_internal_t *client; | |||||
| GSList *node, *tmp; | |||||
| int need_sort = FALSE; | |||||
| jack_lock_graph (engine); | |||||
| /* remove all dead clients */ | |||||
| for (node = engine->clients; node; ) { | |||||
| tmp = g_slist_next (node); | |||||
| client = (jack_client_internal_t *) node->data; | |||||
| if (client->error) { | |||||
| if (engine->verbose) { | |||||
| fprintf (stderr, "removing failed client %s (errors: %d)\n", | |||||
| client->control->name, client->error); | |||||
| } | |||||
| jack_remove_client (engine, (jack_client_internal_t *) node->data); | |||||
| need_sort = TRUE; | |||||
| } | |||||
| node = tmp; | |||||
| } | |||||
| if (need_sort) { | |||||
| jack_sort_graph (engine); | |||||
| } | |||||
| jack_unlock_graph (engine); | |||||
| pthread_mutex_unlock (&engine->cleanup_lock); | |||||
| return NULL; | |||||
| } | |||||
| static int | static int | ||||
| jack_engine_post_process (jack_engine_t *engine) | jack_engine_post_process (jack_engine_t *engine) | ||||
| { | { | ||||
| @@ -579,10 +537,6 @@ jack_engine_post_process (jack_engine_t *engine) | |||||
| client = (jack_client_internal_t *) node->data; | client = (jack_client_internal_t *) node->data; | ||||
| ctl = client->control; | ctl = client->control; | ||||
| if (engine->verbose) { | |||||
| fprintf (stderr, "client %s state = %s\n", ctl->name, client_state_names[ctl->state]); | |||||
| } | |||||
| if (ctl->timed_out || (ctl->state > NotTriggered && ctl->state != Finished)) { | if (ctl->timed_out || (ctl->state > NotTriggered && ctl->state != Finished)) { | ||||
| client->error++; | client->error++; | ||||
| } | } | ||||
| @@ -592,20 +546,40 @@ jack_engine_post_process (jack_engine_t *engine) | |||||
| } | } | ||||
| } | } | ||||
| jack_unlock_graph (engine); | |||||
| if (need_remove) { | if (need_remove) { | ||||
| /* only one thread is allowed to run cleanup at a time. if | |||||
| one is already underway, don't bother starting another. | |||||
| */ | |||||
| GSList *tmp; | |||||
| int need_sort = FALSE; | |||||
| /* remove all dead clients */ | |||||
| if (pthread_mutex_trylock (&engine->cleanup_lock) == 0) { | |||||
| pthread_t cleanup_thread; | |||||
| pthread_create (&cleanup_thread, NULL, jack_cleanup_clients, engine); | |||||
| for (node = engine->clients; node; ) { | |||||
| tmp = g_slist_next (node); | |||||
| client = (jack_client_internal_t *) node->data; | |||||
| if (client->error) { | |||||
| if (engine->verbose) { | |||||
| fprintf (stderr, "removing failed client %s state = %s\n", | |||||
| client->control->name, client_state_names[client->control->state]); | |||||
| } | |||||
| jack_remove_client (engine, (jack_client_internal_t *) node->data); | |||||
| need_sort = TRUE; | |||||
| } | |||||
| node = tmp; | |||||
| } | |||||
| if (need_sort) { | |||||
| jack_sort_graph (engine); | |||||
| } | } | ||||
| } | } | ||||
| jack_unlock_graph (engine); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -1152,7 +1126,6 @@ jack_engine_new (int realtime, int rtpriority, int verbose) | |||||
| engine->asio_mode = FALSE; | engine->asio_mode = FALSE; | ||||
| pthread_mutex_init (&engine->client_lock, 0); | pthread_mutex_init (&engine->client_lock, 0); | ||||
| pthread_mutex_init (&engine->cleanup_lock, 0); | |||||
| pthread_mutex_init (&engine->buffer_lock, 0); | pthread_mutex_init (&engine->buffer_lock, 0); | ||||
| pthread_mutex_init (&engine->port_lock, 0); | pthread_mutex_init (&engine->port_lock, 0); | ||||
| @@ -2563,6 +2536,13 @@ jack_port_assign_buffer (jack_engine_t *engine, jack_port_internal_t *port) | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (engine->verbose) { | |||||
| fprintf (stderr, "port %s assigned buffer in shm key 0x%x at offset %d\n", | |||||
| port->shared->name, | |||||
| port->shared->shm_key, | |||||
| port->shared->offset); | |||||
| } | |||||
| if (port->shared->shm_key >= 0) { | if (port->shared->shm_key >= 0) { | ||||
| engine->port_buffer_freelist = g_slist_remove (engine->port_buffer_freelist, bi); | engine->port_buffer_freelist = g_slist_remove (engine->port_buffer_freelist, bi); | ||||
| @@ -34,7 +34,8 @@ typedef void (*ReadCopyFunction) (sample_t *dst, char *src, | |||||
| unsigned long src_skip_bytes); | unsigned long src_skip_bytes); | ||||
| typedef void (*WriteCopyFunction) (char *dst, sample_t *src, | typedef void (*WriteCopyFunction) (char *dst, sample_t *src, | ||||
| unsigned long src_bytes, | unsigned long src_bytes, | ||||
| unsigned long dst_skip_bytes); | |||||
| unsigned long dst_skip_bytes, | |||||
| dither_state_t *state); | |||||
| typedef void (*CopyCopyFunction) (char *dst, char *src, | typedef void (*CopyCopyFunction) (char *dst, char *src, | ||||
| unsigned long src_bytes, | unsigned long src_bytes, | ||||
| unsigned long dst_skip_bytes, | unsigned long dst_skip_bytes, | ||||
| @@ -102,7 +103,8 @@ typedef struct { | |||||
| WriteCopyFunction write_via_copy; | WriteCopyFunction write_via_copy; | ||||
| CopyCopyFunction channel_copy; | CopyCopyFunction channel_copy; | ||||
| int dither; | |||||
| int dither; | |||||
| dither_state_t *dither_state; | |||||
| SampleClockMode clock_mode; | SampleClockMode clock_mode; | ||||
| GSList *clock_sync_listeners; | GSList *clock_sync_listeners; | ||||
| @@ -161,7 +163,8 @@ static __inline__ void alsa_driver_write_to_channel (alsa_driver_t *driver, | |||||
| driver->write_via_copy (driver->playback_addr[channel], | driver->write_via_copy (driver->playback_addr[channel], | ||||
| buf, | buf, | ||||
| nsamples, | nsamples, | ||||
| driver->playback_interleave_skip); | |||||
| driver->playback_interleave_skip, | |||||
| driver->dither_state+channel); | |||||
| alsa_driver_mark_channel_done (driver, channel); | alsa_driver_mark_channel_done (driver, channel); | ||||
| } | } | ||||
| @@ -38,7 +38,6 @@ struct _jack_engine { | |||||
| void (*process_unlock)(struct _jack_engine *); | void (*process_unlock)(struct _jack_engine *); | ||||
| int (*post_process)(struct _jack_engine *); | int (*post_process)(struct _jack_engine *); | ||||
| pthread_mutex_t client_lock; | pthread_mutex_t client_lock; | ||||
| pthread_mutex_t cleanup_lock; | |||||
| pthread_mutex_t buffer_lock; | pthread_mutex_t buffer_lock; | ||||
| pthread_mutex_t port_lock; | pthread_mutex_t port_lock; | ||||
| int process_errors; | int process_errors; | ||||
| @@ -23,17 +23,18 @@ | |||||
| #include <jack/types.h> | #include <jack/types.h> | ||||
| 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_d32u24_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_rect_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, dither_state_t *state); | |||||
| void sample_move_dither_tri_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dither_shaped_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_move_dS_s32u24 (sample_t *dst, char *src, unsigned long nsamples, unsigned long src_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_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); | |||||
| void sample_merge_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| void sample_merge_d32u24_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
| static __inline__ void | static __inline__ void | ||||
| sample_merge (sample_t *dst, sample_t *src, unsigned long cnt) | sample_merge (sample_t *dst, sample_t *src, unsigned long cnt) | ||||
| @@ -70,4 +70,21 @@ typedef enum { | |||||
| NoSync = 0x8 | NoSync = 0x8 | ||||
| } ClockSyncStatus; | } ClockSyncStatus; | ||||
| typedef enum { | |||||
| None, | |||||
| Rectangular, | |||||
| Triangular, | |||||
| Shaped | |||||
| } DitherAlgorithm; | |||||
| #define DITHER_BUF_SIZE 8 | |||||
| #define DITHER_BUF_MASK 7 | |||||
| typedef struct { | |||||
| unsigned int depth; | |||||
| float rm1; | |||||
| unsigned int idx; | |||||
| float e[DITHER_BUF_SIZE]; | |||||
| } dither_state_t; | |||||
| #endif /* __jack_engine_types_h__ */ | #endif /* __jack_engine_types_h__ */ | ||||
| @@ -41,7 +41,7 @@ inline int f_round(float f) { | |||||
| floating-point => int conversion the compiler provides. | floating-point => int conversion the compiler provides. | ||||
| */ | */ | ||||
| void sample_move_d32u24_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip) | |||||
| void sample_move_d32u24_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) | |||||
| { | { | ||||
| /* ALERT: signed sign-extension portability !!! */ | /* ALERT: signed sign-extension portability !!! */ | ||||
| @@ -64,7 +64,7 @@ void sample_move_dS_s32u24 (sample_t *dst, char *src, unsigned long nsamples, un | |||||
| } | } | ||||
| } | } | ||||
| void sample_move_d16_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, dither_state_t *state) | |||||
| { | { | ||||
| sample_t val; | sample_t val; | ||||
| @@ -89,7 +89,7 @@ void sample_move_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsi | |||||
| } | } | ||||
| } | } | ||||
| void sample_move_dither_rect_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, dither_state_t *state) | |||||
| { | { | ||||
| sample_t val; | sample_t val; | ||||
| @@ -112,6 +112,82 @@ void sample_move_dither_rect_d16_sS (char *dst, sample_t *src, unsigned long ns | |||||
| } | } | ||||
| } | } | ||||
| void sample_move_dither_tri_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) | |||||
| { | |||||
| sample_t x; | |||||
| float r; | |||||
| float rm1 = state->rm1; | |||||
| int y; | |||||
| while (nsamples--) { | |||||
| x = *src * (float)SAMPLE_MAX_16BIT; | |||||
| r = 2.0f * (float)rand() / (float)RAND_MAX - 1.0f; | |||||
| x += r - rm1; | |||||
| rm1 = r; | |||||
| /* swh: This could be some inline asm on x86 */ | |||||
| y = f_round(x); | |||||
| if (y > SHRT_MAX) { | |||||
| *((short *)dst) = SHRT_MAX; | |||||
| } else if (y < SHRT_MIN) { | |||||
| *((short *)dst) = SHRT_MIN; | |||||
| } else { | |||||
| *((short *) dst) = (short)y; | |||||
| } | |||||
| dst += dst_skip; | |||||
| src++; | |||||
| } | |||||
| state->rm1 = rm1; | |||||
| } | |||||
| void sample_move_dither_shaped_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) | |||||
| { | |||||
| sample_t x; | |||||
| sample_t xe; /* the innput sample - filtered error */ | |||||
| sample_t xp; /* x' */ | |||||
| float r; | |||||
| float rm1 = state->rm1; | |||||
| unsigned int idx = state->idx; | |||||
| int y; | |||||
| while (nsamples--) { | |||||
| x = *src * (float)SAMPLE_MAX_16BIT; | |||||
| r = 2.0f * (float)rand() / (float)RAND_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 = f_round(xp); | |||||
| /* Intrinsic z^-1 delay */ | |||||
| idx = (idx + 1) & DITHER_BUF_MASK; | |||||
| state->e[idx] = y - xe; | |||||
| if (y > SHRT_MAX) { | |||||
| *((short *)dst) = SHRT_MAX; | |||||
| } else if (y < SHRT_MIN) { | |||||
| *((short *)dst) = SHRT_MIN; | |||||
| } else { | |||||
| *((short *) dst) = (short)y; | |||||
| } | |||||
| dst += dst_skip; | |||||
| src++; | |||||
| } | |||||
| state->rm1 = rm1; | |||||
| state->idx = idx; | |||||
| } | |||||
| void sample_move_dS_s16 (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) | ||||
| { | { | ||||
| @@ -123,7 +199,7 @@ void sample_move_dS_s16 (sample_t *dst, char *src, unsigned long nsamples, unsig | |||||
| } | } | ||||
| } | } | ||||
| void sample_merge_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip) | |||||
| void sample_merge_d16_sS (char *dst, sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) | |||||
| { | { | ||||
| short val; | short val; | ||||
| @@ -144,7 +220,7 @@ void sample_merge_d16_sS (char *dst, sample_t *src, unsigned long nsamples, uns | |||||
| } | } | ||||
| } | } | ||||
| void sample_merge_d32u24_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, dither_state_t *state) | |||||
| { | { | ||||
| /* ALERT: signed sign-extension portability !!! */ | /* ALERT: signed sign-extension portability !!! */ | ||||