Browse Source

remove cleanup thread, add dither code from steve harris

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@145 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
pbd 24 years ago
parent
commit
a321c5d3e0
9 changed files with 202 additions and 80 deletions
  1. +50
    -7
      alsa_driver.c
  2. +4
    -1
      client.c
  3. +2
    -2
      configure.in
  4. +35
    -55
      engine.c
  5. +6
    -3
      jack/alsa_driver.h
  6. +0
    -1
      jack/engine.h
  7. +7
    -6
      jack/memops.h
  8. +17
    -0
      jack/types.h
  9. +81
    -5
      memops.c

+ 50
- 7
alsa_driver.c View File

@@ -54,6 +54,11 @@ alsa_driver_release_channel_dependent_memory (alsa_driver_t *driver)
free (driver->silent);
driver->silent = 0;
}

if (driver->dither_state) {
free (driver->dither_state);
driver->dither_state = 0;
}
}

static int
@@ -150,12 +155,27 @@ alsa_driver_setup_io_function_pointers (alsa_driver_t *driver)
driver->channel_copy = memcpy_fake;
}

if (driver->dither) {
switch (driver->dither) {
case Rectangular:
printf("Rectangular dithering at 16 bits\n");
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;
break;
}

driver->read_via_copy = sample_move_dS_s16;
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++) {
driver->channel_done_bits |= (1<<chn);
}

driver->dither_state = (dither_state_t *) calloc ( driver->playback_nchannels, sizeof (dither_state_t));
}

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 */
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;
if (!jack_port_connected (port)) {
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 capturing,
int playing,
int dither)
DitherAlgorithm dither)
{
int err;

@@ -1456,6 +1481,7 @@ alsa PCM driver args:
-D (duplex, default: yes)
-C (capture, 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 capture = FALSE;
int playback = FALSE;
int dither = FALSE;
DitherAlgorithm dither = None;
int i;

/* grrrr ... getopt() cannot be called in more than one "loop"
@@ -1518,7 +1544,24 @@ driver_initialize (int argc, char **argv)
break;

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;
default:


+ 4
- 1
client.c View File

@@ -1203,6 +1203,9 @@ jack_port_get_buffer (jack_port_t *port, nframes_t nframes)
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));
}

@@ -1597,7 +1600,7 @@ jack_audio_port_mixdown (jack_port_t *port, nframes_t nframes)
node = port->connections;
input = (jack_port_t *) node->data;
buffer = jack_port_buffer (port);
memcpy (buffer, jack_port_buffer (input), sizeof (sample_t) * nframes);

for (node = g_slist_next (node); node; node = g_slist_next (node)) {


+ 2
- 2
configure.in View File

@@ -4,7 +4,7 @@ AC_INIT(client.c)
AC_CONFIG_AUX_DIR(.)

JACK_MAJOR_VERSION=0
JACK_MINOR_VERSION=19
JACK_MINOR_VERSION=20
JACK_MICRO_VERSION=0

BETA=
@@ -31,7 +31,7 @@ JACK_OPT_CFLAGS="-D_REENTRANT -O6 -Wall -fomit-frame-pointer -ffast-math -fstren

AC_ARG_ENABLE(optimize,
[ --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)



+ 35
- 55
engine.c View File

@@ -520,48 +520,6 @@ jack_process (jack_engine_t *engine, nframes_t nframes)
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
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;
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)) {
client->error++;
}
@@ -592,20 +546,40 @@ jack_engine_post_process (jack_engine_t *engine)
}
}

jack_unlock_graph (engine);

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

@@ -1152,7 +1126,6 @@ jack_engine_new (int realtime, int rtpriority, int verbose)
engine->asio_mode = FALSE;

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->port_lock, 0);

@@ -2563,6 +2536,13 @@ jack_port_assign_buffer (jack_engine_t *engine, jack_port_internal_t *port)
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) {
engine->port_buffer_freelist = g_slist_remove (engine->port_buffer_freelist, bi);


+ 6
- 3
jack/alsa_driver.h View File

@@ -34,7 +34,8 @@ typedef void (*ReadCopyFunction) (sample_t *dst, char *src,
unsigned long src_skip_bytes);
typedef void (*WriteCopyFunction) (char *dst, sample_t *src,
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,
unsigned long src_bytes,
unsigned long dst_skip_bytes,
@@ -102,7 +103,8 @@ typedef struct {
WriteCopyFunction write_via_copy;
CopyCopyFunction channel_copy;

int dither;
int dither;
dither_state_t *dither_state;

SampleClockMode clock_mode;
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],
buf,
nsamples,
driver->playback_interleave_skip);
driver->playback_interleave_skip,
driver->dither_state+channel);
alsa_driver_mark_channel_done (driver, channel);
}



+ 0
- 1
jack/engine.h View File

@@ -38,7 +38,6 @@ struct _jack_engine {
void (*process_unlock)(struct _jack_engine *);
int (*post_process)(struct _jack_engine *);
pthread_mutex_t client_lock;
pthread_mutex_t cleanup_lock;
pthread_mutex_t buffer_lock;
pthread_mutex_t port_lock;
int process_errors;


+ 7
- 6
jack/memops.h View File

@@ -23,17 +23,18 @@

#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_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
sample_merge (sample_t *dst, sample_t *src, unsigned long cnt)


+ 17
- 0
jack/types.h View File

@@ -70,4 +70,21 @@ typedef enum {
NoSync = 0x8
} 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__ */

+ 81
- 5
memops.c View File

@@ -41,7 +41,7 @@ inline int f_round(float f) {
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 !!! */
@@ -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;
@@ -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;
@@ -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)
{
@@ -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;

@@ -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 !!! */


Loading…
Cancel
Save