/* ** $Id: vboxconvert.c,v 1.10 2001/03/01 14:59:16 paul Exp $ ** ** Copyright (C) 1996, 1997 Michael 'Ghandi' Herold ** ** The most converting routines are taken from the mgetty/vgetty v0.98 ** package - this routines are copyright by there autors! */ #include "config.h" #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "libvbox.h" #include "vboxconvert.h" /** Variables ************************************************************/ static state_t InitState = { 0x0000, 0 }; static int mx[3][8] = { { 0x3800, 0x5600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, { 0x399a, 0x3a9f, 0x4d14, 0x6607, 0x0000, 0x0000, 0x0000, 0x0000 }, { 0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607 }, }; static int bitmask[9] = { 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; static char *sun_format_names[] = { "unspecified format", "8-bit mu-law samples", "8-bit linear samples", "16-bit linear samples", "24-bit linear samples", "32-bit linear samples", "floating-point samples", "double-precision float samples", "fragmented sampled data", "?", "dsp program", "8-bit fixed-point samples", "16-bit fixed-point samples", "24-bit fixed-point samples", "32-bit fixed-point samples", "?", "non-audio display data", "?", "16-bit linear with emphasis", "16-bit linear with compression", "16-bit linear with emphasis & compression", "music Kit DSP commands", "?" }; static struct option args_vboxtoau[] = { { "help" , no_argument , NULL, 'h' }, { "version" , no_argument , NULL, 'v' }, { "samplerate", required_argument, NULL, 'r' }, { "ulaw" , no_argument , NULL, 'u' }, { "linear8" , no_argument , NULL, '1' }, { "linear16" , no_argument , NULL, '2' }, { NULL , 0 , NULL, 0 } }; static struct option args_vboxmode[] = { { "help" , no_argument , NULL, 'h' }, { "version" , no_argument , NULL, 'v' }, { "quiet" , no_argument , NULL, 'q' }, { NULL , 0 , NULL, 0 } }; static struct option args_autovbox[] = { { "help" , no_argument , NULL, 'h' }, { "version" , no_argument , NULL, 'v' }, { "adpcm-2" , no_argument , NULL, '2' }, { "adpcm-3" , no_argument , NULL, '3' }, { "adpcm-4" , no_argument , NULL, '4' }, { "ulaw" , no_argument , NULL, 'u' }, { "name" , required_argument , NULL, 'n' }, { "callerid", required_argument , NULL, 'c' }, { "phone" , required_argument , NULL, 'p' }, { "location", required_argument , NULL, 'l' }, { NULL , 0 , NULL, 0 } }; static char *vbasename = NULL; static FILE *vboxtmpfile = NULL; static char perrormsg[256]; /** Prototypes ***********************************************************/ static int start_vboxmode(char *, int); static void start_vboxtoau(int, int); static void start_autovbox(int, char *, char *, char *, char *); static void usage_vboxtoau(void); static void usage_vboxmode(void); static void usage_autovbox(void); static void leave_vboxtoau(int); static void leave_autovbox(int); static void version(void); static int convert_adpcm_to_pvf(int, FILE *, FILE *); static int convert_pvf_to_adpcm(int, FILE *, FILE *); static int convert_au_to_pvf(FILE *, FILE *); static int convert_pvf_to_au(int, int, FILE *, FILE *); static int convert_ulaw_to_pvf(FILE *, FILE *); static int convert_pvf_to_ulaw(FILE *, FILE *); static unsigned char byte_linear_to_ulaw(int); static int byte_ulaw_to_linear(unsigned char); static int test_sample_is_vbox(char *, int); static int test_sample_is_au(char *, int); static void write_one_word(int, FILE *); static int read_one_word(FILE *); static int zget(FILE *); static void zput(int, FILE *); static int get_bits(int, state_t *, FILE *); static void put_bits(int, int, state_t *, FILE *); static int check_io_error(FILE *, FILE *); /*************************************************************************/ /** The magic main... **/ /*************************************************************************/ int main(int argc, char **argv) { struct utsname utsname; struct passwd *passwd; char realname[VAH_MAX_NAME + 1]; int opts; int rate; int mode; char *name; char *phone; char *location; int i; if (!(vbasename = rindex(argv[0], '/'))) vbasename = argv[0]; else vbasename++; /* Called as 'vboxtoau' converts a messages saved with vbox to */ /* sun's au format. */ if (strcasecmp(vbasename, "vboxtoau") == 0) { rate = 8000; mode = SND_FORMAT_LINEAR_16; while ((opts = getopt_long(argc, argv, "vhu12r:", args_vboxtoau, (int *)0)) != EOF) { switch (opts) { case 'r': rate = atoi(optarg); break; case 'u': mode = SND_FORMAT_MULAW_8; break; case '1': mode = SND_FORMAT_LINEAR_8; break; case '2': mode = SND_FORMAT_LINEAR_16; break; case 'v': version(); break; case 'h': default: usage_vboxtoau(); break; } } start_vboxtoau(mode, rate); } /* Called as 'autovbox' converts a sun au sample to any of the */ /* vbox message formats. */ if (strcasecmp(vbasename, "autovbox") == 0) { name = "*** Unknown ***"; phone = "*** Unknown ***"; location = "*** Unknown ***"; mode = 4; if (uname(&utsname) == 0) location = utsname.nodename; if ((passwd = getpwuid(getuid()))) { xstrncpy(realname, passwd->pw_gecos, VAH_MAX_NAME); for (i = 0; i < strlen(realname); i++) { if ((realname[i] == ',') || (realname[i] == ';')) { realname[i] = '\0'; break; } } name = realname; } while ((opts = getopt_long(argc, argv, "hv234un:c:p:l:", args_autovbox, (int *)0)) != EOF) { switch (opts) { case '2': mode = 2; break; case '3': mode = 3; break; case '4': mode = 4; break; case 'u': mode = 6; break; case 'n': name = optarg; break; case 'p': phone = optarg; break; case 'l': location = optarg; break; case 'v': version(); break; case 'h': default: usage_autovbox(); break; } } start_autovbox(mode, name, "0", phone, location); } /* Called as 'vboxmode' displays information about the sample */ /* format. */ if (strcasecmp(vbasename, "vboxmode") == 0) { mode = FALSE; name = ""; while ((opts = getopt_long(argc, argv, "vhq", args_vboxmode, (int *)0)) != EOF) { switch (opts) { case 'v': version(); break; case 'q': mode = TRUE; break; case 'h': default: usage_vboxmode(); break; } } for (i = 1; i < argc; i++) { if (argv[i][0] != '-') name = argv[i]; } if ((argc < 2) || (!*name)) usage_vboxmode(); exit(start_vboxmode(name, mode)); }; fprintf(stderr, "\n"); fprintf(stderr, "The vbox converter can be called as:\n"); fprintf(stderr, "\n"); fprintf(stderr, "vboxtoau - to convert vbox messages to au format.\n"); fprintf(stderr, "autovbox - to convert au format samples to vbox messages.\n"); fprintf(stderr, "vboxmode - to display message information (works also with au).\n"); fprintf(stderr, "\n"); exit(255); } /*************************************************************************/ /** start_vboxtoau(): Converts vbox messages to sun's au format. **/ /*************************************************************************/ static void start_vboxtoau(int samplemode, int samplerate) { vaheader_t header; int compression; int result; vboxtmpfile = NULL; signal(SIGINT , leave_vboxtoau); signal(SIGQUIT, leave_vboxtoau); signal(SIGTERM, leave_vboxtoau); signal(SIGHUP , leave_vboxtoau); signal(SIGPIPE, leave_vboxtoau); if (!(vboxtmpfile = tmpfile())) { sprintf(perrormsg, "%s: can't create tmpfile", vbasename); perror(perrormsg); leave_vboxtoau(255); } if (fread(&header, sizeof(vaheader_t), 1, stdin) != 1) { sprintf(perrormsg, "%s: can't read vbox audio header", vbasename); perror(perrormsg); leave_vboxtoau(255); } if (strncmp(header.magic, VAH_MAGIC, VAH_MAX_MAGIC) != 0) { fprintf(stderr, "%s: sample contains no vbox audio header.\n", vbasename); leave_vboxtoau(255); } compression = (int)ntohl(header.compression); result = 255; switch (compression) { case 2: case 3: case 4: result = convert_adpcm_to_pvf(compression, stdin, vboxtmpfile); break; case 6: result = convert_ulaw_to_pvf(stdin, vboxtmpfile); break; default: fprintf(stderr, "%s: unknown/unsupported compression %d.\n", vbasename, compression); break; } if (result == 0) { result = convert_pvf_to_au(samplemode, samplerate, vboxtmpfile, stdout); } leave_vboxtoau(result); } /**************************************************************************/ /** leave_vboxtoau(): Leave vboxtoau mode. **/ /**************************************************************************/ static void leave_vboxtoau(int sig) { if (vboxtmpfile) fclose(vboxtmpfile); exit(sig); } /*************************************************************************/ /** usage_vboxtoau(): Usage message for "vboxtoau". **/ /*************************************************************************/ static void usage_vboxtoau(void) { fprintf(stderr, "\n"); fprintf(stderr, "Usage: %s OPTION [ OPTION ] [ ... ] OUTFILE\n", vbasename); fprintf(stderr, "\n"); fprintf(stderr, "-r, --samplerate RATE Header sampling rate (default 8000).\n"); fprintf(stderr, "-u, --ulaw Use 8-bit uLaw output.\n"); fprintf(stderr, "-1, --linear8 Use 8-bit linear output.\n"); fprintf(stderr, "-2, --linear16 Use 16-Bit linear output (default).\n"); fprintf(stderr, "-h, --help Prints this usage message.\n"); fprintf(stderr, "-v, --version Prints the package version.\n"); fprintf(stderr, "\n"); fprintf(stderr, "Note: The sampling rate is written into the file header only, it\n doesn't do any sampling rate conversion!\n"); fprintf(stderr, "\n"); exit(255); } /*************************************************************************/ /** start_vboxmode(): Displays sample information. **/ /*************************************************************************/ static int start_vboxmode(char *name, int quiet) { int result; result = test_sample_is_vbox(name, quiet); if (result == 255) { result = test_sample_is_au(name, quiet); } if (result == 255) { fprintf(stderr, "%s: sample contains no vbox or sun au header.\n", vbasename); } return(result); } /*************************************************************************/ /** usage_vboxmode(): Usage message for "vboxmode". **/ /*************************************************************************/ static void usage_vboxmode(void) { fprintf(stderr, "\n"); fprintf(stderr, "Usage: %s OPTION [ OPTION ] [ ... ] SAMPLENAME\n", vbasename); fprintf(stderr, "\n"); fprintf(stderr, "-q, --quiet Returns only the errorcode (no descriptions).\n"); fprintf(stderr, "-h, --help Prints this usage message.\n"); fprintf(stderr, "-v, --version Prints the package version.\n"); fprintf(stderr, "\n"); fprintf(stderr, "The program returns the sample format as errorcode:\n"); fprintf(stderr, "\n"); fprintf(stderr, "- For au samples it returns %d-%d,\n", SUN_FORMAT_MIN + 128, SUN_FORMAT_MAX + 128); fprintf(stderr, "- For vbox messages it returns 2-6,\n"); fprintf(stderr, "- For unknown formats or on errors it returns 255.\n"); fprintf(stderr, "\n"); exit(255); } /*************************************************************************/ /** start_autovbox(): Converts au samples to vbox messages. **/ /*************************************************************************/ static void start_autovbox(int compression, char *name, char *id, char *phone, char *location) { vaheader_t header; int result; vboxtmpfile = NULL; signal(SIGINT , leave_autovbox); signal(SIGQUIT, leave_autovbox); signal(SIGTERM, leave_autovbox); signal(SIGHUP , leave_autovbox); signal(SIGPIPE, leave_autovbox); if (!(vboxtmpfile = tmpfile())) { sprintf(perrormsg, "%s: can't create tmpfile", vbasename); perror(perrormsg); leave_autovbox(255); } xstrncpy(header.magic , VAH_MAGIC , VAH_MAX_MAGIC ); xstrncpy(header.callerid, id , VAH_MAX_CALLERID); xstrncpy(header.name , name , VAH_MAX_NAME ); xstrncpy(header.phone , phone , VAH_MAX_PHONE ); xstrncpy(header.location, location , VAH_MAX_LOCATION); header.time = htonl(time(NULL)); header.compression = htonl(compression); if (fwrite(&header, sizeof(vaheader_t), 1, stdout) != 1) { fprintf(stderr, "%s: can't write vbox audio header.\n", vbasename); leave_autovbox(255); } result = convert_au_to_pvf(stdin, vboxtmpfile); if (result == 0) { result = 255; switch (compression) { case 2: case 3: case 4: result = convert_pvf_to_adpcm(compression, vboxtmpfile, stdout); break; case 6: result = convert_pvf_to_ulaw(vboxtmpfile, stdout); break; default: fprintf(stderr, "%s: unsupported compression type.\n", vbasename); break; } } leave_autovbox(result); } /**************************************************************************/ /** leave_autovbox(): Leave autovbox mode. **/ /**************************************************************************/ static void leave_autovbox(int sig) { if (vboxtmpfile) fclose(vboxtmpfile); exit(sig); } /*************************************************************************/ /** usage_autovbox(): Usage message for "autovbox". **/ /*************************************************************************/ static void usage_autovbox(void) { fprintf(stderr, "\n"); fprintf(stderr, "Usage: %s OPTION [ OPTION ] [ ... ] OUTFILE\n", vbasename); fprintf(stderr, "\n"); fprintf(stderr, "-2, --adpcm-2 Converts sample to adpcm-2.\n"); fprintf(stderr, "-3, --adpcm-3 Converts sample to adpcm-3.\n"); fprintf(stderr, "-4, --adpcm-4 Converts sample to adpcm-4 (default).\n"); fprintf(stderr, "-u, --ulaw Converts sample to ulaw.\n"); fprintf(stderr, "-n, --name NAME Sets header information.\n"); fprintf(stderr, "-p, --phone PHONE Sets header information.\n"); fprintf(stderr, "-l, --location LOCATION Sets header information.\n"); fprintf(stderr, "-h, --help Prints this usage message.\n"); fprintf(stderr, "-v, --version Prints the package version.\n"); fprintf(stderr, "\n"); exit(255); } /*************************************************************************/ /** convert_pvf_to_adpcm(): Converts protable voice format to adpcm-2 **/ /** adpcm-3 or adpcm-4. **/ /*************************************************************************/ static int convert_pvf_to_adpcm(int nbits, FILE *in, FILE *out) { state_t s; int a; int d; int e; int nmax; int sign; int delta; rewind(in); clearerr(in); clearerr(out); a = 0; d = 5; s = InitState; while (1) { e = 0; nmax = 1 << (nbits-1); delta = (zget(in) >> 2) - a; if (feof(in)) break; if (delta < 0) { e = nmax; delta = -delta; } while(--nmax && delta > d) { delta -= d; e++; } if (nbits==4 && ((e & 0x0F) == 0)) e = 0x08; put_bits( e, nbits, &s, out); a = (a * 4093 + 2048) >> 12; sign = (e >> (nbits - 1)) ? -1 : 1; e = (e & bitmask[nbits - 1]); a += sign * ((e<<1)+1) * d >>1; if ((d & 1)) a++; d = (d * mx[nbits - 2][e] + 0x2000) >> 14; if (d < 5) d = 5; } if (s.nleft) put_bits(0, 8-s.nleft, &s, out); return(check_io_error(in, out)); } /*************************************************************************/ /** convert_adpcm_to_pvf(): Converts adpcm-2, adpcm-3 or adpcm-4 to **/ /** portable voice format. **/ /*************************************************************************/ static int convert_adpcm_to_pvf(int nbits, FILE *in, FILE *out) { state_t state; int a; int d; int e; int sign; state = InitState; a = 0; d = 5; clearerr(in); clearerr(out); while (1) { if ((e = get_bits(nbits, &state, in)) == EOF) break; if ((nbits == 4) && (e == 0)) d = 4; sign = (e >> (nbits - 1)) ? -1 : 1; e = e & bitmask[nbits - 1]; a = (a * 4093 + 2048) >> 12; a += sign * ((e << 1) + 1) * d >> 1; if ((d & 1)) a++; zput(a << 2, out); d = (d * mx[nbits - 2][e] + 0x2000) >> 14; if (d < 5) d = 5; } return(check_io_error(in, out)); } /*************************************************************************/ /** convert_au_to_pvf(): Converts sun's au format to portable voice **/ /** format. **/ /*************************************************************************/ static int convert_au_to_pvf(FILE *in, FILE *out) { SNDSoundStruct hdr; int i; int c; rewind(in); clearerr(in); clearerr(out); hdr.magic = read_one_word(in); hdr.dataLocation = read_one_word(in); hdr.dataSize = read_one_word(in); hdr.dataFormat = read_one_word(in); hdr.samplingRate = read_one_word(in); hdr.channelCount = read_one_word(in); if (hdr.magic != SND_MAGIC) { fprintf(stderr, "%s: illegal magic number for an au file.\n", vbasename); return(255); } if (hdr.channelCount != 1) { fprintf(stderr, "%s: number of channels != 1 (only mono supported).\n", vbasename); return(255); } for (i = (SND_HEADER_SIZE - 4); i < hdr.dataLocation; i++) { if (getc(in) == EOF) { fprintf(stderr, "%s: unexpected EOF.\n", vbasename); return(255); } } switch (hdr.dataFormat) { case SND_FORMAT_MULAW_8: while(1) { c = getc(in); if (feof(in)) break; zput(byte_ulaw_to_linear(c), out); } break; case SND_FORMAT_LINEAR_8: while(1) { c = (getc(in) & 0xFF); if (c >= 0x80) c -= 0x100; if (feof(in)) break; zput(c<<8, out); } break; case SND_FORMAT_LINEAR_16: while(1) { c = zget(in); if(feof(in)) break; zput(c, out); } break; default: fprintf(stderr, "%s: unsupported or illegal sound encoding.\n", vbasename); return(255); } return(check_io_error(in, out)); } /*************************************************************************/ /** convert_pvf_to_au(): Converts portable voice format to sun's au **/ /** format. **/ /*************************************************************************/ static int convert_pvf_to_au(int mode, int rate, FILE *in, FILE *out) { SNDSoundStruct Snd; int s; rewind(in); clearerr(in); clearerr(out); Snd.dataFormat = mode; Snd.samplingRate = rate; Snd.magic = SND_MAGIC; Snd.dataLocation = SND_HEADER_SIZE; Snd.dataSize = SND_UNKNOWN_SIZE; Snd.channelCount = 1; Snd.info[0] = 0; write_one_word((int)Snd.magic, out); write_one_word((int)Snd.dataLocation, out); write_one_word((int)Snd.dataSize, out); write_one_word((int)Snd.dataFormat, out); write_one_word((int)Snd.samplingRate, out); write_one_word((int)Snd.channelCount, out); write_one_word(*((int *)Snd.info), out); while (1) { s = zget(in); if ((feof(in)) || (ferror(in))) break; switch (Snd.dataFormat) { case SND_FORMAT_MULAW_8: putc(byte_linear_to_ulaw(s), out); break; case SND_FORMAT_LINEAR_8: putc(s >> 8, out); break; case SND_FORMAT_LINEAR_16: zput(s, out); break; } } return(check_io_error(in, out)); } /*************************************************************************/ /** convert_pvf_to_ulaw(): Converts portable voice format to ulaw. **/ /*************************************************************************/ static int convert_pvf_to_ulaw(FILE *in, FILE *out) { int sample; rewind(in); clearerr(in); clearerr(out); while (1) { sample = zget(in); if(feof(in)) break; putc(byte_linear_to_ulaw(sample), out); } return(check_io_error(in, out)); } /*************************************************************************/ /** convert_ulaw_to_pvf(): Converts ulaw to portable voice format. **/ /*************************************************************************/ static int convert_ulaw_to_pvf(FILE *in, FILE *out) { int c; clearerr(in); clearerr(out); while (1) { if ((c = getc(in)) == EOF) break; zput(byte_ulaw_to_linear(c), out); } return(check_io_error(in, out)); } /*************************************************************************/ /** put_bits(): **/ /*************************************************************************/ static void put_bits(int data, int nbits, state_t *s, FILE *out) { int d; s->word = (s->word << nbits) | (data & bitmask[nbits]); s->nleft += nbits; while (s->nleft >= 8) { d = (s->word >> (s->nleft - 8)); putc(d & 255, out); s->nleft -= 8; } } /*************************************************************************/ /** get_bits(): **/ /*************************************************************************/ static int get_bits(int nbits, state_t *state, FILE *in) { int d; while (state->nleft < nbits) { if ((d = getc(in)) == EOF) return(EOF); state->word = (state->word << 8) | d; state->nleft += 8; } state->nleft -= nbits; return(state->word >> state->nleft) & bitmask[nbits]; } /*************************************************************************/ /** zput(): **/ /*************************************************************************/ static void zput(int d, FILE *out) { if (d > 0x7fff) d = 0x7fff; if (d < -0x8000) d = -0x8000; putc((d >> 8) & 0xFF, out); putc(d & 0xFF, out); } /*************************************************************************/ /** zget(): **/ /*************************************************************************/ static int zget(FILE *in) { int d; d = (getc(in) & 0xFF) << 8; d |= (getc(in) & 0xFF); if (d >= 0x8000) d -= 0x10000; return(d); } /*************************************************************************/ /** write_one_word(): **/ /*************************************************************************/ static void write_one_word(int w, FILE *out) { putc((w & 0xFF000000) >> 24, out); putc((w & 0x00FF0000) >> 16, out); putc((w & 0x0000FF00) >> 8, out); putc((w & 0x000000FF) , out); } /*************************************************************************/ /** read_one_word(): **/ /*************************************************************************/ static int read_one_word(FILE *in) { int w; w = getc(in); w = (w << 8) | getc(in); w = (w << 8) | getc(in); w = (w << 8) | getc(in); return(w); } /*************************************************************************/ /** byte_ulaw_to_linear(): Converts 8 bit ulaw sample to 16 bit linear **/ /** sample. **/ /*************************************************************************/ static int byte_ulaw_to_linear(unsigned char ulawbyte) { static int exp[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 }; int sign; int exponent; int mantissa; int sample; ulawbyte = ~ulawbyte; sign = (ulawbyte & 0x80); exponent = (ulawbyte >> 4) & 0x07; mantissa = ulawbyte & 0x0F; sample = exp[exponent] + (mantissa << (exponent + 3)); if (sign != 0) sample = -sample; return(sample); } /*************************************************************************/ /** byte_linear_to_ulaw(): Converts from signed 16 bit linear to 8 bit **/ /** ulaw. **/ /*************************************************************************/ /** Sample 16 bit linear sample. **/ /** 8 bit ulaw sample. **/ /*************************************************************************/ #define BIAS 0x84 /* Define the add-in bias for 16 bit samples */ #define CLIP 32635 static unsigned char byte_linear_to_ulaw(int sample) { static int exp[256] = { 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 }; unsigned char ulawbyte; int sign; int exponent; int mantissa; sign = (sample >> 8) & 0x80; if (sign != 0) sample = -sample; if (sample > CLIP) sample = CLIP; sample = sample + BIAS; exponent = exp[(sample >> 7) & 0xFF]; mantissa = (sample >> (exponent + 3)) & 0x0F; ulawbyte = ~(sign | (exponent << 4) | mantissa); return(ulawbyte); } /*************************************************************************/ /** test_sample_is_vbox(): Tests if the sample is in vbox format. **/ /*************************************************************************/ static int test_sample_is_vbox(char *name, int quiet) { struct tm *timelocal; struct stat status; vaheader_t header; time_t timestamp; long int compression; int fd; char timestring[256]; compression = 255; if ((fd = open(name, O_RDONLY)) != -1) { if (header_get(fd, &header)) { compression = ntohl(header.compression); if ((compression < 2) || (compression > 6)) compression = 0; if (fstat(fd, &status) == 0) { timestamp = ntohl(header.time); timelocal = localtime(×tamp); if (strftime(timestring, 255, "%c\n", timelocal) == 255) { printstring(timestring, "???\n"); } if (!quiet) { fprintf(stdout, "\n"); fprintf(stdout, "Creation time...........: %s", timestring); fprintf(stdout, "Compression.............: %s\n", compressions[compression]); fprintf(stdout, "Length..................: %d seconds\n", get_message_ptime(compression, (status.st_size - sizeof(vaheader_t)))); fprintf(stdout, "Speaker name............: %s\n", header.name); fprintf(stdout, "Speaker caller number...: %s\n", header.callerid); fprintf(stdout, "Speaker phone number....: %s\n", header.phone); fprintf(stdout, "Speaker location........: %s\n", header.location); fprintf(stdout, "\n"); } } } close(fd); } else fprintf(stderr, "%s: can't open \"%s\" (vbox sample test).\n", vbasename, name); return(compression); } /*************************************************************************/ /** test_sample_is_au(): Tests if the sample is in sun's au format. **/ /*************************************************************************/ static int test_sample_is_au(char *name, int quiet) { SNDSoundStruct snd; FILE *in; if (!(in = fopen(name, "r"))) { fprintf(stderr, "%s: can't open \"%s\" (au sample test).\n", vbasename, name); return(255); } clearerr(in); snd.magic = read_one_word(in); snd.dataLocation = read_one_word(in); snd.dataSize = read_one_word(in); snd.dataFormat = read_one_word(in); snd.samplingRate = read_one_word(in); snd.channelCount = read_one_word(in); if ((snd.magic != SND_MAGIC) || (ferror(in) != 0)) { fclose(in); return(255); } fclose(in); if ((snd.dataFormat < SUN_FORMAT_MIN) || (snd.dataFormat > SUN_FORMAT_MAX)) { return(255); } if (!quiet) { fprintf(stdout, "\n"); fprintf(stdout, "Format..........: %s\n", sun_format_names[snd.dataFormat]); fprintf(stdout, "Sampling rate...: %d\n", snd.samplingRate); fprintf(stdout, "Channels........: %d\n", snd.channelCount); fprintf(stdout, "Size............: %d %s\n", snd.dataSize, snd.dataSize == -1 ? "(unknown size)" : "bytes"); fprintf(stdout, "Data location...: %d\n", snd.dataLocation); fprintf(stdout, "\n"); } return(128 + snd.dataFormat); } /*************************************************************************/ /** version(): Package version. **/ /*************************************************************************/ static void version(void) { fprintf(stderr, "\n"); fprintf(stderr, "%s version %s (%s)\n", vbasename, VERSION, VERDATE); fprintf(stderr, "\n"); exit(255); } /*************************************************************************/ /** check_io_error(): **/ /*************************************************************************/ static int check_io_error(FILE *in, FILE *out) { if (ferror(in) != 0) { fprintf(stderr, "%s: can't read input.\n", vbasename); return(255); } if (ferror(out) != 0) { fprintf(stderr, "%s: can't write output.\n", vbasename); return(255); } return(0); }