/*****************************************************************************
Author/Date                         :  C. Strellis 28/6/02
Version Number                      :  1.0
Comment:

Converts a .em1 Emax sample disk into a 16 bit linear wav file.

*****************************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/*
 * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
 *
 * First, a biased linear code is derived from the code word. An unbiased
 * output can then be obtained by subtracting 33 from the biased code.
 *
 * Note that this function expects to be passed the complement of the
 * original code word. This is in keeping with ISDN conventions.
 */
/*
 * g711.c
 *
 * u-law, A-law and linear PCM conversions.
 */
#define	SIGN_BIT	(0x80)		/* Sign bit for a A-law byte. */
#define	QUANT_MASK	(0xf)		/* Quantization field mask. */
#define	NSEGS		(8)		/* Number of A-law segments. */
#define	SEG_SHIFT	(4)		/* Left shift for segment number. */
#define	SEG_MASK	(0x70)		/* Segment field mask. */
#define	BIAS		(0x84)		/* Bias for linear code. */

int ulaw2linear( unsigned char u_val)
{
	int		t;

	/* Complement to obtain normal u-law value. */
	u_val = ~u_val;

	/*
	 * Extract and bias the quantization bits. Then
	 * shift up by the segment number and subtract out the bias.
	 */
	t = ((u_val & QUANT_MASK) << 3) + BIAS;
	t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;

	return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}



void main(int argc,char *argv[])
{

/* Program variables */

   FILE   *em1file,*wavfile;
   char   *imipf,path[100],wavpath[100];
   int    pathlength;
   long  d, hisf, losf, mostsamp, upsamp, losamp, leastsamp;
   long  len,hertz, samples, mostdat, updat, lodat, leastdat;
   int  func,value;
   char  lo,hi,infname,outfname;
   char	  *sr_val
   ;
/* Print help if no arguments specified */

     if (argc == 1)
     {
	printf("This program converts a .em1 EMax sample disk into a 16 bit linear wav file.\n");
	printf("\nSyntax: emu2wav input_filename samplerate\n\n");
	printf("\ne.g. emu2wav zd700.em1 39000\n\n");
	printf("\nThe output file will be input_filename with a .wav extensions.\n");
	exit ( EXIT_SUCCESS );
     }
/* Open input and output files */

     imipf = argv[1];
     if ((em1file=fopen(imipf,"rb")) == NULL) {
	printf("ERROR in EMU2WAV: Cannot open .em1 data file %s.\n",imipf);
	exit ( EXIT_SUCCESS );
     }
     pathlength = strlen(imipf);
     sprintf(path,"%s",imipf);
     path[pathlength-4]='\0';

     sprintf(wavpath,"%s.wav",path);
     wavfile=fopen(wavpath,"wb");
     if (wavfile == NULL)
     {
	  printf("ERROR in EMU2WAV: Cannot open wav file %s.\n",wavpath);
	  exit ( EXIT_SUCCESS );
     }
/* Read the command line parameters */
	sr_val = argv[2];
	hertz = (int) atoi(sr_val);
	if (hertz == NULL)
	{
	   printf("ERROR in EMU2WAV: Sample Rate not specified");
	   exit ( EXIT_SUCCESS );
	}

   hisf = int(hertz/256);
   losf = int(hertz-(256*hisf));


   fseek(em1file,0L, SEEK_END);
   samples = ftell(em1file);
   fseek(em1file,0L, SEEK_SET);

   printf("Number of samples = %ld",samples);

   samples += 36;

   mostsamp=int(samples/16777216);
   upsamp=int((samples-(16777216*mostsamp))/65536);
   losamp =int((samples-(16777216*mostsamp)-(65536*upsamp))/256);
   leastsamp =int(samples-(16777216*mostsamp)-(65536*upsamp)-(256*losamp));
   samples =samples-36;
   mostdat =int(samples/16777216);
   updat =int((samples-(16777216*mostdat))/65536);
   lodat =int((samples-(16777216*mostdat)-(65536*updat))/256);
   leastdat =int(samples-(16777216*mostdat)-(65536*updat)-(256*lodat));

   putc(0x52, wavfile);
   putc(0x49, wavfile);
   putc(0x46, wavfile);
   putc(0x46, wavfile);
   putc(leastsamp, wavfile);
   putc(losamp, wavfile);
   putc(upsamp, wavfile);
   putc(mostsamp, wavfile);
   putc(0x57, wavfile);
   putc(0x41, wavfile);
   putc(0x56, wavfile);
   putc(0x45, wavfile);
   putc(0x66, wavfile);
   putc(0x6d, wavfile);
   putc(0x74, wavfile);
   putc(0x20, wavfile);
   putc(0x10, wavfile);
   putc(0, wavfile);
   putc(0, wavfile);
   putc(0, wavfile);
   putc(1, wavfile);
   putc(0, wavfile);
   putc(1, wavfile);
   putc(0, wavfile);
   putc(losf, wavfile);
   putc(hisf, wavfile);
   putc(0, wavfile);
   putc(0, wavfile);
   putc(losf, wavfile);
   putc(hisf, wavfile);
   putc(0, wavfile);
   putc(0, wavfile);
/*   putc(1, wavfile); 8 bit  */
   putc(2, wavfile);/* 16 bit */
   putc(0, wavfile);
/*   putc(8, wavfile); 8 bit  */
   putc(16, wavfile);/* 16 bit */
   putc(0, wavfile);
   putc(0x64, wavfile);
   putc(0x61, wavfile);
   putc(0x74, wavfile);
   putc(0x61, wavfile);
   putc(leastdat, wavfile);
   putc(lodat, wavfile);
   putc(updat, wavfile);
   putc(mostdat, wavfile);

   for (len=1;len<=samples;len++)
    {
       func = fgetc(em1file);

       if (func>128)
	 func=384-func;
       else
	 if (func<128)
	    func=127-func;

      value = ulaw2linear(func);
      hi = int(value/256);
      lo = int(value-(256*hi));
      putc(lo, wavfile);
      putc(hi, wavfile);
    }



/* close all files*/
	fclose(em1file);
	fclose(wavfile);

    printf("\nDONE !\n");

}

/***************************************************************************/



