This is musicout.c in view mode; [Download] [Up]
/********************************************************************** Copyright (c) 1991 MPEG/audio software simulation group, All Rights Reserved musicout.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 3.9 * * changes made since last update: * * date programmers comment * * 2/25/91 Douglas Wong start of version 1.0 records * * 3/06/91 Douglas Wong rename setup.h to dedef.h * * removed extraneous variables * * removed window_samples (now part of * * filter_samples) * * 3/07/91 Davis Pan changed output file to "codmusic" * * 5/10/91 Vish (PRISM) Ported to Macintosh and Unix. * * Incorporated new "out_fifo()" which * * writes out last incomplete buffer. * * Incorporated all AIFF routines which * * are also compatible with SUN. * * Incorporated user interface for * * specifying sound file names. * * Also incorporated user interface for * * writing AIFF compatible sound files. * * 27jun91 dpwe (Aware) Added musicout and &sample_frames as * * args to out_fifo (were glob refs). * * Used new 'frame_params' struct. * * Clean,simplify, track clipped output * * and total bits/frame received. * * 7/10/91 Earle Jennings changed to floats to FLOAT * *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 * * buffer_CRC and recover_CRC_error * * Additions and revisions are marked * * with "dhl" for clarity * * 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. * *19 aug 92 Soren H. Nielsen Changed MS-DOS file name extensions. * * 8/27/93 Seymour Shlien, Fixes in Unix and MSDOS ports, * * Daniel Lauzon, and * * Bill Truerniet * **********************************************************************/ #include "common.h" #include "decoder.h" /******************************************************************** /* /* This part contains the MPEG I decoder for Layers I & II. /* /*********************************************************************/ /**************************************************************** /* /* For MS-DOS user (Turbo c) change all instance of malloc /* to _farmalloc and free to _farfree. Compiler model hugh /* Also make sure all the pointer specified are changed to far. /* /*****************************************************************/ /********************************************************************* /* /* Core of the Layer II decoder. Default layer is Layer II. /* /*********************************************************************/ /* Global variable definitions for "musicout.c" */ char *programName; /* Implementations */ main(argc, argv) int argc; char **argv; { typedef short PCM[2][3][SBLIMIT]; PCM FAR *pcm_sample; typedef unsigned int SAM[2][3][SBLIMIT]; SAM FAR *sample; typedef double FRA[2][3][SBLIMIT]; FRA FAR *fraction; typedef double VE[2][HAN_SIZE]; VE FAR *w; Bit_stream_struc bs; frame_params fr_ps; layer info; FILE *musicout; unsigned long sample_frames; int i, j, k, stereo, done=FALSE, clip, sync; int error_protection, crc_error_count, total_error_count; unsigned int old_crc, new_crc; unsigned int bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT], scale_index[2][3][SBLIMIT]; unsigned long bitsPerSlot, samplesPerFrame, frameNum = 0; unsigned long frameBits, gotBits = 0; IFF_AIFF pcm_aiff_data; char encoded_file_name[MAX_NAME_SIZE]; char decoded_file_name[MAX_NAME_SIZE]; char t[50]; int need_aiff; int topSb = 0; #ifdef MACINTOSH console_options.nrows = MAC_WINDOW_SIZE; argc = ccommand(&argv); #endif /* Most large variables are declared dynamically to ensure compatibility with smaller machines */ pcm_sample = (PCM FAR *) mem_alloc((long) sizeof(PCM), "PCM Samp"); sample = (SAM FAR *) mem_alloc((long) sizeof(SAM), "Sample"); fraction = (FRA FAR *) mem_alloc((long) sizeof(FRA), "fraction"); w = (VE FAR *) mem_alloc((long) sizeof(VE), "w"); fr_ps.header = &info; fr_ps.tab_num = -1; /* no table loaded */ fr_ps.alloc = NULL; for (i=0;i<HAN_SIZE;i++) for (j=0;j<2;j++) (*w)[j][i] = 0.0; programName = argv[0]; if(argc==1) { /* no command line args -> interact */ do { printf ("Enter encoded file name <required>: "); gets (encoded_file_name); if (encoded_file_name[0] == NULL_CHAR) printf ("Encoded file name is required. \n"); } while (encoded_file_name[0] == NULL_CHAR); printf (">>> Encoded file name is: %s \n", encoded_file_name); #ifdef MS_DOS printf ("Enter MPEG decoded file name <%s>: ", new_ext(encoded_file_name, DFLT_OPEXT)); /* 92-08-19 shn */ #else printf ("Enter MPEG decoded file name <%s%s>: ", encoded_file_name, DFLT_OPEXT); #endif gets (decoded_file_name); if (decoded_file_name[0] == NULL_CHAR) { #ifdef MS_DOS /* replace old extension with new one, 92-08-19 shn */ strcpy(decoded_file_name,new_ext(encoded_file_name, DFLT_OPEXT)); #else strcat (strcpy(decoded_file_name, encoded_file_name), DFLT_OPEXT); #endif } printf (">>> MPEG decoded file name is: %s \n", decoded_file_name); printf( "Do you wish to write an AIFF compatible sound file ? (y/<n>) : "); gets(t); if (*t == 'y' || *t == 'Y') need_aiff = TRUE; else need_aiff = FALSE; if (need_aiff) printf(">>> An AIFF compatible sound file will be written\n"); else printf(">>> A non-headered PCM sound file will be written\n"); printf( "Do you wish to exit (last chance before decoding) ? (y/<n>) : "); gets(t); if (*t == 'y' || *t == 'Y') exit(0); } else { /* interpret CL Args */ int i=0, err=0; need_aiff = FALSE; encoded_file_name[0] = '\0'; decoded_file_name[0] = '\0'; 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 's': topSb = atoi(arg); argUsed = 1; if(topSb<1 || topSb>SBLIMIT) { fprintf(stderr, "%s: -s band %s not %d..%d\n", programName, arg, 1, SBLIMIT); err = 1; } break; case 'A': need_aiff = TRUE; break; default: fprintf(stderr,"%s: unrecognized 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(encoded_file_name[0] == '\0') strcpy(encoded_file_name, argv[i]); else if(decoded_file_name[0] == '\0') strcpy(decoded_file_name, argv[i]); else { fprintf(stderr, "%s: excess arg %s\n", programName, argv[i]); err = 1; } } } if(err || encoded_file_name[0] == '\0') usage(); /* never returns */ if(decoded_file_name[0] == '\0') { strcpy(decoded_file_name, encoded_file_name); strcat(decoded_file_name, DFLT_OPEXT); } } /* report results of dialog / command line */ printf("Input file = '%s' output file = '%s'\n", encoded_file_name, decoded_file_name); if(need_aiff) printf("Output file written in AIFF format\n"); if(strcmp(decoded_file_name,"stdout") == 0) musicout = stdout; else { if ((musicout = fopen(decoded_file_name, "w+b")) == NULL) { printf ("Could not create \"%s\".\n", decoded_file_name); exit(1); } } open_bit_stream_r(&bs, encoded_file_name, BUFFER_SIZE); if (need_aiff) if (aiff_seek_to_sound_data(musicout) == -1) { printf("Could not seek to PCM sound data in \"%s\".\n", decoded_file_name); exit(1); } sample_frames = 0; while (!end_bs(&bs)) { sync = seek_sync(&bs, SYNC_WORD, SYNC_WORD_LNGTH); frameBits = sstell(&bs) - gotBits; if(frameNum > 0) /* don't want to print on 1st loop; no lay */ if(frameBits%bitsPerSlot) fprintf(stderr,"Got %ld bits = %ld slots plus %ld\n", frameBits, frameBits/bitsPerSlot, frameBits%bitsPerSlot); gotBits += frameBits; if (!sync) { printf("Frame cannot be located\n"); printf("Input stream may be empty\n"); done = TRUE; /* finally write out the buffer */ if (info.lay == 2) out_fifo(*pcm_sample, 3, &fr_ps, done, musicout, &sample_frames); else out_fifo(*pcm_sample, 1, &fr_ps, done, musicout, &sample_frames); break; } decode_info(&bs, &fr_ps); hdr_to_frps(&fr_ps); stereo = fr_ps.stereo; error_protection = info.error_protection; crc_error_count = 0; total_error_count = 0; if(frameNum == 0) WriteHdr(&fr_ps, stdout); /* printout layer/mode */ fprintf(stderr, "{%4lu}\r", frameNum++); fflush(stderr); if (error_protection) buffer_CRC(&bs, &old_crc); switch (info.lay) { case 1: { bitsPerSlot = 32; samplesPerFrame = 384; I_decode_bitalloc(&bs,bit_alloc,&fr_ps); I_decode_scale(&bs, bit_alloc, scale_index, &fr_ps); if (error_protection) { I_CRC_calc(&fr_ps, bit_alloc, &new_crc); if (new_crc != old_crc) { crc_error_count++; total_error_count++; recover_CRC_error(*pcm_sample, crc_error_count, &fr_ps, musicout, &sample_frames); break; } else crc_error_count = 0; } clip = 0; for (i=0;i<SCALE_BLOCK;i++) { I_buffer_sample(&bs,(*sample),bit_alloc,&fr_ps); I_dequantize_sample(*sample,*fraction,bit_alloc,&fr_ps); I_denormalize_sample((*fraction),scale_index,&fr_ps); if(topSb>0) /* clear channels to 0 */ for(j=topSb; j<fr_ps.sblimit; ++j) for(k=0; k<stereo; ++k) (*fraction)[k][0][j] = 0; for (j=0;j<stereo;j++) { clip += SubBandSynthesis (&((*fraction)[j][0][0]), j, &((*pcm_sample)[j][0][0])); } out_fifo(*pcm_sample, 1, &fr_ps, done, musicout, &sample_frames); } if(clip > 0) printf("%d output samples clipped\n", clip); break; } case 2: { bitsPerSlot = 8; samplesPerFrame = 1152; II_decode_bitalloc(&bs, bit_alloc, &fr_ps); II_decode_scale(&bs, scfsi, bit_alloc, scale_index, &fr_ps); if (error_protection) { II_CRC_calc(&fr_ps, bit_alloc, scfsi, &new_crc); if (new_crc != old_crc) { crc_error_count++; total_error_count++; recover_CRC_error(*pcm_sample, crc_error_count, &fr_ps, musicout, &sample_frames); break; } else crc_error_count = 0; } clip = 0; for (i=0;i<SCALE_BLOCK;i++) { II_buffer_sample(&bs,(*sample),bit_alloc,&fr_ps); II_dequantize_sample((*sample),bit_alloc,(*fraction),&fr_ps); II_denormalize_sample((*fraction),scale_index,&fr_ps,i>>2); if(topSb>0) /* debug : clear channels to 0 */ for(j=topSb; j<fr_ps.sblimit; ++j) for(k=0; k<stereo; ++k) (*fraction)[k][0][j] = (*fraction)[k][1][j] = (*fraction)[k][2][j] = 0; for (j=0;j<3;j++) for (k=0;k<stereo;k++) { clip += SubBandSynthesis (&((*fraction)[k][j][0]), k, &((*pcm_sample)[k][j][0])); } out_fifo(*pcm_sample, 3, &fr_ps, done, musicout, &sample_frames); } if(clip > 0) printf("%d samples clipped\n", clip); break; } } } if (need_aiff) { pcm_aiff_data.numChannels = stereo; pcm_aiff_data.numSampleFrames = sample_frames; pcm_aiff_data.sampleSize = 16; pcm_aiff_data.sampleRate = s_freq[info.sampling_frequency]*1000; #ifdef IFF_LONG pcm_aiff_data.sampleType = IFF_ID_SSND; #else strncpy(&pcm_aiff_data.sampleType,IFF_ID_SSND,4); #endif pcm_aiff_data.blkAlgn.offset = 0; pcm_aiff_data.blkAlgn.blockSize = 0; if (aiff_write_headers(musicout, &pcm_aiff_data) == -1) { printf("Could not write AIFF headers to \"%s\"\n", decoded_file_name); exit(2); } } printf("Avg slots/frame = %.3f; b/smp = %.2f; br = %.3f kbps\n", (FLOAT) gotBits / (frameNum * bitsPerSlot), (FLOAT) gotBits / (frameNum * samplesPerFrame), (FLOAT) gotBits / (frameNum * samplesPerFrame) * s_freq[info.sampling_frequency]); close_bit_stream_r(&bs); fclose(musicout); /* for the correct AIFF header information */ /* on the Macintosh */ /* the file type and the file creator for */ /* Macintosh compatible Digidesign is set */ #ifdef MACINTOSH if (need_aiff) set_mac_file_attr(decoded_file_name, VOL_REF_NUM, CREATR_DEC_AIFF, FILTYP_DEC_AIFF); else set_mac_file_attr(decoded_file_name, VOL_REF_NUM, CREATR_DEC_BNRY, FILTYP_DEC_BNRY); #endif printf("Decoding of \"%s\" is finished\n", encoded_file_name); printf("The decoded PCM output file name is \"%s\"\n", decoded_file_name); if (need_aiff) printf("\"%s\" has been written with AIFF header information\n", decoded_file_name); exit( 0 ); } static void usage() /* print syntax & exit */ { fprintf(stderr, "usage: %s queries for all arguments, or\n", programName); fprintf(stderr, " %s [-A][-s sb] inputBS [outPCM]\n", programName); fprintf(stderr,"where\n"); fprintf(stderr," -A write an AIFF output PCM sound file\n"); fprintf(stderr," -s sb resynth only up to this sb (debugging only)\n"); fprintf(stderr," inputBS input bit stream of encoded audio\n"); fprintf(stderr," outPCM output PCM sound file (dflt inName+%s)\n", DFLT_OPEXT); exit(1); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.