mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-11-03 23:53:55 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			931 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			931 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 *	TwoLAME: an optimized MPEG Audio Layer Two encoder
 | 
						|
 *
 | 
						|
 *	Copyright (C) 2001-2004 Michael Cheng
 | 
						|
 *	Copyright (C) 2004-2006 The TwoLAME Project
 | 
						|
 *
 | 
						|
 *	This library is free software; you can redistribute it 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.
 | 
						|
 *
 | 
						|
 *	This library is distributed in the hope that it will be useful,
 | 
						|
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 *	Lesser General Public License for more details.
 | 
						|
 *
 | 
						|
 *	You should have received a copy of the GNU Lesser General Public
 | 
						|
 *	License along with this library; if not, write to the Free Software
 | 
						|
 *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
						|
 *
 | 
						|
 *  $Id: twolame.c,v 1.3 2008-02-01 19:44:35 richardash1981 Exp $
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <math.h>
 | 
						|
#include <assert.h>
 | 
						|
#include <limits.h>
 | 
						|
 | 
						|
#include "twolame.h"
 | 
						|
#include "common.h"
 | 
						|
#include "bitbuffer.h"
 | 
						|
#include "mem.h"
 | 
						|
#include "crc.h"
 | 
						|
#include "dab.h"
 | 
						|
#include "psycho_n1.h"
 | 
						|
#include "psycho_0.h"
 | 
						|
#include "psycho_1.h"
 | 
						|
#include "psycho_2.h"
 | 
						|
#include "psycho_3.h"
 | 
						|
#include "psycho_4.h"
 | 
						|
#include "availbits.h"
 | 
						|
#include "subband.h"
 | 
						|
#include "encode.h"
 | 
						|
#include "energy.h"
 | 
						|
