www.pudn.com > bladeenc-0.90.0-src.zip > codec.c


/* 
			(c) Copyright 1998, 1999 - Tord Jansson 
			======================================= 
 
		This file is part of the BladeEnc MP3 Encoder, based on 
		ISO's reference code for MPEG Layer 3 compression, and might 
		contain smaller or larger sections that are directly taken 
		from ISO's reference code. 
 
		All changes to the ISO reference code herein are either 
		copyrighted by Tord Jansson (tord.jansson@swipnet.se) 
		or sublicensed to Tord Jansson by a third party. 
 
	BladeEnc is free software; you can redistribute this file 
	and/or modify it under the terms of the GNU Lesser General Public 
	License as published by the Free Software Foundation; either 
	version 2.1 of the License, or (at your option) any later version. 
 
*/ 
 
#include  
#include "common.h" 
#include "encoder.h" 
#include "l3psy.h" 
#include "mdct.h" 
#include "loop.h" 
#include "l3bitstream.h" 
#include "formatbitstream2.h" 
#include  "codec.h" 
 
 
extern int	fInit_mdct_sub; 
extern int	fInit_mdct; 
 
extern int fInit_fft; 
 
extern int	fInit_iteration_loop; 
extern int	fInit_huffman_read_flag; 
 
extern void	fixStatic_reservoir(); 
 
 
/************************************************************************/ 
 
#define	SAMPLES_PER_FRAME		1152 
 
    typedef double SBS[2][3][SCALE_BLOCK][SBLIMIT]; 
    typedef double JSBS[3][SCALE_BLOCK][SBLIMIT]; 
 
    static SBS         *sb_sample; 
    static L3SBS       *l3_sb_sample; 
    static JSBS        *j_sample; 
 
    static layer info; 
    static short buffer[2][1152]; 
    static float snr32[32]; 
 
	static short sam[2][1344]; 
    static int whole_SpF, extra_slot; 
 
	static double	frac_SpF, slot_lag; 
 
    static int stereo, error_protection; 
 
 
static CodecInitOut	sOut; 
 
frame_params	fr_ps; 
char			* pEncodedOutput; 
int				outputBit; 
 
/*____ codecInit() ____________________________________________________________*/ 
 
CodecInitOut * codecInit( CodecInitIn * psIn ) 
{ 
	int			j; 
 
    volatile double avg_slots_per_frame; 
 
 
    /* Read psIn */ 
 
	switch (psIn->frequency) 
	{ 
		case 48000: 
			info.sampling_frequency = 1; 
        	break; 
      	case 44100: 
			info.sampling_frequency = 0; 
        	break; 
      	case 32000: 
			info.sampling_frequency = 2; 
        	break; 
      	default: 
        	return  FALSE; 
    } 
 
    switch( psIn->mode) 
    { 
		case 0: 
        	info.mode = MPG_MD_STEREO; 
			info.mode_ext = 0; 
        	break; 
      	case 2: 
        	info.mode = MPG_MD_DUAL_CHANNEL; 
			info.mode_ext = 0; 
        	break; 
      	case 3: 
        	info.mode = MPG_MD_MONO; 
			info.mode_ext = 0; 
        	break; 
      	default: 
        	return FALSE; 
    } 
 
    j = 0; 
    while ( j < 15 ) 
    { 
    	if ( bitratex[1][j] == psIn->bitrate ) 
        	break; 
      	j++; 
    } 
    info.bitrate_index = j; 
 
    info.version 	= 1;   /* Default: MPEG-1 */ 
    info.emphasis 	= psIn->emphasis; 
    info.extension 	= psIn->fPrivate; 
    info.copyright 	= psIn->fCopyright; 
    info.original 	= psIn->fOriginal; 
    info.error_protection = psIn->fCRC; 
	 
 
			 
/*_______ Static-fix _______________*/ 
 
 
	fInit_mdct_sub = 0; 
	fInit_mdct = 0; 
 
	fInit_fft = 0; 
 
	fInit_iteration_loop = 0; 
	fInit_huffman_read_flag = 0; 
 
	fixStatic_loop(); 
	fixStatic_reservoir(); 
 
 
/*___________________________________*/ 
 
    psycho_anal_init( psIn->frequency ); 
	initWindowFilterSubband(); 
	initFormatBitstream(); 
 
 
/*     Most large variables are declared dynamically to ensure 
       compatibility with smaller machines  */ 
     
    sb_sample 		= (SBS *) 	mem_alloc(sizeof(SBS), "sb_sample"); 
    l3_sb_sample 	= (L3SBS *) mem_alloc(sizeof(SBS), "l3_sb_sample"); 
    j_sample 		= (JSBS *) 	mem_alloc(sizeof(JSBS), "j_sample"); 
 
/*     clear buffers */ 
    memset((char *) buffer, 0, sizeof(buffer)); 
    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; 
    fr_ps.actual_mode = info.mode; 
    fr_ps.stereo 	= (info.mode == MPG_MD_MONO) ? 1 : 2; 
	fr_ps.sblimit 	= SBLIMIT; 
    fr_ps.jsbound 	= SBLIMIT; 
 
     
    stereo = fr_ps.stereo; 
    error_protection = info.error_protection; 
 
    avg_slots_per_frame = ((double)SAMPLES_PER_FRAME / 
                           s_freq[1][info.sampling_frequency]) * 
							((double)bitratex[1][info.bitrate_index] / 8.0); 
    whole_SpF = (int) avg_slots_per_frame; 
    frac_SpF  = avg_slots_per_frame - (double)whole_SpF; 
    slot_lag  = -frac_SpF; 
     
    if (frac_SpF == 0) 
    	info.padding = 0; 
 
	genNoisePowTab(); 
 
/*________________________*/ 
 
 
	if( stereo != 2 ) 
		sOut.nSamples = SAMPLES_PER_FRAME; 
	else 
		sOut.nSamples = SAMPLES_PER_FRAME*2; 
 
	sOut.bufferSize = 2048; 
 
	return  &sOut;			/* How many samples we want in each chunk... */ 
} 
 
 
void rebuffer_audio( short buffer[2][1152], short * insamp, unsigned int samples_read, int stereo ); 
 
