summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2009-01-10 20:02:29 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2009-01-10 20:02:29 +0000
commit52950e81d47e2f55bc1e7ea44d1d5afad457e4ba (patch)
tree9c14fc3059518f81d40e6c36fc75c0a353b01126
parent77353b43cbc8c402ffa8cefeede8a922d3e12598 (diff)
add "loopback" mode in which input is connected to the output.
This is useful to mix, demultiplex, resample or reencode audio files off-line. tweak + ok jakemsr
-rw-r--r--usr.bin/aucat/aucat.117
-rw-r--r--usr.bin/aucat/aucat.c40
-rw-r--r--usr.bin/aucat/dev.c68
-rw-r--r--usr.bin/aucat/dev.h4
4 files changed, 113 insertions, 16 deletions
diff --git a/usr.bin/aucat/aucat.1 b/usr.bin/aucat/aucat.1
index e73e823df2e..03a58e7f74c 100644
--- a/usr.bin/aucat/aucat.1
+++ b/usr.bin/aucat/aucat.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: aucat.1,v 1.41 2008/12/05 07:03:52 jmc Exp $
+.\" $OpenBSD: aucat.1,v 1.42 2009/01/10 20:02:28 ratchov Exp $
.\"
.\" Copyright (c) 2006 Alexandre Ratchov <alex@caoua.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: December 5 2008 $
+.Dd $Mdocdate: January 10 2009 $
.Dt AUCAT 1
.Os
.Sh NAME
@@ -23,7 +23,7 @@
.Sh SYNOPSIS
.Nm aucat
.Bk -words
-.Op Fl lu
+.Op Fl lnu
.Op Fl b Ar nsamples
.Op Fl C Ar min : Ns Ar max
.Op Fl c Ar min : Ns Ar max
@@ -102,6 +102,12 @@ and
for play-only, record-only, and full-duplex, respectively.
The default is
.Ar duplex .
+.It Fl n
+Loopback mode.
+Instead of using an audio device, send input streams
+to the output, processing them on the fly.
+This mode is useful to mix, demultiplex, resample or reencode
+audio files off-line.
.It Fl o Ar file
Add this file to the list of files in which to store recorded samples.
If the option argument is
@@ -343,6 +349,11 @@ both:
$ aucat -r 96000 -C 2:3 -o file1.raw -C 6:7 -o file2.raw
.Ed
.Pp
+The following will split a stereo file in two mono files:
+.Bd -literal -offset indent
+$ aucat -n -i stereo.wav -C 0:0 -o left.wav -C 1:1 -o right.wav
+.Ed
+.Pp
The following will start
.Nm
in server mode using default parameters, but will create an
diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c
index 4cabe127593..298c63ccaa7 100644
--- a/usr.bin/aucat/aucat.c
+++ b/usr.bin/aucat/aucat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aucat.c,v 1.50 2008/12/29 17:59:08 ratchov Exp $ */
+/* $OpenBSD: aucat.c,v 1.51 2009/01/10 20:02:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -111,7 +111,7 @@ usage(void)
extern char *__progname;
fprintf(stderr,
- "usage: %s [-lu] [-b nsamples] [-C min:max] [-c min:max] [-e enc] "
+ "usage: %s [-lnu] [-b nsamples] [-C min:max] [-c min:max] [-e enc] "
"[-f device]\n"
"\t[-h fmt] [-i file] [-m mode] [-o file] [-r rate] [-s socket]\n"
"\t[-v volume] [-x policy]\n",
@@ -312,7 +312,7 @@ newoutput(struct farg *fa)
int
main(int argc, char **argv)
{
- int c, u_flag, l_flag, hdr, xrun, suspend = 0;
+ int c, u_flag, l_flag, n_flag, hdr, xrun, suspend = 0;
struct farg *fa;
struct farglist ifiles, ofiles, sfiles;
struct aparams ipar, opar, dipar, dopar;
@@ -336,6 +336,7 @@ main(int argc, char **argv)
aparams_init(&opar, 0, 1, 44100);
u_flag = 0;
l_flag = 0;
+ n_flag = 0;
devpath = NULL;
SLIST_INIT(&ifiles);
SLIST_INIT(&ofiles);
@@ -346,8 +347,11 @@ main(int argc, char **argv)
bufsz = 44100 * 4 / 15; /* XXX: use milliseconds, not frames */
mode = 0;
- while ((c = getopt(argc, argv, "b:c:C:e:r:h:x:v:i:o:f:m:lus:")) != -1) {
+ while ((c = getopt(argc, argv, "nb:c:C:e:r:h:x:v:i:o:f:m:lus:")) != -1) {
switch (c) {
+ case 'n':
+ n_flag = 1;
+ break;
case 'm':
mode = opt_mode();
break;
@@ -446,6 +450,12 @@ main(int argc, char **argv)
if (l_flag || !SLIST_EMPTY(&ofiles))
mode |= MODE_REC;
}
+ if (n_flag) {
+ if (devpath != NULL || l_flag)
+ errx(1, "can't use -n with -f or -l");
+ if (SLIST_EMPTY(&ifiles) || SLIST_EMPTY(&ofiles))
+ errx(1, "both -i and -o are required with -n");
+ }
/*
* if there are no sockets paths provided use the default
@@ -490,15 +500,20 @@ main(int argc, char **argv)
DPRINTF("sigaction(usr2) failed1n");
#endif
filelist_init();
+
/*
* Open the device. Give half of the buffer to the device,
* the other half is for the socket/files
*/
- dev_init(devpath,
- (mode & MODE_REC) ? &dipar : NULL,
- (mode & MODE_PLAY) ? &dopar : NULL,
- bufsz);
-
+ if (n_flag) {
+ dev_loopinit(&dipar, &dopar, bufsz);
+ } else {
+ dev_init(devpath,
+ (mode & MODE_REC) ? &dipar : NULL,
+ (mode & MODE_PLAY) ? &dopar : NULL,
+ bufsz);
+ }
+
/*
* Create buffers for all input and output pipes.
*/
@@ -530,7 +545,7 @@ main(int argc, char **argv)
break;
}
if ((!dev_rec || dev_rec->u.io.file == NULL) &&
- (!dev_play || dev_play->u.io.file == NULL)) {
+ (!dev_play || dev_play->u.io.file == NULL) && !n_flag) {
fprintf(stderr, "device desappeared, terminating\n");
break;
}
@@ -563,7 +578,10 @@ main(int argc, char **argv)
suspend = 0;
dev_start();
}
- dev_done();
+ if (n_flag) {
+ dev_loopdone();
+ } else
+ dev_done();
filelist_done();
sigfillset(&sa.sa_mask);
diff --git a/usr.bin/aucat/dev.c b/usr.bin/aucat/dev.c
index e97dcf57e08..a72513abe57 100644
--- a/usr.bin/aucat/dev.c
+++ b/usr.bin/aucat/dev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.c,v 1.23 2009/01/06 19:27:22 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.24 2009/01/10 20:02:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -29,6 +29,72 @@ unsigned dev_bufsz, dev_round, dev_rate;
struct aparams dev_ipar, dev_opar;
struct aproc *dev_mix, *dev_sub, *dev_rec, *dev_play;
+/*
+ * same as dev_init(), but create a fake device that records what is
+ * played
+ */
+void
+dev_loopinit(struct aparams *dipar, struct aparams *dopar, unsigned bufsz)
+{
+ struct abuf *buf;
+ struct aparams par;
+ unsigned cmin, cmax, rate;
+
+ cmin = (dipar->cmin < dopar->cmin) ? dipar->cmin : dopar->cmin;
+ cmax = (dipar->cmax > dopar->cmax) ? dipar->cmax : dopar->cmax;
+ rate = (dipar->rate > dopar->rate) ? dipar->rate : dopar->rate;
+ aparams_init(&par, cmin, cmax, rate);
+ dev_ipar = par;
+ dev_opar = par;
+ dev_round = (bufsz + 1) / 2;
+ dev_bufsz = dev_round * 2;
+ dev_rate = rate;
+ dev_rec = NULL;
+ dev_play = NULL;
+
+ buf = abuf_new(dev_bufsz, &par);
+ dev_mix = mix_new("mix", dev_bufsz);
+ dev_mix->refs++;
+ dev_sub = sub_new("sub", dev_bufsz);
+ dev_sub->refs++;
+ aproc_setout(dev_mix, buf);
+ aproc_setin(dev_sub, buf);
+
+ dev_mix->u.mix.flags |= MIX_AUTOQUIT;
+ dev_sub->u.sub.flags |= SUB_AUTOQUIT;
+
+ *dipar = dev_ipar;
+ *dopar = dev_opar;
+}
+
+/*
+ * same as dev_done(), but destroy a loopback device
+ */
+void
+dev_loopdone(void)
+{
+ struct file *f;
+
+ DPRINTF("dev_loopdone:\n");
+
+ dev_sub->refs--;
+ dev_sub = NULL;
+ dev_mix->refs--;
+ dev_mix = NULL;
+ /*
+ * generate EOF on all inputs
+ */
+ restart:
+ LIST_FOREACH(f, &file_list, entry) {
+ if (f->rproc != NULL) {
+ file_eof(f);
+ goto restart;
+ }
+ }
+ while (file_poll())
+ ; /* nothing */
+}
+
unsigned
dev_roundof(unsigned newrate)
{
diff --git a/usr.bin/aucat/dev.h b/usr.bin/aucat/dev.h
index 5933f5c7f46..3889f6c58a3 100644
--- a/usr.bin/aucat/dev.h
+++ b/usr.bin/aucat/dev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.h,v 1.8 2008/12/07 17:10:41 ratchov Exp $ */
+/* $OpenBSD: dev.h,v 1.9 2009/01/10 20:02:28 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -28,6 +28,8 @@ extern struct aparams dev_ipar, dev_opar;
extern struct aproc *dev_mix, *dev_sub, *dev_rec, *dev_play;
unsigned dev_roundof(unsigned);
+void dev_loopinit(struct aparams *, struct aparams *, unsigned);
+void dev_loopdone(void);
void dev_init(char *, struct aparams *, struct aparams *, unsigned);
void dev_start(void);
void dev_stop(void);