Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Integrated "autorecord" patch from Adam Sampson

  • Loading branch information...
commit 0bddb47e2a1d6585a5b80f6775007e3808cb142c 1 parent a94a087
@garlik garlik authored
View
37 src/main.c
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2004 Steve Harris
+ * Copyright (C) 2006 Garett Shulman
+ * Copyright (C) 2009 Adam Sampson
*
* 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
@@ -49,8 +51,6 @@ lash_client_t *lash_client;
#include "support.h"
#include "main.h"
-#define DEFAULT_BUF_LENGTH 10 /* in seconds */
-
#define DEBUG(lvl, txt...) \
if (verbosity >= lvl) fprintf(stderr, PACKAGE ": " txt)
@@ -69,6 +69,10 @@ char *prefix = DEFAULT_PREFIX;
char *format_name = DEFAULT_FORMAT;
int format_sf = 0;
int safe_filename = 0;
+int auto_record = 0;
+float auto_begin_threshold = 0.0;
+float auto_end_threshold = 0.0;
+unsigned int auto_end_time = DEFAULT_AUTO_END_TIME;
jack_port_t *ports[MAX_PORTS];
jack_client_t *client;
@@ -96,7 +100,10 @@ int main(int argc, char *argv[])
lash_event_t *event;
#endif
- while ((opt = getopt(argc, argv, "hic:t:n:p:f:s")) != -1) {
+ auto_begin_threshold = db2lin(DEFAULT_AUTO_BEGIN_THRESHOLD);
+ auto_end_threshold = db2lin(DEFAULT_AUTO_END_THRESHOLD);
+
+ while ((opt = getopt(argc, argv, "hic:t:n:p:f:sab:e:T:")) != -1) {
switch (opt) {
case 'h':
help = 1;
@@ -126,6 +133,18 @@ int main(int argc, char *argv[])
case 's':
safe_filename = 1;
break;
+ case 'a':
+ auto_record = 1;
+ break;
+ case 'b':
+ auto_begin_threshold = db2lin(atof(optarg));
+ break;
+ case 'e':
+ auto_end_threshold = db2lin(atof(optarg));
+ break;
+ case 'T':
+ auto_end_time = atoi(optarg);
+ break;
default:
num_ports = 0;
break;
@@ -138,7 +157,8 @@ int main(int argc, char *argv[])
if (num_ports < 1 || num_ports > MAX_PORTS || help) {
fprintf(stderr, "Usage %s: [-h] [-i] [-c channels] [-n jack-name]\n\t"
- "[-t buffer-length] [-p file prefix] [-f format] "
+ "[-t buffer-length] [-p file prefix] [-f format]\n\t"
+ "[-a] [-b begin-threshold] [-e end-threshold] [-T end-time]\n\t"
"[port-name ...]\n\n", argv[0]);
fprintf(stderr, "\t-h\tshow this help\n");
fprintf(stderr, "\t-i\tinteractive mode (console instead of X11) also enabled\n\t\tif DISPLAY is unset\n");
@@ -148,6 +168,10 @@ int main(int argc, char *argv[])
fprintf(stderr, "\t-p\tspecify the saved file prefix, may include path\n");
fprintf(stderr, "\t-s\tuse safer characters in filename (windows compatibility)\n");
fprintf(stderr, "\t-f\tspecify the saved file format\n");
+ fprintf(stderr, "\t-a\tenable automatic sound-triggered recording\n");
+ fprintf(stderr, "\t-b\tspecify threshold above which automatic recording will begin\n");
+ fprintf(stderr, "\t-e\tspecify threshold below which automatic recording will end\n");
+ fprintf(stderr, "\t-T\tspecify silence length before automatic recording ends\n");
fprintf(stderr, "\n");
fprintf(stderr, "\tchannels must be in the range 1-8, default %d\n",
DEFAULT_NUM_PORTS);
@@ -155,6 +179,9 @@ int main(int argc, char *argv[])
fprintf(stderr, "\tfile-prefix, default \"%s\"\n", DEFAULT_PREFIX);
fprintf(stderr, "\tbuffer-length, default %d secs\n", DEFAULT_BUF_LENGTH);
fprintf(stderr, "\tformat, default '%s', options: wav, w64\n", DEFAULT_FORMAT);
+ fprintf(stderr, "\tbegin-threshold, default %.1f dB\n", DEFAULT_AUTO_BEGIN_THRESHOLD);
+ fprintf(stderr, "\tend-threshold, default %.1f dB\n", DEFAULT_AUTO_END_THRESHOLD);
+ fprintf(stderr, "\tend-time, default %d secs\n", DEFAULT_AUTO_END_TIME);
fprintf(stderr, "\n");
fprintf(stderr, "specifying port names to connect to on the command line overrides -c\n\n");
exit(1);
@@ -170,7 +197,7 @@ int main(int argc, char *argv[])
#endif
if (format_sf == 0) {
- fprintf(stderr, "Unkown format '%s'\n", format_name);
+ fprintf(stderr, "Unknown format '%s'\n", format_name);
}
/* Register with jack */
View
9 src/main.h
@@ -9,6 +9,7 @@
#define MAX_PORTS 8
#define MAX_TIME 3600
+#define DEFAULT_BUF_LENGTH 10 /* in seconds */
#define DEFAULT_NUM_PORTS 2
#define DEFAULT_CLIENT_NAME "TimeMachine"
#define DEFAULT_PREFIX "tm-"
@@ -21,6 +22,10 @@
#define OSC_PORT "7133"
+#define DEFAULT_AUTO_BEGIN_THRESHOLD -35.0
+#define DEFAULT_AUTO_END_THRESHOLD DEFAULT_AUTO_BEGIN_THRESHOLD
+#define DEFAULT_AUTO_END_TIME DEFAULT_BUF_LENGTH
+
extern GtkWidget *main_window;
extern GdkPixbuf *img_on, *img_off, *img_busy;
@@ -31,6 +36,10 @@ extern char *prefix;
extern char *format_name;
extern int format_sf;
extern int safe_filename;
+extern int auto_record;
+extern float auto_begin_threshold;
+extern float auto_end_threshold;
+extern unsigned int auto_end_time;
extern jack_client_t *client;
extern jack_port_t *ports[MAX_PORTS];
View
2  src/meters.c
@@ -24,8 +24,8 @@
#include "gtkmeter.h"
#include "threads.h"
#include "support.h"
+#include "meters.h"
-#define lin2db(lin) (20.0f * log10(lin))
static GtkAdjustment *meter_adj[MAX_PORTS];
void bind_meters()
View
7 src/meters.h
@@ -1,8 +1,11 @@
#ifndef METERS_H
#define METERS_H
-void bind_meters();
+#define lin2db(lin) (20.0f * log10(lin))
+#define db2lin(db) (pow(10, db / 20.0f))
-void update_meters(volatile float amp[]);
+void bind_meters(void);
+
+void update_meters(float amp[]);
#endif
View
53 src/threads.c
@@ -36,9 +36,10 @@ float *pre_buffer[MAX_PORTS];
float *disk_buffer[MAX_PORTS];
static int recording = 0; /* recording yes/no */
+static int user_recording = 0; /* recording initiated by user yes/no */
static int quiting = 0; /* quit pending yes/no */
-volatile int recording_done = 0; /* quit pending yes/no */
-volatile int syncing_done = 0; /* finsihed writing pre-buffer */
+volatile int recording_done = 0; /* recording completed after quit */
+volatile int need_ui_sync = 0; /* need to update record button */
static unsigned int pre_time = 0;
static unsigned int pre_size = 0;
@@ -49,10 +50,13 @@ static unsigned int disk_write_pos = 0;
/* Peak data for meters */
static volatile float peak[MAX_PORTS];
+static unsigned int silent_count = 0;
+
int process(jack_nframes_t nframes, void *arg)
{
unsigned int i, port, pos = 0;
const unsigned int rec = recording;
+ const jack_nframes_t sample_rate = jack_get_sample_rate(client);
for (port = 0; port < num_ports; port++) {
jack_default_audio_sample_t *in;
@@ -70,6 +74,29 @@ int process(jack_nframes_t nframes, void *arg)
break;
}
+ if (auto_record) {
+ if (rec && !user_recording) {
+ for (i = 0; i < nframes; i++) {
+ if (fabsf(in[i]) <= auto_end_threshold) {
+ silent_count++;
+ } else {
+ silent_count = 0;
+ }
+ }
+ if (silent_count > (auto_end_time * sample_rate * num_ports)) {
+ recording = 0;
+ }
+ } else {
+ for (i = 0; i < nframes; i++) {
+ if (fabsf(in[i]) > auto_begin_threshold) {
+ recording = 1;
+ silent_count = 0;
+ break;
+ }
+ }
+ }
+ }
+
for (i = 0; i < nframes; i++) {
if (fabsf(in[i]) > peak[port]) {
peak[port] = fabsf(in[i]);
@@ -176,7 +203,7 @@ int writer_thread(void *d)
}
/* This tells the UI that were ready to go again, it will reset it */
- syncing_done = 1;
+ need_ui_sync = 1;
if (recording) printf("writing realtime data...\n");
@@ -196,6 +223,8 @@ int writer_thread(void *d)
}
sf_close(out);
+ need_ui_sync = 1;
+
printf("done writing...\n");
/* Just make sure everythings reset */
@@ -217,7 +246,8 @@ void process_init(unsigned int time)
fprintf(stderr, "timemachine: buffer time must be 1 second or "
"greater\n");
exit(1);
- } if (time > MAX_TIME) {
+ }
+ if (time > MAX_TIME) {
fprintf(stderr, "timemachine: buffer time must be %d seconds or "
"less\nthis is for your own good, it really will not"
"work well with buffers that size\n", MAX_TIME);
@@ -241,11 +271,13 @@ void process_init(unsigned int time)
void recording_start()
{
recording = 1;
+ user_recording = 1;
}
void recording_stop()
{
recording = 0;
+ user_recording = 0;
}
void recording_quit()
@@ -259,12 +291,19 @@ gboolean meter_tick(gpointer user_data)
float data[MAX_PORTS];
unsigned int i;
- if (syncing_done && !recording) {
+ if (need_ui_sync) {
GtkWidget *img = lookup_widget(main_window, "toggle_image");
- syncing_done = 0;
- gtk_image_set_from_pixbuf(GTK_IMAGE(img), img_off);
+ if (recording) {
+ gtk_image_set_from_pixbuf(GTK_IMAGE(img), img_on);
+ gtk_window_set_icon(GTK_WINDOW(main_window), icon_on);
+ } else {
+ gtk_image_set_from_pixbuf(GTK_IMAGE(img), img_off);
+ gtk_window_set_icon(GTK_WINDOW(main_window), icon_off);
+ }
gtk_widget_set_sensitive(img, TRUE);
+
+ need_ui_sync = 0;
}
for (i=0; i<MAX_PORTS; i++) {
Please sign in to comment.
Something went wrong with that request. Please try again.