www.pudn.com > ampegsrc.zip > MUSICIN.C


/********************************************************************** 
Copyright (c) 1991 MPEG/audio software simulation group, All Rights Reserved 
musicin.c 
**********************************************************************/ 
/********************************************************************** 
 * MPEG/audio coding/decoding software, work in progress              * 
 *   NOT for public distribution until verified and approved by the   * 
 *   MPEG/audio committee.  For further information, please contact   * 
 *   Davis Pan, 508-493-2241, e-mail: pan@3d.enet.dec.com             * 
 *                                                                    * 
 * VERSION 4.0                                                        * 
 *   changes made since last update:                                  * 
 *   date   programmers         comment                               * 
 * 3/01/91  Douglas Wong,       start of version 1.1 records          * 
 *          Davis Pan                                                 * 
 * 3/06/91  Douglas Wong,       rename: setup.h to endef.h            * 
 *                              removed extraneous variables          * 
 * 3/21/91  J.Georges Fritsch   introduction of the bit-stream        * 
 *                              package. This package allows you      * 
 *                              to generate the bit-stream in a       * 
 *                              binary or ascii format                * 
 * 3/31/91  Bill Aspromonte     replaced the read of the SB matrix    * 
 *                              by an "code generated" one            * 
 * 5/10/91  W. Joseph Carter    Ported to Macintosh and Unix.         * 
 *                              Incorporated Jean-Georges Fritsch's   * 
 *                              "bitstream.c" package.                * 
 *                              Modified to strictly adhere to        * 
 *                              encoded bitstream specs, including    * 
 *                              "Berlin changes".                     * 
 *                              Modified user interface dialog & code * 
 *                              to accept any input & output          * 
 *                              filenames desired.  Also added        * 
 *                              de-emphasis prompt and final bail-out * 
 *                              opportunity before encoding.          * 
 *                              Added AIFF PCM sound file reading     * 
 *                              capability.                           * 
 *                              Modified PCM sound file handling to   * 
 *                              process all incoming samples and fill * 
 *                              out last encoded frame with zeros     * 
 *                              (silence) if needed.                  * 
 *                              Located and fixed numerous software   * 
 *                              bugs and table data errors.           * 
 * 27jun91  dpwe (Aware Inc)    Used new frame_params struct.         * 
 *                              Clear all automatic arrays.           * 
 *                              Changed some variable names,          * 
 *                              simplified some code.                 * 
 *                              Track number of bits actually sent.   * 
 *                              Fixed padding slot, stereo bitrate    * 
 *                              Added joint-stereo : scales L+R.      * 
 * 6/12/91  Earle Jennings      added fix for MS_DOS in obtain_param  * 
 * 6/13/91  Earle Jennings      added stack length adjustment before  * 
 *                              main for MS_DOS                       * 
 * 7/10/91  Earle Jennings      conversion of all float to FLOAT      * 
 *                              port to MsDos from MacIntosh completed* 
 * 8/ 8/91  Jens Spille         Change for MS-C6.00                   * 
 * 8/22/91  Jens Spille         new obtain_parameters()               * 
 *10/ 1/91  S.I. Sudharsanan,   Ported to IBM AIX platform.           * 
 *          Don H. Lee,                                               * 
 *          Peter W. Farrett                                          * 
 *10/ 3/91  Don H. Lee          implemented CRC-16 error protection   * 
 *                              newly introduced functions are        * 
 *                              I_CRC_calc, II_CRC_calc and encode_CRC* 
 *                              Additions and revisions are marked    * 
 *                              with "dhl" for clarity                * 
 *11/11/91 Katherine Wang       Documentation of code.                * 
 *                                (variables in documentation are     * 
 *                                surround by the # symbol, and an '*'* 
 *                                denotes layer I or II versions)     * 
 * 2/11/92  W. Joseph Carter    Ported new code to Macintosh.  Most   * 
 *                              important fixes involved changing     * 
 *                              16-bit ints to long or unsigned in    * 
 *                              bit alloc routines for quant of 65535 * 
 *                              and passing proper function args.     * 
 *                              Removed "Other Joint Stereo" option   * 
 *                              and made bitrate be total channel     * 
 *                              bitrate, irrespective of the mode.    * 
 *                              Fixed many small bugs & reorganized.  * 
 * 2/25/92  Masahiro Iwadare    made code cleaner and more consistent * 
 * 8/07/92  Mike Coleman        make exit() codes return error status * 
 *                              made slight changes for portability   * 
 *19 aug 92 Soren H. Nielsen    Changed MS-DOS file name extensions.  * 
 * 8/25/92  Shaun Astarabadi    Replaced rint() function with explicit* 
 *                              rounding for portability with MSDOS.  * 
 * 9/22/92  jddevine@aware.com  Fixed _scale_factor_calc() calls.     * 
 *10/19/92  Masahiro Iwadare    added info->mode and info->mode_ext   * 
 *                              updates for AIFF format files         * 
 * 3/10/93  Kevin Peterson      In parse_args, only set non default   * 
 *                              bit rate if specified in arg list.    * 
 *                              Use return value from aiff_read_hdrs  * 
 *                              to fseek to start of sound data       * 
 * 7/26/93  Davis Pan           fixed bug in printing info->mode_ext  * 
 *                              value for joint stereo condition      * 
 * 8/27/93 Seymour Shlien,      Fixes in Unix and MSDOS ports,        * 
 *         Daniel Lauzon, and                                         * 
 *         Bill Truerniet                                             * 
 **********************************************************************/ 
 
 
