git-svn-id: svn+ssh://jackaudio.org/trunk/jack@189 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
@@ -0,0 +1,3 @@ | |||
Welcome to JACK, the Jack Audio Connection Kit. | |||
Please see the website (http://jackit.sf.net/) for more information. |
@@ -1,176 +0,0 @@ | |||
#include <stdio.h> | |||
#include <errno.h> | |||
#include <unistd.h> | |||
#include <stdlib.h> | |||
#include <jack/jack.h> | |||
#include <glib.h> | |||
#include <jack/port.h> | |||
#include <jack/cycles.h> | |||
jack_port_t *input_port; | |||
jack_port_t *output_port; | |||
volatile char *buf; | |||
unsigned long stompsize; | |||
int do_stomp = 0; | |||
pthread_mutex_t foolock = PTHREAD_MUTEX_INITIALIZER; | |||
int | |||
process (jack_nframes_t nframes, void *arg) | |||
{ | |||
unsigned long i; | |||
unsigned long long now, then; | |||
jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes); | |||
jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (input_port, nframes); | |||
now = get_cycles (); | |||
if (pthread_mutex_trylock (&foolock) == 0) { | |||
then = get_cycles (); | |||
if (do_stomp) { | |||
for (i = 0; i < stompsize; ++i) { | |||
buf[i]++; | |||
} | |||
} else { | |||
for (i = 0; i < stompsize; ++i) { | |||
buf[0]++; | |||
} | |||
} | |||
then = get_cycles (); | |||
pthread_mutex_unlock (&foolock); | |||
} | |||
memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes); | |||
return 0; | |||
} | |||
int | |||
bufsize (jack_nframes_t nframes, void *arg) | |||
{ | |||
printf ("the maximum buffer size is now %lu\n", nframes); | |||
return 0; | |||
} | |||
int | |||
srate (jack_nframes_t nframes, void *arg) | |||
{ | |||
printf ("the sample rate is now %lu/sec\n", nframes); | |||
return 0; | |||
} | |||
void | |||
jack_shutdown (void *arg) | |||
{ | |||
printf ("shutdown by JACK\n"); | |||
exit (1); | |||
} | |||
void * | |||
other_thread (void *arg) | |||
{ | |||
while (1) { | |||
pthread_mutex_lock (&foolock); | |||
usleep (3000); | |||
pthread_mutex_unlock (&foolock); | |||
usleep (3000); | |||
} | |||
return 0; | |||
} | |||
int | |||
main (int argc, char *argv[]) | |||
{ | |||
jack_client_t *client; | |||
pthread_t other; | |||
if (argc < 2) { | |||
fprintf (stderr, "usage: jack_simple_client <name>\n"); | |||
return 1; | |||
} | |||
/* try to become a client of the JACK server */ | |||
if ((client = jack_client_new (argv[1])) == 0) { | |||
fprintf (stderr, "jack server not running?\n"); | |||
return 1; | |||
} | |||
stompsize = atoi (argv[2]); | |||
buf = (char *) malloc (sizeof (char) * stompsize); | |||
do_stomp = atoi (argv[3]); | |||
pthread_create (&other, NULL, other_thread, NULL); | |||
/* tell the JACK server to call `process()' whenever | |||
there is work to be done. | |||
*/ | |||
jack_set_process_callback (client, process, 0); | |||
/* tell the JACK server to call `bufsize()' whenever | |||
the maximum number of frames that will be passed | |||
to `process()' changes | |||
*/ | |||
jack_set_buffer_size_callback (client, bufsize, 0); | |||
/* tell the JACK server to call `srate()' whenever | |||
the sample rate of the system changes. | |||
*/ | |||
jack_set_sample_rate_callback (client, srate, 0); | |||
/* tell the JACK server to call `jack_shutdown()' if | |||
it ever shuts down, either entirely, or if it | |||
just decides to stop calling us. | |||
*/ | |||
jack_on_shutdown (client, jack_shutdown, 0); | |||
/* display the current sample rate. once the client is activated | |||
(see below), you should rely on your own sample rate | |||
callback (see above) for this value. | |||
*/ | |||
printf ("engine sample rate: %lu\n", jack_get_sample_rate (client)); | |||
/* create two ports */ | |||
input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
/* tell the JACK server that we are ready to roll */ | |||
if (jack_activate (client)) { | |||
fprintf (stderr, "cannot activate client"); | |||
return 1; | |||
} | |||
/* connect the ports. Note: you can't do this before | |||
the client is activated (this may change in the future). | |||
*/ | |||
if (jack_connect (client, "alsa_pcm:in_1", jack_port_name (input_port))) { | |||
fprintf (stderr, "cannot connect input ports\n"); | |||
} | |||
if (jack_connect (client, jack_port_name (output_port), "alsa_pcm:out_1")) { | |||
fprintf (stderr, "cannot connect output ports\n"); | |||
} | |||
/* Since this is just a toy, run for a few seconds, then finish */ | |||
sleep (10); | |||
jack_client_close (client); | |||
printf ("finished OK\n"); | |||
exit (0); | |||
} | |||
@@ -1,372 +0,0 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
$Id$ | |||
*/ | |||
#include <stdio.h> | |||
#include <errno.h> | |||
#include <unistd.h> | |||
#include <sndfile.h> | |||
#include <pthread.h> | |||
#include <glib.h> | |||
#include <getopt.h> | |||
#include <jack/jack.h> | |||
typedef struct _thread_info { | |||
pthread_t thread_id; | |||
SNDFILE *sf; | |||
jack_nframes_t duration; | |||
jack_client_t *client; | |||
unsigned int channels; | |||
int bitdepth; | |||
int can_capture; | |||
char *path; | |||
int status; | |||
int can_process; | |||
} thread_info_t; | |||
unsigned int nports; | |||
jack_port_t **ports; | |||
pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER; | |||
pthread_cond_t data_ready = PTHREAD_COND_INITIALIZER; | |||
typedef struct _sample_buffer { | |||
jack_nframes_t nframes; | |||
jack_default_audio_sample_t **data; | |||
} sample_buffer_t; | |||
sample_buffer_t * | |||
sample_buffer_new (jack_nframes_t nframes, unsigned int nchans) | |||
{ | |||
sample_buffer_t *buf; | |||
unsigned int i; | |||
buf = (sample_buffer_t *) malloc (sizeof (sample_buffer_t)); | |||
buf->nframes = nframes; | |||
buf->data = (jack_default_audio_sample_t **) malloc (sizeof (jack_default_audio_sample_t *) * nchans); | |||
for (i = 0; i < nchans; i++) { | |||
buf->data[i] = (jack_default_audio_sample_t *) malloc (sizeof (jack_default_audio_sample_t) * nframes); | |||
} | |||
return buf; | |||
} | |||
GSList *pending_writes = NULL; | |||
GSList *free_buffers = NULL; | |||
sample_buffer_t * | |||
get_free_buffer (jack_nframes_t nframes, unsigned int nchans) | |||
{ | |||
sample_buffer_t *buf; | |||
if (free_buffers == NULL) { | |||
buf = sample_buffer_new (nframes, nchans); | |||
} else { | |||
buf = (sample_buffer_t *) free_buffers->data; | |||
free_buffers = g_slist_next (free_buffers); | |||
} | |||
return buf; | |||
} | |||
sample_buffer_t * | |||
get_write_buffer () | |||
{ | |||
sample_buffer_t *buf; | |||
if (pending_writes == NULL) { | |||
return NULL; | |||
} | |||
buf = (sample_buffer_t *) pending_writes->data; | |||
pending_writes = g_slist_next (pending_writes); | |||
return buf; | |||
} | |||
void | |||
put_write_buffer (sample_buffer_t *buf) | |||
{ | |||
pending_writes = g_slist_append (pending_writes, buf); | |||
} | |||
void | |||
put_free_buffer (sample_buffer_t *buf) | |||
{ | |||
free_buffers = g_slist_prepend (free_buffers, buf); | |||
} | |||
void * | |||
disk_thread (void *arg) | |||
{ | |||
sample_buffer_t *buf; | |||
thread_info_t *info = (thread_info_t *) arg; | |||
int i; | |||
unsigned int chn; | |||
jack_nframes_t total_captured = 0; | |||
int done = 0; | |||
double *fbuf; | |||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | |||
pthread_mutex_lock (&buffer_lock); | |||
/* preload the buffer cache */ | |||
for (i = 0; i < 8; i++) { | |||
buf = sample_buffer_new (jack_get_buffer_size (info->client), info->channels); | |||
put_free_buffer (buf); | |||
} | |||
info->status = 0; | |||
while (!done) { | |||
pthread_cond_wait (&data_ready, &buffer_lock); | |||
while ((buf = get_write_buffer ()) != 0) { | |||
pthread_mutex_unlock (&buffer_lock); | |||
/* grrr ... libsndfile doesn't do float data yet, only double */ | |||
if (info->can_capture) { | |||
fbuf = (double *) malloc (sizeof (double) * buf->nframes * info->channels); | |||
for (chn = 0; chn < info->channels; chn++) { | |||
for (i = 0; i < buf->nframes; i++) { | |||
fbuf[chn+(i*info->channels)] = buf->data[chn][i]; | |||
} | |||
} | |||
if (sf_writef_double (info->sf, fbuf, buf->nframes, 1) != buf->nframes) { | |||
char errstr[256]; | |||
sf_error_str (0, errstr, sizeof (errstr) - 1); | |||
fprintf (stderr, "cannot write data to sndfile (%s)\n", errstr); | |||
info->status = -1; | |||
done = 1; | |||
break; | |||
} | |||
free (fbuf); | |||
total_captured += buf->nframes; | |||
if (total_captured >= info->duration) { | |||
printf ("disk thread finished\n"); | |||
done = 1; | |||
break; | |||
} | |||
} | |||
pthread_mutex_lock (&buffer_lock); | |||
put_free_buffer (buf); | |||
} | |||
} | |||
pthread_mutex_unlock (&buffer_lock); | |||
return 0; | |||
} | |||
int | |||
process (jack_nframes_t nframes, void *arg) | |||
{ | |||
thread_info_t *info = (thread_info_t *) arg; | |||
jack_default_audio_sample_t *in; | |||
sample_buffer_t *buf; | |||
unsigned int i; | |||
if (!info->can_process) { | |||
return 0; | |||
} | |||
/* we don't like taking locks, but until we have a lock | |||
free ringbuffer written in C, this is what has to be done | |||
*/ | |||
pthread_mutex_lock (&buffer_lock); | |||
buf = get_free_buffer (nframes, nports); | |||
for (i = 0; i < nports; i++) { | |||
in = (jack_default_audio_sample_t *) jack_port_get_buffer (ports[i], nframes); | |||
memcpy (buf->data[i], in, sizeof (jack_default_audio_sample_t) * nframes); | |||
} | |||
put_write_buffer (buf); | |||
/* tell the disk thread that there is work to do */ | |||
pthread_cond_signal (&data_ready); | |||
pthread_mutex_unlock (&buffer_lock); | |||
return 0; | |||
} | |||
void | |||
jack_shutdown (void *arg) | |||
{ | |||
fprintf (stderr, "JACK shutdown\n"); | |||
exit (0); | |||
} | |||
void | |||
setup_disk_thread (thread_info_t *info) | |||
{ | |||
SF_INFO sf_info; | |||
sf_info.samplerate = jack_get_sample_rate (info->client); | |||
sf_info.channels = info->channels; | |||
sf_info.format = SF_FORMAT_WAV|SF_FORMAT_PCM; | |||
sf_info.pcmbitwidth = info->bitdepth; | |||
if ((info->sf = sf_open_write (info->path, &sf_info)) == NULL) { | |||
char errstr[256]; | |||
sf_error_str (0, errstr, sizeof (errstr) - 1); | |||
fprintf (stderr, "cannot open sndfile \"%s\" for output (%s)\n", info->path, errstr); | |||
jack_client_close (info->client); | |||
exit (1); | |||
} | |||
info->duration *= sf_info.samplerate; | |||
info->can_capture = 0; | |||
pthread_create (&info->thread_id, NULL, disk_thread, info); | |||
} | |||
void | |||
run_disk_thread (thread_info_t *info) | |||
{ | |||
info->can_capture = 1; | |||
pthread_join (info->thread_id, NULL); | |||
sf_close (info->sf); | |||
if (info->status) { | |||
unlink (info->path); | |||
} | |||
} | |||
void | |||
setup_ports (int sources, char *source_names[], thread_info_t *info) | |||
{ | |||
int i; | |||
nports = sources; | |||
ports = (jack_port_t **) malloc (sizeof (jack_port_t *) * nports); | |||
for (i = 0; i < nports; i++) { | |||
char name[64]; | |||
sprintf (name, "input%d", i+1); | |||
if ((ports[i] = jack_port_register (info->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) { | |||
fprintf (stderr, "cannot register input port \"%s\"!\n", name); | |||
jack_client_close (info->client); | |||
exit (1); | |||
} | |||
} | |||
for (i = 0; i < nports; i++) { | |||
if (jack_connect (info->client, source_names[i], jack_port_name (ports[i]))) { | |||
fprintf (stderr, "cannot connect input port %s to %s\n", jack_port_name (ports[i]), source_names[i]); | |||
jack_client_close (info->client); | |||
exit (1); | |||
} | |||
} | |||
info->can_process = 1; | |||
} | |||
int | |||
main (int argc, char *argv[]) | |||
{ | |||
jack_client_t *client; | |||
thread_info_t thread_info; | |||
int c; | |||
int longopt_index = 0; | |||
extern int optind, opterr; | |||
int show_usage = 0; | |||
char *optstring = "d:f:b:h"; | |||
struct option long_options[] = { | |||
{ "help", 1, 0, 'h' }, | |||
{ "duration", 1, 0, 'd' }, | |||
{ "file", 1, 0, 'f' }, | |||
{ "bitdepth", 1, 0, 'b' }, | |||
{ 0, 0, 0, 0 } | |||
}; | |||
memset (&thread_info, 0, sizeof (thread_info)); | |||
opterr = 0; | |||
while ((c = getopt_long (argc, argv, optstring, long_options, &longopt_index)) != -1) { | |||
switch (c) { | |||
case 1: | |||
/* getopt signals end of '-' options */ | |||
break; | |||
case 'h': | |||
show_usage++; | |||
break; | |||
case 'd': | |||
thread_info.duration = atoi (optarg); | |||
break; | |||
case 'f': | |||
thread_info.path = optarg; | |||
break; | |||
case 'b': | |||
thread_info.bitdepth = atoi (optarg); | |||
break; | |||
default: | |||
fprintf (stderr, "error\n"); | |||
show_usage++; | |||
break; | |||
} | |||
} | |||
if (show_usage || thread_info.path == NULL || optind == argc) { | |||
fprintf (stderr, "usage: jackrec -f filename [ -d second ] [ -b bitdepth ] port1 [ port2 ... ]\n"); | |||
exit (1); | |||
} | |||
if ((client = jack_client_new ("jackrec")) == 0) { | |||
fprintf (stderr, "jack server not running?\n"); | |||
exit (1); | |||
} | |||
thread_info.client = client; | |||
thread_info.channels = argc - optind; | |||
thread_info.can_process = 0; | |||
setup_disk_thread (&thread_info); | |||
jack_set_process_callback (client, process, &thread_info); | |||
jack_on_shutdown (client, jack_shutdown, NULL); | |||
if (jack_activate (client)) { | |||
fprintf (stderr, "cannot activate client"); | |||
} | |||
setup_ports (argc - optind, &argv[optind], &thread_info); | |||
run_disk_thread (&thread_info); | |||
jack_client_close (client); | |||
exit (0); | |||
} |
@@ -1,121 +0,0 @@ | |||
#include <stdio.h> | |||
/* | |||
Copyright (C) 2002 Jeremy Hall | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
$Id$ | |||
*/ | |||
#include <errno.h> | |||
#include <unistd.h> | |||
#include <string.h> | |||
#include <jack/jack.h> | |||
jack_port_t *input_port; | |||
jack_port_t *output_port; | |||
int connecting, disconnecting; | |||
#define TRUE 1 | |||
#define FALSE 0 | |||
int | |||
main (int argc, char *argv[]) | |||
{ | |||
jack_client_t *client; | |||
char *my_name = strrchr(argv[0], '/'); | |||
connecting = disconnecting = FALSE; | |||
if (my_name == 0) { | |||
my_name = argv[0]; | |||
} else { | |||
my_name ++; | |||
} | |||
if (strstr(my_name, "disconnect")) { | |||
disconnecting = TRUE; | |||
} else | |||
if (strstr(my_name, "connect")) { | |||
connecting = TRUE; | |||
} else { | |||
fprintf(stderr, "ERROR! client should be called jack_connect or jack_disconnect. client is called %s\n", my_name); | |||
return 1; | |||
} | |||
if (argc != 3) { | |||
fprintf (stderr, "usage: %s <src_port> <dst_port>\n", my_name); | |||
fprintf(stderr, "The source port must be an output port of the source client.\n"); | |||
fprintf (stderr, "The destination port must be an input port of the destination client.\n"); | |||
return 1; | |||
} | |||
/* try to become a client of the JACK server */ | |||
if ((client = jack_client_new (my_name)) == 0) { | |||
fprintf (stderr, "jack server not running?\n"); | |||
return 1; | |||
} | |||
/* display the current sample rate. once the client is activated | |||
(see below), you should rely on your own sample rate | |||
callback (see above) for this value. | |||
*/ | |||
printf ("engine sample rate: %lu\n", jack_get_sample_rate (client)); | |||
/* find the two ports */ | |||
if ((input_port = jack_port_by_name(client, argv[1])) == 0) { | |||
fprintf (stderr, "ERROR %s not a valid port\n", argv[1]); | |||
return 1; | |||
} | |||
if ((output_port = jack_port_by_name(client, argv[2])) == 0) { | |||
fprintf (stderr, "ERROR %s not a valid port\n", argv[2]); | |||
return 1; | |||
} | |||
/* tell the JACK server that we are ready to roll */ | |||
if (jack_activate (client)) { | |||
fprintf (stderr, "cannot activate client"); | |||
return 1; | |||
} | |||
/* connect the ports. Note: you can't do this before | |||
the client is activated (this may change in the future). | |||
*/ | |||
/* jack_port_connect not implemented | |||
if (jack_port_connect(client, input_port, output_port)) { | |||
fprintf (stderr, "cannot connect ports\n"); | |||
} | |||
*/ | |||
if (connecting) { | |||
if (jack_connect(client, jack_port_name(input_port), jack_port_name(output_port))) { | |||
fprintf (stderr, "cannot connect ports\n"); | |||
return 1; | |||
} | |||
} | |||
if (disconnecting) { | |||
if (jack_disconnect(client, jack_port_name(input_port), jack_port_name(output_port))) { | |||
fprintf (stderr, "cannot disconnect ports\n"); | |||
return 1; | |||
} | |||
} | |||
jack_client_close (client); | |||
exit (0); | |||
} | |||
@@ -1,106 +0,0 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
$Id$ | |||
*/ | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <stdarg.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <jack/driver.h> | |||
#include <jack/internal.h> | |||
#include <jack/error.h> | |||
static int dummy_attach (jack_driver_t *drv, jack_engine_t *eng) { return 0; } | |||
static int dummy_detach (jack_driver_t *drv, jack_engine_t *eng) { return 0; } | |||
static jack_nframes_t dummy_wait (jack_driver_t *drv, int fd, int *status, float *delayed_usecs) { *status = 0; *delayed_usecs = 0; return 0; } | |||
static int dummy_process (jack_driver_t *drv, jack_nframes_t nframes) { return 0; } | |||
static int dummy_stop (jack_driver_t *drv) { return 0; } | |||
static int dummy_start (jack_driver_t *drv) { return 0; } | |||
void | |||
jack_driver_init (jack_driver_t *driver) | |||
{ | |||
memset (driver, 0, sizeof (*driver)); | |||
driver->attach = dummy_attach; | |||
driver->detach = dummy_detach; | |||
driver->wait = dummy_wait; | |||
driver->process = dummy_process; | |||
driver->start = dummy_start; | |||
driver->stop = dummy_stop; | |||
} | |||
jack_driver_t * | |||
jack_driver_load (int argc, char **argv) | |||
{ | |||
const char *errstr; | |||
dlhandle handle; | |||
jack_driver_t *driver; | |||
jack_driver_t *(*initialize)(int, char **); | |||
void (*finish)(jack_driver_t *); | |||
char path_to_so[PATH_MAX+1]; | |||
snprintf (path_to_so, sizeof (path_to_so), ADDON_DIR "/jack_%s.so", argv[0]); | |||
handle = dlopen (path_to_so, RTLD_NOW|RTLD_GLOBAL); | |||
if (handle == 0) { | |||
if ((errstr = dlerror ()) != 0) { | |||
jack_error ("can't load \"%s\": %s", path_to_so, errstr); | |||
} else { | |||
jack_error ("bizarre error loading driver shared object %s", path_to_so); | |||
} | |||
return 0; | |||
} | |||
initialize = dlsym (handle, "driver_initialize"); | |||
if ((errstr = dlerror ()) != 0) { | |||
jack_error ("no initialize function in shared object %s\n", path_to_so); | |||
dlclose (handle); | |||
return 0; | |||
} | |||
finish = dlsym (handle, "driver_finish"); | |||
if ((errstr = dlerror ()) != 0) { | |||
jack_error ("no finish function in in shared driver object %s", path_to_so); | |||
dlclose (handle); | |||
return 0; | |||
} | |||
if ((driver = initialize (argc, argv)) != 0) { | |||
driver->handle = handle; | |||
driver->finish = finish; | |||
} | |||
return driver; | |||
} | |||
void | |||
jack_driver_unload (jack_driver_t *driver) | |||
{ | |||
driver->finish (driver); | |||
dlclose (driver->handle); | |||
} |
@@ -1,99 +0,0 @@ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <errno.h> | |||
#include <unistd.h> | |||
extern "C" | |||
{ | |||
#include <jack/jack.h> | |||
} | |||
#include <FL/Fl.H> | |||
#include <FL/Fl_Window.H> | |||
#include <FL/Fl_Slider.H> | |||
jack_port_t *input_port; | |||
jack_port_t *output_port; | |||
float gain = 0.0; /* slider starts out with zero gain */ | |||
int | |||
process (jack_nframes_t nframes, void *arg) | |||
{ | |||
jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes); | |||
jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (input_port, nframes); | |||
while (nframes--) | |||
out[nframes] = in[nframes] * gain; | |||
return 0; | |||
} | |||
int | |||
bufsize (jack_nframes_t nframes, void *arg) | |||
{ | |||
printf ("the maximum buffer size is now %lu\n", nframes); | |||
return 0; | |||
} | |||
int | |||
srate (jack_nframes_t nframes, void *arg) | |||
{ | |||
printf ("the sample rate is now %lu/sec\n", nframes); | |||
return 0; | |||
} | |||
void callback(Fl_Slider* s) | |||
{ | |||
gain = s->value(); | |||
} | |||
int | |||
main (int argc, char *argv[]) | |||
{ | |||
Fl_Window w(0,0,100,120); | |||
Fl_Slider s(10,10,20,100); | |||
w.show(); | |||
s.callback((Fl_Callback*) callback); | |||
jack_client_t *client; | |||
if ((client = jack_client_new ("fltktest")) == 0) { | |||
fprintf (stderr, "jack server not running?\n"); | |||
return 1; | |||
} | |||
jack_set_process_callback (client, process, 0); | |||
jack_set_buffer_size_callback (client, bufsize, 0); | |||
jack_set_sample_rate_callback (client, srate, 0); | |||
printf ("engine sample rate: %lu\n", jack_get_sample_rate (client)); | |||
input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
if (jack_activate (client)) { | |||
fprintf (stderr, "cannot activate client"); | |||
} | |||
printf ("client activated\n"); | |||
if (jack_connect (client, "alsa_pcm:in_1", jack_port_name (input_port))) { | |||
fprintf (stderr, "cannot connect input ports\n"); | |||
} | |||
if (jack_connect (client, jack_port_name (output_port), "alsa_pcm:out_1")) { | |||
fprintf (stderr, "cannot connect output ports\n"); | |||
} | |||
Fl::run(); | |||
printf ("done sleeping, now closing...\n"); | |||
jack_client_close (client); | |||
exit (0); | |||
} | |||
@@ -1,57 +0,0 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
$Id$ | |||
*/ | |||
#include <jack/hardware.h> | |||
#include <jack/alsa_driver.h> | |||
static int generic_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) | |||
{ | |||
return -1; | |||
} | |||
static int generic_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode) | |||
{ | |||
return -1; | |||
} | |||
void | |||
jack_alsa_generic_hw_release (jack_hardware_t *hw) | |||
{ | |||
return; | |||
} | |||
jack_hardware_t * | |||
jack_alsa_generic_hw_new (alsa_driver_t *driver) | |||
{ | |||
jack_hardware_t *hw; | |||
hw = (jack_hardware_t *) malloc (sizeof (jack_hardware_t)); | |||
hw->capabilities = 0; | |||
hw->input_monitor_mask = 0; | |||
hw->set_input_monitor_mask = generic_set_input_monitor_mask; | |||
hw->change_sample_clock = generic_change_sample_clock; | |||
hw->release = jack_alsa_generic_hw_release; | |||
return hw; | |||
} |
@@ -1,296 +0,0 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
$Id$ | |||
*/ | |||
#include <jack/hardware.h> | |||
#include <jack/alsa_driver.h> | |||
#include <jack/hammerfall.h> | |||
#include <jack/error.h> | |||
static void | |||
set_control_id (snd_ctl_elem_id_t *ctl, const char *name) | |||
{ | |||
snd_ctl_elem_id_set_name (ctl, name); | |||
snd_ctl_elem_id_set_numid (ctl, 0); | |||
snd_ctl_elem_id_set_interface (ctl, SND_CTL_ELEM_IFACE_PCM); | |||
snd_ctl_elem_id_set_device (ctl, 0); | |||
snd_ctl_elem_id_set_subdevice (ctl, 0); | |||
snd_ctl_elem_id_set_index (ctl, 0); | |||
} | |||
static void | |||
hammerfall_broadcast_channel_status_change (hammerfall_t *h, int lock, int sync, channel_t lowchn, channel_t highchn) | |||
{ | |||
channel_t chn; | |||
ClockSyncStatus status = 0; | |||
if (lock) { | |||
status |= Lock; | |||
} else { | |||
status |= NoLock; | |||
} | |||
if (sync) { | |||
status |= Sync; | |||
} else { | |||
status |= NoSync; | |||
} | |||
for (chn = lowchn; chn < highchn; chn++) { | |||
alsa_driver_set_clock_sync_status (h->driver, chn, status); | |||
} | |||
} | |||
static void | |||
hammerfall_check_sync_state (hammerfall_t *h, int val, int adat_id) | |||
{ | |||
int lock; | |||
int sync; | |||
/* S/PDIF channel is always locked and synced, but we only | |||
need tell people once that this is TRUE. | |||
XXX - maybe need to make sure that the rate matches our | |||
idea of the current rate ? | |||
*/ | |||
if (!h->said_that_spdif_is_fine) { | |||
ClockSyncStatus status; | |||
status = Lock|Sync; | |||
/* XXX broken! fix for hammerfall light ! */ | |||
alsa_driver_set_clock_sync_status (h->driver, 24, status); | |||
alsa_driver_set_clock_sync_status (h->driver, 25, status); | |||
h->said_that_spdif_is_fine = TRUE; | |||
} | |||
lock = (val & 0x1) ? TRUE : FALSE; | |||
sync = (val & 0x2) ? TRUE : FALSE; | |||
if (h->lock_status[adat_id] != lock || | |||
h->sync_status[adat_id] != sync) { | |||
hammerfall_broadcast_channel_status_change (h, lock, sync, adat_id*8, (adat_id*8)+8); | |||
} | |||
h->lock_status[adat_id] = lock; | |||
h->sync_status[adat_id] = sync; | |||
} | |||
static void | |||
hammerfall_check_sync (hammerfall_t *h, snd_ctl_elem_value_t *ctl) | |||
{ | |||
const char *name; | |||
int val; | |||
snd_ctl_elem_id_t *ctl_id; | |||
printf ("check sync\n"); | |||
snd_ctl_elem_id_alloca (&ctl_id); | |||
snd_ctl_elem_value_get_id (ctl, ctl_id); | |||
name = snd_ctl_elem_id_get_name (ctl_id); | |||
if (strcmp (name, "ADAT1 Sync Check") == 0) { | |||
val = snd_ctl_elem_value_get_enumerated (ctl, 0); | |||
hammerfall_check_sync_state (h, val, 0); | |||
} else if (strcmp (name, "ADAT2 Sync Check") == 0) { | |||
val = snd_ctl_elem_value_get_enumerated (ctl, 0); | |||
hammerfall_check_sync_state (h, val, 1); | |||
} else if (strcmp (name, "ADAT3 Sync Check") == 0) { | |||
val = snd_ctl_elem_value_get_enumerated (ctl, 0); | |||
hammerfall_check_sync_state (h, val, 2); | |||
} else { | |||
jack_error ("Hammerfall: unknown control \"%s\"", name); | |||
} | |||
} | |||
static int | |||
hammerfall_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) | |||
{ | |||
hammerfall_t *h = (hammerfall_t *) hw->private; | |||
snd_ctl_elem_value_t *ctl; | |||
snd_ctl_elem_id_t *ctl_id; | |||
int err; | |||
int i; | |||
snd_ctl_elem_value_alloca (&ctl); | |||
snd_ctl_elem_id_alloca (&ctl_id); | |||
set_control_id (ctl_id, "Channels Thru"); | |||
snd_ctl_elem_value_set_id (ctl, ctl_id); | |||
for (i = 0; i < 26; i++) { | |||
snd_ctl_elem_value_set_integer (ctl, i, (mask & (1<<i)) ? 1 : 0); | |||
} | |||
if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) != 0) { | |||
jack_error ("ALSA/Hammerfall: cannot set input monitoring (%s)", snd_strerror (err)); | |||
return -1; | |||
} | |||
hw->input_monitor_mask = mask; | |||
return 0; | |||
} | |||
static int | |||
hammerfall_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode) | |||
{ | |||
hammerfall_t *h = (hammerfall_t *) hw->private; | |||
snd_ctl_elem_value_t *ctl; | |||
snd_ctl_elem_id_t *ctl_id; | |||
int err; | |||
snd_ctl_elem_value_alloca (&ctl); | |||
snd_ctl_elem_id_alloca (&ctl_id); | |||
set_control_id (ctl_id, "Sync Mode"); | |||
snd_ctl_elem_value_set_id (ctl, ctl_id); | |||
switch (mode) { | |||
case AutoSync: | |||
snd_ctl_elem_value_set_enumerated (ctl, 0, 0); | |||
break; | |||
case ClockMaster: | |||
snd_ctl_elem_value_set_enumerated (ctl, 0, 1); | |||
break; | |||
case WordClock: | |||
snd_ctl_elem_value_set_enumerated (ctl, 0, 2); | |||
break; | |||
} | |||
if ((err = snd_ctl_elem_write (h->driver->ctl_handle, ctl)) < 0) { | |||
jack_error ("ALSA-Hammerfall: cannot set clock mode"); | |||
} | |||
return 0; | |||
} | |||
static void | |||
hammerfall_release (jack_hardware_t *hw) | |||
{ | |||
hammerfall_t *h = (hammerfall_t *) hw->private; | |||
void *status; | |||
if (h == 0) { | |||
return; | |||
} | |||
pthread_cancel (h->monitor_thread); | |||
pthread_join (h->monitor_thread, &status); | |||
free (h); | |||
} | |||
static void * | |||
hammerfall_monitor_controls (void *arg) | |||
{ | |||
jack_hardware_t *hw = (jack_hardware_t *) arg; | |||
hammerfall_t *h = (hammerfall_t *) hw->private; | |||
snd_ctl_elem_id_t *switch_id[3]; | |||
snd_ctl_elem_value_t *sw[3]; | |||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | |||
snd_ctl_elem_id_malloc (&switch_id[0]); | |||
snd_ctl_elem_id_malloc (&switch_id[1]); | |||
snd_ctl_elem_id_malloc (&switch_id[2]); | |||
snd_ctl_elem_value_malloc (&sw[0]); | |||
snd_ctl_elem_value_malloc (&sw[1]); | |||
snd_ctl_elem_value_malloc (&sw[2]); | |||
set_control_id (switch_id[0], "ADAT1 Sync Check"); | |||
set_control_id (switch_id[1], "ADAT2 Sync Check"); | |||
set_control_id (switch_id[2], "ADAT3 Sync Check"); | |||
snd_ctl_elem_value_set_id (sw[0], switch_id[0]); | |||
snd_ctl_elem_value_set_id (sw[1], switch_id[1]); | |||
snd_ctl_elem_value_set_id (sw[2], switch_id[2]); | |||
while (1) { | |||
if (snd_ctl_elem_read (h->driver->ctl_handle, sw[0])) { | |||
jack_error ("cannot read control switch 0 ..."); | |||
} | |||
hammerfall_check_sync (h, sw[0]); | |||
if (snd_ctl_elem_read (h->driver->ctl_handle, sw[1])) { | |||
jack_error ("cannot read control switch 0 ..."); | |||
} | |||
hammerfall_check_sync (h, sw[1]); | |||
if (snd_ctl_elem_read (h->driver->ctl_handle, sw[2])) { | |||
jack_error ("cannot read control switch 0 ..."); | |||
} | |||
hammerfall_check_sync (h, sw[2]); | |||
if (nanosleep (&h->monitor_interval, 0)) { | |||
break; | |||
} | |||
} | |||
pthread_exit (0); | |||
} | |||
jack_hardware_t * | |||
jack_alsa_hammerfall_hw_new (alsa_driver_t *driver) | |||
{ | |||
jack_hardware_t *hw; | |||
hammerfall_t *h; | |||
hw = (jack_hardware_t *) malloc (sizeof (jack_hardware_t)); | |||
hw->capabilities = Cap_HardwareMonitoring|Cap_AutoSync|Cap_WordClock|Cap_ClockMaster|Cap_ClockLockReporting; | |||
hw->input_monitor_mask = 0; | |||
hw->private = 0; | |||
hw->set_input_monitor_mask = hammerfall_set_input_monitor_mask; | |||
hw->change_sample_clock = hammerfall_change_sample_clock; | |||
hw->release = hammerfall_release; | |||
h = (hammerfall_t *) malloc (sizeof (hammerfall_t)); | |||
h->lock_status[0] = FALSE; | |||
h->sync_status[0] = FALSE; | |||
h->lock_status[1] = FALSE; | |||
h->sync_status[1] = FALSE; | |||
h->lock_status[2] = FALSE; | |||
h->sync_status[2] = FALSE; | |||
h->said_that_spdif_is_fine = FALSE; | |||
h->driver = driver; | |||
h->monitor_interval.tv_sec = 1; | |||
h->monitor_interval.tv_nsec = 0; | |||
hw->private = h; | |||
#if 0 | |||
if (pthread_create (&h->monitor_thread, 0, hammerfall_monitor_controls, hw)) { | |||
jack_error ("ALSA/Hammerfall: cannot create sync monitor thread"); | |||
} | |||
#endif | |||
return hw; | |||
} |
@@ -1,152 +0,0 @@ | |||
/* | |||
Copyright (C) 2002 Anthony Van Groningen | |||
Parts based on source code taken from the | |||
"Env24 chipset (ICE1712) control utility" that is | |||
Copyright (C) 2000 by Jaroslav Kysela <perex@suse.cz> | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
*/ | |||
#include <jack/hardware.h> | |||
#include <jack/alsa_driver.h> | |||
#include <jack/ice1712.h> | |||
#include <jack/error.h> | |||
static int | |||
ice1712_hw_monitor_toggle(jack_hardware_t *hw, int idx, int onoff) | |||
{ | |||
ice1712_t *h = (ice1712_t *) hw->private; | |||
snd_ctl_elem_value_t *val; | |||
int err; | |||
snd_ctl_elem_value_alloca (&val); | |||
snd_ctl_elem_value_set_interface (val, SND_CTL_ELEM_IFACE_MIXER); | |||
if (idx >= 8) { | |||
snd_ctl_elem_value_set_name (val, SPDIF_PLAYBACK_ROUTE_NAME); | |||
snd_ctl_elem_value_set_index (val, idx - 8); | |||
} else { | |||
snd_ctl_elem_value_set_name (val, ANALOG_PLAYBACK_ROUTE_NAME); | |||
snd_ctl_elem_value_set_index (val, idx); | |||
} | |||
if (onoff) { | |||
snd_ctl_elem_value_set_enumerated (val, 0, idx + 1); | |||
} else { | |||
snd_ctl_elem_value_set_enumerated (val, 0, 0); | |||
} | |||
if ((err = snd_ctl_elem_write (h->driver->ctl_handle, val)) != 0) { | |||
jack_error ("ALSA/ICE1712: (%d) cannot set input monitoring (%s)", | |||
idx,snd_strerror (err)); | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
static int | |||
ice1712_set_input_monitor_mask (jack_hardware_t *hw, unsigned long mask) | |||
{ | |||
int idx; | |||
ice1712_t *h = (ice1712_t *) hw->private; | |||
for (idx = 0; idx < 10; idx++) { | |||
if (h->active_channels & (1<<idx)) { | |||
ice1712_hw_monitor_toggle (hw, idx, mask & (1<<idx) ? 1 : 0); | |||
} | |||
} | |||
hw->input_monitor_mask = mask; | |||
return 0; | |||
} | |||
static int | |||
ice1712_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode) | |||
{ | |||
return -1; | |||
} | |||
static void | |||
ice1712_release (jack_hardware_t *hw) | |||
{ | |||
return; | |||
} | |||
jack_hardware_t * | |||
jack_alsa_ice1712_hw_new (alsa_driver_t *driver) | |||
{ | |||
jack_hardware_t *hw; | |||
ice1712_t *h; | |||
snd_ctl_elem_value_t *val; | |||
int err; | |||
hw = (jack_hardware_t *) malloc (sizeof (jack_hardware_t)); | |||
hw->capabilities = Cap_HardwareMonitoring; | |||
hw->input_monitor_mask = 0; | |||
hw->private = 0; | |||
hw->set_input_monitor_mask = ice1712_set_input_monitor_mask; | |||
hw->change_sample_clock = ice1712_change_sample_clock; | |||
hw->release = ice1712_release; | |||
h = (ice1712_t *) malloc (sizeof (ice1712_t)); | |||
h->driver = driver; | |||
/* Get the EEPROM (adopted from envy24control) */ | |||
h->eeprom = (ice1712_eeprom_t *) malloc (sizeof (ice1712_eeprom_t)); | |||
snd_ctl_elem_value_alloca (&val); | |||
snd_ctl_elem_value_set_interface (val, SND_CTL_ELEM_IFACE_CARD); | |||
snd_ctl_elem_value_set_name (val, "ICE1712 EEPROM"); | |||
if ((err = snd_ctl_elem_read (driver->ctl_handle, val)) < 0) { | |||
jack_error( "ALSA/ICE1712: Unable to read EEPROM contents (%s)\n", snd_strerror (err)); | |||
/* Recover? */ | |||
} | |||
memcpy(h->eeprom, snd_ctl_elem_value_get_bytes(val), 32); | |||
/* determine number of pro ADC's. We're asumming that there is at least one stereo pair. | |||
Should check this first, but how? */ | |||
switch((h->eeprom->codec & 0xCU) >> 2) { | |||
case 0: | |||
h->active_channels = 0x3U; | |||
break; | |||
case 1: | |||
h->active_channels = 0xfU; | |||
break; | |||
case 2: | |||
h->active_channels = 0x3fU; | |||
break; | |||
case 3: | |||
h->active_channels = 0xffU; | |||
break; | |||
} | |||
/* check for SPDIF In's */ | |||
if (h->eeprom->spdif & 0x1U) { | |||
h->active_channels |= 0x300U; | |||
} | |||
hw->private = h; | |||
return hw; | |||
} |
@@ -1,217 +0,0 @@ | |||
/* | |||
* Copyright (C) 2001 Steve Harris | |||
* | |||
* This program is free software; you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation; either version 2 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with this program; if not, write to the Free Software | |||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
* | |||
* $Id$ | |||
*/ | |||
#include <stdio.h> | |||
#include <errno.h> | |||
#include <unistd.h> | |||
#include <stdlib.h> | |||
#include <math.h> | |||
#include <getopt.h> | |||
#include <jack/jack.h> | |||
jack_port_t *input_port; | |||
jack_port_t *output_port; | |||
unsigned int impulse_sent = 0; | |||
float *response; | |||
unsigned long response_duration; | |||
unsigned long response_pos; | |||
int grab_finished = 0; | |||
int | |||
process (jack_nframes_t nframes, void *arg) | |||
{ | |||
jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes); | |||
jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (input_port, nframes); | |||
unsigned int i; | |||
if (grab_finished) { | |||
return 0; | |||
} else if (impulse_sent) { | |||
for(i=0; i<nframes && response_pos < response_duration; i++) { | |||
response[response_pos++] = in[i]; | |||
} | |||
if (response_pos >= response_duration) { | |||
grab_finished = 1; | |||
} | |||
for (i=0; i<nframes; i++) { | |||
out[i] = 0.0f;; | |||
} | |||
} else { | |||
out[0] = 1.0f; | |||
for (i=1; i<nframes; i++) { | |||
out[i] = 0.0f; | |||
} | |||
impulse_sent = 1; | |||
} | |||
return 0; | |||
} | |||
void | |||
jack_shutdown (void *arg) | |||
{ | |||
exit (1); | |||
} | |||
int | |||
main (int argc, char *argv[]) | |||
{ | |||
jack_client_t *client; | |||
float fs; // The sample rate | |||
float peak; | |||
unsigned long peak_sample; | |||
unsigned int i; | |||
float duration = 0.0f; | |||
unsigned int c_format = 0; | |||
int longopt_index = 0; | |||
int c; | |||
extern int optind, opterr; | |||
int show_usage = 0; | |||
char *optstring = "d:f"; | |||
struct option long_options[] = { | |||
{ "help", 1, 0, 'h' }, | |||
{ "duration", 1, 0, 'd' }, | |||
{ "format", 1, 0, 'f' }, | |||
{ 0, 0, 0, 0 } | |||
}; | |||
while ((c = getopt_long (argc, argv, optstring, long_options, &longopt_index)) != -1) { | |||
switch (c) { | |||
case 1: | |||
// end of opts, but don't care | |||
break; | |||
case 'h': | |||
show_usage++; | |||
break; | |||
case 'd': | |||
duration = (float)atof(optarg); | |||
break; | |||
case 'f': | |||
if (*optarg == 'c' || *optarg == 'C') { | |||
c_format = 1; | |||
} | |||
break; | |||
default: | |||
show_usage++; | |||
break; | |||
} | |||
} | |||
if (show_usage || duration <= 0.0f) { | |||
fprintf(stderr, "usage: jack_impulse_grab -d duration [-f (C|gnuplot)]\n"); | |||
exit(1); | |||
} | |||
/* try to become a client of the JACK server */ | |||
if ((client = jack_client_new("impulse_grabber")) == 0) { | |||
fprintf (stderr, "jack server not running?\n"); | |||
return 1; | |||
} | |||
/* tell the JACK server to call `process()' whenever | |||
there is work to be done. | |||
*/ | |||
jack_set_process_callback (client, process, 0); | |||
/* tell the JACK server to call `jack_shutdown()' if | |||
it ever shuts down, either entirely, or if it | |||
just decides to stop calling us. | |||
*/ | |||
jack_on_shutdown (client, jack_shutdown, 0); | |||
/* display the current sample rate. once the client is activated | |||
(see below), you should rely on your own sample rate | |||
callback (see above) for this value. | |||
*/ | |||
fs = jack_get_sample_rate(client); | |||
response_duration = (int)(fs * duration); | |||
response = malloc(response_duration * sizeof(float)); | |||
fprintf(stderr, "Grabbing %f seconds (%lu samples) of impulse response\n", duration, response_duration); | |||
/* create two ports */ | |||
input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
/* tell the JACK server that we are ready to roll */ | |||
if (jack_activate (client)) { | |||
fprintf (stderr, "cannot activate client"); | |||
return 1; | |||
} | |||
/* connect the ports. Note: you can't do this before | |||
the client is activated (this may change in the future). | |||
*/ | |||
if (jack_connect (client, "alsa_pcm:in_1", jack_port_name (input_port))) { | |||
fprintf (stderr, "cannot connect input ports\n"); | |||
} | |||
if (jack_connect (client, jack_port_name (output_port), "alsa_pcm:out_1")) { | |||
fprintf (stderr, "cannot connect output ports\n"); | |||
} | |||
/* Wait for grab to finish */ | |||
while (!grab_finished) { | |||
sleep (1); | |||
} | |||
jack_client_close (client); | |||
peak = response[0]; | |||
peak_sample = 0; | |||
if (c_format) { | |||
printf("impulse[%lu] = {", response_duration); | |||
for (i=0; i<response_duration; i++) { | |||
if (i % 4 != 0) { | |||
printf(" "); | |||
} else { | |||
printf("\n\t"); | |||
} | |||
printf("\"%+1.10f\"", response[i]); | |||
if (i < response_duration - 1) { | |||
printf(","); | |||
} | |||
if (fabs(response[i]) > peak) { | |||
peak = fabs(response[i]); | |||
peak_sample = i; | |||
} | |||
} | |||
printf("\n};\n"); | |||
} else { | |||
for (i=0; i<response_duration; i++) { | |||
printf("%1.12f\n", response[i]); | |||
if (fabs(response[i]) > peak) { | |||
peak = fabs(response[i]); | |||
peak_sample = i; | |||
} | |||
} | |||
} | |||
fprintf(stderr, "Peak value was %f at sample %lu\n", peak, peak_sample); | |||
exit (0); | |||
} |
@@ -1,445 +0,0 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
$Id$ | |||
*/ | |||
#include <stdio.h> | |||
#include <signal.h> | |||
#include <getopt.h> | |||
#include <sys/types.h> | |||
#include <sys/shm.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <wait.h> | |||
#include <jack/engine.h> | |||
#include <jack/internal.h> | |||
#include <jack/driver.h> | |||
static sigset_t signals; | |||
static jack_engine_t *engine = 0; | |||
static int jackd_pid; | |||
static int realtime = 0; | |||
static int realtime_priority = 10; | |||
static int with_fork = 1; | |||
static int verbose = 0; | |||
static int asio_mode = 0; | |||
typedef struct { | |||
pid_t pid; | |||
int argc; | |||
char **argv; | |||
} waiter_arg_t; | |||
#define ILOWER 0 | |||
#define IRANGE 3000 | |||
int wait_times[IRANGE]; | |||
int unders = 0; | |||
int overs = 0; | |||
int max_over = 0; | |||
int min_under = INT_MAX; | |||
#define WRANGE 3000 | |||
int work_times[WRANGE]; | |||
int work_overs = 0; | |||
int work_max = 0; | |||
void | |||
store_work_time (int howlong) | |||
{ | |||
if (howlong < WRANGE) { | |||
work_times[howlong]++; | |||
} else { | |||
work_overs++; | |||
} | |||
if (work_max < howlong) { | |||
work_max = howlong; | |||
} | |||
} | |||
void | |||
show_work_times () | |||
{ | |||
int i; | |||
for (i = 0; i < WRANGE; ++i) { | |||
printf ("%d %d\n", i, work_times[i]); | |||
} | |||
printf ("work overs = %d\nmax = %d\n", work_overs, work_max); | |||
} | |||
void | |||
store_wait_time (int interval) | |||
{ | |||
if (interval < ILOWER) { | |||
unders++; | |||
} else if (interval >= ILOWER + IRANGE) { | |||
overs++; | |||
} else { | |||
wait_times[interval-ILOWER]++; | |||
} | |||
if (interval > max_over) { | |||
max_over = interval; | |||
} | |||
if (interval < min_under) { | |||
min_under = interval; | |||
} | |||
} | |||
void | |||
show_wait_times () | |||
{ | |||
int i; | |||
for (i = 0; i < IRANGE; i++) { | |||
printf ("%d %d\n", i+ILOWER, wait_times[i]); | |||
} | |||
printf ("unders: %d\novers: %d\n", unders, overs); | |||
printf ("max: %d\nmin: %d\n", max_over, min_under); | |||
} | |||
static void | |||
signal_handler (int sig) | |||
{ | |||
fprintf (stderr, "jackd: signal %d received\n", sig); | |||
kill (jackd_pid, SIGTERM); | |||
} | |||
static void | |||
posix_me_harder (void) | |||
{ | |||
/* what's this for? | |||
POSIX says that signals are delivered like this: | |||
* if a thread has blocked that signal, it is not | |||
a candidate to receive the signal. | |||
* of all threads not blocking the signal, pick | |||
one at random, and deliver the signal. | |||
this means that a simple-minded multi-threaded | |||
program can expect to get POSIX signals delivered | |||
randomly to any one of its threads, | |||
here, we block all signals that we think we | |||
might receive and want to catch. all "child" | |||
threads will inherit this setting. if we | |||
create a thread that calls sigwait() on the | |||
same set of signals, implicitly unblocking | |||
all those signals. any of those signals that | |||
are delivered to the process will be delivered | |||
to that thread, and that thread alone. this | |||
makes cleanup for a signal-driven exit much | |||
easier, since we know which thread is doing | |||
it and more importantly, we are free to | |||
call async-unsafe functions, because the | |||
code is executing in normal thread context | |||
after a return from sigwait(). | |||
*/ | |||
sigemptyset (&signals); | |||
sigaddset(&signals, SIGHUP); | |||
sigaddset(&signals, SIGINT); | |||
sigaddset(&signals, SIGQUIT); | |||
sigaddset(&signals, SIGILL); | |||
sigaddset(&signals, SIGTRAP); | |||
sigaddset(&signals, SIGABRT); | |||
sigaddset(&signals, SIGIOT); | |||
sigaddset(&signals, SIGFPE); | |||
sigaddset(&signals, SIGPIPE); | |||
sigaddset(&signals, SIGTERM); | |||
sigaddset(&signals, SIGUSR1); | |||
/* this can make debugging a pain, but it also makes | |||
segv-exits cleanup_files after themselves rather than | |||
leaving the audio thread active. i still | |||
find it truly wierd that _exit() or whatever is done | |||
by the default SIGSEGV handler does not | |||
cancel all threads in a process, but what | |||
else can we do? | |||
*/ | |||
sigaddset(&signals, SIGSEGV); | |||
/* all child threads will inherit this mask */ | |||
pthread_sigmask (SIG_BLOCK, &signals, 0); | |||
} | |||
static void * | |||
jack_engine_waiter_thread (void *arg) | |||
{ | |||
waiter_arg_t *warg = (waiter_arg_t *) arg; | |||
jack_driver_t *driver; | |||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | |||
if ((engine = jack_engine_new (realtime, realtime_priority, verbose)) == 0) { | |||
fprintf (stderr, "cannot create engine\n"); | |||
kill (warg->pid, SIGTERM); | |||
return 0; | |||
} | |||
if (warg->argc) { | |||
if ((driver = jack_driver_load (warg->argc, warg->argv)) == 0) { | |||
fprintf (stderr, "cannot load driver module %s\n", warg->argv[0]); | |||
kill (warg->pid, SIGTERM); | |||
return 0; | |||
} | |||
jack_use_driver (engine, driver); | |||
} | |||
if (asio_mode) { | |||
jack_set_asio_mode (engine, TRUE); | |||
} | |||
if (jack_run (engine)) { | |||
fprintf (stderr, "cannot start main JACK thread\n"); | |||
kill (warg->pid, SIGTERM); | |||
return 0; | |||
} | |||
jack_wait (engine); | |||
fprintf (stderr, "telling signal thread that the engine is done\n"); | |||
kill (warg->pid, SIGHUP); | |||
return 0; /* nobody cares what this returns */ | |||
} | |||
static void | |||
jack_main (int argc, char **argv) | |||
{ | |||
int sig; | |||
pthread_t waiter_thread; | |||
waiter_arg_t warg; | |||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | |||
posix_me_harder (); | |||
/* what we'd really like to do here is to be able to | |||
wait for either the engine to stop or a POSIX signal, | |||
whichever arrives sooner. but there is no mechanism | |||
to do that, so instead we create a thread to wait | |||
for the engine to finish, and here we stop and wait | |||
for any (reasonably likely) POSIX signal. | |||
if the engine finishes first, the waiter thread will | |||
tell us about it via a signal. | |||
if a signal arrives, we'll stop the engine and then | |||
exit. | |||
in normal operation, our parent process will be waiting | |||
for us and will cleanup. | |||
*/ | |||
warg.pid = getpid(); | |||
warg.argc = argc; | |||
warg.argv = argv; | |||
if (pthread_create (&waiter_thread, 0, jack_engine_waiter_thread, &warg)) { | |||
fprintf (stderr, "jackd: cannot create engine waiting thread\n"); | |||
return; | |||
} | |||
/* Note: normal operation has with_fork == 1 */ | |||
if (with_fork) { | |||
/* let the parent handle SIGINT */ | |||
sigdelset (&signals, SIGINT); | |||
} | |||
if (verbose) { | |||
fprintf (stderr, "%d waiting for signals\n", getpid()); | |||
} | |||
while(1) { | |||
sigwait (&signals, &sig); | |||
printf ("jack main caught signal %d\n", sig); | |||
if (sig == SIGUSR1) { | |||
jack_dump_configuration(engine, 1); | |||
} else { | |||
/* continue to kill engine */ | |||
break; | |||
} | |||
} | |||
pthread_cancel (waiter_thread); | |||
jack_engine_delete (engine); | |||
return; | |||
} | |||
static void usage () | |||
{ | |||
fprintf (stderr, "\ | |||
usage: jackd [ --asio OR -a ] | |||
[ --realtime OR -R [ --realtime-priority OR -P priority ] ] | |||
[ --verbose OR -v ] | |||
[ --getcap OR -g capability-program-name ] | |||
[ --tmpdir OR -D directory-for-temporary-files ] | |||
-d driver [ ... driver args ... ] | |||
"); | |||
} | |||
int | |||
main (int argc, char *argv[]) | |||
{ | |||
const char *options = "ad:D:P:vhRFl:"; | |||
struct option long_options[] = | |||
{ | |||
{ "asio", 0, 0, 'a' }, | |||
{ "driver", 1, 0, 'd' }, | |||
{ "tmpdir", 1, 0, 'D' }, | |||
{ "getcap", 1, 0, 'g' }, | |||
{ "verbose", 0, 0, 'v' }, | |||
{ "help", 0, 0, 'h' }, | |||
{ "realtime", 0, 0, 'R' }, | |||
{ "realtime-priority", 1, 0, 'P' }, | |||
{ "spoon", 0, 0, 'F' }, | |||
{ 0, 0, 0, 0 } | |||
}; | |||
int option_index; | |||
int opt; | |||
int seen_driver = 0; | |||
char *driver_name = 0; | |||
char *getcap_name = 0; | |||
char **driver_args = 0; | |||
int driver_nargs = 1; | |||
int i; | |||
opterr = 0; | |||
while (!seen_driver && (opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | |||
switch (opt) { | |||
case 'a': | |||
asio_mode = TRUE; | |||
break; | |||
case 'D': | |||
jack_set_temp_dir (optarg); | |||
break; | |||
case 'd': | |||
seen_driver = 1; | |||
driver_name = optarg; | |||
break; | |||
case 'g': | |||
getcap_name = optarg; | |||
break; | |||
case 'v': | |||
verbose = 1; | |||
break; | |||
case 'F': | |||
with_fork = 0; | |||
break; | |||
case 'P': | |||
realtime_priority = atoi (optarg); | |||
break; | |||
case 'R': | |||
realtime = 1; | |||
break; | |||
default: | |||
fprintf (stderr, "unknown option character %c\n", optopt); | |||
/*fallthru*/ | |||
case 'h': | |||
usage(); | |||
return -1; | |||
} | |||
} | |||
if (!seen_driver) { | |||
usage (); | |||
exit (1); | |||
} | |||
if (optind < argc) { | |||
driver_nargs = 1 + argc - optind; | |||
} else { | |||
driver_nargs = 1; | |||
} | |||
driver_args = (char **) malloc (sizeof (char *) * driver_nargs); | |||
driver_args[0] = driver_name; | |||
for (i = 1; i < driver_nargs; i++) { | |||
driver_args[i] = argv[optind++]; | |||
} | |||
printf ( "jackd " VERSION "\n" | |||
"Copyright 2001-2002 Paul Davis and others.\n" | |||
"jackd comes with ABSOLUTELY NO WARRANTY\n" | |||
"This is free software, and you are welcome to redistribute it\n" | |||
"under certain conditions; see the file COPYING for details\n\n"); | |||
/* get real-time capabilities for this process, we should check for errors */ | |||
if (getcap_name) system (getcap_name); | |||
if (!with_fork) { | |||
/* This is really here so that we can run gdb easily */ | |||
jack_main (driver_nargs, driver_args); | |||
} else { | |||
int pid = fork (); | |||
if (pid < 0) { | |||
fprintf (stderr, "could not fork jack server (%s)", strerror (errno)); | |||
exit (1); | |||
} else if (pid == 0) { | |||
jack_main (driver_nargs, driver_args); | |||
} else { | |||
jackd_pid = pid; | |||
signal (SIGHUP, signal_handler); | |||
signal (SIGINT, signal_handler); | |||
signal (SIGQUIT, signal_handler); | |||
signal (SIGTERM, signal_handler); | |||
waitpid (pid, NULL, 0); | |||
} | |||
} | |||
jack_cleanup_shm (); | |||
jack_cleanup_files (); | |||
return 0; | |||
} |
@@ -1,459 +0,0 @@ | |||
/* | |||
Copyright (C) 2000 Paul Davis | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
$Id$ | |||
*/ | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <math.h> | |||
#include <memory.h> | |||
#include <stdlib.h> | |||
#include <limits.h> | |||
#include <jack/memops.h> | |||
#define SAMPLE_MAX_24BIT 8388607.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. | |||
*/ | |||
void sample_move_d32u24_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) << 8; | |||
if (y > INT_MAX) { | |||
*((int *) dst) = INT_MAX; | |||
} else if (y < INT_MIN) { | |||
*((int *) dst) = INT_MIN; | |||
} else { | |||
*((int *) dst) = (int)y; | |||
} | |||
dst += dst_skip; | |||
src++; | |||
} | |||
} | |||
void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) | |||
{ | |||
/* ALERT: signed sign-extension portability !!! */ | |||
while (nsamples--) { | |||
*dst = (*((int *) src) >> 8) / SAMPLE_MAX_24BIT; | |||
dst++; | |||
src += src_skip; | |||
} | |||
} | |||
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) | |||
{ | |||
/* ALERT: signed sign-extension portability !!! */ | |||
jack_default_audio_sample_t x; | |||
long long y; | |||
while (nsamples--) { | |||
x = *src * SAMPLE_MAX_16BIT; | |||
x -= (float)rand() / (float)RAND_MAX; | |||
y = (long long)f_round(x); | |||
y <<= 16; | |||
if (y > INT_MAX) { | |||
*((int *) dst) = INT_MAX; | |||
} else if (y < INT_MIN) { | |||
*((int *) dst) = INT_MIN; | |||
} else { | |||
*((int *) dst) = (int)y; | |||
} | |||
dst += dst_skip; | |||
src++; | |||
} | |||
} | |||
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) | |||
{ | |||
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)rand() / (float)RAND_MAX - 1.0f; | |||
x += r - rm1; | |||
rm1 = r; | |||
/* swh: This could be some inline asm on x86 */ | |||
y = (long long)f_round(x); | |||
y <<= 16; | |||
if (y > INT_MAX) { | |||
*((int *) dst) = INT_MAX; | |||
} else if (y < INT_MIN) { | |||
*((int *) dst) = INT_MIN; | |||
} else { | |||
*((int *) dst) = (int)y; | |||
} | |||
dst += dst_skip; | |||
src++; | |||
} | |||
state->rm1 = rm1; | |||
} | |||
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) | |||
{ | |||
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)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 = (long long)f_round(xp); | |||
/* Intrinsic z^-1 delay */ | |||
idx = (idx + 1) & DITHER_BUF_MASK; | |||
state->e[idx] = y - xe; | |||
y <<= 16; | |||
if (y > INT_MAX) { | |||
*((int *) dst) = INT_MAX; | |||
} else if (y < INT_MIN) { | |||
*((int *) dst) = INT_MIN; | |||
} else { | |||
*((int *) dst) = (int)y; | |||
} | |||
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) | |||
{ | |||
jack_default_audio_sample_t val; | |||
/* ALERT: signed sign-extension portability !!! */ | |||
/* XXX good to use x86 assembler here, since float->short | |||
sucks that h/w. | |||
*/ | |||
while (nsamples--) { | |||
val = *src; | |||
if (val > 1.0f) { | |||
*((short *)dst) = SHRT_MAX; | |||
} else if (val < -1.0f) { | |||
*((short *)dst) = SHRT_MIN; | |||
} else { | |||
*((short *) dst) = (short) (val * SAMPLE_MAX_16BIT); | |||
} | |||
dst += dst_skip; | |||
src++; | |||
} | |||
} | |||
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) | |||
{ | |||
jack_default_audio_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_dither_tri_d16_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; | |||
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, 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; | |||
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 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) | |||
{ | |||
/* ALERT: signed sign-extension portability !!! */ | |||
while (nsamples--) { | |||
*dst = (*((short *) src)) / SAMPLE_MAX_16BIT; | |||
dst++; | |||
src += 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) | |||
{ | |||
short val; | |||
/* ALERT: signed sign-extension portability !!! */ | |||
while (nsamples--) { | |||
val = (short) (*src * SAMPLE_MAX_16BIT); | |||
if (val > SHRT_MAX - *((short *) dst)) { | |||
*((short *)dst) = SHRT_MAX; | |||
} else if (val < SHRT_MIN - *((short *) dst)) { | |||
*((short *)dst) = SHRT_MIN; | |||
} else { | |||
*((short *) dst) += val; | |||
} | |||
dst += dst_skip; | |||
src++; | |||
} | |||
} | |||
void sample_merge_d32u24_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 !!! */ | |||
while (nsamples--) { | |||
*((int *) dst) += (((int) (*src * SAMPLE_MAX_24BIT)) << 8); | |||
dst += dst_skip; | |||
src++; | |||
} | |||
} | |||
void memset_interleave (char *dst, char val, unsigned long bytes, | |||
unsigned long unit_bytes, | |||
unsigned long skip_bytes) | |||
{ | |||
switch (unit_bytes) { | |||
case 1: | |||
while (bytes--) { | |||
*dst = val; | |||
dst += skip_bytes; | |||
} | |||
break; | |||
case 2: | |||
while (bytes) { | |||
*((short *) dst) = (short) val; | |||
dst += skip_bytes; | |||
bytes -= 2; | |||
} | |||
break; | |||
case 4: | |||
while (bytes) { | |||
*((int *) dst) = (int) val; | |||
dst += skip_bytes; | |||
bytes -= 4; | |||
} | |||
break; | |||
} | |||
} | |||
/* COPY FUNCTIONS: used to move data from an input channel to an | |||
output channel. Note that we assume that the skip distance | |||
is the same for both channels. This is completely fine | |||
unless the input and output were on different audio interfaces that | |||
were interleaved differently. We don't try to handle that. | |||
*/ | |||
void | |||
memcpy_fake (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar) | |||
{ | |||
memcpy (dst, src, src_bytes); | |||
} | |||
void | |||
merge_memcpy_d16_s16 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
{ | |||
while (src_bytes) { | |||
*((short *) dst) += *((short *) src); | |||
dst += 2; | |||
src += 2; | |||
src_bytes -= 2; | |||
} | |||
} | |||
void | |||
merge_memcpy_d32_s32 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
{ | |||
while (src_bytes) { | |||
*((int *) dst) += *((int *) src); | |||
dst += 4; | |||
src += 4; | |||
src_bytes -= 4; | |||
} | |||
} | |||
void | |||
merge_memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
{ | |||
while (src_bytes) { | |||
*((short *) dst) += *((short *) src); | |||
dst += dst_skip_bytes; | |||
src += src_skip_bytes; | |||
src_bytes -= 2; | |||
} | |||
} | |||
void | |||
merge_memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
{ | |||
while (src_bytes) { | |||
*((int *) dst) += *((int *) src); | |||
dst += dst_skip_bytes; | |||
src += src_skip_bytes; | |||
src_bytes -= 4; | |||
} | |||
} | |||
void | |||
memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
{ | |||
while (src_bytes) { | |||
*((short *) dst) = *((short *) src); | |||
dst += dst_skip_bytes; | |||
src += src_skip_bytes; | |||
src_bytes -= 2; | |||
} | |||
} | |||
void | |||
memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, | |||
unsigned long dst_skip_bytes, unsigned long src_skip_bytes) | |||
{ | |||
while (src_bytes) { | |||
*((int *) dst) = *((int *) src); | |||
dst += dst_skip_bytes; | |||
src += src_skip_bytes; | |||
src_bytes -= 4; | |||
} | |||
} |
@@ -1,30 +0,0 @@ | |||
#include <stdio.h> | |||
#include <unistd.h> | |||
#include <jack/jack.h> | |||
#define TRUE 1 | |||
#define FALSE 0 | |||
int | |||
main (int argc, char *argv[]) | |||
{ | |||
jack_client_t *client; | |||
if ((client = jack_client_new ("input monitoring")) == 0) { | |||
fprintf (stderr, "jack server not running?\n"); | |||
return 1; | |||
} | |||
if (jack_port_request_monitor_by_name (client, "alsa_pcm:in_1", TRUE)) { | |||
fprintf (stderr, "could not enable monitoring for in_1\n"); | |||
} | |||
sleep (30); | |||
if (jack_port_request_monitor_by_name (client, "alsa_pcm:in_1", FALSE)) { | |||
fprintf (stderr, "could not disable monitoring for in_1\n"); | |||
} | |||
jack_client_close (client); | |||
exit (0); | |||
} | |||
@@ -1,37 +0,0 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
$Id$ | |||
*/ | |||
#include <stdlib.h> | |||
#include <jack/pool.h> | |||
void * | |||
jack_pool_alloc (size_t bytes) | |||
{ | |||
/* XXX need RT-pool based allocator here */ | |||
return malloc (bytes); | |||
} | |||
void | |||
jack_pool_release (void *ptr) | |||
{ | |||
free (ptr); | |||
} |
@@ -1,128 +0,0 @@ | |||
#include <stdio.h> | |||
#include <errno.h> | |||
#include <unistd.h> | |||
#include <jack/jack.h> | |||
jack_port_t *input_port; | |||
jack_port_t *output_port; | |||
int | |||
process (jack_nframes_t nframes, void *arg) | |||
{ | |||
jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes); | |||
jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (input_port, nframes); | |||
memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes); | |||
return 0; | |||
} | |||
int | |||
bufsize (jack_nframes_t nframes, void *arg) | |||
{ | |||
printf ("the maximum buffer size is now %lu\n", nframes); | |||
return 0; | |||
} | |||
int | |||
srate (jack_nframes_t nframes, void *arg) | |||
{ | |||
printf ("the sample rate is now %lu/sec\n", nframes); | |||
return 0; | |||
} | |||
void | |||
jack_shutdown (void *arg) | |||
{ | |||
exit (1); | |||
} | |||
int | |||
main (int argc, char *argv[]) | |||
{ | |||
jack_client_t *client; | |||
if (argc < 2) { | |||
fprintf (stderr, "usage: jack_simple_client <name>\n"); | |||
return 1; | |||
} | |||
/* try to become a client of the JACK server */ | |||
if ((client = jack_client_new (argv[1])) == 0) { | |||
fprintf (stderr, "jack server not running?\n"); | |||
return 1; | |||
} | |||
/* tell the JACK server to call `process()' whenever | |||
there is work to be done. | |||
*/ | |||
jack_set_process_callback (client, process, 0); | |||
/* tell the JACK server to call `bufsize()' whenever | |||
the maximum number of frames that will be passed | |||
to `process()' changes | |||
*/ | |||
jack_set_buffer_size_callback (client, bufsize, 0); | |||
/* tell the JACK server to call `srate()' whenever | |||
the sample rate of the system changes. | |||
*/ | |||
jack_set_sample_rate_callback (client, srate, 0); | |||
/* tell the JACK server to call `jack_shutdown()' if | |||
it ever shuts down, either entirely, or if it | |||
just decides to stop calling us. | |||
*/ | |||
jack_on_shutdown (client, jack_shutdown, 0); | |||
/* display the current sample rate. once the client is activated | |||
(see below), you should rely on your own sample rate | |||
callback (see above) for this value. | |||
*/ | |||
printf ("engine sample rate: %lu\n", jack_get_sample_rate (client)); | |||
/* create two ports */ | |||
input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
/* tell the JACK server that we are ready to roll */ | |||
if (jack_activate (client)) { | |||
fprintf (stderr, "cannot activate client"); | |||
return 1; | |||
} | |||
/* connect the ports. Note: you can't do this before | |||
the client is activated, because we can't allow | |||
connections to be made to clients that aren't | |||
running. | |||
*/ | |||
if (jack_connect (client, "alsa_pcm:in_1", jack_port_name (input_port))) { | |||
fprintf (stderr, "cannot connect input ports\n"); | |||
} | |||
if (jack_connect (client, jack_port_name (output_port), "alsa_pcm:out_1")) { | |||
fprintf (stderr, "cannot connect output ports\n"); | |||
} | |||
/* Since this is just a toy, run for a few seconds, then finish */ | |||
sleep (10); | |||
jack_client_close (client); | |||
exit (0); | |||
} | |||