[linux-audio-dev] timemachine auto recorder patch

From: Garett Shulman <shulmang@email-addr-hidden>
Date: Sat Jan 14 2006 - 21:41:33 EET

Hello, I have created a patch that allows timeachine to automatically
start and stop recording based on the audio signal. Recording will start
when a sample value exceeds a start threashold. Recording stops when
sample values remain below a stop threashold for a period of time.
Recording of a new file will then start again when a sample value again
exceeds the start threashold. These values as well as enabeling auto
recording can all be set at the command line.

With this functionallity I would like to be able to launch timemachine
backgrounded.
Eg: timemachine args &
I would also need to be able to send the process SIGINT and SIGTERM
signals and have it exit gracefully. I have attempted to add the
necessary handlers for this.

However if I try to start timemachine backgrounded it just seems to exit
and brings jack down with it. If I run it in the foreground and try to
killall timemachine it does not exit gracefully but brings jack down as
well. In either case I see output from jack like:

subgraph starting at time timed out (subgraph_wait_fd = 7, status = 0,
state = Triggered)
jackd watchdog: timeout - killed jack
[1]+ Killed timemachine

Any suggestions or ideas are greatly appreciated. Also, the auto
recorder functionallity works great asside from the backgrounding and
SIGTERM business.

Thanks!
-Garett

PATCH FOLLOWS
diff -urN timemachine-0.3.1/src/main.c
timemachine-0.3.1.autorecord/src/main.c
--- timemachine-0.3.1/src/main.c 2005-09-19 03:41:30.000000000 -0600
+++ timemachine-0.3.1.autorecord/src/main.c 2006-01-14
11:24:13.000000000 -0700
@@ -28,6 +28,10 @@
#include <sndfile.h>
#include <gtk/gtk.h>
 
+/* garetts mod here */
+#include <signal.h>
+/* end garetts mod */
+
#ifdef HAVE_LASH
#include <lash/lash.h>
 
@@ -71,6 +75,10 @@
GdkPixbuf *img_on, *img_off, *img_busy;
GdkPixbuf *icon_on, *icon_off;
 