#include  
#include "common.h" 
#include "encoder.h" 
 
/* Global variable definitions for "musicin.c" */ 
 
FILE               *musicin; 
Bit_stream_struc   bs; 
char               *programName; 
 
/* Implementations */ 
 
/************************************************************************ 
/* 
/* obtain_parameters 
/* 
/* PURPOSE:  Prompts for and reads user input for encoding parameters 
/* 
/* SEMANTICS:  The parameters read are: 
/* - input and output filenames 
/* - sampling frequency (if AIFF file, will read from the AIFF file header) 
/* - layer number 
/* - mode (stereo, joint stereo, dual channel or mono) 
/* - psychoacoustic model (I or II) 
/* - total bitrate, irrespective of the mode 
/* - de-emphasis, error protection, copyright and original or copy flags 
/* 
/************************************************************************/ 
 
void 
obtain_parameters(fr_ps,psy,num_samples,original_file_name,encoded_file_name) 
frame_params    *fr_ps; 
int             *psy; 
unsigned long   *num_samples; 
char            original_file_name[MAX_NAME_SIZE]; 
char            encoded_file_name[MAX_NAME_SIZE]; 
 
{ 
    int j; 
    int x; 
    char default_file_name[MAX_NAME_SIZE]; 
    long int freq; 
    int model, brt; 
    char t[50]; 
    IFF_AIFF pcm_aiff_data; 
    layer *info = fr_ps->header; 
    long soundPosition; 
  
    do  { 
       printf("Enter PCM input file name : "); 
       gets(original_file_name); 
       if (original_file_name[0] == NULL_CHAR) 
       printf("PCM input file name is required.\n"); 
    } while (original_file_name[0] == NULL_CHAR); 
    printf(">>> PCM input file name is: %s\n", original_file_name); 
  
    if ((musicin = fopen(original_file_name, "rb")) == NULL) { 
       printf("Could not find \"%s\".\n", original_file_name); 
       exit(1); 
    } 
    x=0; 
    while (x <= MAX_NAME_SIZE) 
    { 
	default_file_name[x] = NULL_CHAR; 
	++x; 
	} 
    x=0; 
    while (x <= 8) 
    { 
   default_file_name[x] = original_file_name[x]; 
    if (original_file_name[++x] == '.')  
	x = 9; 
   
    } 
    
    strcat(default_file_name,DFLT_EXT); 
 
    printf("Enter MPEG encoded output file name <%s>: ", 
	   default_file_name); /* 92-08-19 shn */ 
    gets(encoded_file_name); 
    if (encoded_file_name[0] == NULL_CHAR) { 
  
	/* replace old extension with new one, 92-08-19 shn */ 
       strcpy(encoded_file_name,default_file_name); 
/* 
	strcat(strcpy(encoded_file_name, original_file_name), DFLT_EXT); 
*/  
    } 
        
 
    printf(">>> MPEG encoded output file name is: %s\n", encoded_file_name); 
  
    open_bit_stream_w(&bs, encoded_file_name, BUFFER_SIZE); 
  
    if ((soundPosition = aiff_read_headers(musicin, &pcm_aiff_data)) != -1) { 
 
       printf(">>> Using Audio IFF sound file headers\n"); 
 
       aiff_check(original_file_name, &pcm_aiff_data); 
 
       if (fseek(musicin, soundPosition, SEEK_SET) != 0) { 
	  printf("Could not seek to PCM sound data in \"%s\".\n", 
		 original_file_name); 
	  exit(1); 
       } 
 
       info->sampling_frequency = SmpFrqIndex((long)pcm_aiff_data.sampleRate); 
       printf(">>> %.f Hz sampling frequency selected\n", 
	      pcm_aiff_data.sampleRate); 
 
       /* Determine number of samples in sound file */ 
#ifndef MS_DOS 
       *num_samples = pcm_aiff_data.numChannels * 
		      pcm_aiff_data.numSampleFrames; 
#else 
       *num_samples = (long)(pcm_aiff_data.numChannels) * 
		      (long)(pcm_aiff_data.numSampleFrames); 
#endif 
 
    } 
    else {    /* Not using Audio IFF sound file headers. */ 
 
       printf("What is the sampling frequency? <44100>[Hz]: "); 
       gets(t); 
       freq = atol(t); 
       switch (freq) { 
	  case 48000 : info->sampling_frequency = 1; 
	      printf(">>> %ld Hz sampling freq selected\n", freq); 
	      break; 
	  case 44100 : info->sampling_frequency = 0; 
	      printf(">>> %ld Hz sampling freq selected\n", freq); 
	      break; 
	  case 32000 : info->sampling_frequency = 2; 
	      printf(">>> %ld Hz sampling freq selected\n", freq); 
	      break; 
	  default:    info->sampling_frequency = 0; 
	      printf(">>> Default 44.1 kHz samp freq selected\n"); 
       } 
  
       if (fseek(musicin, 0, SEEK_SET) != 0) { 
	  printf("Could not seek to PCM sound data in \"%s\".\n", 
		  original_file_name); 
	  exit(1); 
       } 
  
       /* Declare sound file to have "infinite" number of samples. */ 
       *num_samples = MAX_U_32_NUM; 
 
    } 
 
    printf("Which layer do you want to use?\n"); 
    printf("Available: Layer (1), Layer (<2>): "); 
    gets(t); 
    switch(*t){ 
       case '1': info->lay = 1; printf(">>> Using Layer %s\n",t); break; 
       case '2': info->lay = 2; printf(">>> Using Layer %s\n",t); break; 
       default:  info->lay = 2; printf(">>> Using default Layer 2\n"); break; 
    } 
 
    printf("Which mode do you want?\n"); 
    printf("Available: ()tereo, (j)oint stereo, "); 
    printf("(d)ual channel, s(i)ngle Channel: "); 
    gets(t); 
    switch(*t){ 
       case 's': 
       case 'S': 
	  info->mode = MPG_MD_STEREO; info->mode_ext = 0; 
	  printf(">>> Using mode %s\n",t); 
	  break; 
       case 'j': 
       case 'J': 
	  info->mode = MPG_MD_JOINT_STEREO; 
	  printf(">>> Using mode %s\n",t); 
	  break; 
       case 'd': 
       case 'D': 
	  info->mode = MPG_MD_DUAL_CHANNEL; info->mode_ext = 0; 
	  printf(">>> Using mode %s\n",t); 
	  break; 
       case 'i': 
       case 'I': 
	  info->mode = MPG_MD_MONO; info->mode_ext = 0; 
	  printf(">>> Using mode %s\n",t); 
	  break; 
       default: 
	  info->mode = MPG_MD_STEREO; info->mode_ext = 0; 
	  printf(">>> Using default stereo mode\n"); 
	  break; 
    } 
 
    printf("Which psychoacoustic model do you want to use? <2>: "); 
    gets(t); 
    model = atoi(t); 
    if (model > 2 || model < 1) { 
       printf(">>> Default model 2 selected\n"); 
       *psy = 2; 
    } 
    else { 
       *psy = model; 
       printf(">>> Using psychoacoustic model %d\n", model); 
    } 
  
    printf("What is the total bitrate? <%u>[kbps]: ", DFLT_BRT); 
    gets(t); 
    brt = atoi(t); 
    if (brt == 0) brt = -10; 
    j=0; 
    while (j<15) { 
       if (bitrate[info->lay-1][j] == brt) break; 
       j++; 
    } 
    if (j==15) { 
       printf(">>> Using default %u kbps\n", DFLT_BRT); 
       for (j=0;j<15;j++) 
	  if (bitrate[info->lay-1][j] == DFLT_BRT) { 
	     info->bitrate_index = j; 
	     break; 
	  } 
    } 
    else{ 
       info->bitrate_index = j; 
       printf(">>> Bitrate = %d kbps\n", bitrate[info->lay-1][j]); 
    } 
  
    printf("What type of de-emphasis should the decoder use?\n"); 
    printf("Available: ()one, (5)0/15 microseconds, (c)citt j.17: "); 
    gets(t); 
    if (*t != 'n' && *t != '5' && *t != 'c') { 
       printf(">>> Using default no de-emphasis\n"); 
       info->emphasis = 0; 
    } 
    else { 
       if (*t == 'n')      info->emphasis = 0; 
       else if (*t == '5') info->emphasis = 1; 
       else if (*t == 'c') info->emphasis = 3; 
       printf(">>> Using de-emphasis %s\n",t); 
    } 
  
/*  Start 2. Part changes for CD Ver 3.2; jsp; 22-Aug-1991 */ 
  
    printf("Do you want to set the private bit? (y/): "); 
    gets(t); 
    if (*t == 'y' || *t == 'Y') info->extension = 1; 
    else                        info->extension = 0; 
    if(info->extension) printf(">>> Private bit set\n"); 
    else                printf(">>> Private bit not set\n"); 
  
/*  End changes for CD Ver 3.2; jsp; 22-Aug-1991 */ 
  
    printf("Do you want error protection? (y/): "); 
    gets(t); 
    if (*t == 'y' || *t == 'Y') info->error_protection = TRUE; 
    else                        info->error_protection = FALSE; 
    if(info->error_protection) printf(">>> Error protection used\n"); 
    else printf(">>> Error protection not used\n"); 
  
    printf("Is the material copyrighted? (y/): "); 
    gets(t); 
    if (*t == 'y' || *t == 'Y') info->copyright = 1; 
    else                        info->copyright = 0; 
    if(info->copyright) printf(">>> Copyrighted material\n"); 
    else                printf(">>> Material not copyrighted\n"); 
  
    printf("Is this the original? (y/): "); 
    gets(t); 
    if (*t == 'y' || *t == 'Y') info->original = 1; 
    else                        info->original = 0; 
    if(info->original) printf(">>> Original material\n"); 
    else               printf(">>> Material not original\n"); 
  
    printf("Do you wish to exit (last chance before encoding)? (y/): "); 
    gets(t); 
    if (*t == 'y' || *t == 'Y') exit(0); 
} 
 
