diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2009-01-10 20:02:29 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2009-01-10 20:02:29 +0000 |
commit | 52950e81d47e2f55bc1e7ea44d1d5afad457e4ba (patch) | |
tree | 9c14fc3059518f81d40e6c36fc75c0a353b01126 | |
parent | 77353b43cbc8c402ffa8cefeede8a922d3e12598 (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.1 | 17 | ||||
-rw-r--r-- | usr.bin/aucat/aucat.c | 40 | ||||
-rw-r--r-- | usr.bin/aucat/dev.c | 68 | ||||
-rw-r--r-- | usr.bin/aucat/dev.h | 4 |
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); |