+/* garetts mod here */
+void signal_handler(int signal);
+/* end garetts mod */
+
int main(int argc, char *argv[])
{
    unsigned int i;
@@ -78,13 +86,22 @@
    int help = 0;
    int console = 0;
    char port_name[32];
+ /* garetts mod here */
+ int AUTO_RECORD = 0;
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+ float SECONDS_OF_SILENCE_BEFORE_STOP = 5;
+ float START_THREASHOLD = 0.000005;
+ float STOP_THREASHOLD = 0;
+ /* end garetts mod */
+
    pthread_t dt;
#ifdef HAVE_LASH
    lash_args_t *lash_args = lash_extract_args(&argc, &argv);
     lash_event_t *event;
#endif
 
- while ((opt = getopt(argc, argv, "hic:t:n:p:f:")) != -1) {
+ while ((opt = getopt(argc, argv, "hic:t:n:p:f:q:w:e:r")) != -1) {
 switch (opt) {
 case 'h':
     help = 1;
@@ -111,6 +128,20 @@
 case 'f':
     format_name = optarg;
     break;
+ /* garetts mod here */
+ case 'q':
+ SECONDS_OF_SILENCE_BEFORE_STOP = atof(optarg);
+ break;
+ case 'w':
+ START_THREASHOLD = atof(optarg);
+ break;
+ case 'e':
+ STOP_THREASHOLD = atof(optarg);
+ break;
+ case 'r':
+ AUTO_RECORD = 1;
+ break;
+ /* end garetts mod */
 default:
     num_ports = 0;
     break;
@@ -132,6 +163,9 @@
 fprintf(stderr, "\t-t\tspecify the pre-recording buffer length\n");
 fprintf(stderr, "\t-p\tspecify the saved file prefix, may include
path\n");
 fprintf(stderr, "\t-f\tspecify the saved file format\n");
+ fprintf(stderr, "\t-q\tspecify the seconds of silence before stop\n");
+ fprintf(stderr, "\t-w\tspecify the start threashold\n");
+ fprintf(stderr, "\t-e\tspecify the stop threashold\n");
 fprintf(stderr, "\n");
 fprintf(stderr, "\tchannels must be in the range 1-8, default %d\n",
   DEFAULT_NUM_PORTS);
@@ -164,7 +198,10 @@
    }
    DEBUG(1, "registering as %s\n", client_name);
 
- process_init(buf_length);
+ /* garetts mod here
+ * process_init(buf_length)
+ */
+ process_init(buf_length, SECONDS_OF_SILENCE_BEFORE_STOP,
START_THREASHOLD, STOP_THREASHOLD, AUTO_RECORD);
 
#ifdef HAVE_LASH
    lash_client = lash_init (lash_args, "TimeMachine",
@@ -287,6 +324,11 @@
    exit(0);
}
 
+void signal_handler(int iSignal) {
+ recording_stop();
+ cleanup();
+}
+
#ifdef HAVE_LASH
gboolean idle_cb(gpointer data)
{
diff -urN timemachine-0.3.1/src/threads.c
timemachine-0.3.1.autorecord/src/threads.c
--- timemachine-0.3.1/src/threads.c 2005-07-18 08:03:06.000000000 -0600
+++ timemachine-0.3.1.autorecord/src/threads.c 2006-01-14
10:58:18.000000000 -0700
@@ -19,7 +19,7 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
-#include <time.h>
+#include <sys/time.h>
#include <sndfile.h>
#include <jack/jack.h>
#include <gtk/gtk.h>
@@ -46,6 +46,15 @@
static unsigned int disk_read_pos = 0;
static unsigned int disk_write_pos = 0;
 
+/* garetts mod here */
+static float seconds_of_silence_before_stop = 0;
+static float start_threashold = 0;
+static float stop_threashold = 0;
+static float seconds_of_silence = 0;
+static int sample_rate = 0;
+static int autorecord = 0;
+/* end garetts mod */
+
/* Peak data for meters */
static volatile float peak[MAX_PORTS];
 
@@ -69,6 +78,32 @@
     fprintf(stderr, "bad buffer!\n");
     break;
 }
+
+ /* garetts mod here */
+ if (autorecord) {
+ if (rec) {
+ for (i = 0; i < nframes; i++) {
+ if (fabsf(in[i]) <= stop_threashold) {
+ seconds_of_silence = seconds_of_silence + 1.0/sample_rate;
+ }
+ else {
+ seconds_of_silence = 0;
+ }
+ if (seconds_of_silence > seconds_of_silence_before_stop) {
+ recording_stop();
+ }
+ }
+ }
+ else {
+ for (i = 0; i < nframes; i++) {
+ if (fabsf(in[i]) > start_threashold) {
+ recording_start();
+ break;
+ }
+ }
+ }
+ }
+ /* end garetts mod */
 
 for (i = 0; i < nframes; i++) {
     if (fabsf(in[i]) > peak[port]) {
@@ -202,7 +236,10 @@
    return 0;
}
 
-void process_init(unsigned int time)
+/* garetts mod here
+ * void process_init(unsigned int time)
+ */
+void process_init(unsigned int time, float secs_of_silence_before_stop,
float strt_threashold, float stp_threashold, int use_autorecord)
{
    unsigned int port;
 
@@ -220,6 +257,14 @@
    pre_size = time * jack_get_sample_rate(client);
    pre_time = time;
 
+ /* garetts mod here */
+ seconds_of_silence_before_stop = secs_of_silence_before_stop;
+ start_threashold = strt_threashold;
+ stop_threashold = stp_threashold;
+ sample_rate = jack_get_sample_rate(client);
+ autorecord = use_autorecord;
+ /* end garetts mod */
+
    for (port = 0; port < num_ports; port++) {
 pre_buffer[port] = calloc(pre_size, sizeof(float));
 disk_buffer[port] = calloc(DISK_SIZE, sizeof(float));
diff -urN timemachine-0.3.1/src/threads.h
timemachine-0.3.1.autorecord/src/threads.h
--- timemachine-0.3.1/src/threads.h 2005-07-18 08:03:06.000000000 -0600
+++ timemachine-0.3.1.autorecord/src/threads.h 2006-01-14
10:56:37.000000000 -0700
@@ -9,7 +9,10 @@
 
int process(jack_nframes_t nframes, void *arg);
 
-void process_init(unsigned int time);
+/* garetts mod here
+ * void process_init(unsigned int time)
+ */
+void process_init(unsigned int time, float secs_of_silence_before_stop,
float strt_threashold, float stp_threashold, int use_autorecord);
 
int writer_thread(void *d);
 
Received on Sun Jan 15 00:15:05 2006

This archive was generated by hypermail 2.1.8 : Sun Jan 15 2006 - 00:15:05 EET