/************************************************************************ 
/* 
/* parse_args 
/* 
/* PURPOSE:  Sets encoding parameters to the specifications of the 
/* command line.  Default settings are used for parameters 
/* not specified in the command line. 
/* 
/* SEMANTICS:  The command line is parsed according to the following 
/* syntax: 
/* 
/* -l  is followed by the layer number 
/* -m  is followed by the mode 
/* -p  is followed by the psychoacoustic model number 
/* -s  is followed by the sampling rate 
/* -b  is followed by the total bitrate, irrespective of the mode 
/* -d  is followed by the emphasis flag 
/* -c  is followed by the copyright/no_copyright flag 
/* -o  is followed by the original/not_original flag 
/* -e  is followed by the error_protection on/off flag 
/* 
/* If the input file is in AIFF format, the sampling frequency is read 
/* from the AIFF header. 
/* 
/* The input and output filenames are read into #inpath# and #outpath#. 
/* 
/************************************************************************/ 
  
void 
parse_args(argc, argv, fr_ps, psy, num_samples, inPath, outPath) 
int     argc; 
char    **argv; 
frame_params  *fr_ps; 
int     *psy; 
unsigned long *num_samples; 
char    inPath[MAX_NAME_SIZE]; 
char    outPath[MAX_NAME_SIZE]; 
{ 
   FLOAT srate; 
   int   brate; 
   layer *info = fr_ps->header; 
   int   err = 0, i = 0; 
   IFF_AIFF pcm_aiff_data; 
   long samplerate; 
   long soundPosition; 
  
   /* preset defaults */ 
   inPath[0] = '\0';   outPath[0] = '\0'; 
   info->lay = DFLT_LAY; 
   switch(DFLT_MOD) { 
      case 's': info->mode = MPG_MD_STEREO; info->mode_ext = 0; break; 
      case 'd': info->mode = MPG_MD_DUAL_CHANNEL; info->mode_ext=0; break; 
      case 'j': info->mode = MPG_MD_JOINT_STEREO; break; 
      case 'm': info->mode = MPG_MD_MONO; info->mode_ext = 0; break; 
      default: 
	 fprintf(stderr, "%s: Bad mode dflt %c\n", programName, DFLT_MOD); 
	 abort(); 
   } 
   *psy = DFLT_PSY; 
   if((info->sampling_frequency = SmpFrqIndex((long)(1000*DFLT_SFQ))) < 0) { 
      fprintf(stderr, "%s: bad sfrq default %.2f\n", programName, DFLT_SFQ); 
      abort(); 
   } 
   if((info->bitrate_index = BitrateIndex(info->lay, DFLT_BRT)) < 0) { 
      fprintf(stderr, "%s: bad default bitrate %u\n", programName, DFLT_BRT); 
      abort(); 
   } 
   switch(DFLT_EMP) { 
      case 'n': info->emphasis = 0; break; 
      case '5': info->emphasis = 1; break; 
      case 'c': info->emphasis = 3; break; 
      default:  
	 fprintf(stderr, "%s: Bad emph dflt %c\n", programName, DFLT_EMP); 
	 abort(); 
   } 
   info->copyright = 0; info->original = 0; info->error_protection = FALSE; 
  
   /* process args */ 
   while(++ilay = atoi(arg); argUsed = 1; 
		  if(info->lay<1 || info->lay>2) { 
		     fprintf(stderr,"%s: -l layer must be 1 or 2, not %s\n", 
			  programName, arg); 
		     err = 1; 
		  } 
		  break; 
	       case 'm':        argUsed = 1; 
		  if (*arg == 's') 
		    { info->mode = MPG_MD_STEREO; info->mode_ext = 0; } 
		  else if (*arg == 'd') 
		    { info->mode = MPG_MD_DUAL_CHANNEL; info->mode_ext=0; } 
		  else if (*arg == 'j') 
		    { info->mode = MPG_MD_JOINT_STEREO; } 
		  else if (*arg == 'm') 
		    { info->mode = MPG_MD_MONO; info->mode_ext = 0; } 
		  else { 
		    fprintf(stderr,"%s: -m mode must be s/d/j/m not %s\n", 
			    programName, arg); 
		    err = 1; 
		  } 
		  break; 
	       case 'p':        *psy = atoi(arg); argUsed = 1; 
		  if(*psy<1 || *psy>2) { 
		     fprintf(stderr,"%s: -p model must be 1 or 2, not %s\n", 
			     programName, arg); 
		     err = 1; 
		  } 
		  break; 
 
	       case 's': 
		  argUsed = 1; 
		  srate = atof( arg ); 
		  /* samplerate = rint( 1000.0 * srate ); $A  */ 
		  samplerate = (long) (( 1000.0 * srate ) + 0.5); 
		  if( (info->sampling_frequency = SmpFrqIndex((long) samplerate)) < 0 ) 
		      err = 1; 
		  break; 
		   
	       case 'b':         
		  argUsed = 1; 
		  brate = atoi(arg);  
		  if( (info->bitrate_index = BitrateIndex(info->lay, brate)) < 0) 
		     err=1;                   
		 break; 
	       case 'd':        argUsed = 1; 
		  if (*arg == 'n')                    info->emphasis = 0; 
		  else if (*arg == '5')               info->emphasis = 1; 
		  else if (*arg == 'c')               info->emphasis = 3; 
		  else { 
		     fprintf(stderr,"%s: -d emp must be n/5/c not %s\n", 
			     programName, arg); 
		     err = 1; 
		  } 
		  break; 
		case 'c':       info->copyright = 1; break; 
		case 'o':       info->original  = 1; break; 
		case 'e':       info->error_protection = TRUE; break; 
		default:        fprintf(stderr,"%s: unrec option %c\n", 
					programName, c); 
				err = 1; break; 
	    } 
	    if(argUsed) { 
	       if(arg == token)    token = "";   /* no more from token */ 
	       else                ++i;          /* skip arg we used */ 
	       arg = ""; argUsed = 0; 
	    } 
	 } 
      } 
      else { 
	 if(inPath[0] == '\0')       strcpy(inPath, argv[i]); 
	 else if(outPath[0] == '\0') strcpy(outPath, argv[i]); 
	 else { 
	    fprintf(stderr,"%s: excess arg %s\n", programName, argv[i]); 
	    err = 1; 
	 } 
      } 
   } 
 
   if(err || inPath[0] == '\0') usage();  /* never returns */ 
  
   if(outPath[0] == '\0') { 
      strcpy(outPath, inPath); 
      strcat(outPath, DFLT_EXT); 
   } 
  
   if ((musicin = fopen(inPath, "rb")) == NULL) { 
      printf("Could not find \"%s\".\n", inPath); 
      exit(1); 
   } 
  
   open_bit_stream_w(&bs, outPath, BUFFER_SIZE); 
 
   if ((soundPosition = aiff_read_headers(musicin, &pcm_aiff_data)) != -1) { 
 
      printf(">>> Using Audio IFF sound file headers\n"); 
 
      aiff_check(inPath, &pcm_aiff_data); 
 
      if (fseek(musicin, soundPosition, SEEK_SET) != 0) { 
	 printf("Could not seek to PCM sound data in \"%s\".\n", inPath); 
	 exit(1); 
      } 
 
      info->sampling_frequency = SmpFrqIndex((long)pcm_aiff_data.sampleRate); 
      printf(">>> %.f Hz sampling frequency selected\n", 
	     pcm_aiff_data.sampleRate); 
 
      /* Determine number of samples in sound file */ 
#ifndef MS_DOS 
      *num_samples = pcm_aiff_data.numChannels * 
		     pcm_aiff_data.numSampleFrames; 
#else 
      *num_samples = (long)(pcm_aiff_data.numChannels) * 
		     (long)(pcm_aiff_data.numSampleFrames); 
#endif 
      if ( pcm_aiff_data.numChannels == 1 ) { 
	info->mode = MPG_MD_MONO; 
	info->mode_ext = 0; 
      } 
   } 
   else {    /* Not using Audio IFF sound file headers. */ 
 
      if (fseek(musicin, 0, SEEK_SET) != 0) { 
	 printf("Could not seek to PCM sound data in \"%s\".\n", inPath); 
	 exit(1); 
      } 
  
      /* Declare sound file to have "infinite" number of samples. */ 
      *num_samples = MAX_U_32_NUM; 
 
   } 
 
} 
 
