home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
MM1
/
SOUNDUTILS
/
audioplay.lzh
/
AUDIOPLAY
/
SRC
/
vocplay.c
< prev
next >
Wrap
Text File
|
1995-03-28
|
8KB
|
376 lines
/* vocplay.c - play Creative Voice *.voc file on MM/1 - Andrzej Kotanski 1994 */
#include "play.h"
static struct head {
char magic[20];
short offset;
short version;
short version2;
} hdr;
static unsigned char hdr2[10];
static char type;
static unsigned char *buf1, *buf2, *buf, hd[2];
unsigned char *malloc();
static int sample_rate, data_size;
static int channels = 1;
static u_int32 sleepTime;
static char comment[80];
enum types { Terminator, Sound_data, Sound_continue, Silence, Marker,
ASCII, Repeat, End_repeat, Extended };
void vocplay(fd)
path_id fd;
{
int res;
int repeat;
long loop_pos, lseek();
int sig_pending = 0;
int comp_type;
int got_extended = FALSE;
size = sizeof(hdr);
sample_rate = 0;
if (read(fd, &hdr, size) == -1) {
cleanup(errno, "cannot read header");
}
if (strncmp(hdr.magic, "Creative Voice File\x1a", 20)) {
cleanup(0, "bad header title !");
}
if (hdr.version + hdr.version2 != 0x3312) {
if (!quiet) {
fprintf(stderr, "bad header checksum - trying to play anyway\n");
}
}
hdr.offset = swab(&hdr.offset);
/* reposition our to first data block */
if (lseek(fd,hdr.offset,SEEK_SET) == -1)
cleanup(errno, "cannot seek to first datablock");
/* allocate out buffers once...
* there may be more than one sample or we might have to loop.
*/
buf1 = malloc(bufferSize*2);
buf2 = malloc(bufferSize*2);
if (buf1 == NULL || buf2 == NULL) {
cleanup(errno, "cannot allocate buffer");
}
/* point to one of the buffers */
buf = buf2;
/* set out signal flag to true for first time through */
sigarrived = 1;
for (;;) {
size = 1;
if ((read(fd, &type, size)) == -1) {
if (errno == E_EOF) {
close(fd);
return;
} else {
cleanup(errno, "cannot read header2");
}
}
if (debug)
printf("type = %d\n",type);
/* extended lasts only if next block is sound */
if (got_extended == TRUE && type != Sound_data)
got_extended = FALSE;
switch (type) {
case Terminator:
/* let's wait till the sound has been played before
* we deallocate the memory on _ss_play(). It's the
* polite thing to do. :)
*/
if (sig_pending)
{
while (! sigarrived)
tsleep(0);
sig_pending = 0;
}
/* deallocate out buffers */
free(buf1);
free(buf2);
close(fd);
return;
case Silence:
size = 6;
if ((read(fd, hdr2, size)) == -1) {
cleanup(errno, "cannot read header2");
}
data_size = hdr2[3] + 256*hdr2[4];
sample_rate = 1000000 / (256 - hdr2[5]);
sleepTime = (data_size * 256 / sample_rate) | 0x80000000;
/* we want to sleep till we get our signal back */
if (sig_pending)
{
while (! sigarrived)
tsleep(0);
sig_pending = 0;
}
/* now sleep for the silence time */
tsleep(sleepTime);
break;
case Marker:
size = 5;
if ((read(fd, hdr2, size)) == -1) {
cleanup(errno, "cannot read header2");
}
res = hdr2[3] + 256*hdr2[4];
break;
case ASCII:
size = 2;
if ((read(fd, hdr2, size)) == -1) {
cleanup(errno, "cannot read header2");
}
res = hdr2[0] + 256*hdr2[1];
size = res;
if ((read(fd, comment, size)) == -1) {
cleanup(errno, "cannot read text");
}
fprintf(stderr, "%s\n", comment);
break;
case Repeat:
size = 5;
if ((read(fd, hdr2, size)) == -1) {
cleanup(errno, "cannot read header2");
}
repeat = hdr2[3] + 256*hdr2[4];
loop_pos = _gs_pos(fd);
break;
case End_repeat:
if (repeat > 1)
{
if (lseek(fd,loop_pos,SEEK_SET) == -1)
cleanup(errno, "cannot seek back to loop point");
repeat--;
}
else
repeat = 0;
sample_rate = 0;
break;
case Extended:
size = 7;
if ((read(fd, hdr2, size)) == -1) {
cleanup(errno, "cannot read header2");
}
channels = hdr2[6] + 1;
res = hdr2[3] + 256*hdr2[4];
sample_rate = (256000000 / (65536 - res)) / channels;
comp_type = hdr2[5];
if (!quiet) {
fprintf(stderr, "Time Constant: %-8d ",res);
fprintf(stderr, "Sample Rate: %-8d ",sample_rate);
fprintf(stderr, "Channels: %-2d ", channels);
fprintf(stderr, "Compression type: %-2d\n", comp_type);
}
got_extended = TRUE;
break;
case Sound_continue:
size = 3;
if ((read(fd, hdr2, size)) == -1) {
cleanup(errno, "cannot read header2");
}
data_size = swab3(&hdr2[0]);
if (!quiet) {
fprintf(stderr, "Sound length: %-8d ", data_size);
fprintf(stderr, "Sample Rate: %-8d ",sample_rate);
fprintf(stderr, "Channels: %-2d ", channels);
fprintf(stderr, "Compression type: %-2d\n", comp_type);
}
/* fall through */
case Sound_data:
if (type == Sound_data) {
size = 5;
if ((read(fd, hdr2, size)) == -1) {
cleanup(errno, "cannot read header2");
}
data_size = swab3(&hdr2[0]) - 2;
/* ignore sample_rate if set by extended block */
if (!got_extended)
{
sample_rate = (1000000 / (256 - hdr2[3])) / channels;
comp_type = hdr2[4];
}
if (!quiet) {
fprintf(stderr, "Sound length: %-8d ", data_size);
fprintf(stderr, "Sample Rate: %-8d ",sample_rate);
fprintf(stderr, "Channels: %-2d ", channels);
fprintf(stderr, "Compression type: %-2d\n", comp_type);
}
}
if ( channels != 1 && channels != 2 ) {
cleanup("cannot handle more than 2 channels");
}
do {
buf = buf == buf1 ? buf2 : buf1;
switch (comp_type) {
case 3: /* 2 bit sound */
size = data_size > bufferSize/4 ? bufferSize/4 : data_size;
break;
case 2: /* 2.6 bit sound */
size = data_size > bufferSize/3 ? bufferSize/3 : data_size;
break;
case 1: /* 4 bit sound */
size = data_size > bufferSize/2 ? bufferSize/2 : data_size;
break;
case 0: /* 8 bit sound */
default:
size = data_size > bufferSize ? bufferSize : data_size;
break;
}
if ((read(fd, buf, size)) == -1) {
if (errno == E_EOF) {
break;
} else {
cleanup(errno, "cannot read file");
}
}
data_size -= size;
switch (comp_type) {
case 1: /* 4 bit sound */
expand2(buf,size);
size <<= 1;
break;
case 2: /* 2.6 bit sound */
expand3(buf,size);
size *= 3;
break;
case 3: /* 2 bit sound */
expand4(buf,size);
size <<= 2;
break;
}
if (channels == 2) {
process(buf, size);
} else {
process1(buf, size);
}
/* wait till last play is done */
while ( sigarrived == 0) {
sleepTime = 0;
tsleep(sleepTime);
sig_pending = 0;
}
sigarrived = 0;
_ss_play(1, buf, channels == 1 ? size*2 : size,
sample_rate, SND_SENDSIG, SIG_CODE);
} while (data_size > 0);
/* set flag so we don't sleep till we get the signal back */
sig_pending = 1;
break;
#if 0
default:
fprintf(stderr, "Unknown data block type: %d\n", type);
#endif
}
}
}
process(buf, n)
unsigned char *buf;
int n;
{
int i;
for (i = 0; i < n; i++) {
buf[i] -= 0x80;
}
}
process1(buf, n)
unsigned char *buf;
int n;
{
int i;
for (i = n - 1; i >= 0 ; i--) {
buf[2*i + 1] = buf[2*i] = buf[i] - 0x80;
}
}
/* 4-bit compression - expand 4,4 bits into 2 samples */
static expand2(buf, n)
unsigned char *buf;
int n;
{
int i;
for (i = n-1; i >= 0; i--) {
buf[2*i] = buf[i] & 0xf0;
buf[2*i + 1] = (buf[i] << 4) & 0xf0;
}
}
/* 2.6-bit compression - expand 3,3,2 bits into 3 samples */
static expand3(buf, n)
unsigned char *buf;
int n;
{
int i;
for (i = n-1; i >= 0; i--) {
buf[3*i] = buf[i] & 0xe0;
buf[3*i + 1] = (buf[i] << 3) & 0xe0;
buf[3*i + 2] = (buf[i] << 6) & 0xc0;
}
}
/* 2-bit compression - expand 2,2,2,2 bits into 4 samples */
static expand4(buf, n)
unsigned char *buf;
int n;
{
int i;
for (i = n-1; i >= 0; i--) {
buf[4*i] = buf[i] & 0xc0;
buf[4*i + 1] = (buf[i] << 2) & 0xc0;
buf[4*i + 2] = (buf[i] << 4) & 0xc0;
buf[4*i + 3] = (buf[i] << 6) & 0xc0;
}
}
int swab3(x)
register unsigned char *x;
{
return x[0] | (x[1] << 8) | (x[2] << 16);
}
static int swab(x)
register unsigned char *x;
{
return x[0] | (x[1] << 8);
}