#include "util.h"
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  twolame_init
 | 
						|
  Create a set of encoding options and return a pointer to this structure
 | 
						|
  
 | 
						|
  Returns NULL if unsuccessful (can't allocate memory)
 | 
						|
  Otherwise returns pointer to memory block
 | 
						|
*/
 | 
						|
twolame_options *twolame_init(void) {
 | 
						|
	twolame_options *newoptions = NULL;	 
 | 
						|
	
 | 
						|
	newoptions = (twolame_options *)TWOLAME_MALLOC(sizeof(twolame_options));
 | 
						|
	if (newoptions==NULL) {
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	
 | 
						|
	newoptions->version = -1;
 | 
						|
	newoptions->num_channels_in = 0;
 | 
						|
	newoptions->num_channels_out = 0;
 | 
						|
	newoptions->samplerate_in = 0;
 | 
						|
	newoptions->samplerate_out = 0;
 | 
						|
	
 | 
						|
	newoptions->mode = TWOLAME_AUTO_MODE;	// Choose a proper mode later
 | 
						|
	newoptions->psymodel = 3;
 | 
						|
	newoptions->bitrate = -1;				// Default bitrate is set in init_params
 | 
						|
	newoptions->vbr = FALSE;
 | 
						|
	newoptions->vbrlevel = 5.0;
 | 
						|
	newoptions->athlevel = 0.0;
 | 
						|
	
 | 
						|
	newoptions->quickmode = FALSE;
 | 
						|
	newoptions->quickcount = 10;
 | 
						|
	newoptions->emphasis = TWOLAME_EMPHASIS_N;
 | 
						|
	newoptions->private_bit = 0;
 | 
						|
	newoptions->copyright = FALSE;
 | 
						|
	newoptions->original = TRUE;
 | 
						|
	newoptions->error_protection = FALSE;
 | 
						|
	newoptions->padding = TWOLAME_PAD_NO;
 | 
						|
	newoptions->do_dab = FALSE;
 | 
						|
	newoptions->dab_crc_len = 2;
 | 
						|
	newoptions->dab_xpad_len = 0;
 | 
						|
	newoptions->verbosity = 2;
 | 
						|
	newoptions->vbr_upper_index = 0;
 | 
						|
	
 | 
						|
	newoptions->scale = 1.0;			// scaling disabled
 | 
						|
	newoptions->scale_left = 1.0;		// scaling disabled
 | 
						|
	newoptions->scale_right = 1.0;		// scaling disabled
 | 
						|
	
 | 
						|
	newoptions->do_energy_levels = FALSE;
 | 
						|
	newoptions->num_ancillary_bits = -1;
 | 
						|
	
 | 
						|
	
 | 
						|
	newoptions->vbr_frame_count = 0;	// only used for debugging
 | 
						|
	newoptions->tablenum = 0;	
 | 
						|
 | 
						|
	newoptions->twolame_init = 0;
 | 
						|
	newoptions->subband = NULL;
 | 
						|
	newoptions->j_sample = NULL;
 | 
						|
	newoptions->sb_sample = NULL;
 | 
						|
	newoptions->psycount = 0;
 | 
						|
 | 
						|
	newoptions->p0mem = NULL;
 | 
						|
	newoptions->p1mem = NULL;
 | 
						|
	newoptions->p2mem = NULL;
 | 
						|
	newoptions->p3mem = NULL;
 | 
						|
	newoptions->p4mem = NULL;
 | 
						|
 | 
						|
	memset(newoptions->vbrstats, 0, sizeof(newoptions->vbrstats));
 | 
						|
	
 | 
						|
	return(newoptions);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// Returns 0 if successful
 | 
						|
// Returns -1 if unsuccessful
 | 
						|
static int init_header_info( twolame_options *glopts ) {
 | 
						|
	frame_header *header = &glopts->header;
 | 
						|
	
 | 
						|
	/* use the options to create header info structure */
 | 
						|
	header->lay = 2;
 | 
						|
	header->error_protection = glopts->error_protection;
 | 
						|
	header->version = glopts->version;
 | 
						|
	
 | 
						|
	// Convert the sampling frequency to the required index
 | 
						|
	header->samplerate_idx = twolame_get_samplerate_index( glopts->samplerate_out ); 
 | 
						|
	if (header->samplerate_idx < 0) {
 | 
						|
		fprintf(stdout,"Not a valid samplerate: %i\n",glopts->samplerate_out );
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	
 | 
						|
	// Convert the bitrate to the an index	
 | 
						|
	header->bitrate_index = twolame_get_bitrate_index(glopts->bitrate, header->version);
 | 
						|
	if (header->bitrate_index < 0) {
 | 
						|
		fprintf(stdout,"Not a valid bitrate (%i) for MPEG version '%s'\n", glopts->bitrate, 
 | 
						|
			twolame_mpeg_version_name(glopts->version));
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
		
 | 
						|
	// Convert the max VBR bitrate to the an index	
 | 
						|
	glopts->vbr_upper_index = twolame_get_bitrate_index(glopts->vbr_max_bitrate, header->version);
 | 
						|
	if (glopts->vbr_upper_index < 0) {
 | 
						|
		fprintf(stdout,"Not a valid max VBR bitrate for this version: %i\n",glopts->vbr_max_bitrate);
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	
 | 
						|
	// Copy accross the other settings	
 | 
						|
	header->padding = glopts->padding;
 | 
						|
	header->private_bit = glopts->private_bit;
 | 
						|
	header->mode = glopts->mode;
 | 
						|
	header->mode_ext = 0;
 | 
						|
	header->copyright = glopts->copyright;
 | 
						|
	header->original = glopts->original;
 | 
						|
	header->emphasis = glopts->emphasis;
 | 
						|
	
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * This function should actually *check* the parameters to see if they
 | 
						|
 * make sense. 
 | 
						|
 */
 | 
						|
 | 
						|
int twolame_init_params (twolame_options *glopts) {
 | 
						|
 | 
						|
	if (glopts->twolame_init) {
 | 
						|
		fprintf(stderr,"Already called twolame_init_params() once.\n");
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
 | 
						|
	// Check the number of channels
 | 
						|
	if (glopts->num_channels_in != 1 && glopts->num_channels_in != 2) {
 | 
						|
		fprintf(stderr,"twolame_init_params(): must specify number of input channels using twolame_set_num_channels().\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	
 | 
						|
	// If not output samplerate has been set, then set it to the input sample rate
 | 
						|
	if (glopts->samplerate_out < 1) {
 | 
						|
		glopts->samplerate_out = glopts->samplerate_in;
 | 
						|
	}
 | 
						|
	
 | 
						|
	// If the MPEG version has not been set, then choose automatically
 | 
						|
	if (glopts->version == -1) {
 | 
						|
		// Get the MPEG version for the chosen samplerate
 | 
						|
		glopts->version = twolame_get_version_for_samplerate( glopts->samplerate_out );
 | 
						|
		if (glopts->version < 0) {
 | 
						|
			fprintf(stdout,"twolame_init_params(): invalid samplerate: %i\n", glopts->samplerate_out );
 | 
						|
			return -1;
 | 
						|
		} else if (glopts->verbosity>=3) {
 | 
						|
			fprintf(stderr, "Chosen version '%s' for samplerate of %d Hz.\n",
 | 
						|
				twolame_mpeg_version_name(glopts->version), glopts->samplerate_out);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Choose mode (if none chosen)
 | 
						|
	if (glopts->mode == TWOLAME_AUTO_MODE) {
 | 
						|
		if (glopts->num_channels_in == 2) glopts->mode = TWOLAME_STEREO;
 | 
						|
		else glopts->mode = TWOLAME_MONO;
 | 
						|
		if (glopts->verbosity>=3) {
 | 
						|
			fprintf(stderr, "Chosen mode to be '%s' because of %d input channels.\n",
 | 
						|
				twolame_get_mode_name(glopts), glopts->num_channels_in);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Choose the bitrate (if none chosen)
 | 
						|
	if (glopts->bitrate <= 0) {
 | 
						|
		if (glopts->mode == TWOLAME_MONO) {
 | 
						|
			switch(glopts->samplerate_out) {
 | 
						|
				case 48000: glopts->bitrate = 96; break;	// (LAME=64)
 | 
						|
				case 44100: glopts->bitrate = 96; break;	// (LAME=64)
 | 
						|
				case 32000: glopts->bitrate = 80; break;	// (LAME=48)
 | 
						|
				case 24000: glopts->bitrate = 48; break;	// (LAME=32)
 | 
						|
				case 22050: glopts->bitrate = 48; break;	// (LAME=32)
 | 
						|
				case 16000: glopts->bitrate = 32; break;	// (LAME=24)
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			switch(glopts->samplerate_out) {
 | 
						|
				case 48000: glopts->bitrate = 192; break;	// (LAME=128)
 | 
						|
				case 44100: glopts->bitrate = 192; break;	// (LAME=128)
 | 
						|
				case 32000: glopts->bitrate = 160; break;	// (LAME=96)
 | 
						|
				case 24000: glopts->bitrate = 96; break;	// (LAME=64)
 | 
						|
				case 22050: glopts->bitrate = 96; break;	// (LAME=64)
 | 
						|
				case 16000: glopts->bitrate = 64; break;	// (LAME=48)
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (glopts->verbosity>=3) {
 | 
						|
			fprintf(stderr, "Chosen bitrate of %dkbps for samplerate of %d Hz.\n",
 | 
						|
				glopts->bitrate, glopts->samplerate_out);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* Can't do DAB and energylevel extensions at the same time
 | 
						|
	   Because both of them think they're the only ones inserting
 | 
						|
	   information into the ancillary section of the frame */
 | 
						|
	if (glopts->do_dab && glopts->do_energy_levels) {
 | 
						|
		fprintf(stderr,"Error: Can't do DAB and Energy Levels at the same time\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Set the number of ancillary bits automatically, if none set */
 | 
						|
	if (glopts->num_ancillary_bits < 0) {
 | 
						|
		if (glopts->do_energy_levels) {
 | 
						|
			glopts->num_ancillary_bits = get_required_energy_bits( glopts );
 | 
						|
		} else {
 | 
						|
			glopts->num_ancillary_bits = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	
 | 
						|
	/* Check that if we're doing energy levels, that there's enough space to put the information */
 | 
						|
	if (glopts->do_energy_levels) {
 | 
						|
		int required = get_required_energy_bits(glopts);
 | 
						|
		if (glopts->num_ancillary_bits < required) {
 | 
						|
			fprintf(stderr,"Warning: Too few ancillary bits to store energy levels: %i<%i\n",glopts->num_ancillary_bits, required);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/*
 | 
						|
	 * MFC Feb 2003: in VBR mode, joint
 | 
						|
	 * stereo doesn't make any sense at
 | 
						|
	 * the moment, as there are no noisy
 | 
						|
	 * subbands according to
 | 
						|
	 * bits_for_nonoise in vbr mode
 | 
						|
	 */
 | 
						|
	if (glopts->vbr && glopts->mode==TWOLAME_JOINT_STEREO) {
 | 
						|
		fprintf(stderr,"Warning: Can't do Joint Stereo with VBR, switching to normal stereo.\n");
 | 
						|
 | 
						|
		// force stereo mode
 | 
						|
		twolame_set_mode(glopts, TWOLAME_STEREO);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Can't do padding and VBR at same time */
 | 
						|
	if (glopts->vbr && glopts->padding == TRUE) {
 | 
						|
		fprintf(stderr,"Error: Can't do padding and VBR at same time\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	
 | 
						|
	// Set the Number of output channels
 | 
						|
	glopts->num_channels_out = (glopts->mode == TWOLAME_MONO) ? 1 : 2;
 | 
						|
	
 | 
						|
 | 
						|
 | 
						|
	// build mpeg header from parameters
 | 
						|
	if (init_header_info( glopts )<0) {
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	
 | 
						|
	// Select table number and sblimit
 | 
						|
	if (encode_init( glopts )<0) {
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	
 | 
						|
	// initialise bitrate allocation
 | 
						|
	if (init_bit_allocation( glopts )<0) {
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	
 | 
						|
	// Check input samplerate is same as output samplerate
 | 
						|
	if (glopts->samplerate_out != glopts->samplerate_in) {
 | 
						|
		fprintf(stderr,"twolame_init_params(): sorry, twolame doesn't support resampling (yet).\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
	// Initialise interal variables
 | 
						|
	glopts->samples_in_buffer = 0;
 | 
						|
	glopts->psycount = 0;
 | 
						|
 | 
						|
  
 | 
						|
	// Allocate memory to larger buffers 
 | 
						|
	glopts->subband = (subband_t *) TWOLAME_MALLOC(sizeof (subband_t));
 | 
						|
	glopts->j_sample = (jsb_sample_t *) TWOLAME_MALLOC(sizeof (jsb_sample_t));
 | 
						|
	glopts->sb_sample = (sb_sample_t *) TWOLAME_MALLOC(sizeof (sb_sample_t));
 | 
						|
	
 | 
						|
	// clear buffers
 | 
						|
	memset ((char *) glopts->buffer, 0, sizeof(glopts->buffer));
 | 
						|
	memset ((char *) glopts->bit_alloc, 0, sizeof (glopts->bit_alloc));
 | 
						|
	memset ((char *) glopts->scfsi, 0, sizeof (glopts->scfsi));
 | 
						|
	memset ((char *) glopts->scalar, 0, sizeof (glopts->scalar));
 | 
						|
	memset ((char *) glopts->j_scale, 0, sizeof (glopts->j_scale));
 | 
						|
	memset ((char *) glopts->smrdef, 0, sizeof (glopts->smrdef));
 | 
						|
	memset ((char *) glopts->smr, 0, sizeof (glopts->smr));
 | 
						|
	memset ((char *) glopts->max_sc, 0, sizeof (glopts->max_sc));
 | 
						|
 | 
						|
	// Initialise subband windowfilter
 | 
						|
	if (init_subband(&glopts->smem)<0) {
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	// All initalised now :)
 | 
						|
	glopts->twolame_init++;
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Scale the samples in the frame sample buffer
 | 
						|
   using the user specified values
 | 
						|
   and downmix/upmix according to the number of input/output channels 
 | 
						|
*/
 | 
						|
static void scale_and_mix_samples( twolame_options *glopts )
 | 
						|
{
 | 
						|
	int num_samples = glopts->samples_in_buffer;
 | 
						|
	int i;
 | 
						|
	
 | 
						|
	// apply scaling to both channels 
 | 
						|
	if (glopts->scale != 0 && glopts->scale != 1.0) {
 | 
						|
		for (i=0 ; i<num_samples; ++i) {
 | 
						|
			glopts->buffer[0][i] *= glopts->scale;
 | 
						|
			if (glopts->num_channels_in == 2)
 | 
						|
			glopts->buffer[1][i] *= glopts->scale;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// apply scaling to channel 0 (left) 
 | 
						|
	if (glopts->scale_left != 0 && glopts->scale_left != 1.0) {
 | 
						|
		for (i=0 ; i<num_samples; ++i) {
 | 
						|
			glopts->buffer[0][i] *= glopts->scale_left;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// apply scaling to channel 1 (right) 
 | 
						|
	if (glopts->scale_right != 0 && glopts->scale_right != 1.0) {
 | 
						|
		for (i=0 ; i<num_samples; ++i) {
 | 
						|
			glopts->buffer[1][i] *= glopts->scale_right;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Downmix to Mono if 2 channels in and 1 channel out 
 | 
						|
	if (glopts->num_channels_in == 2 && glopts->num_channels_out == 1) {
 | 
						|
		for (i=0; i<num_samples; ++i) {
 | 
						|
			glopts->buffer[0][i] = ((long) glopts->buffer[0][i] + glopts->buffer[1][i]) / 2;
 | 
						|
			glopts->buffer[1][i] = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
   // Upmix to Stereo if 2 channels out and 1 channel in
 | 
						|
	if (glopts->num_channels_in == 1 && glopts->num_channels_out == 2) {
 | 
						|
		for (i=0; i<num_samples; ++i) {
 | 
						|
			glopts->buffer[1][i] = glopts->buffer[0][i];
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
	Encode a single frame of audio from 1152 samples
 | 
						|
	Audio samples are taken from glopts->buffer
 | 
						|
	Encoded bit stream is placed in to parameter bs
 | 
						|
	(not intended for use outside the library)
 | 
						|
	
 | 
						|
	Returns the size of the frame
 | 
						|
	or -1 if there is an error
 | 
						|
*/
 | 
						|
static int encode_frame(twolame_options *glopts, bit_stream *bs)
 | 
						|
{
 | 
						|
	int nch = glopts->num_channels_out;
 | 
						|
	int sb, ch, adb, i;
 | 
						|
	unsigned long frameBits, initial_bits;
 | 
						|
	short sam[2][1056];
 | 
						|
 | 
						|
	if (!glopts->twolame_init) {
 | 
						|
		fprintf (stderr, "Please call twolame_init_params() before starting encoding.\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	
 | 
						|
	// Scale and mix the input buffer
 | 
						|
	scale_and_mix_samples( glopts );
 | 
						|
	
 | 
						|
	
 | 
						|
	// Clear the saved audio buffer
 | 
						|
	memset ((char *) sam, 0, sizeof (sam));
 | 
						|
	
 | 
						|
	// Number of bits to calculate CRC on
 | 
						|
	glopts->num_crc_bits=0;
 | 
						|
 | 
						|
	// Store the number of bits initially in the bit buffer
 | 
						|
	initial_bits = buffer_sstell(bs);
 | 
						|
 | 
						|
	adb = available_bits ( glopts );
 | 
						|
 | 
						|
	/* allow the user to reserve some space at the end of the frame
 | 
						|
	   This will however leave fewer bits for the audio.
 | 
						|
	   Need to do a sanity check here to see that there are *some* 
 | 
						|
	   bits left. */
 | 
						|
	if (glopts->num_ancillary_bits > 0.6*adb) {
 | 
						|
		/* Trying to reserve more than 60% of the frame.
 | 
						|
		   0.6 is arbitrary. but since most applications
 | 
						|
		   probably only want to reserve a few bytes, this seems fine.
 | 
						|
		   Typical frame size is about 800bytes */
 | 
						|
		fprintf(stderr,"You're trying to reserve more than 60%% of the mpeg frame for ancillary data\n");
 | 
						|
		fprintf(stderr,"This is probably an error. But I'll keep going anyway...\n");
 | 
						|
	} 
 | 
						|
 | 
						|
	adb -= glopts->num_ancillary_bits;
 | 
						|
 | 
						|
 | 
						|
	/* MFC 26 July 2003
 | 
						|
	   Doing DAB became a bit harder in the reorganisation of the code.
 | 
						|
	   Now there is no guarantee that there is more than one frame in the bitbuffer.
 | 
						|
	   But DAB requires that the CRC for the *current* frame be written at the end 
 | 
						|
	   of the *previous* frame.
 | 
						|
	   Workaround: Users (Nicholas?) wanting to implement DAB will have to do some work
 | 
						|
	   in the frontend.
 | 
						|
			First: Reserve some bits for yourself (options->num_ancillary_bits)
 | 
						|
		Second: Put the encoder into "single frame mode" i.e. only read 1152 samples
 | 
						|
				per channel. (frontendoptions->singleFrameMode)
 | 
						|
		Third: When you receive each mp2 frame back from the library, you'll have to insert
 | 
						|
			   the options->dabCrc[i] values into the end of the frame yourself. (DAB crc calc is 
 | 
						|
		   done below)
 | 
						|
	   The frontend will have to keep the previous frame in memory. 
 | 
						|
	   As of 26July all that needs to be done is for the frontend to buffer one frame in memory, such that
 | 
						|
	   the CRC for the next frame can be written in at the end of it.
 | 
						|
	*/
 | 
						|
 | 
						|
	{
 | 
						|
		int gr, bl, ch;
 | 
						|
		/* New polyphase filter
 | 
						|
		 Combines windowing and filtering. Ricardo Feb'03 */
 | 
						|
		for( gr = 0; gr < 3; gr++ )
 | 
						|
		for ( bl = 0; bl < 12; bl++ )
 | 
						|
		for ( ch = 0; ch < nch; ch++ )
 | 
						|
			window_filter_subband( &glopts->smem, &glopts->buffer[ch][gr * 12 * 32 + 32 * bl], ch,
 | 
						|
				 &(*glopts->sb_sample)[ch][gr][bl][0] );
 | 
						|
	}
 | 
						|
 | 
						|
	scalefactor_calc(*glopts->sb_sample, glopts->scalar, nch, glopts->sblimit);
 | 
						|
	find_sf_max (glopts, glopts->scalar, glopts->max_sc);
 | 
						|
	if (glopts->mode == TWOLAME_JOINT_STEREO) {
 | 
						|
		// this way we calculate more mono than we need but it is cheap 
 | 
						|
		combine_lr (*glopts->sb_sample, *glopts->j_sample, glopts->sblimit);
 | 
						|
		scalefactor_calc (glopts->j_sample, &glopts->j_scale, 1, glopts->sblimit);
 | 
						|
	}
 | 
						|
 | 
						|
	if ((glopts->quickmode == TRUE) && (++glopts->psycount % glopts->quickcount != 0)) {
 | 
						|
		/* We're using quick mode, so we're only calculating the model every
 | 
						|
		 'quickcount' frames. Otherwise, just copy the old ones across */
 | 
						|
		for (ch = 0; ch < nch; ch++) {
 | 
						|
			for (sb = 0; sb < SBLIMIT; sb++) {
 | 
						|
				glopts->smr[ch][sb] = glopts->smrdef[ch][sb];
 | 
						|
			}
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		// calculate the psymodel 
 | 
						|
		switch (glopts->psymodel) {
 | 
						|
			case -1:
 | 
						|
				psycho_n1 (glopts, glopts->smr, nch);
 | 
						|
			break;
 | 
						|
			case 0: // Psy Model A
 | 
						|
				psycho_0 (glopts, glopts->smr, glopts->scalar); 
 | 
						|
			break;
 | 
						|
			case 1:
 | 
						|
				psycho_1 (glopts, glopts->buffer, glopts->max_sc, glopts->smr);
 | 
						|
			break;
 | 
						|
			case 2:
 | 
						|
				psycho_2 (glopts, glopts->buffer, sam, glopts->smr );	
 | 
						|
			break;
 | 
						|
			case 3:
 | 
						|
				// Modified psy model 1
 | 
						|
				psycho_3 (glopts, glopts->buffer, glopts->max_sc, glopts->smr);
 | 
						|
			break;
 | 
						|
			case 4:
 | 
						|
				// Modified psy model 2
 | 
						|
				psycho_4 (glopts, glopts->buffer, sam, glopts->smr );
 | 
						|
			break;	
 | 
						|
			default:
 | 
						|
				fprintf (stderr, "Invalid psy model specification: %i\n", glopts->psymodel);
 | 
						|
				return -1;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
 | 
						|
		if (glopts->quickmode == TRUE) {
 | 
						|
			// copy the smr values and reuse them later 
 | 
						|
			for (ch = 0; ch < nch; ch++) {
 | 
						|
				for (sb = 0; sb < SBLIMIT; sb++) glopts->smrdef[ch][sb] = glopts->smr[ch][sb];
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	sf_transmission_pattern (glopts, glopts->scalar, glopts->scfsi);
 | 
						|
	main_bit_allocation (glopts, glopts->smr, glopts->scfsi, glopts->bit_alloc, &adb);
 | 
						|
	
 | 
						|
	write_header (glopts, bs);
 | 
						|
	
 | 
						|
	// Leave space for 2 bytes of CRC to be filled in later
 | 
						|
	if (glopts->error_protection)
 | 
						|
		buffer_putbits (bs, 0, 16);
 | 
						|
	
 | 
						|
	write_bit_alloc (glopts, glopts->bit_alloc, bs);
 | 
						|
	write_scalefactors(glopts, glopts->bit_alloc, glopts->scfsi, glopts->scalar, bs);
 | 
						|
	
 | 
						|
	subband_quantization (glopts, glopts->scalar, *glopts->sb_sample, glopts->j_scale, *glopts->j_sample, glopts->bit_alloc,
 | 
						|
				  *glopts->subband);
 | 
						|
	write_samples(glopts, *glopts->subband, glopts->bit_alloc, bs);
 | 
						|
 | 
						|
	// If not all the bits were used, write out a stack of zeros 
 | 
						|
	for (i = 0; i < adb; i++)	buffer_put1bit (bs, 0);
 | 
						|
 | 
						|
 | 
						|
	/* MFC July 03 FIXME
 | 
						|
	   Write an extra byte for 16/24/32/48 input when padding is on.
 | 
						|
	   Something must be going astray with the frame size calcs.
 | 
						|
	   This fudge works fine for the moment */
 | 
						|
	if ((glopts->header.samplerate_idx != 0) && (glopts->padding)) // i.e. not a 44.1 or 22kHz input file
 | 
						|
		buffer_putbits (bs, 0, 8);
 | 
						|
 | 
						|
	if (glopts->do_dab) {
 | 
						|
		// Do the CRC calc for DAB stuff if required.
 | 
						|
		// It will be up to the frontend to insert it into the end of the 
 | 
						|
		// previous frame.
 | 
						|
		for (i=glopts->dab_crc_len-1; i>=0; i--) {
 | 
						|
			dab_crc_calc (glopts, glopts->bit_alloc, glopts->scfsi, glopts->scalar, &glopts->dab_crc[i], i);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	// Allocate space for the reserved ancillary bits
 | 
						|
	for (i=0; i<glopts->num_ancillary_bits;i++) 
 | 
						|
		buffer_put1bit(bs, 0);
 | 
						|
 | 
						|
 | 
						|
	// Calulate the number of bits in this frame
 | 
						|
	frameBits = buffer_sstell(bs) - initial_bits;
 | 
						|
	if (frameBits % 8) {	/* a program failure */
 | 
						|
		fprintf (stderr, "Sent %ld bits = %ld slots plus %ld\n", frameBits, frameBits/8, frameBits%8);
 | 
						|
		fprintf (stderr, "If you are reading this, the program is broken\n");
 | 
						|
		fprintf (stderr, "email %s with the command line arguments and other info\n", PACKAGE_BUGREPORT);
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	// Store the energy levels at the end of the frame
 | 
						|
	if (glopts->do_energy_levels)
 | 
						|
		do_energy_levels(glopts, bs);
 | 
						|
 | 
						|
	// MEANX: Recompute checksum from bitstream
 | 
						|
	if (glopts->error_protection)
 | 
						|
	{
 | 
						|
		unsigned char *frame_ptr=bs->buf+(initial_bits>>3);
 | 
						|
		crc_writeheader(frame_ptr, glopts->num_crc_bits );
 | 
						|
	}
 | 
						|
 | 
						|
	//fprintf(stdout,"Frame size: %li\n\n",frameBits/8);
 | 
						|
 | 
						|
	return frameBits/8;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  glopts
 | 
						|
  leftpcm - holds left channel (or mono channel)
 | 
						|
  rightpcm - d'uh
 | 
						|
  num_samples - the number of samples in each channel
 | 
						|
  mp2buffer - a pointer to the place where we want the mpeg data to be written
 | 
						|
  mp2buffer_size - how much space the user allocated for this buffer
 | 
						|
  mp2fill_size - how much mpeg data the library has put into the mp2buffer 
 | 
						|
*/
 | 
						|
 | 
						|
int twolame_encode_buffer(
 | 
						|
		twolame_options *glopts,
 | 
						|
		const short int leftpcm[],
 | 
						|
		const short int rightpcm[],
 | 
						|
		int num_samples,
 | 
						|
		unsigned char *mp2buffer,
 | 
						|
		int mp2buffer_size )
 | 
						|
{
 | 
						|
	int mp2_size=0;
 | 
						|
	bit_stream *mybs;
 | 
						|
	int i;
 | 
						|
 | 
						|
	if (num_samples==0) return 0;
 | 
						|
 | 
						|
 | 
						|
	// now would be a great time to validate the size of the buffer.
 | 
						|
	// samples/1152 * sizeof(frame) < mp2buffer_size 
 | 
						|
	mybs = buffer_init( mp2buffer, mp2buffer_size );
 | 
						|
 | 
						|
 | 
						|
	// Use up all the samples in in_buffer
 | 
						|
	while( num_samples ) {
 | 
						|
	
 | 
						|
		// fill up glopts->buffer with as much as we can
 | 
						|
		int samples_to_copy = TWOLAME_SAMPLES_PER_FRAME - glopts->samples_in_buffer;
 | 
						|
		if (num_samples < samples_to_copy) samples_to_copy = num_samples;
 | 
						|
 | 
						|
		/* Copy across samples */
 | 
						|
		for(i=0; i<samples_to_copy; i++) {
 | 
						|
			glopts->buffer[0][glopts->samples_in_buffer+i] = *leftpcm++;
 | 
						|
			if (glopts->num_channels_in==2)
 | 
						|
			glopts->buffer[1][glopts->samples_in_buffer+i] = *rightpcm++;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		/* Update sample counts */
 | 
						|
		glopts->samples_in_buffer += samples_to_copy;
 | 
						|
		num_samples -= samples_to_copy;
 | 
						|
		
 | 
						|
		
 | 
						|
		// is there enough to encode a whole frame ?
 | 
						|
		if (glopts->samples_in_buffer >= TWOLAME_SAMPLES_PER_FRAME) {
 | 
						|
			int bytes = encode_frame( glopts, mybs );
 | 
						|
			if (bytes<=0) {
 | 
						|
				buffer_deinit( &mybs );
 | 
						|
				return bytes;
 | 
						|
			}
 | 
						|
			mp2_size += bytes;
 | 
						|
			glopts->samples_in_buffer -= TWOLAME_SAMPLES_PER_FRAME;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// free up the bit stream buffer structure
 | 
						|
	buffer_deinit( &mybs );
 | 
						|
 | 
						|
	return(mp2_size);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int twolame_encode_buffer_interleaved(
 | 
						|
		twolame_options *glopts,
 | 
						|
		const short int pcm[],
 | 
						|
		int num_samples,
 | 
						|
		unsigned char *mp2buffer,
 | 
						|
		int mp2buffer_size )
 | 
						|
{
 | 
						|
	int mp2_size=0;
 | 
						|
	bit_stream *mybs;
 | 
						|
	int i;
 | 
						|
 | 
						|
	if (num_samples==0) return 0;
 | 
						|
 | 
						|
 | 
						|
	// now would be a great time to validate the size of the buffer.
 | 
						|
	// samples/1152 * sizeof(frame) < mp2buffer_size 
 | 
						|
	mybs = buffer_init( mp2buffer, mp2buffer_size );
 | 
						|
 | 
						|
	// Use up all the samples in in_buffer
 | 
						|
	while( num_samples ) {
 | 
						|
	
 | 
						|
		// fill up glopts->buffer with as much as we can
 | 
						|
		int samples_to_copy = TWOLAME_SAMPLES_PER_FRAME - glopts->samples_in_buffer;
 | 
						|
		if (num_samples < samples_to_copy) samples_to_copy = num_samples;
 | 
						|
 | 
						|
		/* Copy across samples */
 | 
						|
		for(i=0; i<samples_to_copy; i++) {
 | 
						|
			glopts->buffer[0][glopts->samples_in_buffer+i] = *pcm++;
 | 
						|
			if (glopts->num_channels_in==2)
 | 
						|
			glopts->buffer[1][glopts->samples_in_buffer+i] = *pcm++;
 | 
						|
		}
 | 
						|
		
 | 
						|
		
 | 
						|
		/* Update sample counts */
 | 
						|
		glopts->samples_in_buffer += samples_to_copy;
 | 
						|
		num_samples -= samples_to_copy;
 | 
						|
		
 | 
						|
		
 | 
						|
		// is there enough to encode a whole frame ?
 | 
						|
		if (glopts->samples_in_buffer >= TWOLAME_SAMPLES_PER_FRAME) {
 | 
						|
			int bytes = encode_frame( glopts, mybs );
 | 
						|
			if (bytes<=0) {
 | 
						|
				buffer_deinit( &mybs );
 | 
						|
				return bytes;
 | 
						|
			}
 | 
						|
			mp2_size += bytes;
 | 
						|
			glopts->samples_in_buffer -= TWOLAME_SAMPLES_PER_FRAME;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// free up the bit stream buffer structure
 | 
						|
	buffer_deinit( &mybs );
 | 
						|
	
 | 
						|
	
 | 
						|
	return(mp2_size);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void float32_to_short(
 | 
						|
	const float in[],
 | 
						|
	short out[],
 | 
						|
	int num_samples,
 | 
						|
	int stride)
 | 
						|
{
 | 
						|
	int n;
 | 
						|
	
 | 
						|
	for(n=0; n<num_samples; n++) {
 | 
						|
		int tmp = lrintf(in[n*stride] * 32768.0f);
 | 
						|
		if (tmp > SHRT_MAX) {
 | 
						|
			out[n] = SHRT_MAX;
 | 
						|
		} else if (tmp < SHRT_MIN) {
 | 
						|
			out[n] = SHRT_MIN;
 | 
						|
		} else {
 | 
						|
			out[n] = (short) tmp;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  glopts
 | 
						|
  leftpcm - holds left channel (or mono channel)
 | 
						|
  rightpcm - d'uh
 | 
						|
  num_samples - the number of samples in each channel
 | 
						|
  mp2buffer - a pointer to the place where we want the mpeg data to be written
 | 
						|
  mp2buffer_size - how much space the user allocated for this buffer
 | 
						|
  mp2fill_size - how much mpeg data the library has put into the mp2buffer 
 | 
						|
*/
 | 
						|
 | 
						|
int twolame_encode_buffer_float32(
 | 
						|
		twolame_options *glopts,
 | 
						|
		const float leftpcm[],
 | 
						|
		const float rightpcm[],
 | 
						|
		int num_samples,
 | 
						|
		unsigned char *mp2buffer,
 | 
						|
		int mp2buffer_size )
 | 
						|
{
 | 
						|
	int mp2_size=0;
 | 
						|
	bit_stream *mybs;
 | 
						|
 | 
						|
	if (num_samples==0) return 0;
 | 
						|
 | 
						|
 | 
						|
	// now would be a great time to validate the size of the buffer.
 | 
						|
	// samples/1152 * sizeof(frame) < mp2buffer_size 
 | 
						|
	mybs = buffer_init( mp2buffer, mp2buffer_size );
 | 
						|
 | 
						|
 | 
						|
	// Use up all the samples in in_buffer
 | 
						|
	while( num_samples ) {
 | 
						|
	
 | 
						|
		// fill up glopts->buffer with as much as we can
 | 
						|
		int samples_to_copy = TWOLAME_SAMPLES_PER_FRAME - glopts->samples_in_buffer;
 | 
						|
		if (num_samples < samples_to_copy) samples_to_copy = num_samples;
 | 
						|
 | 
						|
		/* Copy across samples */
 | 
						|
		float32_to_short( leftpcm, &glopts->buffer[0][glopts->samples_in_buffer], samples_to_copy, 1 );
 | 
						|
		if (glopts->num_channels_in==2)
 | 
						|
		float32_to_short( rightpcm, &glopts->buffer[1][glopts->samples_in_buffer], samples_to_copy, 1 );
 | 
						|
		leftpcm+=samples_to_copy;
 | 
						|
		rightpcm+=samples_to_copy;		
 | 
						|
		
 | 
						|
		/* Update sample counts */
 | 
						|
		glopts->samples_in_buffer += samples_to_copy;
 | 
						|
		num_samples -= samples_to_copy;
 | 
						|
		
 | 
						|
		
 | 
						|
		// is there enough to encode a whole frame ?
 | 
						|
		if (glopts->samples_in_buffer >= TWOLAME_SAMPLES_PER_FRAME) {
 | 
						|
			int bytes = encode_frame( glopts, mybs );
 | 
						|
			if (bytes<=0) {
 | 
						|
				buffer_deinit( &mybs );
 | 
						|
				return bytes;
 | 
						|
			}
 | 
						|
			mp2_size += bytes;
 | 
						|
			glopts->samples_in_buffer -= TWOLAME_SAMPLES_PER_FRAME;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// free up the bit stream buffer structure
 | 
						|
	buffer_deinit( &mybs );
 | 
						|
 | 
						|
	return(mp2_size);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int twolame_encode_buffer_float32_interleaved(
 | 
						|
		twolame_options *glopts,
 | 
						|
		const float pcm[],
 | 
						|
		int num_samples,
 | 
						|
		unsigned char *mp2buffer,
 | 
						|
		int mp2buffer_size )
 | 
						|
{
 | 
						|
	int mp2_size=0;
 | 
						|
	bit_stream *mybs;
 | 
						|
 | 
						|
	if (num_samples==0) return 0;
 | 
						|
 | 
						|
 | 
						|
	// now would be a great time to validate the size of the buffer.
 | 
						|
	// samples/1152 * sizeof(frame) < mp2buffer_size 
 | 
						|
	mybs = buffer_init( mp2buffer, mp2buffer_size );
 | 
						|
 | 
						|
	// Use up all the samples in in_buffer
 | 
						|
	while( num_samples ) {
 | 
						|
	
 | 
						|
		// fill up glopts->buffer with as much as we can
 | 
						|
		int samples_to_copy = TWOLAME_SAMPLES_PER_FRAME - glopts->samples_in_buffer;
 | 
						|
		if (num_samples < samples_to_copy) samples_to_copy = num_samples;
 | 
						|
 | 
						|
		/* Copy across samples */
 | 
						|
		float32_to_short( pcm, &glopts->buffer[0][glopts->samples_in_buffer], samples_to_copy, glopts->num_channels_in );
 | 
						|
		if (glopts->num_channels_in==2)
 | 
						|
		float32_to_short( pcm+1, &glopts->buffer[1][glopts->samples_in_buffer], samples_to_copy, glopts->num_channels_in );
 | 
						|
		pcm+=(samples_to_copy*glopts->num_channels_in);
 | 
						|
		
 | 
						|
		
 | 
						|
		/* Update sample counts */
 | 
						|
		glopts->samples_in_buffer += samples_to_copy;
 | 
						|
		num_samples -= samples_to_copy;
 | 
						|
		
 | 
						|
		
 | 
						|
		// is there enough to encode a whole frame ?
 | 
						|
		if (glopts->samples_in_buffer >= TWOLAME_SAMPLES_PER_FRAME) {
 | 
						|
			int bytes = encode_frame( glopts, mybs );
 | 
						|
			if (bytes<=0) {
 | 
						|
				buffer_deinit( &mybs );
 | 
						|
				return bytes;
 | 
						|
			}
 | 
						|
			mp2_size += bytes;
 | 
						|
			glopts->samples_in_buffer -= TWOLAME_SAMPLES_PER_FRAME;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// free up the bit stream buffer structure
 | 
						|
	buffer_deinit( &mybs );
 | 
						|
	
 | 
						|
	
 | 
						|
	return(mp2_size);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int twolame_encode_flush(twolame_options *glopts, unsigned char *mp2buffer, int mp2buffer_size) {
 | 
						|
	bit_stream *mybs = NULL;
 | 
						|
	int mp2_size = 0;
 | 
						|
	int i;
 | 
						|
 | 
						|
	if (glopts->samples_in_buffer==0) {
 | 
						|
		// No samples left over
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	// Create bit stream structure
 | 
						|
	mybs = buffer_init( mp2buffer, mp2buffer_size );
 | 
						|
 | 
						|
	// Pad out the PCM buffers with 0 and encode the frame
 | 
						|
	for (i=glopts->samples_in_buffer; i< TWOLAME_SAMPLES_PER_FRAME; i++) {
 | 
						|
		glopts->buffer[0][i] = glopts->buffer[1][i] = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	// Encode the frame 
 | 
						|
	mp2_size = encode_frame( glopts, mybs );
 | 
						|
	glopts->samples_in_buffer=0;
 | 
						|
 | 
						|
	// free up the bit stream buffer structure
 | 
						|
	buffer_deinit( &mybs );
 | 
						|
 | 
						|
	return mp2_size;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void twolame_close(twolame_options **glopts) {
 | 
						|
	twolame_options *opts = NULL;
 | 
						|
 | 
						|
	// Check input pointers aren't NULL
 | 
						|
	if (glopts==NULL) return;
 | 
						|
	opts = *glopts;
 | 
						|
	if (opts==NULL) return;
 | 
						|
 | 
						|
	// free mem
 | 
						|
	psycho_4_deinit( &opts->p4mem );
 | 
						|
	psycho_3_deinit( &opts->p3mem );
 | 
						|
	psycho_2_deinit( &opts->p2mem );
 | 
						|
	psycho_1_deinit( &opts->p1mem );
 | 
						|
	psycho_0_deinit( &opts->p0mem );
 | 
						|
	
 | 
						|
	TWOLAME_FREE( opts->subband );
 | 
						|
	TWOLAME_FREE( opts->j_sample );
 | 
						|
	TWOLAME_FREE( opts->sb_sample );
 | 
						|
	
 | 
						|
	// Free the memory and zero the pointer
 | 
						|
	TWOLAME_FREE( opts );
 | 
						|
}
 | 
						|
 | 
						|
// vim:ts=4:sw=4:nowrap: 
 |