/************************************************************************ 
/* 
/* print_config 
/* 
/* PURPOSE:  Prints the encoding parameters used 
/* 
/************************************************************************/ 
  
void 
print_config(fr_ps, psy, num_samples, inPath, outPath) 
frame_params *fr_ps; 
int     *psy; 
unsigned long *num_samples; 
char    inPath[MAX_NAME_SIZE]; 
char    outPath[MAX_NAME_SIZE]; 
{ 
 layer *info = fr_ps->header; 
  
   printf("Encoding configuration:\n"); 
   if(info->mode != MPG_MD_JOINT_STEREO) 
      printf("Layer=%s   mode=%s   extn=%d   psy model=%d\n", 
	     layer_names[info->lay-1], mode_names[info->mode], 
	     info->mode_ext, *psy); 
   else printf("Layer=%s   mode=%s   extn=data dependant   psy model=%d\n", 
	       layer_names[info->lay-1], mode_names[info->mode], *psy); 
   printf("samp frq=%.1f kHz   total bitrate=%d kbps\n", 
	  s_freq[info->sampling_frequency], 
	  bitrate[info->lay-1][info->bitrate_index]); 
   printf("de-emph=%d   c/right=%d   orig=%d   errprot=%d\n", 
	  info->emphasis, info->copyright, info->original, 
	  info->error_protection); 
   printf("input file: '%s'   output file: '%s'\n", inPath, outPath); 
} 
  
