home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 4
/
AACD04.ISO
/
AACD
/
Sound
/
LAME
/
Source
/
musicin.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-06-03
|
34KB
|
1,123 lines
/**********************************************************************
* ISO MPEG Audio Subgroup Software Simulation Group (1996)
* ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension
*
* $Id: musicin.c,v 1.2 1997/01/19 22:28:29 rowlands Exp $
*
* $Log: musicin.c,v $
* Revision 1.2 1997/01/19 22:28:29 rowlands
* Layer 3 bug fixes from Seymour Shlien
*
* Revision 1.1 1996/02/14 04:04:23 rowlands
* Initial revision
*
* Received from Mike Coleman
**********************************************************************/
#include <fcntl.h>
#include <stdlib.h>
#include "common.h"
#include "globalflags.h"
#include "encoder.h"
#include "l3psy.h"
#include "mdct.h"
#include "loop.h"
#include "l3bitstream.h"
#include "gtkanal.h"
#include "version.h"
#include <assert.h>
#ifdef __FreeBSD__
#include <floatingpoint.h>
#endif
#ifdef linux
#include <fpu_control.h>
#endif
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
/* Global flags. set defaults here, defined extern in common.h */
int autoconvert=FALSE;
int force_ms=FALSE;
int gpsycho=1;
int sfb21=1;
int VBR=0;
int VBR_q=4;
#ifdef _BLADEDLL
int silent=1;
#else
int silent=0;
#endif
int highq=0;
int fast_mode=0;
int allow_diff_short=0;
#ifdef DISTRIB
int gtkflag=1;
#else
int gtkflag=0;
#endif
void usage();
/* Global variable definitions for "musicin.c" */
struct stat sb;
int firstcall = 1; /* define like this so Dll/BladeMP3EncDll.c can change value */
int target_bitrate;
long totalframes;
int swapbytes = FALSE; /* force byte swapping */
FILE *musicin;
Bit_stream_struc bs;
char *programName;
int iswav=0;
short FAR BigBuf[2][2304];
FLOAT snr32[32];
L3SBS FAR l3_sb_sample;
III_side_info_t l3_side;
frame_params fr_ps;
unsigned long num_samples;
int frameNum=0;
#ifdef HAVEGTK
static int MPGLAG=1;
#endif
int original_file_type; /* 0=WAV, 1=MP3 */
int original_file_fd; /* file descriptor */
/* Implementations */
/*********************************************************/
/* Timeconvert: convert given time (in secs) to hh:mm:ss */
/*********************************************************/
void timestatus(int frameNum, int totalframes, int samp_rate)
{
int time_so_far;
int remain,estimated;
double speedup;
char str1[20],str2[20],str3[20];
time_so_far = clock()/CLOCKS_PER_SEC;
/* calc estimated total CPU time */
estimated = (int)((float)totalframes/(float)frameNum * (float)time_so_far);
remain=estimated - time_so_far;
/* estimated encoding time / playing time. (protected from divide by 0) */
speedup = (estimated*totalframes*1.152)/
(1e-12+samp_rate*estimated*estimated);
sprintf(str1,"%02d:%02d",(time_so_far/60)%60, time_so_far%60);
sprintf(str2,"%02d:%02d",(remain/60)%60, remain%60);
sprintf(str3,"%02d:%02d",(estimated/60)%60, estimated%60);
fprintf(stderr,
/*"Frame: [%4lu/%4lu] Encoding Time %5s/%5s (%.2fx) ETA %5s\r", */
"Frame: [%4d/%4d] Encoding Time %5s/%5s (%.2fx) ETA %5s\r",
frameNum,totalframes,str1,str3,speedup,str2);
fflush(stderr);
}
/************************************************************************
*
* parse_args
*
* PURPOSE: Sets encoding parameters to the specifications of the
* command line. Default settings are used for parameters
* not specified in the command line.
*
* If the input file is in AIFF format, the sampling frequency is read
* from the AIFF header.
*
* The input and output filenames are read into #inpath# and #outpath#.
*
************************************************************************/
void
parse_args(argc, argv, fr_ps, psy, num_samples, inPath, outPath)
int argc;
char **argv;
frame_params *fr_ps;
int *psy;
unsigned long *num_samples;
char inPath[MAX_NAME_SIZE];
char outPath[MAX_NAME_SIZE];
{
FLOAT srate;
int brate;
layer *info = fr_ps->header;
int err = 0, i = 0;
IFF_AIFF pcm_aiff_data;
long samplerate;
long soundPosition;
char ckwav[5]={0,0,0,0,0};
/* preset defaults */
inPath[0] = '\0'; outPath[0] = '\0';
info->lay = DFLT_LAY;
switch(DFLT_MOD) {
case 's': info->mode = MPG_MD_STEREO; info->mode_ext = 0; break;
case 'd': info->mode = MPG_MD_DUAL_CHANNEL; info->mode_ext=0; break;
case 'j': info->mode = MPG_MD_JOINT_STEREO; info->mode_ext=0; break;
case 'm': info->mode = MPG_MD_MONO; info->mode_ext = 0; break;
default:
fprintf(stderr, "%s: Bad mode dflt %c\n", programName, DFLT_MOD);
abort();
}
*psy = DFLT_PSY;
if((info->sampling_frequency = SmpFrqIndex((long)(1000*DFLT_SFQ), &info->version)) < 0) {
fprintf(stderr, "%s: bad sfrq default %.2f\n", programName, DFLT_SFQ);
abort();
}
info->bitrate_index = 9;
brate = 0;
switch(DFLT_EMP) {
case 'n': info->emphasis = 0; break;
case '5': info->emphasis = 1; break;
case 'c': info->emphasis = 3; break;
default:
fprintf(stderr, "%s: Bad emph dflt %c\n", programName, DFLT_EMP);
abort();
}
info->copyright = 0;
info->original = 1;
info->error_protection = FALSE;
/* process args */
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;
if (! *token) {
/* The user wants to use stdin and/or stdout. */
if(inPath[0] == '\0') strcpy(inPath, argv[i]);
else if(outPath[0] == '\0') strcpy(outPath, argv[i]);
}
while( (c = *token++) ) {
if(*token ) arg = token;
else arg = nextArg;
switch(c) {
case 'm': argUsed = 1;
if (*arg == 's')
{ info->mode = MPG_MD_STEREO; info->mode_ext = 0; }
else if (*arg == 'd')
{ info->mode = MPG_MD_DUAL_CHANNEL; info->mode_ext=0; }
else if (*arg == 'j')
{ info->mode = MPG_MD_JOINT_STEREO; info->mode_ext=0; }
else if (*arg == 'f')
{ info->mode = MPG_MD_JOINT_STEREO; force_ms=1; info->mode_ext=0; }
else if (*arg == 'm')
{ info->mode = MPG_MD_MONO; info->mode_ext = 0; }
else {
fprintf(stderr,"%s: -m mode must be s/d/j/f/m not %s\n",
programName, arg);
err = 1;
}
break;
case 'V': argUsed = 1; VBR = 1;
if (*arg == '0')
{ VBR_q=0; }
else if (*arg == '1')
{ VBR_q=1; }
else if (*arg == '2')
{ VBR_q=2; }
else if (*arg == '3')
{ VBR_q=3; }
else if (*arg == '4')
{ VBR_q=4; }
else if (*arg == '5')
{ VBR_q=5; }
else if (*arg == '6')
{ VBR_q=6; }
else if (*arg == '7')
{ VBR_q=7; }
else if (*arg == '8')
{ VBR_q=8; }
else if (*arg == '9')
{ VBR_q=9; }
else {
fprintf(stderr,"%s: -V n must be 0-9 not %s\n",
programName, arg);
err = 1;
}
break;
case 's':
argUsed = 1;
srate = atof( arg );
/* samplerate = rint( 1000.0 * srate ); $A */
samplerate = (long) (( 1000.0 * srate ) + 0.5);
if( (info->sampling_frequency =
SmpFrqIndex((long) samplerate, &info->version)) < 0 )
err = 1;
break;
case 'b':
argUsed = 1;
brate = atoi(arg);
break;
case 'x': /* force byte swapping */
swapbytes=TRUE;
break;
case 'a': /* autoconvert input file from stereo to mono - for mono mp3 encoding */
autoconvert = TRUE;
break;
case 'h':
highq = TRUE;
break;
case 'k':
sfb21 = FALSE;
break;
case 'd':
allow_diff_short = 1;
break;
case 'v':
VBR = 1;
gpsycho=1;
break;
case 'S':
silent = TRUE;
break;
case 'f':
fast_mode = TRUE;
break;
case 'O':
gpsycho = FALSE;
break;
#ifdef HAVEGTK
case 'g': /* turn on gtk analysis */
gtkflag = TRUE;
#endif
break;
case 'e': argUsed = 1;
if (*arg == 'n') info->emphasis = 0;
else if (*arg == '5') info->emphasis = 1;
else if (*arg == 'c') info->emphasis = 3;
else {
fprintf(stderr,"%s: -e emp must be n/5/c not %s\n",
programName, arg);
err = 1;
}
break;
case 'c': info->copyright = 1; break;
case 'o': info->original = 0; break;
default: fprintf(stderr,"%s: unrec 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(inPath[0] == '\0') strcpy(inPath, argv[i]);
else if(outPath[0] == '\0') strcpy(outPath, argv[i]);
else {
fprintf(stderr,"%s: excess arg %s\n", programName, argv[i]);
err = 1;
}
}
}
if(err || inPath[0] == '\0') usage(); /* never returns */
if (inPath[0]=='-') silent=1; /* turn off status - it's broken for stdin */
if(outPath[0] == '\0') {
if (inPath[0]=='-') {
/* if input is stdin, default output is stdout */
strcpy(outPath,"-");
}else {
strcpy(outPath, inPath);
strcat(outPath, DFLT_EXT);
}
}
// SPECIAL FOR BLADE ENCODER
#ifdef _BLADEDLL
open_bit_stream_w(&bs, outPath, BUFFER_SIZE);
#else
original_file_type=!(strcmp((char *) &inPath[strlen(inPath)-4],".mp3"));
if (original_file_type) {
/* MP3 file. */
totalframes = -1;
original_file_fd = open(inPath,O_RDONLY);
if (original_file_fd == -1) {
fprintf(stderr,"Could not find \"%s\".\n", inPath);
exit(1);
}
if (!gtkflag) {
fprintf(stderr,"Use option -g to analyze mp3 files.\n");
exit(1);
}
}
else {
if (!strcmp(inPath, "-")) {
/* Read from standard input. */
musicin = stdin;
} else {
if ((musicin = fopen(inPath, "rb")) == NULL) {
fprintf(stderr, "Could not find \"%s\".\n", inPath);
exit(1);
}
}
#ifdef DISTRIB
outPath="/dev/null";
#endif
open_bit_stream_w(&bs, outPath, BUFFER_SIZE);
if ((soundPosition = aiff_read_headers(musicin, &pcm_aiff_data)) != -1) {
fprintf(stderr, "Found Audio IFF sound file headers: ");
aiff_check(inPath, &pcm_aiff_data, &info->version);
if (fseek(musicin, soundPosition, SEEK_SET) != 0) {
/*
fprintf(stderr, "Could not seek to PCM sound data in \"%s\".\n", inPath);
exit(1);
*/
fprintf(stderr,"Could not seek to PCM sound data in \"%s\".\n",inPath);
fprintf(stderr,"Crossing Fingers.....\n");
}
info->sampling_frequency = SmpFrqIndex((long)pcm_aiff_data.sampleRate, &info->version);
fprintf(stderr, "%.1f kHz samples\n",
pcm_aiff_data.sampleRate/1000);
/* Determine number of samples in sound file */
*num_samples = (long)(pcm_aiff_data.numChannels) *
(long)(pcm_aiff_data.numSampleFrames);
if ( pcm_aiff_data.numChannels == 1 ) {
info->mode = MPG_MD_MONO;
info->mode_ext = 0;
}
}
else { /* Not using Audio IFF sound file headers. */
if (fseek(musicin, 8, SEEK_SET) != 0) {
/*
fprintf(stderr, "Could not seek to PCM sound data in \"%s\".\n", inPath);
exit(1);
*/
fprintf(stderr,"Could not seek to PCM sound data in \"%s\".\n",inPath);
fprintf(stderr,"Crossing Fingers.....\n");
}
fread(ckwav, 4, 1, musicin);
if (strncmp(ckwav, "WAVE",4)==0) {
iswav = 1;
fseek(musicin, 0x2c, SEEK_SET); /* skip wav file header */
/* NO PARSING OF WAV HEADERS YET */
fprintf(stderr, "%s : Found WAV header. Assuming 44.1khz 16bit stereo samples\n",ckwav);
}
else {
fseek(musicin, 0, SEEK_SET);
fprintf(stderr, "Assuming raw pcm input file");
if (swapbytes==TRUE)
fprintf(stderr, " : Forcing byte-swapping\n");
else
fprintf(stderr, "\n");
}
/* Declare sound file to have "infinite" number of samples. */
*num_samples = MAX_U_32_NUM;
}
/* Timing, autoconvert and resampling checks and setup */
stat(inPath,&sb);
totalframes = sb.st_size/4608;
if ((info->mode == MPG_MD_MONO)&&(autoconvert==FALSE))
totalframes *= 2;
if (autoconvert==TRUE) {
fprintf(stderr, "Autoconverting from stereo to mono. Setting encoding to mono mode.\n");
info->mode = MPG_MD_MONO;
info->mode_ext = 0;
}
}
#endif // END OF BLADE ENCODER SPECIAL
if ( brate == 0 ) {
if (VBR) brate = bitrate[info->version][info->lay-1][8];
else brate = bitrate[info->version][info->lay-1][9];
}
if( (info->bitrate_index = BitrateIndex(info->lay, brate, info->version)) < 0)
err=1;
if(err || inPath[0] == '\0') usage(); /* never returns */
target_bitrate = info->bitrate_index;
if (info->bitrate_index==14) VBR=0; /* dont bother with VBR at 320kbs */
}
/************************************************************************
*
* print_config
*
* PURPOSE: Prints the encoding parameters used
*
************************************************************************/
void print_config( frame_params *fr_ps, int *psy, char *inPath, char *outPath)
{
layer *info = fr_ps->header;
#if 0
fprintf(stderr, "Encoding configuration:\n");
fprintf(stderr, "Algorithm=%s\n", version_names[info->version]);
if(info->mode != MPG_MD_JOINT_STEREO)
fprintf(stderr, "Layer=III mode=%s extn=%d psy model=%d\n",
mode_names[info->mode], info->mode_ext, *psy);
else fprintf(stderr, "Layer=III mode=%s extn=data dependant psy model=%d\n",
mode_names[info->mode], *psy);
fprintf(stderr, "samp frq=%.1f kHz total bitrate=%d kbps\n",
s_freq[info->version][info->sampling_frequency],
bitrate[info->version][info->lay-1][info->bitrate_index]);
fprintf(stderr, "de-emph=%d c/right=%d orig=%d\n",
info->emphasis, info->copyright, info->original);
fprintf(stderr, "input file: '%s' output file: '%s'\n", inPath, outPath);
#endif
if (original_file_type) {
fprintf(stderr, "Analyzing %s \n",inPath);
}
else {
fprintf(stderr, "Encoding %s to %s\n",
(strcmp(inPath, "-")? inPath : "stdin"),
(strcmp(outPath, "-")? outPath : "stdout"));
if (VBR)
fprintf(stderr, "Encoding as %.1f kHz VBR(min: %d kbps) %s MPEG-1 LayerIII file\n",
s_freq[info->version][info->sampling_frequency],
bitrate[info->version][info->lay-1][info->bitrate_index],
mode_names[info->mode]);
else
fprintf(stderr, "Encoding as %.1f kHz %d kbps %s MPEG-1 LayerIII file\n",
s_freq[info->version][info->sampling_frequency],
bitrate[info->version][info->lay-1][info->bitrate_index],
mode_names[info->mode]);
}
}
#ifdef HAVEGTK
int readframe()
{
int j,ch,stereo,out=0;
short mpg123pcm[2][1152];
static int frameNum=0;
stereo = fr_ps.stereo;
frameNum++;
/* create a 1 frame lag so MP3 analysis syncs with WAV analysis */
if (frameNum == 1 ) out=1152;
else out=decode1file(original_file_fd,mpg123pcm,stereo);
/* delay pcm data by yet another frame */
for ( ch = 0; ch < stereo; ch++ ) {
for ( j = 0; j < DECDELAY; j++ )
pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j+1152];
for ( j = 0; j < 1152; j++ ) {
pinfo->pcmdata2[ch][j+DECDELAY] = mpg123pcm[ch][j];
}
}
MPGLAG = 2;
pinfo->frameNum = frameNum;
pinfo->mpglag = MPGLAG;
return out;
}
#endif
int makeframe()
{
static unsigned long frameBits, sentBits = 0;
static unsigned long bitsPerSlot;
static double frac_SpF;
static double slot_lag;
static int mode_gr;
static int mpg123count=0;
int j,ch,gr,mean_bits;
double xr[2][2][576];
double xr_dec[2][2][576];
double pe[2][2];
double pe3[2];
int l3_enc[2][2][576];
III_psy_ratio ratio,ratio3;
III_scalefac_t scalefac;
int blocktype[2];
int blocktype3[2];
int bitsPerFrame;
short *win_buf[2];
double win_que[2][HAN_SIZE];
int stereo;
int iread;
layer *info;
int i;
#ifdef HAVEGTK
char mpg123bs[BUFFER_SIZE];
short mpg123pcm[2][1152];
#endif
int check_ms_stereo;
int bit_rate;
double samp;
double ms_ener_ratio[2];
stereo = fr_ps.stereo;
info = fr_ps.header;
#ifdef HAVEGTK
if (gtkflag) {
pinfo->frameNum = frameNum;
pinfo->sampfreq=s_freq[info->version][info->sampling_frequency]*1000.0;
}
#endif
info->mode_ext = 0;
/* use m/s stereo? */
check_ms_stereo = ((info->mode == MPG_MD_JOINT_STEREO) &&
(!force_ms) &&
(stereo==2) &&
(gpsycho));
info->bitrate_index = target_bitrate;
bit_rate = bitrate[info->version][info->lay-1][info->bitrate_index];
samp = s_freq[info->version][info->sampling_frequency];
if (firstcall) {
double avg_slots_per_frame;
unsigned long samplesPerFrame;
int whole_SpF;
firstcall = 0;
mpg123count=0;
/* Figure average number of 'slots' per frame. */
/* Bitrate means TOTAL for both channels, not per side. */
bitsPerSlot = 8;
samplesPerFrame = info->version == 1 ? 1152 : 576;
avg_slots_per_frame = ((double)samplesPerFrame /samp) *
((double)bit_rate / (double)bitsPerSlot);
whole_SpF = (int) avg_slots_per_frame;
frac_SpF = avg_slots_per_frame - (double)whole_SpF;
slot_lag = -frac_SpF;
info->padding = 1;
if (fabs(frac_SpF) < 1e-9) info->padding = 0;
mode_gr = (info->version == 1) ? 2 : 1; /* mode_gr = 2 */
if (mode_gr != 2) exit(-99);
#ifndef _BLADEDLL
// AF, modified this code, so it will read to first samples into the lower halve of
// the buffer, this way it is easier to support the _BLADEDLL hack
iread = get_audio(musicin,&BigBuf[0][0],&BigBuf[1][0],num_samples,fr_ps.stereo,fr_ps.header);
#else
// Don't read the data, it is already in the BugBuf
{
extern int nBladeBufferSize;
iread=nBladeBufferSize;
}
#endif
/* we are still working with short int, so we cannot devide by
* sqrt(2) (overflow). divide by 2, rescale later */
if (force_ms)
{
// AF: Correct the lower halve of the buffer, instead of the upper halve
for (i=0; i< 1152; i++)
{
double mid = (BigBuf[0][i]+BigBuf[1][i])/(2.0);
double side= (BigBuf[0][i]-BigBuf[1][i])/(2.0);
BigBuf[0][i]=mid;
BigBuf[1][i]=side;
}
}
}
#ifndef _BLADEDLL
else
{
// AF: If not the first call, do shift the data
// Shift the data from the upper halve of the BigBuf to to lower halve
for (ch=0; ch<2; ch++)
for (i=0; i<1152; i++)
BigBuf[ch][i]=BigBuf[ch][i+1152];
}
// Read the sam
iread = get_audio(musicin,&BigBuf[0][1152],&BigBuf[1][1152],num_samples,fr_ps.stereo,fr_ps.header);
#else
{
// Don't read the data, it is already in the BugBuf
extern int nBladeBufferSize;
iread=nBladeBufferSize;
}
#endif
/********************** padding *****************************/
if (VBR) {
/* leave info_padding as it was set above */
} else {
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);
}
}
}
/********************** process InputBuffer *****************************/
frameNum++;
if (force_ms)
for (i=0; i< 1152; i++) {
double mid = (BigBuf[0][1152+i]+BigBuf[1][1152+i])/(2.0);
double side= (BigBuf[0][1152+i]-BigBuf[1][1152+i])/(2.0);
BigBuf[0][1152+i]=mid;
BigBuf[1][1152+i]=side;
}
if (frameNum%10==0 && !gtkflag && !silent) {
timestatus(frameNum,totalframes,s_freq[info->version][info->sampling_frequency]);
}
/***************************** Layer 3 **********************************/
win_buf[0] = &BigBuf[0][0];
win_buf[1] = &BigBuf[1][0];
if (!fast_mode) {
/* psychoacoustic model */
/* this mess will be cleaned up in the future. It is coded like this
* to maintain original ISO and GPSYCHO psy-models
*/
short int *bufp[2]; /* address of beginninf of left & right granule */
gr = 0;
if (frameNum ==1 ) {
/* prime the psy-model pump */
for ( ch = 0; ch < stereo; ch++ )
bufp[ch]=&BigBuf[ch][gr*576];
L3psycho_anal( bufp,stereo,gr, info,
s_freq[info->version][info->sampling_frequency] * 1000.0,
check_ms_stereo,&ms_ener_ratio[0],
ratio.l[gr], ratio.s[gr],
pe[gr], blocktype);
if (!gpsycho) {
for ( ch = 0; ch < stereo; ch++ )
l3_side.gr[gr].ch[ch].tt.block_type=blocktype[ch];
}
} else {
if (!gpsycho){
memcpy(&ratio,&ratio3,sizeof(ratio));
for ( ch = 0; ch < stereo; ch++ ) {
pe[gr][ch]=pe3[ch];
l3_side.gr[0].ch[ch].tt.block_type=blocktype3[ch];
}
}
}
gr = 1;
for ( ch = 0; ch < stereo; ch++ )
bufp[ch]=&BigBuf[ch][gr*576];
L3psycho_anal( bufp, stereo,gr, info,
s_freq[info->version][info->sampling_frequency] * 1000.0,
check_ms_stereo,&ms_ener_ratio[0],
ratio.l[gr], ratio.s[gr],
pe[gr], blocktype);
for ( ch = 0; ch < stereo; ch++ ) {
if (gpsycho) {
/* data returned for gr=0: memcpy */
pe[0][ch]=pe[1][ch];
memcpy(&ratio.l[0][ch][0],&ratio.l[1][ch][0],sizeof(ratio.l[gr][ch]));
memcpy(&ratio.s[0][ch][0],&ratio.s[1][ch][0],sizeof(ratio.s[gr][ch]));
l3_side.gr[0].ch[ch].tt.block_type=blocktype[ch];
} else {
l3_side.gr[gr].ch[ch].tt.block_type=blocktype[ch];
}
}
/* do a third call */
gr = 0;
for ( ch = 0; ch < stereo; ch++ )
bufp[ch]=&BigBuf[ch][1152 + gr*576];
L3psycho_anal( bufp, stereo,gr, info,
s_freq[info->version][info->sampling_frequency] * 1000.0,
check_ms_stereo,&ms_ener_ratio[1],
ratio3.l[gr], ratio3.s[gr],
pe3, blocktype3);
for ( ch = 0; ch < stereo; ch++ ) {
if (gpsycho) {
/* data returned for gr=1, prev. frame. memcpy */
pe[1][ch]=pe3[ch];
memcpy(&ratio.l[1][ch][0],&ratio3.l[0][ch][0],sizeof(ratio3.l[0][ch]));
memcpy(&ratio.s[1][ch][0],&ratio3.s[0][ch][0],sizeof(ratio3.s[0][ch]));
l3_side.gr[1].ch[ch].tt.block_type=blocktype3[ch];
}
}
}
/* block type flags */
for( gr = 0; gr < mode_gr; gr++ ) {
for ( ch = 0; ch < stereo; ch++ ) {
gr_info *cod_info = &l3_side.gr[gr].ch[ch].tt;
cod_info->mixed_block_flag = 0; /* never used by this model */
if (cod_info->block_type == NORM_TYPE )
cod_info->window_switching_flag = 0;
else
cod_info->window_switching_flag = 1;
}
}
/* polyphase filtering */
for( gr = 0; gr < mode_gr; gr++ )
for ( ch = 0; ch < stereo; ch++ )
for ( j = 0; j < 18; j++ ) {
window_subband( &win_buf[ch], &win_que[ch][0], ch );
filter_subband( &win_que[ch][0], &(l3_sb_sample)[ch][gr+1][j][0] ); }
/* apply mdct to the polyphase outputs */
mdct_sub( &l3_sb_sample, xr, stereo, &l3_side, mode_gr );
/* data was scaled by 1/2. fix so effectively it was scaled by 1/sqrt(2) */
if (force_ms) {
for ( gr = 0; gr < mode_gr; gr++ )
for ( ch = 0; ch < stereo; ch++ )
for (i =0 ; i< 576; i++)
xr[gr][ch][i] *= sqrt(2.0);
}
if (check_ms_stereo) {
/* make sure block type is the same in each channel */
check_ms_stereo =
(l3_side.gr[0].ch[0].tt.block_type==l3_side.gr[0].ch[1].tt.block_type) &&
(l3_side.gr[1].ch[0].tt.block_type==l3_side.gr[1].ch[1].tt.block_type);
}
if (check_ms_stereo) {
if ((ms_ener_ratio[0]+ms_ener_ratio[1])<.7 ) info->mode_ext = 2;
}
#ifdef HAVEGTK
if (gtkflag) {
for ( gr = 0; gr < mode_gr; gr++ )
for ( ch = 0; ch < stereo; ch++ ) {
pinfo->ms_ratio[gr]=ms_ener_ratio[gr];
pinfo->blocktype[gr][ch]=
l3_side.gr[gr].ch[ch].tt.block_type;
for ( j = 0; j < 576; j++ ) pinfo->xr[gr][ch][j]=xr[gr][ch][j];
}
}
#endif
/* bit and noise allocation */
iteration_loop( pe, ms_ener_ratio, xr, &ratio, &l3_side, l3_enc,
xr_dec, &scalefac, &fr_ps);
/* flag for our ms_stereo with psy-model on mid & side channels */
if (force_ms) info->mode_ext = 2;
/* write the frame to the bitstream */
getframebits(info,stereo,&bitsPerFrame,&mean_bits);
III_format_bitstream( bitsPerFrame, &fr_ps, l3_enc, &l3_side,
&scalefac, &bs, xr, NULL, 0 );
frameBits = sstell( &bs ) - sentBits;
if ( frameBits % bitsPerSlot ) /* a program failure */
fprintf( stderr, "Sent %ld bits = %ld slots plus %ld\n",
frameBits, frameBits/bitsPerSlot,
frameBits%bitsPerSlot );
sentBits += frameBits;
#ifdef HAVEGTK
/* copy bit buffer into array and send to mpg123 to synthesis the pcm data */
if (gtkflag) {
mpg123count=0;
for (i=bs.buf_size-1 ; i > bs.buf_byte_idx ; (i-- ))
mpg123bs[mpg123count++]=bs.buf[i];
/* re-synthesize pcm data from mp3 frame */
if (!decode1(mpg123bs,mpg123count,&mpg123pcm,stereo)) {
if (MPGLAG == MAXMPGLAG)
fprintf(stderr, "MAXMPGLAG set too low. The following frames will be mis-aligned \n");
else MPGLAG+=1;
}
pinfo->mpglag = MPGLAG;
}
/* empty data from bit buffer into mp3 file */
empty_buffer(&bs, 1+bs.buf_byte_idx);
bs.buf[bs.buf_byte_idx] = 0;
if (gtkflag) {
for ( ch = 0; ch < stereo; ch++ ) {
for ( j = 0; j < WINDELAY; j++ )
pinfo->pcmdata[ch][j] = pinfo->pcmdata[ch][j+1152];
for ( j = 0; j < 1152; j++ ) {
pinfo->pcmdata[ch][j+WINDELAY] = BigBuf[ch][j];
}
}
for ( ch = 0; ch < stereo; ch++ ) {
for ( j = 0; j < DECDELAY; j++ )
pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j+1152];
for ( j = 0; j < 1152; j++ ) {
pinfo->pcmdata2[ch][j+DECDELAY] = mpg123pcm[ch][j];
}
}
pinfo->frameNum = frameNum;
}
#endif
return iread/stereo;
}
/************************************************************************
*
* main
*
* PURPOSE: MPEG-1 Layer III encoder, with
* psychoacoustic models ISO-2 (AT&T) and GPSYCHO
*
* SEMANTICS: One overlapping frame of audio of up to 2 channels are
* processed at a time in the following order:
* (associated routines are in parentheses)
*
* 1. Filter sliding window of data to get 32 subband
* samples per channel.
* (window_subband,filter_subband)
*
* 2. Calculate scalefactors for the frame, and if layer 2,
* also calculate scalefactor select information.
* (*_scale_factor_calc)
*
* 3. Calculate psychoacoustic masking levels using selected
* psychoacoustic model.
* (*_Psycho_One, psycho_anal)
*
* 4. Perform iterative bit allocation for subbands with low
* mask_to_noise ratios using masking levels from step 4.
* (*_main_bit_allocation)
*
* 5. Pack bit allocation and scalefactors onto bitstream.
* (*_encode_bit_alloc,*_encode_scale)
*
* 6. Quantize subbands and pack them into bitstream
* (*_subband_quantization, *_sample_encoding)
*
************************************************************************/
int main(argc, argv)
int argc;
char **argv;
{
char original_file_name[MAX_NAME_SIZE];
char encoded_file_name[MAX_NAME_SIZE];
int model, stereo;
layer info;
char lpszVersion[80];
#ifdef HAVEGTK
gtk_init (&argc, &argv);
#endif
#ifdef __FreeBSD__
{
fp_except_t mask;
mask=fpgetmask();
/* printf("FreeBSD mask is 0x%x\n",mask); */
}
#endif
#ifdef linux
{
unsigned int mask;
_FPU_GETCW(mask);
/* Set the Linux mask to the FreeBSD default mask */
mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM );
_FPU_SETCW(mask);
}
#endif
/* clear buffers */
memset((char *) BigBuf, 0, sizeof(BigBuf));
memset((char *) snr32, 0, sizeof(snr32));
// Clear info structure
memset(&info,0,sizeof(info));
fr_ps.header = &info;
fr_ps.tab_num = -1; /* no table loaded */
fr_ps.alloc = NULL;
info.version = MPEG_AUDIO_ID; /* =1 Default: MPEG-1 */
info.extension = 0;
/* get version string */
if (gpsycho && !original_file_type)
fprintf(stderr,"LAME version %s (www.sulaco.org/mp3) \n",get_lame_version(lpszVersion));
programName = argv[0];
if(argc==1) /* no command-line args
obtain_parameters(&fr_ps, &model, &num_samples,
original_file_name, encoded_file_name);*/
usage();
else
parse_args(argc, argv, &fr_ps, &model, &num_samples,
original_file_name, encoded_file_name);
print_config(&fr_ps, &model,
original_file_name, encoded_file_name);
hdr_to_frps(&fr_ps);
stereo = fr_ps.stereo;
if (gpsycho && !original_file_type) fprintf(stderr,
"using GPSYCHO: GPL'd psycho-acoustic model \n");
#ifdef HAVEGTK
if (gtkflag) gtkcontrol(totalframes,original_file_type,original_file_name,gpsycho);
else
#endif
while (makeframe());
/* clean up if we were analyzing a wav file */
if (!original_file_type) {
if ( info.lay == 3 ) III_FlushBitstream();
close_bit_stream_w( &bs );
if (fclose(musicin) != 0){
fprintf(stderr, "Could not close \"%s\".\n", original_file_name);
exit(2);
}
frameNum--;
timestatus(frameNum,frameNum,s_freq[info.version][info.sampling_frequency]);
fprintf(stderr,"\n");
}
fflush(stderr);
exit(0);
}
/************************************************************************
*
* usage
*
* PURPOSE: Writes command line syntax to the file specified by #stderr#
*
************************************************************************/
void usage() /* print syntax & exit */
{
fprintf(stderr," LAMER Ain't an Mp3 Encoder (Reconstruction-iso)\n");
fprintf(stderr," version %s\n",get_lame_version());
fprintf(stderr," with GPSYCHO psycho-acoustic model (version %s). \n\n",get_psy_version());
fprintf(stderr,"USAGE : %s [options] <infile> <outfile>\n",programName);
fprintf(stderr,"OPTIONS :\n");
fprintf(stderr," -m mode (s)tereo, (j)oint, (f)orce or (m)ono (default %c)\n",DFLT_MOD);
fprintf(stderr," force = force ms_stereo on all frames. Faster and\n");
fprintf(stderr," uses special Mid & Side masking thresholds\n");
fprintf(stderr," -s sample freq frequency of input file (kHz) - default %4.1f\n",DFLT_SFQ);
fprintf(stderr," -b <bitrate> set the bitrate, default 128kbps\n");
fprintf(stderr," (for VBR, this sets the minimum bitrate)\n");
fprintf(stderr," -x force byte-swapping of input\n");
fprintf(stderr," -a downmix from stereo to mono file for mono encoding\n");
fprintf(stderr," -e emp de-emphasis n/5/c (default %4c)\n",DFLT_EMP);
fprintf(stderr," -c mark as copyright\n");
fprintf(stderr," -o mark as non-original\n");
fprintf(stderr," -f fast mode (low quality)\n");
fprintf(stderr," -k disable sfb=21 cutoff\n");
fprintf(stderr," -d allow channels to have different blocktypes\n");
fprintf(stderr," -v use variable bitrate (VBR)\n");
fprintf(stderr," -V n quality setting for VBR. default n=%i\n",VBR_q);
fprintf(stderr," 0=high quality,bigger files. 9=smaller files\n");
fprintf(stderr," -h use (maybe) some experimental quality improvements\n");
#ifdef HAVEGTK
fprintf(stderr," -g run graphical analysis on <infile>\n");
#endif
fprintf(stderr," -S don't print progress report\n");
fprintf(stderr," -O use original (buggy) ISO psycho-acoustic model \n");
fprintf(stderr,"\n<infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n");
exit(1);
}
/************************************************************************
*
* aiff_check
*
* PURPOSE: Checks AIFF header information to make sure it is valid.
* Exits if not.
*
************************************************************************/
void aiff_check( char *file_name, IFF_AIFF *pcm_aiff_data, int *version)
{
if (pcm_aiff_data->sampleType != IFF_ID_SSND) {
fprintf(stderr, "Sound data is not PCM in \"%s\".\n", file_name);
exit(1);
}
if(SmpFrqIndex((long)pcm_aiff_data->sampleRate, version) < 0) {
fprintf(stderr, "in \"%s\".\n", file_name);
exit(1);
}
if (pcm_aiff_data->sampleSize != sizeof(short) * BITS_IN_A_BYTE) {
fprintf(stderr, "Sound data is not %d bits in \"%s\".\n",
sizeof(short) * BITS_IN_A_BYTE, file_name);
exit(1);
}
if (pcm_aiff_data->numChannels != MONO &&
pcm_aiff_data->numChannels != STEREO) {
fprintf(stderr, "Sound data is not mono or stereo in \"%s\".\n",
file_name);
exit(1);
}
if (pcm_aiff_data->blkAlgn.blockSize != 0) {
fprintf(stderr, "Block size is not %d bytes in \"%s\".\n",
0, file_name);
exit(1);
}
if (pcm_aiff_data->blkAlgn.offset != 0) {
fprintf(stderr, "Block offset is not %d bytes in \"%s\".\n",
0, file_name);
exit(1);
}
}