Plan 9 from Bell Labs’s /usr/web/sources/contrib/cnielsen/bladeenc/codec.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
			(c) Copyright 1998-2000 - 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 ([email protected])
		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.



	------------    CHANGES    ------------

	2000-11-22  Andre Piotrowski

	-	big fix: module - original dist10 error - l3_sb_sample has to be of type 'L3SBS' not 'SBS'.
	-	bug fix: codecInit() - don't reset fInit-huffman_read_flag - read_huffcodetab() is a memory eater!

	2000-12-11  ap

	-	reformatted
	-	speed up: use single buffer
*/

#include	<stdlib.h>
#include	<assert.h>

#include	"common.h"
#include	"l3psy.h"
#include	"mdct.h"
#include	"reservoir.h"
#include	"formatbitstream2.h"
#include	"l3bitstream.h"
#include	"loop.h"
#include	"encoder.h"
#include	"codec.h"





extern	int				fInit_fft;





/************************************************************************/

#define	SAMPLES_PER_FRAME		1152

static	L3SBS					l3_sb_sample;

static	layer					info;



#if ORG_BUFFERS
static	short					buffer[2][1152];
/*	static	float					snr32[32]; */
static	short					sam[2][2048];
#else
static	FLOAT					buffer[2][2048];
static	int						buffer_idx;
#endif



static	int						whole_SpF;

static	double					frac_SpF, slot_lag;

static	int						stereo, error_protection;

static	III_side_info_t			l3_side;
static	CodecInitOut			sOut;

static	frame_params			fr_ps;



char					*pEncodedOutput;
int						outputBit;

volatile double			avg_slots_per_frame;





/*____ codecInit() ____________________________________________________________*/

CodecInitOut			*codecInit (CodecInitIn *psIn)
{
	int						j;

	/* 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  &&  bitratex[1][j] != psIn->bitrate)
		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;
/*	DON'T DO THAT ALL THE TIME
	fInit_huffman_read_flag = 0;
*/

	fixStatic_loop();

	l3_side.main_data_begin = 0;
	fixStatic_reservoir();


/*___________________________________*/

    psycho_anal_init (psIn->frequency);
	initWindowFilterSubband ();
	initFormatBitstream ();

/*     clear buffers */
	memset ((char *) l3_sb_sample, 0, sizeof(l3_sb_sample));
    memset((char *) buffer, 0, sizeof(buffer));
/*    memset((char *) snr32, 0, sizeof(snr32));*/
#if ORG_BUFFERS
    memset((char *) sam, 0, sizeof(sam));
#endif



    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... */
}





/*____ 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_scalefac_t		scalefac;
	int							gr, ch;
	int							mean_bits, sideinfo_len;
	int							bitsPerFrame;
	int							j;

/*
	static	int					fFirst = TRUE;

	if (fFirst)
	{
		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;
	}
*/


/* rebuffer audio */

#if ORG_BUFFERS
	rebuffer_audio (buffer, pSamples, nSamples, stereo);
#else
	rebuffer_audio (pSamples, buffer, &buffer_idx, nSamples, stereo);
#endif


/* psychoacoustic model */

	for (gr = 0;  gr < 2;  gr++)
		for (ch = 0;  ch < stereo;  ch++)
			psycho_anal
			(
#if ORG_BUFFERS
				&buffer[ch][gr*576],
				&sam[ch][0],
#else
		    	buffer[ch],
		    	(buffer_idx+gr*576) & 2047,
#endif
				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++)
	{
		int		gr_plus_1 = gr_idx[gr+1];

		for (ch = 0;  ch < stereo;  ch++)
		{
			for (j = 0;  j < 18;  j++)
			{
				windowFilterSubband
				(
#if ORG_BUFFERS
					&buffer[ch][gr*18*32+32*j],
					ch,
#else
					buffer[ch],
					(buffer_idx+768-480+gr*18*32+32*j) & 2047,
#endif
					l3_sb_sample[ch][gr_plus_1][j]
				);
			}
		}
	}


/* apply mdct to the polyphase outputs */

	mdct_sub (&l3_sb_sample, xr, stereo, &l3_side, 2);


	pEncodedOutput = pDest;
	outputBit = 8;
	pEncodedOutput[0] = 0;


	if (frac_SpF != 0)
	{
		if (slot_lag > (frac_SpF-1.0))
		{
			slot_lag -= frac_SpF;
			info.padding = 0;
		}
		else
		{
			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;


/* 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;

	psycho_anal_exit ();
	exitFormatBitstream ();
	III_FlushBitstream ();

	return pEncodedOutput - pDest;
}





/*____ codecFlush() _________________________________________________________*/

unsigned int			codecFlush (char *pDest)
{
	pEncodedOutput = pDest;
	outputBit = 8;
	pEncodedOutput[0] = 0;

	flushFrame ();

	whole_SpF = (int) avg_slots_per_frame;
	frac_SpF  = avg_slots_per_frame - (double) whole_SpF;
	slot_lag  = -frac_SpF;

	l3_side.main_data_begin = 0;
	fixStatic_reservoir ();

	return pEncodedOutput - pDest;
}




Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].