/************************************************************************ 
/* 
/* main 
/* 
/* PURPOSE:  MPEG I Encoder supporting layers 1 and 2, and 
/* psychoacoustic models 1 (MUSICAM) and 2 (AT&T) 
/* 
/* SEMANTICS:  One overlapping frame of audio of up to 2 channels are 
/* processed at a time in the following order: 
/* (associated routines are in parentheses) 
/* 
/* 1.  Filter sliding window of data to get 32 subband 
/* samples per channel. 
/* (window_subband,filter_subband) 
/* 
/* 2.  If joint stereo mode, combine left and right channels 
/* for subbands above #jsbound#. 
/* (*_combine_LR) 
/* 
/* 3.  Calculate scalefactors for the frame, and if layer 2, 
/* also calculate scalefactor select information. 
/* (*_scale_factor_calc) 
/* 
/* 4.  Calculate psychoacoustic masking levels using selected 
/* psychoacoustic model. 
/* (*_Psycho_One, psycho_anal) 
/* 
/* 5.  Perform iterative bit allocation for subbands with low 
/* mask_to_noise ratios using masking levels from step 4. 
/* (*_main_bit_allocation) 
/* 
/* 6.  If error protection flag is active, add redundancy for 
/* error protection. 
/* (*_CRC_calc) 
/* 
/* 7.  Pack bit allocation, scalefactors, and scalefactor select 
/* information (layer 2) onto bitstream. 
/* (*_encode_bit_alloc,*_encode_scale,II_transmission_pattern) 
/* 
/* 8.  Quantize subbands and pack them into bitstream 
/* (*_subband_quantization, *_sample_encoding) 
/* 
/************************************************************************/ 
 
