This is cnv.c in view mode; [Download] [Up]
/*
cnv.c
author : jolly - alias Patrick
version : 1.00
additional remark : lines between the defines FROM_Thomas_Funke are added from
Thomas Funke - thf@z*.de
ADPCM3 support added by kiwi@belly, April '94
*/
#import <libc.h>
#import <sound/sound.h>
#import "precomp.h"
void cnv_snd(char *newdir,char *outdir,char *fname)
{
struct zyxel header;
char str[MAXPATHLEN];
char str2[MAXPATHLEN];
FILE *feil,*infd,*outfd;
feil=tmpfile();
sprintf(str,"%s/%s%s",newdir,fname,Z_EXT);
infd=fopen(str,"r");
if(infd==NULL) log("cnv_snd: no infile %s", str);
else
{
sprintf(str2,"%s/conv.snd",outdir);
outfd=fopen(str2,"w+");
if(outfd==NULL) log("cnv_snd: error opening outfile %s",str2);
else
{
fread(&header,sizeof(struct zyxel),1,infd);
switch(isZyXEL(&header))
{
case ZYX_AD2: ad2(feil,infd);lin96_to_mulaw(feil,outfd);break;
case ZYX_AD3: ad3(feil,infd);lin96_to_mulaw(feil,outfd);break;
default :return;
}
fclose(outfd);
}
fclose(infd);
/* The nohup prevents the sndconvert being killed by am's Hangup.
Absolute paths are needed because the chdir(PATH) in am.c doesn't
affect the CWD of the shell.
kiwi@belly
NEEDS WORK
*/
sprintf(str,"nohup sndconvert -o %s/%s/%s.snd -f 1 -s 8012 %s/%s >/dev/console 2>&1 &",
PATH,outdir,fname,PATH,str2);
#if DEBUG
log(str);
#endif
system(str);
}
return;
}
void ad2(FILE *feil,FILE *infd)
{
u_char buf;
short sample[4];
#ifndef __BIG_ENDIAN__
char *little_endian=(char *)sample;
#endif
do
{
fread(&buf,1,1,infd);
if(buf==DLE)
{
fread(&buf,1,1,infd);
if(buf!=DLE) fread(&buf,1,1,infd);
}
sample[0]=ad2_to_lin16( (buf&0xc0)>>6);
sample[1]=ad2_to_lin16( (buf&0x30)>>4);
sample[2]=ad2_to_lin16( (buf&0x0c)>>2);
sample[3]=ad2_to_lin16( (buf&0x03) );
#ifdef __BIG_ENDIAN__
fwrite(sample,sizeof(short),4,feil);
#else
fwrite(little_endian+1,sizeof(char),1,feil);
fwrite(little_endian+0,sizeof(char),1,feil);
fwrite(little_endian+3,sizeof(char),1,feil);
fwrite(little_endian+2,sizeof(char),1,feil);
fwrite(little_endian+5,sizeof(char),1,feil);
fwrite(little_endian+4,sizeof(char),1,feil);
fwrite(little_endian+7,sizeof(char),1,feil);
fwrite(little_endian+6,sizeof(char),1,feil);
#endif
}
while(!feof(infd));
}
/* pos needs to be reset when starting new conversion, so I moved it
out of con_ad3 (pos is the byte position relative to start of sample)
*/
static int pos = 0;
void con_ad3(u_char buf, FILE *feil)
{
static int Pack;
static short sample[8];
#ifndef __BIG_ENDIAN__
char *little_endian=(char *)sample;
#endif
switch(pos)
{
case 0: sample[0]=ad3_to_lin16((buf&0xe0)>>5) ; /* XXX- ---- */
sample[1]=ad3_to_lin16((buf&0x1c)>>2) ; /* ---X XX-- */
Pack = (buf&0x03)<<1 ;
break;
case 1: sample[2]=ad3_to_lin16(Pack|((buf&0x80)>>7)) ;
sample[3]=ad3_to_lin16((buf&0x70)>>4) ; /* -XXX ---- */
sample[4]=ad3_to_lin16((buf&0x0e)>>1) ; /* ---- XXX- */
Pack = (buf&0x01)<<2 ;
break;
case 2: sample[5]=ad3_to_lin16(Pack|((buf&0xc0)>>6)) ;
sample[6]=ad3_to_lin16((buf&0x38)>>3) ; /* --XX X--- */
sample[7]=ad3_to_lin16(buf&0x07) ; /* ---- -XXX */
#ifdef __BIG_ENDIAN__
fwrite(sample,sizeof(short),8,feil);
#else
fwrite(little_endian+1,sizeof(char),1,feil);
fwrite(little_endian+0,sizeof(char),1,feil);
fwrite(little_endian+3,sizeof(char),1,feil);
fwrite(little_endian+2,sizeof(char),1,feil);
fwrite(little_endian+5,sizeof(char),1,feil);
fwrite(little_endian+4,sizeof(char),1,feil);
fwrite(little_endian+7,sizeof(char),1,feil);
fwrite(little_endian+6,sizeof(char),1,feil);
fwrite(little_endian+9,sizeof(char),1,feil);
fwrite(little_endian+8,sizeof(char),1,feil);
fwrite(little_endian+11,sizeof(char),1,feil);
fwrite(little_endian+10,sizeof(char),1,feil);
fwrite(little_endian+13,sizeof(char),1,feil);
fwrite(little_endian+12,sizeof(char),1,feil);
fwrite(little_endian+15,sizeof(char),1,feil);
fwrite(little_endian+14,sizeof(char),1,feil);
#endif
break;
};
pos++;
if(pos == 3) pos = 0;
}
void ad3(FILE *feil,FILE *infd)
{
u_char buf;
pos = 0; /* starting at position zero (see con_ad3 for details) */
do
{
fread(&buf,1,1,infd);
if(buf==DLE)
{
fread(&buf,1,1,infd);
if(buf!=DLE)
{
/* This is a workaround for a bug in rec_message, but
since rec_message was fixed, it shouldn't be triggered
in future recordings (see DOUBLE_DLE in am.c)
kiwi@belly
*/
fprintf(stderr, "Bug triggered with %x\n",buf);
con_ad3(0x10, feil);
}
}
con_ad3(buf, feil);
}
while(!feof(infd));
}
short ad2_to_lin16(u_char c)
{
static int M[]={0x3800,0x5600};
static int A=0;
static int delta=5;
static char sign;
static char data;
sign=c>>1;
data=c&1;
#define FROM_Thomas_Funke
if (!sign)
A += delta * data + 0.5 *delta;
else
A -= delta * data + 0.5 *delta;
if (A <= -0x7ffe)
A = -0x7ffe;
else {
if (A >= 0x7ffe)
A = 0x7ffe;
}
delta = M[(int)data] * delta;
delta += 0x2000;
delta >>= 14; // div 16384
if (delta < 5)
delta = 5;
#undef FROM_Thomas_Funke
return A;
}
/*********************
ADPCM3 conversion was included by kiwi@belly on 31.3.94.
The code is based heavily on a program source by ZyXEL Corporation.
I just adapted it to fit in here.
kiwi@belly
**********************/
short ad3_to_lin16(u_char c)
{
static int M[]={0x399A, 0x3A9F, 0x4D14, 0x6607 };
static int A=0;
static int delta=5;
static char sign;
static char data;
int TmpMax ;
long t0 ;
/******* This part is modified for the Firmware > 6.10 **************/
t0 = (long)A ;
t0 *= 3973 ;
t0 += 2048 ;
t0 /= 4096 ;
A = (int)t0 ;
/********************************************************************/
sign=c & 4;
data=c & 3;
if ( (delta&1) && !sign )
++A ;
/* calculate A */
TmpMax = (delta>>1) ;
while ( data-- )
TmpMax += delta ;
if ( sign )
A -= TmpMax ;
else
A += TmpMax ;
if (A <= -0x7ffe)
A = 0;
else {
if (A >= 0x7ffe)
A = 0;
}
/* calc new delta */
delta = delta * M[(int)c & 3];
delta += 0x2000;
delta >>= 14; // div 16384
if(delta <1) delta=1;
return A;
}
/* */
void lin96_to_mulaw(FILE *feil,FILE *outfd)
{
int len;
SNDSoundStruct snd;
short sample[6];
len=ftell(feil);
rewind(feil);
snd.magic =htonl(SND_MAGIC);
snd.dataLocation =htonl(sizeof(SNDSoundStruct));
snd.dataSize =htonl((long)len/sizeof(short));
snd.dataFormat =htonl(SND_FORMAT_LINEAR_16);
snd.samplingRate =htonl(9600);
snd.channelCount =htonl(1);
strcpy(snd.info,"jr"); // yep Jolly Roger !
fwrite(&snd,sizeof(SNDSoundStruct),1,outfd);
do
{
fread(sample,sizeof(short),1,feil);
fwrite(sample,sizeof(short),1,outfd );
}
while(!feof(feil));
return;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.