MUSICIN.C
资源名称:mpeg.zip [点击查看]
上传用户:njqiyou
上传日期:2007-01-08
资源大小:574k
文件大小:42k
源码类别:
mpeg/mp3
开发平台:
C/C++
- /**********************************************************************
- * ISO MPEG Audio Subgroup Software Simulation Group (1996)
- * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension
- *
- * $Id: musicin.c,v 1.2 1997/01/19 22:28:29 rowlands Exp $
- *
- * $Log: musicin.c,v $
- * Revision 1.2 1997/01/19 22:28:29 rowlands
- * Layer 3 bug fixes from Seymour Shlien
- *
- * Revision 1.1 1996/02/14 04:04:23 rowlands
- * Initial revision
- *
- * Received from Mike Coleman
- **********************************************************************/
- /**********************************************************************
- * 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 *
- * 11/7/95 Soeren H. Nielsen LSF added. Bug fix in MSDOS ext. *
- * 8/02/95 mc@fivebats.com Changed default bitrate selection so *
- * it works with the new LSF stuff *
- *10/01/95 mc@fivebats.com Added layer3 *
- **********************************************************************/
- #ifdef MS_DOS
- #include <dos.h>
- #endif
- #include <stdlib.h>
- #include "common.h"
- #include "encoder.h"
- #include "l3psy.h"
- #include "mdct.h"
- #include "loop.h"
- #include "l3bitstream.h"
- #include <assert.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;
- long int freq;
- int model, brt;
- char t[50];
- IFF_AIFF pcm_aiff_data;
- layer *info = fr_ps->header;
- long soundPosition;
- #ifdef MS_DOS
- char temp_str[MAX_NAME_SIZE];
- #endif
- do {
- printf("Enter PCM input file name <required>: ");
- 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: %sn", original_file_name);
- if ((musicin = fopen(original_file_name, "rb")) == NULL) {
- printf("Could not find "%s".n", original_file_name);
- exit(1);
- }
- #ifdef MS_DOS
- /* replace old extension with new one, 1992-08-19, 1995-06-12 shn */
- new_ext(original_file_name, DFLT_EXT, temp_str);
- printf("Enter MPEG encoded output file name <%s>: ",
- temp_str);
- #else
- printf("Enter MPEG encoded output file name <%s%s>: ",
- original_file_name, DFLT_EXT);
- #endif
- gets(encoded_file_name);
- if (encoded_file_name[0] == NULL_CHAR) {
- #ifdef MS_DOS
- strcpy(encoded_file_name, temp_str);
- #else
- strcat(strcpy(encoded_file_name, original_file_name), DFLT_EXT);
- #endif
- }
- printf(">>> MPEG encoded output file name is: %sn", 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 headersn");
- aiff_check(original_file_name, &pcm_aiff_data, &info->version);
- 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, &info->version);
- printf(">>> %f Hz sampling frequency selectedn",
- 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 selectedn", freq);
- break;
- case 44100 : info->sampling_frequency = 0;
- printf(">>> %ld Hz sampling freq selectedn", freq);
- break;
- case 32000 : info->sampling_frequency = 2;
- printf(">>> %ld Hz sampling freq selectedn", freq);
- break;
- case 24000 : info->sampling_frequency = 1;
- info->version = MPEG_PHASE2_LSF;
- printf(">>> %ld Hz sampling freq selectedn", freq);
- break;
- case 22050 : info->sampling_frequency = 0;
- info->version = MPEG_PHASE2_LSF;
- printf(">>> %ld Hz sampling freq selectedn", freq);
- break;
- case 16000 : info->sampling_frequency = 2;
- info->version = MPEG_PHASE2_LSF;
- printf(">>> %ld Hz sampling freq selectedn", freq);
- break;
- default: info->sampling_frequency = 0;
- printf(">>> Default 44.1 kHz samp freq selectedn");
- }
- printf(">>> Encoding algorithm is %sn", version_names[info->version]);
- 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>), Layer (3): ");
- gets(t);
- switch(*t){
- case '1': info->lay = 1; printf(">>> Using Layer %sn",t); break;
- case '2': info->lay = 2; printf(">>> Using Layer %sn",t); break;
- case '3': info->lay = 3; printf(">>> Using Layer %sn",t); break;
- default: info->lay = 2; printf(">>> Using default Layer 2n"); break;
- }
- printf("Which mode do you want?n");
- printf("Available: (<s>)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 %sn",t);
- break;
- case 'j':
- case 'J':
- info->mode = MPG_MD_JOINT_STEREO;
- printf(">>> Using mode %sn",t);
- break;
- case 'd':
- case 'D':
- info->mode = MPG_MD_DUAL_CHANNEL; info->mode_ext = 0;
- printf(">>> Using mode %sn",t);
- break;
- case 'i':
- case 'I':
- info->mode = MPG_MD_MONO; info->mode_ext = 0;
- printf(">>> Using mode %sn",t);
- break;
- default:
- info->mode = MPG_MD_STEREO; info->mode_ext = 0;
- printf(">>> Using default stereo moden");
- break;
- }
- printf("Which psychoacoustic model do you want to use? <1>: ");
- gets(t);
- model = atoi(t);
- if (model > 2 || model < 1) {
- printf(">>> Default model 1 selectedn");
- *psy = 1;
- }
- else {
- *psy = model;
- printf(">>> Using psychoacoustic model %dn", model);
- }
- /* set default bitrate to highest allowed, which is index 14 */
- brt = bitrate[info->version][info->lay-1][14];
- printf( "What is the total bitrate? <%u>[kbps]: ", brt );
- gets( t );
- brt = atoi( t );
- if ( brt == 0 )
- j = 15;
- else
- j = 0;
- while ( j < 15 )
- {
- if ( bitrate[info->version][info->lay-1][j] == brt )
- break;
- j++;
- }
- if ( j == 15 )
- {
- brt = bitrate[info->version][info->lay-1][14];
- printf( ">>> Using default %u kbpsn", brt );
- info->bitrate_index = 14;
- }
- else
- {
- info->bitrate_index = j;
- printf( ">>> Bitrate = %d kbpsn", bitrate[info->version][info->lay-1][j] );
- }
- printf("What type of de-emphasis should the decoder use?n");
- printf("Available: (<n>)one, (5)0/15 microseconds, (c)citt j.17: ");
- gets(t);
- if (*t != 'n' && *t != '5' && *t != 'c') {
- printf(">>> Using default no de-emphasisn");
- 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 %sn",t);
- }
- /* Start 2. Part changes for CD Ver 3.2; jsp; 22-Aug-1991 */
- printf("Do you want to set the private bit? (y/<n>): ");
- gets(t);
- if (*t == 'y' || *t == 'Y') info->extension = 1;
- else info->extension = 0;
- if(info->extension) printf(">>> Private bit setn");
- else printf(">>> Private bit not setn");
- /* End changes for CD Ver 3.2; jsp; 22-Aug-1991 */
- printf("Do you want error protection? (y/<n>): ");
- gets(t);
- if (*t == 'y' || *t == 'Y') info->error_protection = TRUE;
- else info->error_protection = FALSE;
- if(info->error_protection) printf(">>> Error protection usedn");
- else printf(">>> Error protection not usedn");
- printf("Is the material copyrighted? (y/<n>): ");
- gets(t);
- if (*t == 'y' || *t == 'Y') info->copyright = 1;
- else info->copyright = 0;
- if(info->copyright) printf(">>> Copyrighted materialn");
- else printf(">>> Material not copyrightedn");
- printf("Is this the original? (y/<n>): ");
- gets(t);
- if (*t == 'y' || *t == 'Y') info->original = 1;
- else info->original = 0;
- if(info->original) printf(">>> Original materialn");
- else printf(">>> Material not originaln");
- printf("Do you wish to exit (last chance before encoding)? (y/<n>): ");
- 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] = ' '; outPath[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 %cn", programName, DFLT_MOD);
- abort();
- }
- *psy = DFLT_PSY;
- if((info->sampling_frequency = SmpFrqIndex((long)(1000*DFLT_SFQ), &info->version)) < 0) {
- fprintf(stderr, "%s: bad sfrq default %.2fn", programName, DFLT_SFQ);
- abort();
- }
- info->bitrate_index = 14;
- brate = 0;
- 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 %cn", programName, DFLT_EMP);
- abort();
- }
- info->copyright = 0; info->original = 0; info->error_protection = FALSE;
- /* process args */
- while(++i<argc && err == 0) {
- char c, *token, *arg, *nextArg;
- int argUsed;
- token = argv[i];
- if(*token++ == '-') {
- if(i+1 < argc) nextArg = argv[i+1];
- else nextArg = "";
- argUsed = 0;
- while( (c = *token++) ) {
- if(*token /* NumericQ(token) */) arg = token;
- else arg = nextArg;
- switch(c) {
- case 'l': info->lay = atoi(arg); argUsed = 1;
- if(info->lay<1 || info->lay>3) {
- fprintf(stderr,"%s: -l layer must be 1, 2, or 3, not %sn",
- 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 %sn",
- 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 %sn",
- 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, &info->version)) < 0 )
- err = 1;
- break;
- case 'b':
- argUsed = 1;
- brate = atoi(arg);
- 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 %sn",
- 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 %cn",
- 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] == ' ') strcpy(inPath, argv[i]);
- else if(outPath[0] == ' ') strcpy(outPath, argv[i]);
- else {
- fprintf(stderr,"%s: excess arg %sn", programName, argv[i]);
- err = 1;
- }
- }
- }
- if(err || inPath[0] == ' ') usage(); /* never returns */
- if(outPath[0] == ' ') {
- #ifdef MS_DOS
- /* replace old extension with new one, 1992-08-19, 1995-06-12 shn */
- new_ext(inPath, DFLT_EXT, outPath);
- #else
- strcpy(outPath, inPath);
- strcat(outPath, DFLT_EXT);
- #endif
- }
- 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 headersn");
- aiff_check(inPath, &pcm_aiff_data, &info->version);
- 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, &info->version);
- printf(">>> %f Hz sampling frequency selectedn",
- 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;
- }
- if ( brate == 0 )
- brate = bitrate[info->version][info->lay-1][14];
- if( (info->bitrate_index = BitrateIndex(info->lay, brate, info->version)) < 0) err=1;
- if(err || inPath[0] == ' ') usage(); /* never returns */
- }
- /************************************************************************
- *
- * print_config
- *
- * PURPOSE: Prints the encoding parameters used
- *
- ************************************************************************/
- void print_config( frame_params *fr_ps, int *psy, char *inPath, char *outPath)
- {
- layer *info = fr_ps->header;
- printf("Encoding configuration:n");
- printf("Algorithm=%sn", version_names[info->version]);
- if(info->mode != MPG_MD_JOINT_STEREO)
- printf("Layer=%s mode=%s extn=%d psy model=%dn",
- layer_names[info->lay-1], mode_names[info->mode],
- info->mode_ext, *psy);
- else printf("Layer=%s mode=%s extn=data dependant psy model=%dn",
- layer_names[info->lay-1], mode_names[info->mode], *psy);
- printf("samp frq=%.1f kHz total bitrate=%d kbpsn",
- s_freq[info->version][info->sampling_frequency],
- bitrate[info->version][info->lay-1][info->bitrate_index]);
- printf("de-emph=%d c/right=%d orig=%d errprot=%sn",
- info->emphasis, info->copyright, info->original,
- ((info->error_protection) ? "on" : "off"));
- printf("input file: '%s' output file: '%s'n", inPath, outPath);
- }
- /************************************************************************
- *
- * main
- *
- * PURPOSE: MPEG I Encoder supporting layers 1 and 2, and 3, with
- * 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)
- *
- ************************************************************************/
- int frameNum=0;
- void main(argc, argv)
- int argc;
- char **argv;
- {
- typedef double SBS[2][3][SCALE_BLOCK][SBLIMIT];
- SBS FAR *sb_sample;
- L3SBS FAR *l3_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][1344]; /* was [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;
- unsigned long frameBits, sentBits = 0;
- unsigned long num_samples;
- #ifdef MACINTOSH
- 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");
- l3_sb_sample = (L3SBS FAR *) mem_alloc(sizeof(SBS), "l3_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; /* Default: MPEG-1 */
- 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,
- 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
- if ( info.lay == 2 )
- { bitsPerSlot = 8; samplesPerFrame = 1152; }
- else
- { /* layer 3 */
- bitsPerSlot = 8;
- samplesPerFrame = info.version == 1 ? 1152 : 576;
- /* Apologize for missing features */
- if ( info.mode == MPG_MD_JOINT_STEREO )
- {
- fprintf( stderr, "Sorry, joint stereo not yet available for layer3n" );
- exit( 1 );
- }
- #if 0
- if ( info.version != MPEG_AUDIO_ID )
- {
- fprintf( stderr, "Sorry, MPEG2-LSF not yet available for layer3n" );
- exit( 1 );
- }
- #endif
- if ( model != 2 )
- {
- fprintf( stderr, "Sorry, psycho model 1 not available for layer3n" );
- exit( 1 );
- }
- }
- /* 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.version][info.sampling_frequency]) *
- ((double)bitrate[info.version][info.lay-1][info.bitrate_index] /
- (double)bitsPerSlot);
- whole_SpF = (int) avg_slots_per_frame;
- printf("slots/frame = %dn",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 kHzn",
- frac_SpF, bitrate[info.version][info.lay-1][info.bitrate_index],
- s_freq[info.version][info.sampling_frequency]);
- if (frac_SpF != 0)
- printf("Fractional number of slots, padding requiredn");
- else info.padding = 0;
- while ( get_audio(musicin, buffer, num_samples, stereo, &info) > 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 framen"); */
- }
- else {
- extra_slot = 1;
- info.padding = 1;
- slot_lag += (1-frac_SpF);
- /* printf("Padding for this framen"); */
- }
- }
- adb = (whole_SpF+extra_slot) * bitsPerSlot;
- switch (info.lay)
- {
- /***************************** Layer I **********************************/
- case 1 :
- for (j=0;j<SCALE_BLOCK;j++)
- for (k=0;k<stereo;k++) {
- window_subband(&win_buf[k], &(*win_que)[k][0], k);
- filter_subband(&(*win_que)[k][0], &(*sb_sample)[k][0][j][0]);
- }
- I_scale_factor_calc(*sb_sample, scalar, stereo);
- if(fr_ps.actual_mode == MPG_MD_JOINT_STEREO) {
- I_combine_LR(*sb_sample, *j_sample);
- I_scale_factor_calc(j_sample, &j_scale, 1);
- }
- put_scale(scalar, &fr_ps, max_sc);
- if (model == 1) I_Psycho_One(buffer, max_sc, ltmin, &fr_ps);
- else {
- for (k=0;k<stereo;k++) {
- psycho_anal(&buffer[k][0],&sam[k][0], k, info.lay, snr32,
- (FLOAT)s_freq[info.version][info.sampling_frequency]*1000);
- for (i=0;i<SBLIMIT;i++) ltmin[k][i] = (double) snr32[i];
- }
- }
- I_main_bit_allocation(ltmin, bit_alloc, &adb, &fr_ps);
- if (error_protection) I_CRC_calc(&fr_ps, bit_alloc, &crc);
- encode_info(&fr_ps, &bs);
- if (error_protection) encode_CRC(crc, &bs);
- I_encode_bit_alloc(bit_alloc, &fr_ps, &bs);
- I_encode_scale(scalar, bit_alloc, &fr_ps, &bs);
- I_subband_quantization(scalar, *sb_sample, j_scale, *j_sample,
- bit_alloc, *subband, &fr_ps);
- I_sample_encoding(*subband, bit_alloc, &fr_ps, &bs);
- for (i=0;i<adb;i++) put1bit(&bs, 0);
- break;
- /***************************** Layer 2 **********************************/
- case 2 :
- for (i=0;i<3;i++) for (j=0;j<SCALE_BLOCK;j++)
- for (k=0;k<stereo;k++) {
- window_subband(&win_buf[k], &(*win_que)[k][0], k);
- filter_subband(&(*win_que)[k][0], &(*sb_sample)[k][i][j][0]);
- }
- II_scale_factor_calc(*sb_sample, scalar, stereo, fr_ps.sblimit);
- pick_scale(scalar, &fr_ps, max_sc);
- if(fr_ps.actual_mode == MPG_MD_JOINT_STEREO) {
- II_combine_LR(*sb_sample, *j_sample, fr_ps.sblimit);
- II_scale_factor_calc(j_sample, &j_scale, 1, fr_ps.sblimit);
- } /* this way we calculate more mono than we need */
- /* but it is cheap */
- if (model == 1) II_Psycho_One(buffer, max_sc, ltmin, &fr_ps);
- else {
- for (k=0;k<stereo;k++) {
- psycho_anal(&buffer[k][0],&sam[k][0], k,
- info.lay, snr32,
- (FLOAT)s_freq[info.version][info.sampling_frequency]*1000);
- for (i=0;i<SBLIMIT;i++) ltmin[k][i] = (double) snr32[i];
- }
- }
- II_transmission_pattern(scalar, scfsi, &fr_ps);
- II_main_bit_allocation(ltmin, scfsi, bit_alloc, &adb, &fr_ps);
- if (error_protection)
- II_CRC_calc(&fr_ps, bit_alloc, scfsi, &crc);
- encode_info(&fr_ps, &bs);
- if (error_protection) encode_CRC(crc, &bs);
- II_encode_bit_alloc(bit_alloc, &fr_ps, &bs);
- II_encode_scale(bit_alloc, scfsi, scalar, &fr_ps, &bs);
- II_subband_quantization(scalar, *sb_sample, j_scale,
- *j_sample, bit_alloc, *subband, &fr_ps);
- II_sample_encoding(*subband, bit_alloc, &fr_ps, &bs);
- for (i=0;i<adb;i++) put1bit(&bs, 0);
- break;
- /***************************** Layer 3 **********************************/
- case 3:
- {
- /*
- large "auto" vars are static due to the Macintosh linker
- */
- static double xr[2][2][576];
- static double xr_dec[2][2][576];
- static double pe[2][2];
- static int l3_enc[2][2][576];
- static III_psy_ratio ratio;
- static III_side_info_t l3_side;
- static III_scalefac_t scalefac;
- int gr, mode_gr, ch;
- int mean_bits, sideinfo_len;
- int bitsPerFrame = 8 * whole_SpF + (info.padding * 8);
- mode_gr = (info.version == 1) ? 2 : 1;
- /*
- determine the mean bitrate for main data
- */
- sideinfo_len = 32;
- if ( info.version == 1 )
- { /* MPEG 1 */
- if ( stereo == 1 )
- sideinfo_len += 136;
- else
- sideinfo_len += 256;
- }
- else
- { /* MPEG 2 */
- if ( stereo == 1 )
- sideinfo_len += 72;
- else
- sideinfo_len += 136;
- }
- if ( info.error_protection )
- sideinfo_len += 16;
- mean_bits = (bitsPerFrame - sideinfo_len) / mode_gr;
- /*
- psychoacoustic model
- */
- for ( gr = 0; gr < mode_gr; gr++ )
- for ( ch = 0; ch < stereo; ch++ )
- {
- L3psycho_anal( &buffer[ch][gr*576], &sam[ch][0], ch, info.lay,
- snr32, s_freq[info.version][info.sampling_frequency] * 1000.0,
- &ratio.l[gr][ch][0], &ratio.s[gr][ch][0],
- &pe[gr][ch], &l3_side.gr[gr].ch[ch].tt );
- }
- /*
- polyphase filtering
- */
- for( gr = 0; gr < mode_gr; gr++ )
- for ( ch = 0; ch < stereo; ch++ )
- for ( j = 0; j < 18; j++ )
- {
- window_subband( &win_buf[ch], &(*win_que)[ch][0], ch );
- filter_subband( &(*win_que)[ch][0], &(*l3_sb_sample)[ch][gr+1][j][0] );
- }
- /*
- apply mdct to the polyphase outputs
- */
- mdct_sub( l3_sb_sample, xr, stereo, &l3_side, mode_gr );
- #if 0
- delay( xr, stereo );
- #endif
- /*
- bit and noise allocation
- */
- iteration_loop( pe, xr, &ratio, &l3_side, l3_enc, mean_bits,
- stereo, xr_dec, &scalefac, &fr_ps, 0, bitsPerFrame );
- /*
- write the frame to the bitstream
- */
- III_format_bitstream( bitsPerFrame, &fr_ps, l3_enc, &l3_side, &scalefac, &bs,
- xr, NULL, 0 );
- }
- break; /* end of layer 3 */
- } /* end switch */
- frameBits = sstell( &bs ) - sentBits;
- if ( frameBits % bitsPerSlot ) /* a program failure */
- fprintf( stderr, "Sent %ld bits = %ld slots plus %ldn",
- frameBits, frameBits/bitsPerSlot,
- frameBits%bitsPerSlot );
- sentBits += frameBits;
- }
- if ( info.lay == 3 )
- III_FlushBitstream();
- close_bit_stream_w( &bs );
- printf("Avg slots/frame = %.3f; b/smp = %.2f; br = %.3f kbpsn",
- (FLOAT) sentBits / (frameNum * bitsPerSlot),
- (FLOAT) sentBits / (frameNum * samplesPerFrame),
- (FLOAT) sentBits / (frameNum * samplesPerFrame) *
- s_freq[info.version][info.sampling_frequency]);
- if (fclose(musicin) != 0){
- printf("Could not close "%s".n", original_file_name);
- exit(2);
- }
- #ifdef MACINTOSH
- set_mac_file_attr( encoded_file_name, VOL_REF_NUM, CREATOR_ENCODE,
- FILETYPE_ENCODE );
- #endif
- printf("Encoding of "%s" with psychoacoustic model %d is finishedn",
- original_file_name, model);
- printf("The MPEG encoded output file name is "%s"n",
- encoded_file_name);
- exit(0);
- }
- /************************************************************************
- *
- * usage
- *
- * PURPOSE: Writes command line syntax to the file specified by #stderr#
- *
- ************************************************************************/
- void usage() /* print syntax & exit */
- {
- fprintf(stderr,
- "usage: %s queries for all arguments, orn",
- programName);
- fprintf(stderr,
- " %s [-l lay][-m mode][-p psy][-s sfrq][-b br][-d emp]n",
- programName);
- fprintf(stderr,
- " [-c][-o][-e] inputPCM [outBS]n");
- fprintf(stderr,"wheren");
- fprintf(stderr," -l lay use layer <lay> 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 highest)n");
- fprintf(stderr," -d emp de-emphasis n/5/c (dflt %4c)n",DFLT_EMP);
- fprintf(stderr," -c mark as copyrightn");
- fprintf(stderr," -o mark as originaln");
- fprintf(stderr," -e add error protectionn");
- 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( char *file_name, IFF_AIFF *pcm_aiff_data, int *version)
- {
- if (pcm_aiff_data->sampleType != IFF_ID_SSND) {
- printf("Sound data is not PCM in "%s".n", file_name);
- exit(1);
- }
- if(SmpFrqIndex((long)pcm_aiff_data->sampleRate, version) < 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 %d bytes in "%s".n", 0, file_name);
- exit(1);
- }
- if (pcm_aiff_data->blkAlgn.offset != 0) {
- printf("Block offset is not %d bytes in "%s".n", 0, file_name);
- exit(1);
- }
- }