main(argc, argv) 
int     argc; 
char    **argv; 
{ 
typedef double SBS[2][3][SCALE_BLOCK][SBLIMIT]; 
    SBS  FAR        *sb_sample; 
typedef double JSBS[3][SCALE_BLOCK][SBLIMIT]; 
    JSBS FAR        *j_sample; 
typedef double IN[2][HAN_SIZE]; 
    IN   FAR        *win_que; 
typedef unsigned int SUB[2][3][SCALE_BLOCK][SBLIMIT]; 
    SUB  FAR        *subband; 
  
    frame_params fr_ps; 
    layer info; 
    char original_file_name[MAX_NAME_SIZE]; 
    char encoded_file_name[MAX_NAME_SIZE]; 
    short FAR **win_buf; 
static short FAR buffer[2][1152]; 
static unsigned int bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT]; 
static unsigned int scalar[2][3][SBLIMIT], j_scale[3][SBLIMIT]; 
static double FAR ltmin[2][SBLIMIT], lgmin[2][SBLIMIT], max_sc[2][SBLIMIT]; 
    FLOAT snr32[32]; 
    short sam[2][1056]; 
    int whole_SpF, extra_slot = 0; 
    double avg_slots_per_frame, frac_SpF, slot_lag; 
    int model, stereo, error_protection; 
