📄 encode.c
字号:
/**********************************************************************
* ISO MPEG Audio Subgroup Software Simulation Group (1996)
* ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension
*
* $Id: encode.c,v 1.1 1996/02/14 04:04:23 rowlands Exp $
*
* $Log: encode.c,v $
* 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 *
* efilter to enfilter *
* ewindow to enwindow *
* integrated "quantizer", "scalefactor",*
* and "transmission" files *
* update routine "window_subband" *
* 3/31/91 Bill Aspromonte replaced read_filter by *
* create_an_filter *
* 5/10/91 W. Joseph Carter Ported to Macintosh and Unix. *
* Incorporated Jean-Georges Fritsch's *
* "bitstream.c" package. *
* Incorporated Bill Aspromonte's *
* filterbank coefficient matrix *
* calculation routines and added *
* roundoff to coincide with specs. *
* Modified to strictly adhere to *
* encoded bitstream specs, including *
* "Berlin changes". *
* 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. *
* 19jun91 dpwe (Aware) moved "alloc_*" reader to common.c *
* Globals sblimit, alloc replaced by new*
* struct 'frame_params' passed as arg. *
* Added JOINT STEREO coding, layers I,II*
* Affects: *_bit_allocation, *
* subband_quantization, encode_bit_alloc*
* sample_encoding *
* 6/10/91 Earle Jennings modified II_subband_quantization to *
* resolve type cast problem for MS_DOS *
* 6/11/91 Earle Jennings modified to avoid overflow on MS_DOS *
* in routine filter_subband *
* 7/10/91 Earle Jennings port to MsDos from MacIntosh version *
* 8/ 8/91 Jens Spille Change for MS-C6.00 *
*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 function encode_CRC *
*11/ 8/91 Kathy Wang Documentation of code *
* All variablenames are referred to *
* with surrounding pound (#) signs *
* 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. *
* 6/16/92 Shaun Astarabadi Changed I_scale_factor_calc() and *
* II_scale_factor_calc() to use scale *
* factor 0 thru 62 only and not to *
* encode index 63 into the bit stream. *
* 7/27/92 Mike Li (re-)Port to MS-DOS *
* 9/22/92 jddevine@aware.com Fixed _scale_factor_calc() defs *
* 3/31/93 Giogio Dimino changed II_a_bit_allocation() from: *
* if( ad > ...) to if(ad >= ...) *
* 8/05/93 TEST changed I_a_bit_allocation() from: *
* if( ad > ...) to if(ad >= ...) *
* 8/02/95 mc@fivebats.com Changed audio file reading code to *
* read samples big-endian *
*10/15/95 mc@fivebats.com Modified get_audio() for layer3-LSF *
**********************************************************************/
#include "common.h"
#include "encoder.h"
#ifdef MS_DOS
extern unsigned _stklen = 16384;
#endif
/*=======================================================================\
| |
| This segment contains all the core routines of the encoder, |
| except for the psychoacoustic models. |
| |
| The user can select either one of the two psychoacoustic |
| models. Model I is a simple tonal and noise masking threshold |
| generator, and Model II is a more sophisticated cochlear masking |
| threshold generator. Model I is recommended for lower complexity |
| applications whereas Model II gives better subjective quality at low |
| bit rates. |
| |
| Layers I and II of mono, stereo, and joint stereo modes are supported.|
| Routines associated with a given layer are prefixed by "I_" for layer |
| 1 and "II_" for layer 2. |
\=======================================================================*/
/************************************************************************
*
* read_samples()
*
* PURPOSE: reads the PCM samples from a file to the buffer
*
* SEMANTICS:
* Reads #samples_read# number of shorts from #musicin# filepointer
* into #sample_buffer[]#. Returns the number of samples read.
*
************************************************************************/
unsigned long read_samples(musicin, sample_buffer, num_samples, frame_size)
FILE *musicin;
short sample_buffer[2304];
unsigned long num_samples, frame_size;
{
unsigned long samples_read;
static unsigned long samples_to_read;
static char init = TRUE;
if (init) {
samples_to_read = num_samples;
init = FALSE;
}
if (samples_to_read >= frame_size)
samples_read = frame_size;
else
samples_read = samples_to_read;
if ((samples_read =
fread(sample_buffer, sizeof(short), (int)samples_read, musicin)) == 0)
printf("Hit end of audio data\n");
/*
Samples are big-endian. If this is a little-endian machine
we must swap
*/
if ( NativeByteOrder == order_unknown )
{
NativeByteOrder = DetermineByteOrder();
if ( NativeByteOrder == order_unknown )
{
fprintf( stderr, "byte order not determined\n" );
exit( 1 );
}
}
if ( NativeByteOrder == order_littleEndian )
SwapBytesInWords( sample_buffer, samples_read );
samples_to_read -= samples_read;
if (samples_read < frame_size && samples_read > 0) {
printf("Insufficient PCM input for one frame - fillout with zeros\n");
for (; samples_read < frame_size; sample_buffer[samples_read++] = 0);
samples_to_read = 0;
}
return(samples_read);
}
/************************************************************************
*
* get_audio()
*
* PURPOSE: reads a frame of audio data from a file to the buffer,
* aligns the data for future processing, and separates the
* left and right channels
*
*
************************************************************************/
unsigned long get_audio( musicin, buffer, num_samples, stereo, info )
FILE *musicin;
short FAR buffer[2][1152];
unsigned long num_samples;
int stereo;
layer *info;
{
int j;
short insamp[2304];
unsigned long samples_read;
int lay;
lay = info->lay;
if ( (lay == 3) && (info->version == 0) )
{
if ( stereo == 2 )
{
samples_read = read_samples( musicin, insamp, num_samples,
(unsigned long) 1152 );
for ( j = 0; j < 576; j++ )
{
buffer[0][j] = insamp[2 * j];
buffer[1][j] = insamp[2 * j + 1];
}
}
else
{
samples_read = read_samples( musicin, insamp, num_samples,
(unsigned long) 576 );
for ( j = 0; j < 576; j++ )
{
buffer[0][j] = insamp[j];
buffer[1][j] = 0;
}
}
}
else
{
if (lay == 1){
if(stereo == 2){ /* layer 1, stereo */
samples_read = read_samples(musicin, insamp, num_samples,
(unsigned long) 768);
for(j=0;j<448;j++) {
if(j<64) {
buffer[0][j] = buffer[0][j+384];
buffer[1][j] = buffer[1][j+384];
}
else {
buffer[0][j] = insamp[2*j-128];
buffer[1][j] = insamp[2*j-127];
}
}
}
else { /* layer 1, mono */
samples_read = read_samples(musicin, insamp, num_samples,
(unsigned long) 384);
for(j=0;j<448;j++){
if(j<64) {
buffer[0][j] = buffer[0][j+384];
buffer[1][j] = 0;
}
else {
buffer[0][j] = insamp[j-64];
buffer[1][j] = 0;
}
}
}
}
else {
if(stereo == 2){ /* layer 2 (or 3), stereo */
samples_read = read_samples(musicin, insamp, num_samples,
(unsigned long) 2304);
for(j=0;j<1152;j++) {
buffer[0][j] = insamp[2*j];
buffer[1][j] = insamp[2*j+1];
}
}
else { /* layer 2 (or 3), mono */
samples_read = read_samples(musicin, insamp, num_samples,
(unsigned long) 1152);
for(j=0;j<1152;j++){
buffer[0][j] = insamp[j];
buffer[1][j] = 0;
}
}
}
}
return(samples_read);
}
/************************************************************************
*
* read_ana_window()
*
* PURPOSE: Reads encoder window file "enwindow" into array #ana_win#
*
************************************************************************/
void read_ana_window(ana_win)
double FAR ana_win[HAN_SIZE];
{
int i,j[4];
FILE *fp;
double f[4];
char t[150];
if (!(fp = OpenTableFile("enwindow") ) ) {
printf("Please check analysis window table 'enwindow'\n");
exit(1);
}
for (i=0;i<512;i+=4) {
fgets(t, 150, fp);
sscanf(t,"C[%d] = %lf C[%d] = %lf C[%d] = %lf C[%d] = %lf\n",
j, f,j+1,f+1,j+2,f+2,j+3,f+3);
if (i==j[0]) {
ana_win[i] = f[0];
ana_win[i+1] = f[1];
ana_win[i+2] = f[2];
ana_win[i+3] = f[3];
}
else {
printf("Check index in analysis window table\n");
exit(1);
}
fgets(t,150,fp);
}
fclose(fp);
}
/************************************************************************
*
* window_subband()
*
* PURPOSE: Overlapping window on PCM samples
*
* SEMANTICS:
* 32 16-bit pcm samples are scaled to fractional 2's complement and
* concatenated to the end of the window buffer #x#. The updated window
* buffer #x# is then windowed by the analysis window #c# to produce the
* windowed sample #z#
*
************************************************************************/
void window_subband(buffer, z, k)
short FAR **buffer;
double FAR z[HAN_SIZE];
int k;
{
typedef double FAR XX[2][HAN_SIZE];
static XX FAR *x;
int i, j;
static off[2] = {0,0};
static char init = 0;
static double FAR *c;
if (!init) {
c = (double FAR *) mem_alloc(sizeof(double) * HAN_SIZE, "window");
read_ana_window(c);
x = (XX FAR *) mem_alloc(sizeof(XX),"x");
for (i=0;i<2;i++)
for (j=0;j<HAN_SIZE;j++)
(*x)[i][j] = 0;
init = 1;
}
/* replace 32 oldest samples with 32 new samples */
for (i=0;i<32;i++) (*x)[k][31-i+off[k]] = (double) *(*buffer)++/SCALE;
/* shift samples into proper window positions */
for (i=0;i<HAN_SIZE;i++) z[i] = (*x)[k][(i+off[k])&HAN_SIZE-1] * c[i];
off[k] += 480; /*offset is modulo (HAN_SIZE-1)*/
off[k] &= HAN_SIZE-1;
}
/************************************************************************
*
* create_ana_filter()
*
* PURPOSE: Calculates the analysis filter bank coefficients
*
* SEMANTICS:
* Calculates the analysis filterbank coefficients and rounds to the
* 9th decimal place accuracy of the filterbank tables in the ISO
* document. The coefficients are stored in #filter#
************************************************************************/
void create_ana_filter(filter)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -