123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- #include <assert.h>
- #include <errno.h>
- #include <inttypes.h>
- #include <limits.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <unistd.h>
- #ifdef USE_CAPSICUM
- #include <sys/capsicum.h>
- #endif
- #include <err.h>
- #include <sysexits.h>
- #include "au.h"
- #include "common.h"
- #ifndef MIN
- #define MIN(a, b) ((a) < (b) ? (a) : (b))
- #endif
- #ifndef MAX
- #define MAX(a, b) ((a) > (b) ? (a) : (b))
- #endif
- #ifndef BSIZE
- #define BSIZE 8000
- #endif
- #ifdef SIGINFO
- static size_t info_in = 0;
- static size_t info_out = 0;
- #endif
- #ifdef SIGINFO
- static void siginfo(int);
- #endif
- static ssize_t auresample_simple(struct au *, uint32_t, void *,
- size_t, void *);
- static ssize_t ncpy(int, int, void *, size_t);
- int
- main(int argc, char *argv[])
- {
- #ifdef USE_CAPSICUM
- cap_rights_t rights;
- #endif
- struct au au = AU_INITIALIZER;
- void *b;
- char *p;
- double rmod = 0;
- ssize_t r;
- size_t bsize = BSIZE;
- size_t isize;
- size_t osize;
- size_t ssize;
- size_t i;
- uint32_t rate = 0;
- int setrate = 0;
- int nflag = 0;
- int c;
- while ((c = getopt(argc, argv, "nm:r:")) != -1)
- switch (c) {
- case 'n':
- nflag = 1;
- break;
- case 'm':
- errno = 0;
- rmod = strtod(optarg, &p);
- if (!(rmod > 0))
- errno = ERANGE;
- if (errno != 0 || p == optarg || *p != '\0')
- err(EX_USAGE, "Invalid number %s",
- optarg);
- setrate = 1;
- break;
- case 'r':
- if ((rate = strtou32(optarg)) == 0)
- err(EX_USAGE,
- "The target rate must not be zero");
- setrate = 1;
- break;
- default:
- goto usage;
- }
- if (optind != argc)
- goto usage;
- #ifdef SIGINFO
- (void)signal(SIGINFO, &siginfo);
- #endif
- if ((b = malloc(bsize)) == NULL)
- err(EX_OSERR, "Could not allocate the buffer");
- #ifdef USE_PLEDGE
- (void)pledge("stdio", NULL);
- #endif
- #ifdef USE_CAPSICUM
- (void)cap_rights_init(&rights, CAP_READ);
- if (cap_rights_limit(STDIN_FILENO, &rights) == -1 &&
- errno != ENOSYS)
- err(EX_OSERR, "Could not limit the standard input");
- (void)cap_rights_init(&rights, CAP_WRITE);
- if (cap_rights_limit(STDOUT_FILENO, &rights) == -1 &&
- errno != ENOSYS)
- err(EX_OSERR, "Could not limit the standard output");
- if (cap_rights_limit(STDERR_FILENO, &rights) == -1 &&
- errno != ENOSYS)
- err(EX_OSERR, "Could not limit the standard error");
- #endif
- while (nread(STDIN_FILENO, b, AU_SIZE) == AU_SIZE) {
- if (au_gethdr(&au, b) != 0)
- errx(EX_DATAERR, "Bad header");
- if (rmod > 0)
- rate = (double)au.au_rate * rmod;
- ssize = au_ssize(&au);
- isize = (size_t)au.au_rate * ssize;
- osize = (size_t)rate * ssize;
- if (isize > bsize || osize > bsize) {
- bsize = MAX(isize, osize);
- if ((b = realloc(b, bsize)) == NULL)
- err(EX_OSERR,
- "Could not realloc buffer");
- }
- if (!setrate) {
- if ((rate = au.au_rate) == 0)
- err(EX_DATAERR,
- "The target rate must not be zero");
- setrate = 1;
- }
- if (!nflag)
- put4((char *)b + 16, rate);
- if (nwrite(STDOUT_FILENO, b, AU_SIZE) < 0)
- err(EX_IOERR,
- "Could not write audio Header");
- for (i = AU_SIZE; i < au.au_off; i += r)
- if ((r = ncpy(STDIN_FILENO, STDOUT_FILENO, b,
- MIN(au.au_off - i, isize))) < 0)
- err(EX_IOERR, "error while copying "
- "stdin -> stdout");
- while ((r = nread(STDIN_FILENO,
- (char *)b + (bsize - isize),
- MIN(isize, au.au_size))) > 0) {
- #ifdef SIGINFO
- info_in += r / ssize;
- #endif
- i = r;
- if (isize != osize &&
- (r = auresample_simple(&au, rate,
- (char *)b + (bsize - isize), r, b)) < 0)
- err(EX_SOFTWARE, "auresample_simple");
- if ((r = nwrite(STDOUT_FILENO, b, r)) < 0)
- err(EX_IOERR, "Write error");
- #ifdef SIGINFO
- info_out += r / ssize;
- #endif
- if (au.au_size != UINT32_MAX &&
- (au.au_size -= i) == 0)
- break;
- }
- if (r == 0)
- break;
- }
- free(b);
- return (0);
- usage:
- (void)fprintf(stderr,
- "usage: auresample [-n] [-r rate] [-m modifier]\n");
- return (EX_USAGE);
- }
- #ifdef SIGINFO
- void
- siginfo(int sig)
- {
- /* auresample: XXXXXX samples in XXXXXX samples out */
- char b[12 + 6 + 12 + 6 + 13];
- size_t i = 0;
- (void)memcpy((char *)b + i, "auresample: ", 12);
- i += 12;
- i += szwrite(b + i, info_in, NULL, NULL);
- (void)memcpy(b + i, " samples in ", 12);
- i += 12;
- i += szwrite(b + i, info_out, NULL, NULL);
- (void)memcpy(b + i, " samples out\n ", 13);
- i += 13;
- (void)write(STDERR_FILENO, b, i);
- }
- #endif
- ssize_t
- auresample_simple(struct au *au, uint32_t rate, void *b, size_t s,
- void *o)
- {
- size_t ssize;
- size_t i;
- size_t j;
- uint64_t x;
- assert(au != NULL);
- for (i = 0, j = 0, x = 0, ssize = au_ssize(au); i + ssize <= s;
- i += ssize)
- for (x += rate; x >= au->au_rate;
- j += ssize, x -= au->au_rate)
- (void)memcpy((char *)o + j, (char *)b + i,
- ssize);
- return (j);
- }
- ssize_t
- ncpy(int in, int out, void *b, size_t s)
- {
- ssize_t t;
- if ((t = nread(in, b, s)) > 0)
- t = nwrite(out, b, s);
- return (t);
- }
|