static unsigned int crc; 
    int i, j, k, adb; 
    unsigned long bitsPerSlot, samplesPerFrame, frameNum = 0; 
    unsigned long frameBits, sentBits = 0; 
    unsigned long num_samples; 
 
#ifdef  MACINTOSH 
    console_options.nrows = MAC_WINDOW_SIZE; 
    argc = ccommand(&argv); 
#endif 
 
    /* Most large variables are declared dynamically to ensure 
       compatibility with smaller machines */ 
 
    sb_sample = (SBS FAR *) mem_alloc(sizeof(SBS), "sb_sample"); 
    j_sample = (JSBS FAR *) mem_alloc(sizeof(JSBS), "j_sample"); 
    win_que = (IN FAR *) mem_alloc(sizeof(IN), "Win_que"); 
    subband = (SUB FAR *) mem_alloc(sizeof(SUB),"subband"); 
    win_buf = (short FAR **) mem_alloc(sizeof(short *)*2, "win_buf"); 
  
    /* clear buffers */ 
    memset((char *) buffer, 0, sizeof(buffer)); 
    memset((char *) bit_alloc, 0, sizeof(bit_alloc)); 
    memset((char *) scalar, 0, sizeof(scalar)); 
    memset((char *) j_scale, 0, sizeof(j_scale)); 
    memset((char *) scfsi, 0, sizeof(scfsi)); 
    memset((char *) ltmin, 0, sizeof(ltmin)); 
    memset((char *) lgmin, 0, sizeof(lgmin)); 
    memset((char *) max_sc, 0, sizeof(max_sc)); 
    memset((char *) snr32, 0, sizeof(snr32)); 
    memset((char *) sam, 0, sizeof(sam)); 
  
    fr_ps.header = &info; 
    fr_ps.tab_num = -1;             /* no table loaded */ 
    fr_ps.alloc = NULL; 
    info.version = MPEG_AUDIO_ID; 
 
    programName = argv[0]; 
    if(argc==1)     /* no command-line args */ 
       obtain_parameters(&fr_ps, &model, &num_samples, 
			 original_file_name, encoded_file_name); 
    else 
       parse_args(argc, argv, &fr_ps, &model, &num_samples, 
		  original_file_name, encoded_file_name); 
    print_config(&fr_ps, &model, &num_samples, 
		 original_file_name, encoded_file_name); 
 
    hdr_to_frps(&fr_ps); 
    stereo = fr_ps.stereo; 
    error_protection = info.error_protection; 
  
    if (info.lay == 1) { bitsPerSlot = 32; samplesPerFrame = 384;  } 
    else               { bitsPerSlot = 8;  samplesPerFrame = 1152; } 
    /* Figure average number of 'slots' per frame. */ 
    /* Bitrate means TOTAL for both channels, not per side. */ 
    avg_slots_per_frame = ((double)samplesPerFrame / 
			   s_freq[info.sampling_frequency]) * 
			  ((double)bitrate[info.lay-1][info.bitrate_index] / 
			   (double)bitsPerSlot); 
    whole_SpF = (int) avg_slots_per_frame; 
    printf("slots/frame = %d\n",whole_SpF); 
    frac_SpF  = avg_slots_per_frame - (double)whole_SpF; 
    slot_lag  = -frac_SpF; 
    printf("frac SpF=%.3f, tot bitrate=%d kbps, s freq=%.1f kHz\n", 
	   frac_SpF, bitrate[info.lay-1][info.bitrate_index], 
	   s_freq[info.sampling_frequency]); 
  
    if (frac_SpF != 0) 
       printf("Fractional number of slots, padding required\n"); 
    else info.padding = 0; 
  
    while (get_audio(musicin, buffer, num_samples, stereo, info.lay) > 0) { 
 
       fprintf(stderr, "{%4lu}", frameNum++); fflush(stderr); 
       win_buf[0] = &buffer[0][0]; 
       win_buf[1] = &buffer[1][0]; 
       if (frac_SpF != 0) { 
	  if (slot_lag > (frac_SpF-1.0) ) { 
	     slot_lag -= frac_SpF; 
	     extra_slot = 0; 
	     info.padding = 0; 
	     /*  printf("No padding for this frame\n"); */ 
	  } 
	  else { 
	     extra_slot = 1; 
	     info.padding = 1; 
	     slot_lag += (1-frac_SpF); 
	     /*  printf("Padding for this frame\n");    */ 
	  } 
       } 
       adb = (whole_SpF+extra_slot) * bitsPerSlot; 
 
       switch (info.lay) { 
  
/***************************** Layer I **********************************/ 
  
	  case 1 : 
	     for (j=0;j coding   (dflt %4u)\n",DFLT_LAY); 
    fprintf(stderr," -m mode  channel mode : s/d/j/m   (dflt %4c)\n",DFLT_MOD); 
    fprintf(stderr," -p psy   psychoacoustic model 1/2 (dflt %4u)\n",DFLT_PSY); 
    fprintf(stderr," -s sfrq  input smpl rate in kHz   (dflt %4.1f)\n",DFLT_SFQ); 
    fprintf(stderr," -b br    total bitrate in kbps    (dflt %4u)\n",DFLT_BRT); 
    fprintf(stderr," -d emp   de-emphasis n/5/c        (dflt %4c)\n",DFLT_EMP); 
    fprintf(stderr," -c       mark as copyright\n"); 
    fprintf(stderr," -o       mark as original\n"); 
    fprintf(stderr," -e       add error protection\n"); 
    fprintf(stderr," inputPCM input PCM sound file (standard or AIFF)\n"); 
    fprintf(stderr," outBS    output bit stream of encoded audio (dflt inName+%s)\n", 
	    DFLT_EXT); 
    exit(1); 
} 
 
/************************************************************************ 
/* 
/* aiff_check 
/* 
/* PURPOSE:  Checks AIFF header information to make sure it is valid. 
/*           Exits if not. 
/* 
/************************************************************************/ 
 
void aiff_check(file_name, pcm_aiff_data) 
char *file_name;          /* Pointer to name of AIFF file */ 
IFF_AIFF *pcm_aiff_data;  /* Pointer to AIFF data structure */ 
{ 
 
#ifdef IFF_LONG 
    if (pcm_aiff_data->sampleType != IFF_ID_SSND) { 
#else 
    if (strncmp(&pcm_aiff_data->sampleType,IFF_ID_SSND,4)) { 
#endif 
       printf("Sound data is not PCM in \"%s\".\n", file_name); 
       exit(1); 
    } 
 
    if(SmpFrqIndex((long)pcm_aiff_data->sampleRate) < 0) { 
       printf("in \"%s\".\n", file_name); 
       exit(1); 
    } 
 
    if (pcm_aiff_data->sampleSize != sizeof(short) * BITS_IN_A_BYTE) { 
	printf("Sound data is not %d bits in \"%s\".\n", 
	       sizeof(short) * BITS_IN_A_BYTE, file_name); 
	exit(1); 
    } 
 
    if (pcm_aiff_data->numChannels != MONO && 
	pcm_aiff_data->numChannels != STEREO) { 
       printf("Sound data is not mono or stereo in \"%s\".\n", file_name); 
       exit(1); 
    } 
 
    if (pcm_aiff_data->blkAlgn.blockSize != 0) { 
       printf("Block size is not %lu bytes in \"%s\".\n", 0, file_name); 
       exit(1); 
    } 
 
    if (pcm_aiff_data->blkAlgn.offset != 0) { 
       printf("Block offset is not %lu bytes in \"%s\".\n", 0, file_name); 
       exit(1); 
    } 
 
}