/*____ codecEncodeChunk() _____________________________________________________*/ 
 
unsigned int codecEncodeChunk( int nSamples, short * pSamples, char * pDest ) 
{ 
 
	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, ch; 
	int				mean_bits, sideinfo_len; 
	int				bitsPerFrame; 
	int				j; 
/* 
	static int 		fFirst = TRUE; 
 
	if( fFirst == TRUE ) 
	{ 
		memset( (char *) &xr, 0, sizeof( xr ) ); 
		memset( (char *) &xr_dec, 0, sizeof( xr_dec ) ); 
		memset( (char *) &pe, 0, sizeof( pe ) ); 
		memset( (char *) &l3_enc, 0, sizeof( l3_enc ) ); 
		memset( (char *) &ratio, 0, sizeof( ratio ) ); 
		memset( (char *) &l3_side, 0, sizeof( l3_side ) ); 
		memset( (char *) &scalefac, 0, sizeof( scalefac ) ); 
 
        fFirst = FALSE; 
	} 
*/ 
 
	pEncodedOutput = pDest; 
	outputBit = 8; 
	pEncodedOutput[0] = 0; 
 
	rebuffer_audio( buffer, pSamples, nSamples, stereo ); 
 
	if (frac_SpF != 0) 
	{ 
	    if (slot_lag > (frac_SpF-1.0) ) 
		{ 
			slot_lag -= frac_SpF; 
			extra_slot = 0; 
			info.padding = 0; 
	    } 
		else 
		{ 
			extra_slot = 1; 
			info.padding = 1; 
			slot_lag += (1-frac_SpF); 
	  } 
	} 
	 
	       
	bitsPerFrame = 8 * whole_SpF + (info.padding * 8); 
 
/*		determine the mean bitrate for main data */ 
 
	sideinfo_len = 32; 
 
	if ( stereo == 1 ) 
		sideinfo_len += 136; 
	else 
		sideinfo_len += 256; 
 
	if ( info.error_protection ) 
		sideinfo_len += 16; 
	mean_bits = (bitsPerFrame - sideinfo_len) / 2; 
 
/*		psychoacoustic model */ 
 
	for ( gr = 0; gr < 2; gr++ ) 
		for ( ch = 0; ch < stereo; ch++ ) 
		{ 
		    psycho_anal( &buffer[ch][gr*576], &sam[ch][0], ch, 3, snr32, &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 < 2; gr++ ) 
		for ( ch = 0; ch < stereo; ch++ ) 
			for ( j = 0; j < 18; j++ ) 
		    	windowFilterSubband( &buffer[ch][gr*18*32+32*j], ch, &(*l3_sb_sample)[ch][gr+1][j][0] ); 
 
 
/*		apply mdct to the polyphase outputs */ 
 
	mdct_sub( l3_sb_sample, xr, stereo, &l3_side, 2 ); 
 
 
/*    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, 
						  xr, NULL, 0 ); 
	     
 
	return  pEncodedOutput - pDest; 
} 
 
/*____ codecExit() ____________________________________________________________*/ 
 
unsigned int codecExit( char * pDest ) 
{ 
	pEncodedOutput = pDest; 
	outputBit = 8; 
	pEncodedOutput[0] = 0; 
 
 
	free( sb_sample ); 
	free( l3_sb_sample ); 
	free( j_sample ); 
 
	psycho_anal_exit(); 
	exitFormatBitstream(); 
 	III_FlushBitstream(); 
 
	return  pEncodedOutput - pDest; 
}