isdn4k-utils/vbox/src/vboxconvert.c

1201 lines
29 KiB
C

/*
** $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 <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <sys/utsname.h>
#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 ] [ ... ] <INFILE >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 ] [ ... ] <INFILE >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. **/
/** <RC> 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(&timestamp);
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);
}