./0000755000175000017500000000000011605061716010242 5ustar rizlarizla./mp3gain.c0000644000175000017500000024251711374657622011771 0ustar rizlarizla/* * mp3gain.c - analyzes mp3 files, determines the perceived volume, * and adjusts the volume of the mp3 accordingly * * Copyright (C) 2001-2009 Glen Sawyer * AAC support (C) 2004-2009 David Lasker, Altos Design, Inc. * * 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 * * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA * -- go ahead and laugh at me for my lousy coding skillz, I can take it :) * Just do me a favor and let me know how you improve the code. * Thanks. * * Unix-ification by Stefan Partheymüller * (other people have made Unix-compatible alterations-- I just ended up using * Stefan's because it involved the least re-work) * * DLL-ification by John Zitterkopf (zitt@hotmail.com) * * Additional tweaks by Artur Polaczynski, Mark Armbrust, and others */ /* * General warning: I coded this in several stages over the course of several * months. During that time, I changed my mind about my coding style and * naming conventions many, many times. So there's not a lot of consistency * in the code. Sorry about that. I may clean it up some day, but by the time * I would be getting around to it, I'm sure that the more clever programmers * out there will have come up with superior versions already... * * So have fun dissecting. */ #include #include #include #include "apetag.h" #include "id3tag.h" #ifdef AACGAIN #include "aacgain.h" #endif #ifndef WIN32 #undef asWIN32DLL #ifdef __FreeBSD__ #include #endif /* __FreeBSD__ */ #include #endif /* WIN32 */ #ifdef WIN32 #include #define SWITCH_CHAR '/' #else /* time stamp preservation when using temp file */ # include # include # include # if defined(__BEOS__) # include # endif #define SWITCH_CHAR '-' #endif /* WIN32 */ #ifdef __BEOS__ #include #endif /* __BEOS__ */ #include #include /* I tweaked the mpglib library just a bit to spit out the raw * decoded double values, instead of rounding them to 16-bit integers. * Hence the "mpglibDBL" directory */ #ifndef asWIN32DLL #include "mpglibDBL/interface.h" #include "gain_analysis.h" #endif #include "mp3gain.h" /*jzitt*/ #include "rg_error.h" /*jzitt*/ #define HEADERSIZE 4 #define CRC16_POLYNOMIAL 0x8005 #define BUFFERSIZE 3000000 #define WRITEBUFFERSIZE 100000 #define FULL_RECALC 1 #define AMP_RECALC 2 #define MIN_MAX_GAIN_RECALC 4 #ifdef AACGAIN #define AACGAIN_ARG(x) , x #else #define AACGAIN_ARG(x) #endif typedef struct { unsigned long fileposition; unsigned char val[2]; } wbuffer; /* Yes, yes, I know I should do something about these globals */ wbuffer writebuffer[WRITEBUFFERSIZE]; unsigned long writebuffercnt; unsigned char buffer[BUFFERSIZE]; int writeself = 0; int QuietMode = 0; int UsingTemp = 0; int NowWriting = 0; double lastfreq = -1.0; int whichChannel = 0; int BadLayer = 0; int LayerSet = 0; int Reckless = 0; int wrapGain = 0; int undoChanges = 0; int skipTag = 0; int deleteTag = 0; int forceRecalculateTag = 0; int checkTagOnly = 0; static int useId3 = 0; int gSuccess; long inbuffer; unsigned long bitidx; unsigned char *wrdpntr; unsigned char *curframe; char *curfilename; FILE *inf = NULL; FILE *outf; short int saveTime; unsigned long filepos; static const double bitrate[4][16] = { { 1, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 1 }, { 1, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 1 } }; static const double frequency[4][4] = { { 11.025, 12, 8, 1 }, { 1, 1, 1, 1 }, { 22.05, 24, 16, 1 }, { 44.1, 48, 32, 1 } }; long arrbytesinframe[16]; /* instead of writing each byte change, I buffer them up */ static void flushWriteBuff() { unsigned long i; for (i = 0; i < writebuffercnt; i++) { fseek(inf,writebuffer[i].fileposition,SEEK_SET); fwrite(writebuffer[i].val,1,2,inf); } writebuffercnt = 0; }; static void addWriteBuff(unsigned long pos, unsigned char *vals) { if (writebuffercnt >= WRITEBUFFERSIZE) { flushWriteBuff(); fseek(inf,filepos,SEEK_SET); } writebuffer[writebuffercnt].fileposition = pos; writebuffer[writebuffercnt].val[0] = *vals; writebuffer[writebuffercnt].val[1] = vals[1]; writebuffercnt++; }; /* fill the mp3 buffer */ static unsigned long fillBuffer(long savelastbytes) { unsigned long i; unsigned long skip; unsigned long skipbuf; skip = 0; if (savelastbytes < 0) { skip = -savelastbytes; savelastbytes = 0; } if (UsingTemp && NowWriting) { if (fwrite(buffer,1,inbuffer-savelastbytes,outf) != (size_t)(inbuffer-savelastbytes)) return 0; } if (savelastbytes != 0) /* save some of the bytes at the end of the buffer */ memmove((void*)buffer,(const void*)(buffer+inbuffer-savelastbytes),savelastbytes); while (skip > 0) { /* skip some bytes from the input file */ skipbuf = skip > BUFFERSIZE ? BUFFERSIZE : skip; i = (unsigned long)fread(buffer,1,skipbuf,inf); if (i != skipbuf) return 0; if (UsingTemp && NowWriting) { if (fwrite(buffer,1,skipbuf,outf) != skipbuf) return 0; } filepos += i; skip -= skipbuf; } i = (unsigned long)fread(buffer+savelastbytes,1,BUFFERSIZE-savelastbytes,inf); filepos = filepos + i; inbuffer = i + savelastbytes; return i; } static const unsigned char maskLeft8bits[8] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE }; static const unsigned char maskRight8bits[8] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 }; static void set8Bits(unsigned short val) { val <<= (8 - bitidx); wrdpntr[0] &= maskLeft8bits[bitidx]; wrdpntr[0] |= (val >> 8); wrdpntr[1] &= maskRight8bits[bitidx]; wrdpntr[1] |= (val & 0xFF); if (!UsingTemp) addWriteBuff(filepos-(inbuffer-(wrdpntr-buffer)),wrdpntr); } static void skipBits(int nbits) { bitidx += nbits; wrdpntr += (bitidx >> 3); bitidx &= 7; return; } static unsigned char peek8Bits() { unsigned short rval; rval = wrdpntr[0]; rval <<= 8; rval |= wrdpntr[1]; rval >>= (8 - bitidx); return (rval & 0xFF); } static unsigned long skipID3v2() { /* * An ID3v2 tag can be detected with the following pattern: * $49 44 33 yy yy xx zz zz zz zz * Where yy is less than $FF, xx is the 'flags' byte and zz is less than * $80. */ unsigned long ok; unsigned long ID3Size; ok = 1; if (wrdpntr[0] == 'I' && wrdpntr[1] == 'D' && wrdpntr[2] == '3' && wrdpntr[3] < 0xFF && wrdpntr[4] < 0xFF) { ID3Size = (long)(wrdpntr[9]) | ((long)(wrdpntr[8]) << 7) | ((long)(wrdpntr[7]) << 14) | ((long)(wrdpntr[6]) << 21); ID3Size += 10; wrdpntr = wrdpntr + ID3Size; if ((wrdpntr+HEADERSIZE-buffer) > inbuffer) { ok = fillBuffer(inbuffer-(wrdpntr-buffer)); wrdpntr = buffer; } } return ok; } void passError(MMRESULT lerrnum, int numStrings, ...) { char * errstr; size_t totalStrLen = 0; int i; va_list marker; va_start(marker, numStrings); for (i = 0; i < numStrings; i++) { totalStrLen += strlen(va_arg(marker, const char *)); } va_end(marker); errstr = (char *)malloc(totalStrLen + 3); errstr[0] = '\0'; va_start(marker, numStrings); for (i = 0; i < numStrings; i++) { strcat(errstr,va_arg(marker, const char *)); } va_end(marker); DoError(errstr,lerrnum); free(errstr); errstr = NULL; } static unsigned long frameSearch(int startup) { unsigned long ok; int done; static int startfreq; static int startmpegver; long tempmpegver; double bitbase; int i; done = 0; ok = 1; if ((wrdpntr+HEADERSIZE-buffer) > inbuffer) { ok = fillBuffer(inbuffer-(wrdpntr-buffer)); wrdpntr = buffer; if (!ok) done = 1; } while (!done) { done = 1; if ((wrdpntr[0] & 0xFF) != 0xFF) done = 0; /* first 8 bits must be '1' */ else if ((wrdpntr[1] & 0xE0) != 0xE0) done = 0; /* next 3 bits are also '1' */ else if ((wrdpntr[1] & 0x18) == 0x08) done = 0; /* invalid MPEG version */ else if ((wrdpntr[2] & 0xF0) == 0xF0) done = 0; /* bad bitrate */ else if ((wrdpntr[2] & 0xF0) == 0x00) done = 0; /* we'll just completely ignore "free format" bitrates */ else if ((wrdpntr[2] & 0x0C) == 0x0C) done = 0; /* bad sample frequency */ else if ((wrdpntr[1] & 0x06) != 0x02) { /* not Layer III */ if (!LayerSet) { switch (wrdpntr[1] & 0x06) { case 0x06: BadLayer = !0; passError(MP3GAIN_FILEFORMAT_NOTSUPPORTED, 2, curfilename, " is an MPEG Layer I file, not a layer III file\n"); return 0; case 0x04: BadLayer = !0; passError(MP3GAIN_FILEFORMAT_NOTSUPPORTED, 2, curfilename, " is an MPEG Layer II file, not a layer III file\n"); return 0; } } done = 0; /* probably just corrupt data, keep trying */ } else if (startup) { startmpegver = wrdpntr[1] & 0x18; startfreq = wrdpntr[2] & 0x0C; tempmpegver = startmpegver >> 3; if (tempmpegver == 3) bitbase = 1152.0; else bitbase = 576.0; for (i = 0; i < 16; i++) arrbytesinframe[i] = (long)(floor(floor((bitbase*bitrate[tempmpegver][i])/frequency[tempmpegver][startfreq >> 2]) / 8.0)); } else { /* !startup -- if MPEG version or frequency is different, then probably not correctly synched yet */ if ((wrdpntr[1] & 0x18) != startmpegver) done = 0; else if ((wrdpntr[2] & 0x0C) != startfreq) done = 0; else if ((wrdpntr[2] & 0xF0) == 0) /* bitrate is "free format" probably just corrupt data if we've already found valid frames */ done = 0; } if (!done) wrdpntr++; if ((wrdpntr+HEADERSIZE-buffer) > inbuffer) { ok = fillBuffer(inbuffer-(wrdpntr-buffer)); wrdpntr = buffer; if (!ok) done = 1; } } if (ok) { if (inbuffer - (wrdpntr-buffer) < (arrbytesinframe[(wrdpntr[2] >> 4) & 0x0F] + ((wrdpntr[2] >> 1) & 0x01))) { ok = fillBuffer(inbuffer-(wrdpntr-buffer)); wrdpntr = buffer; } bitidx = 0; curframe = wrdpntr; } return ok; } static int crcUpdate(int value, int crc) { int i; value <<= 8; for (i = 0; i < 8; i++) { value <<= 1; crc <<= 1; if (((crc ^ value) & 0x10000)) crc ^= CRC16_POLYNOMIAL; } return crc; } static void crcWriteHeader(int headerlength, char *header) { int crc = 0xffff; /* (jo) init crc16 for error_protection */ int i; crc = crcUpdate(((unsigned char*)header)[2], crc); crc = crcUpdate(((unsigned char*)header)[3], crc); for (i = 6; i < headerlength; i++) { crc = crcUpdate(((unsigned char*)header)[i], crc); } header[4] = crc >> 8; header[5] = crc & 255; } static long getSizeOfFile(char *filename) { long size = 0; FILE *file; file = fopen(filename, "rb"); if (file) { fseek(file, 0, SEEK_END); size = ftell(file); fclose(file); } return size; } int deleteFile(char *filename) { return remove(filename); } int moveFile(char *currentfilename, char *newfilename) { return rename(currentfilename, newfilename); } /* Get File size and datetime stamp */ void fileTime(char *filename, timeAction action) { static int timeSaved=0; #ifdef WIN32 HANDLE outfh; static FILETIME create_time, access_time, write_time; #else static struct stat savedAttributes; #endif if (action == storeTime) { #ifdef WIN32 outfh = CreateFile((LPCTSTR)filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (outfh != INVALID_HANDLE_VALUE) { if (GetFileTime(outfh,&create_time,&access_time,&write_time)) timeSaved = !0; CloseHandle(outfh); } #else timeSaved = (stat(filename, &savedAttributes) == 0); #endif } else { if (timeSaved) { #ifdef WIN32 outfh = CreateFile((LPCTSTR)filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (outfh != INVALID_HANDLE_VALUE) { SetFileTime(outfh,&create_time,&access_time,&write_time); CloseHandle(outfh); } #else struct utimbuf setTime; setTime.actime = savedAttributes.st_atime; setTime.modtime = savedAttributes.st_mtime; timeSaved = 0; utime(filename, &setTime); #endif } } } unsigned long reportPercentWritten(unsigned long percent, unsigned long bytes) { int ok = 1; #ifndef asWIN32DLL fprintf(stderr," \r %2lu%% of %lu bytes written\r" ,percent,bytes); fflush(stderr); #else /* report % back to calling app */ ok = sendpercentdone( (int)percent, bytes ); //non-zero return means error bail out if ( ok != 0) return 0; ok = 1; /* allow us to continue processing file */ #endif return ok; } int numFiles, totFiles; unsigned long reportPercentAnalyzed(unsigned long percent, unsigned long bytes) { char fileDivFiles[21]; fileDivFiles[0]='\0'; if (totFiles-1) /* if 1 file then don't show [x/n] */ sprintf(fileDivFiles,"[%d/%d]",numFiles,totFiles); fprintf(stderr," \r%s %2lu%% of %lu bytes analyzed\r" ,fileDivFiles,percent,bytes); fflush(stderr); return 1; } void scanFrameGain() { int crcflag; int mpegver; int mode; int nchan; int gr, ch; int gain; mpegver = (curframe[1] >> 3) & 0x03; crcflag = curframe[1] & 0x01; mode = (curframe[3] >> 6) & 0x03; nchan = (mode == 3) ? 1 : 2; if (!crcflag) wrdpntr = curframe + 6; else wrdpntr = curframe + 4; bitidx = 0; if (mpegver == 3) { /* 9 bit main_data_begin */ wrdpntr++; bitidx = 1; if (mode == 3) skipBits(5); /* private bits */ else skipBits(3); /* private bits */ skipBits(nchan * 4); /* scfsi[ch][band] */ for (gr = 0; gr < 2; gr++) { for (ch = 0; ch < nchan; ch++) { skipBits(21); gain = peek8Bits(); if (*minGain > gain) { *minGain = gain; } if (*maxGain < gain) { *maxGain = gain; } skipBits(38); } } } else { /* mpegver != 3 */ wrdpntr++; /* 8 bit main_data_begin */ if (mode == 3) skipBits(1); else skipBits(2); /* only one granule, so no loop */ for (ch = 0; ch < nchan; ch++) { skipBits(21); gain = peek8Bits(); if (*minGain > gain) { *minGain = gain; } if (*maxGain < gain) { *maxGain = gain; } skipBits(42); } } } #ifndef asWIN32DLL static #endif int changeGain(char *filename AACGAIN_ARG(AACGainHandle aacH), int leftgainchange, int rightgainchange) { unsigned long ok; int mode; int crcflag; unsigned char *Xingcheck; unsigned long frame; int nchan; int ch; int gr; unsigned char gain; int bitridx; int freqidx; long bytesinframe; int sideinfo_len; int mpegver; long gFilesize = 0; char *outfilename; int gainchange[2]; int singlechannel; long outlength, inlength; /* size checker when using Temp files */ outfilename = NULL; frame = 0; BadLayer = 0; LayerSet = Reckless; NowWriting = !0; if ((leftgainchange == 0) && (rightgainchange == 0)) return 0; #ifdef AACGAIN if (aacH) { int rc = aac_modify_gain(aacH, leftgainchange, rightgainchange, QuietMode ? NULL : reportPercentWritten); NowWriting = 0; if (rc) passError(MP3GAIN_FILEFORMAT_NOTSUPPORTED, 1, "failed to modify gain\n"); return rc; } #endif gainchange[0] = leftgainchange; gainchange[1] = rightgainchange; singlechannel = !(leftgainchange == rightgainchange); if (saveTime) fileTime(filename, storeTime); gFilesize = getSizeOfFile(filename); if (UsingTemp) { fflush(stderr); fflush(stdout); outlength = (long)strlen(filename); outfilename = (char *)malloc(outlength+5); strcpy(outfilename,filename); if ((filename[outlength-3] == 'T' || filename[outlength-3] == 't') && (filename[outlength-2] == 'M' || filename[outlength-2] == 'm') && (filename[outlength-1] == 'P' || filename[outlength-1] == 'p')) { strcat(outfilename,".TMP"); } else { outfilename[outlength-3] = 'T'; outfilename[outlength-2] = 'M'; outfilename[outlength-1] = 'P'; } inf = fopen(filename,"r+b"); if (inf != NULL) { outf = fopen(outfilename, "wb"); if (outf == NULL) { fclose(inf); inf = NULL; passError(MP3GAIN_UNSPECIFED_ERROR, 3, "\nCan't open ", outfilename, " for temp writing\n"); return M3G_ERR_CANT_MAKE_TMP; } } } else { inf = fopen(filename,"r+b"); } if (inf == NULL) { if (UsingTemp && (outf != NULL)) fclose(outf); passError( MP3GAIN_UNSPECIFED_ERROR, 3, "\nCan't open ", filename, " for modifying\n"); return M3G_ERR_CANT_MODIFY_FILE; } else { writebuffercnt = 0; inbuffer = 0; filepos = 0; bitidx = 0; ok = fillBuffer(0); if (ok) { wrdpntr = buffer; ok = skipID3v2(); ok = frameSearch(!0); if (!ok) { if (!BadLayer) passError( MP3GAIN_UNSPECIFED_ERROR, 3, "Can't find any valid MP3 frames in file ", filename, "\n"); } else { LayerSet = 1; /* We've found at least one valid layer 3 frame. * Assume any later layer 1 or 2 frames are just * bitstream corruption */ mode = (curframe[3] >> 6) & 3; if ((curframe[1] & 0x08) == 0x08) /* MPEG 1 */ sideinfo_len = (mode == 3) ? 4 + 17 : 4 + 32; else /* MPEG 2 */ sideinfo_len = (mode == 3) ? 4 + 9 : 4 + 17; if (!(curframe[1] & 0x01)) sideinfo_len += 2; Xingcheck = curframe + sideinfo_len; //LAME CBR files have "Info" tags, not "Xing" tags if ((Xingcheck[0] == 'X' && Xingcheck[1] == 'i' && Xingcheck[2] == 'n' && Xingcheck[3] == 'g') || (Xingcheck[0] == 'I' && Xingcheck[1] == 'n' && Xingcheck[2] == 'f' && Xingcheck[3] == 'o')) { bitridx = (curframe[2] >> 4) & 0x0F; if (bitridx == 0) { passError( MP3GAIN_FILEFORMAT_NOTSUPPORTED, 2, filename, " is free format (not currently supported)\n"); ok = 0; } else { mpegver = (curframe[1] >> 3) & 0x03; freqidx = (curframe[2] >> 2) & 0x03; bytesinframe = arrbytesinframe[bitridx] + ((curframe[2] >> 1) & 0x01); wrdpntr = curframe + bytesinframe; ok = frameSearch(0); } } frame = 1; } /* if (!ok) else */ #ifdef asWIN32DLL while (ok && (!blnCancel)) { #else while (ok) { #endif bitridx = (curframe[2] >> 4) & 0x0F; if (singlechannel) { if ((curframe[3] >> 6) & 0x01) { /* if mode is NOT stereo or dual channel */ passError( MP3GAIN_FILEFORMAT_NOTSUPPORTED, 2, filename, ": Can't adjust single channel for mono or joint stereo\n"); ok = 0; } } if (bitridx == 0) { passError( MP3GAIN_FILEFORMAT_NOTSUPPORTED, 2, filename, " is free format (not currently supported)\n"); ok = 0; } if (ok) { mpegver = (curframe[1] >> 3) & 0x03; crcflag = curframe[1] & 0x01; freqidx = (curframe[2] >> 2) & 0x03; bytesinframe = arrbytesinframe[bitridx] + ((curframe[2] >> 1) & 0x01); mode = (curframe[3] >> 6) & 0x03; nchan = (mode == 3) ? 1 : 2; if (!crcflag) /* we DO have a crc field */ wrdpntr = curframe + 6; /* 4-byte header, 2-byte CRC */ else wrdpntr = curframe + 4; /* 4-byte header */ bitidx = 0; if (mpegver == 3) { /* 9 bit main_data_begin */ wrdpntr++; bitidx = 1; if (mode == 3) skipBits(5); /* private bits */ else skipBits(3); /* private bits */ skipBits(nchan*4); /* scfsi[ch][band] */ for (gr = 0; gr < 2; gr++) for (ch = 0; ch < nchan; ch++) { skipBits(21); gain = peek8Bits(); if (wrapGain) gain += (unsigned char)(gainchange[ch]); else { if (gain != 0) { if ((int)(gain) + gainchange[ch] > 255) gain = 255; else if ((int)gain + gainchange[ch] < 0) gain = 0; else gain += (unsigned char)(gainchange[ch]); } } set8Bits(gain); skipBits(38); } if (!crcflag) { if (nchan == 1) crcWriteHeader(23,(char*)curframe); else crcWriteHeader(38,(char*)curframe); /* WRITETOFILE */ if (!UsingTemp) addWriteBuff(filepos-(inbuffer-(curframe+4-buffer)),curframe+4); } } else { /* mpegver != 3 */ wrdpntr++; /* 8 bit main_data_begin */ if (mode == 3) skipBits(1); else skipBits(2); /* only one granule, so no loop */ for (ch = 0; ch < nchan; ch++) { skipBits(21); gain = peek8Bits(); if (wrapGain) gain += (unsigned char)(gainchange[ch]); else { if (gain != 0) { if ((int)(gain) + gainchange[ch] > 255) gain = 255; else if ((int)gain + gainchange[ch] < 0) gain = 0; else gain += (unsigned char)(gainchange[ch]); } } set8Bits(gain); skipBits(42); } if (!crcflag) { if (nchan == 1) crcWriteHeader(15,(char*)curframe); else crcWriteHeader(23,(char*)curframe); /* WRITETOFILE */ if (!UsingTemp) addWriteBuff(filepos-(inbuffer-(curframe+4-buffer)),curframe+4); } } if (!QuietMode) { frame++; if (frame%200 == 0) { ok = reportPercentWritten((unsigned long)(((double)(filepos-(inbuffer-(curframe+bytesinframe-buffer))) * 100.0) / gFilesize),gFilesize); if (!ok) return ok; } } wrdpntr = curframe+bytesinframe; ok = frameSearch(0); } } } #ifdef asWIN32DLL if (blnCancel) { //need to clean up as best as possible fclose(inf); if (UsingTemp) { fclose(outf); deleteFile(outfilename); free(outfilename); passError(MP3GAIN_CANCELLED,2,"Cancelled processing of ",filename); } else { passError(MP3GAIN_CANCELLED,3,"Cancelled processing.\n", filename, " is probably corrupted now."); } if (saveTime) fileTime(filename, setStoredTime); return; } #endif if (!QuietMode) { #ifndef asWIN32DLL fprintf(stderr," \r"); #else /* report DONE (100%) message back to calling app */ sendpercentdone( 100, gFilesize ); #endif } fflush(stderr); fflush(stdout); if (UsingTemp) { while (fillBuffer(0)); fflush(outf); #ifdef WIN32 outlength = _filelength(_fileno(outf)); inlength = _filelength(_fileno(inf)); #else fseek(outf, 0, SEEK_END); fseek(inf, 0, SEEK_END); outlength=ftell(outf); inlength =ftell(inf); #endif #ifdef __BEOS__ /* some stuff to preserve attributes */ do { DIR *attrs = NULL; struct dirent *de; struct attr_info ai; int infd, outfd; void *attrdata; infd = fileno(inf); if (infd < 0) goto attrerror; outfd = fileno(outf); if (outfd < 0) goto attrerror; attrs = fs_fopen_attr_dir(infd); while ((de = fs_read_attr_dir(attrs)) != NULL) { if (fs_stat_attr(infd, de->d_name, &ai) < B_OK) goto attrerror; if ((attrdata = malloc(ai.size)) == NULL) goto attrerror; fs_read_attr(infd, de->d_name, ai.type, 0, attrdata, ai.size); fs_write_attr(outfd, de->d_name, ai.type, 0, attrdata, ai.size); free(attrdata); } fs_close_attr_dir(attrs); break; attrerror: if (attrdata) free(attrdata); if (attrs) fs_close_attr_dir(attrs); fprintf(stderr, "can't preserve attributes for '%s': %s\n", filename, strerror(errno)); } while (0); #endif fclose(outf); fclose(inf); inf = NULL; if (outlength != inlength) { deleteFile(outfilename); passError( MP3GAIN_UNSPECIFED_ERROR, 3, "Not enough temp space on disk to modify ", filename, "\nEither free some space, or do not use \"temp file\" option\n"); return M3G_ERR_NOT_ENOUGH_TMP_SPACE; } else { if (deleteFile(filename)) { deleteFile(outfilename); //try to delete tmp file passError( MP3GAIN_UNSPECIFED_ERROR, 3, "Can't open ", filename, " for modifying\n"); return M3G_ERR_CANT_MODIFY_FILE; } if (moveFile(outfilename, filename)) { passError( MP3GAIN_UNSPECIFED_ERROR, 9, "Problem re-naming ", outfilename, " to ", filename, "\nThe mp3 was correctly modified, but you will need to re-name ", outfilename, " to ", filename, " yourself.\n"); return M3G_ERR_RENAME_TMP; }; if (saveTime) fileTime(filename, setStoredTime); } free(outfilename); } else { flushWriteBuff(); fclose(inf); inf = NULL; if (saveTime) fileTime(filename, setStoredTime); } } NowWriting = 0; return 0; } #ifndef asWIN32DLL #ifdef AACGAIN void WriteAacGainTags (AACGainHandle aacH, struct MP3GainTagInfo *info) { if (info->haveAlbumGain) aac_set_tag_float(aacH, replaygain_album_gain, info->albumGain); if (info->haveAlbumPeak) aac_set_tag_float(aacH, replaygain_album_peak, info->albumPeak); if (info->haveAlbumMinMaxGain) aac_set_tag_int_2(aacH, replaygain_album_minmax, info->albumMinGain, info->albumMaxGain); if (info->haveTrackGain) aac_set_tag_float(aacH, replaygain_track_gain, info->trackGain); if (info->haveTrackPeak) aac_set_tag_float(aacH, replaygain_track_peak, info->trackPeak); if (info->haveMinMaxGain) aac_set_tag_int_2(aacH, replaygain_track_minmax, info->minGain, info->maxGain); if (info->haveUndo) aac_set_tag_int_2(aacH, replaygain_undo, info->undoLeft, info->undoRight); } #endif static void WriteMP3GainTag(char *filename AACGAIN_ARG(AACGainHandle aacH), struct MP3GainTagInfo *info, struct FileTagsStruct *fileTags, int saveTimeStamp) { #ifdef AACGAIN if (aacH) { WriteAacGainTags(aacH, info); } else #endif if (useId3) { /* Write ID3 tag; remove stale APE tag if it exists. */ if (WriteMP3GainID3Tag(filename, info, saveTimeStamp) >= 0) RemoveMP3GainAPETag(filename, saveTimeStamp); } else { /* Write APE tag */ WriteMP3GainAPETag(filename, info, fileTags, saveTimeStamp); } } void changeGainAndTag(char *filename AACGAIN_ARG(AACGainHandle aacH), int leftgainchange, int rightgainchange, struct MP3GainTagInfo *tag, struct FileTagsStruct *fileTag) { double dblGainChange; int curMin; int curMax; if (leftgainchange != 0 || rightgainchange != 0) { if (!changeGain(filename AACGAIN_ARG(aacH), leftgainchange, rightgainchange)) { if (!tag->haveUndo) { tag->undoLeft = 0; tag->undoRight = 0; } tag->dirty = !0; tag->undoRight -= rightgainchange; tag->undoLeft -= leftgainchange; tag->undoWrap = wrapGain; /* if undo == 0, then remove Undo tag */ tag->haveUndo = !0; /* on second thought, don't remove it. Shortening the tag causes full file copy, which is slow so we avoid it if we can tag->haveUndo = ((tag->undoRight != 0) || (tag->undoLeft != 0)); */ if (leftgainchange == rightgainchange) { /* don't screw around with other fields if mis-matched left/right */ dblGainChange = leftgainchange * 1.505; /* approx. 5 * log10(2) */ if (tag->haveTrackGain) { tag->trackGain -= dblGainChange; } if (tag->haveTrackPeak) { tag->trackPeak *= pow(2.0,(double)(leftgainchange)/4.0); } if (tag->haveAlbumGain) { tag->albumGain -= dblGainChange; } if (tag->haveAlbumPeak) { tag->albumPeak *= pow(2.0,(double)(leftgainchange)/4.0); } if (tag->haveMinMaxGain) { curMin = tag->minGain; curMax = tag->maxGain; curMin += leftgainchange; curMax += leftgainchange; if (wrapGain) { if (curMin < 0 || curMin > 255 || curMax < 0 || curMax > 255) { /* we've lost the "real" min or max because of wrapping */ tag->haveMinMaxGain = 0; } } else { tag->minGain = tag->minGain == 0 ? 0 : curMin < 0 ? 0 : curMin > 255 ? 255 : curMin; tag->maxGain = curMax < 0 ? 0 : curMax > 255 ? 255 : curMax; } } if (tag->haveAlbumMinMaxGain) { curMin = tag->albumMinGain; curMax = tag->albumMaxGain; curMin += leftgainchange; curMax += leftgainchange; if (wrapGain) { if (curMin < 0 || curMin > 255 || curMax < 0 || curMax > 255) { /* we've lost the "real" min or max because of wrapping */ tag->haveAlbumMinMaxGain = 0; } } else { tag->albumMinGain = tag->albumMinGain == 0 ? 0 : curMin < 0 ? 0 : curMin > 255 ? 255 : curMin; tag->albumMaxGain = curMax < 0 ? 0 : curMax > 255 ? 255 : curMax; } } } // if (leftgainchange == rightgainchange ... WriteMP3GainTag(filename AACGAIN_ARG(aacH), tag, fileTag, saveTime); } // if (!changeGain(filename ... }// if (leftgainchange !=0 ... } static int queryUserForClipping(char * argv_mainloop,int intGainChange) { char ch; fprintf(stderr,"\nWARNING: %s may clip with mp3 gain change %d\n",argv_mainloop,intGainChange); ch = 0; fflush(stdout); fflush(stderr); while ((ch != 'Y') && (ch != 'N')) { fprintf(stderr,"Make change? [y/n]:"); fflush(stderr); ch = getchar(); ch = toupper(ch); } if (ch == 'N') return 0; return 1; } static void showVersion(char *progname) { #ifdef AACGAIN fprintf(stderr,"aacgain version %s, derived from mp3gain version %s\n",AACGAIN_VERSION,MP3GAIN_VERSION); #else fprintf(stderr,"%s version %s\n",progname,MP3GAIN_VERSION); #endif } static void wrapExplanation() { fprintf(stderr,"Here's the problem:\n"); fprintf(stderr,"The \"global gain\" field that mp3gain adjusts is an 8-bit unsigned integer, so\n"); fprintf(stderr,"the possible values are 0 to 255.\n"); fprintf(stderr,"\n"); fprintf(stderr,"MOST mp3 files (in fact, ALL the mp3 files I've examined so far) don't go\n"); fprintf(stderr,"over 230. So there's plenty of headroom on top-- you can increase the gain\n"); fprintf(stderr,"by 37dB (multiplying the amplitude by 76) without a problem.\n"); fprintf(stderr,"\n"); fprintf(stderr,"The problem is at the bottom of the range. Some encoders create frames with\n"); fprintf(stderr,"0 as the global gain for silent frames.\n"); fprintf(stderr,"What happens when you _lower_ the global gain by 1?\n"); fprintf(stderr,"Well, in the past, mp3gain always simply wrapped the result up to 255.\n"); fprintf(stderr,"That way, if you lowered the gain by any amount and then raised it by the\n"); fprintf(stderr,"same amount, the mp3 would always be _exactly_ the same.\n"); fprintf(stderr,"\n"); fprintf(stderr,"There are a few encoders out there, unfortunately, that create 0-gain frames\n"); fprintf(stderr,"with other audio data in the frame.\n"); fprintf(stderr,"As long as the global gain is 0, you'll never hear the data.\n"); fprintf(stderr,"But if you lower the gain on such a file, the global gain is suddenly _huge_.\n"); fprintf(stderr,"If you play this modified file, there might be a brief, very loud blip.\n"); fprintf(stderr,"\n"); fprintf(stderr,"So now the default behavior of mp3gain is to _not_ wrap gain changes.\n"); fprintf(stderr,"In other words,\n"); fprintf(stderr,"1) If the gain change would make a frame's global gain drop below 0,\n"); fprintf(stderr," then the global gain is set to 0.\n"); fprintf(stderr,"2) If the gain change would make a frame's global gain grow above 255,\n"); fprintf(stderr," then the global gain is set to 255.\n"); fprintf(stderr,"3) If a frame's global gain field is already 0, it is not changed, even if\n"); fprintf(stderr," the gain change is a positive number\n"); fprintf(stderr,"\n"); fprintf(stderr,"To use the original \"wrapping\" behavior, use the \"%cw\" switch.\n",SWITCH_CHAR); #ifdef AACGAIN fprintf(stderr,"\n"); fprintf(stderr,"The \"%cw\" switch is not supported for AAC files. An attempt to wrap\n",SWITCH_CHAR); fprintf(stderr,"an AAC file is treated as an error, and the file will not be modified.\n"); #endif exit(0); } static void errUsage(char *progname) { showVersion(progname); fprintf(stderr,"copyright(c) 2001-2009 by Glen Sawyer\n"); #ifdef AACGAIN fprintf(stderr,"AAC support copyright(c) 2004-2009 David Lasker, Altos Design, Inc.\n"); #endif fprintf(stderr,"uses mpglib, which can be found at http://www.mpg123.de\n"); #ifdef AACGAIN fprintf(stderr,"AAC support uses faad2 (http://www.audiocoding.com), and\n"); fprintf(stderr,"mpeg4ip's mp4v2 (http://www.mpeg4ip.net)\n"); #endif fprintf(stderr,"Usage: %s [options] [ ...]\n",progname); fprintf(stderr," --use %c? or %ch for a full list of options\n",SWITCH_CHAR,SWITCH_CHAR); fclose(stdout); fclose(stderr); exit(1); } static void fullUsage(char *progname) { showVersion(progname); fprintf(stderr,"copyright(c) 2001-2009 by Glen Sawyer\n"); #ifdef AACGAIN fprintf(stderr,"AAC support copyright(c) 2004-2009 David Lasker, Altos Design, Inc.\n"); #endif fprintf(stderr,"uses mpglib, which can be found at http://www.mpg123.de\n"); #ifdef AACGAIN fprintf(stderr,"AAC support uses faad2 (http://www.audiocoding.com), and\n"); fprintf(stderr,"mpeg4ip's mp4v2 (http://www.mpeg4ip.net)\n"); #endif fprintf(stderr,"Usage: %s [options] [ ...]\n",progname); fprintf(stderr,"options:\n"); fprintf(stderr,"\t%cv - show version number\n",SWITCH_CHAR); fprintf(stderr,"\t%cg - apply gain i without doing any analysis\n",SWITCH_CHAR); fprintf(stderr,"\t%cl 0 - apply gain i to channel 0 (left channel)\n",SWITCH_CHAR); fprintf(stderr,"\t without doing any analysis (ONLY works for STEREO files,\n"); fprintf(stderr,"\t not Joint Stereo)\n"); fprintf(stderr,"\t%cl 1 - apply gain i to channel 1 (right channel)\n",SWITCH_CHAR); fprintf(stderr,"\t%ce - skip Album analysis, even if multiple files listed\n",SWITCH_CHAR); fprintf(stderr,"\t%cr - apply Track gain automatically (all files set to equal loudness)\n",SWITCH_CHAR); fprintf(stderr,"\t%ck - automatically lower Track/Album gain to not clip audio\n",SWITCH_CHAR); fprintf(stderr,"\t%ca - apply Album gain automatically (files are all from the same\n",SWITCH_CHAR); fprintf(stderr,"\t album: a single gain change is applied to all files, so\n"); fprintf(stderr,"\t their loudness relative to each other remains unchanged,\n"); fprintf(stderr,"\t but the average album loudness is normalized)\n"); fprintf(stderr,"\t%cm - modify suggested MP3 gain by integer i\n",SWITCH_CHAR); fprintf(stderr,"\t%cd - modify suggested dB gain by floating-point n\n",SWITCH_CHAR); fprintf(stderr,"\t%cc - ignore clipping warning when applying gain\n",SWITCH_CHAR); fprintf(stderr,"\t%co - output is a database-friendly tab-delimited list\n",SWITCH_CHAR); fprintf(stderr,"\t%ct - writes modified data to temp file, then deletes original\n",SWITCH_CHAR); fprintf(stderr,"\t instead of modifying bytes in original file\n"); #ifdef AACGAIN fprintf(stderr,"\t A temp file is always used for AAC files.\n"); #endif fprintf(stderr,"\t%cq - Quiet mode: no status messages\n",SWITCH_CHAR); fprintf(stderr,"\t%cp - Preserve original file timestamp\n",SWITCH_CHAR); fprintf(stderr,"\t%cx - Only find max. amplitude of file\n",SWITCH_CHAR); fprintf(stderr,"\t%cf - Assume input file is an MPEG 2 Layer III file\n",SWITCH_CHAR); fprintf(stderr,"\t (i.e. don't check for mis-named Layer I or Layer II files)\n"); #ifdef AACGAIN fprintf(stderr,"\t This option is ignored for AAC files.\n"); #endif fprintf(stderr,"\t%c? or %ch - show this message\n",SWITCH_CHAR,SWITCH_CHAR); fprintf(stderr,"\t%cs c - only check stored tag info (no other processing)\n",SWITCH_CHAR); fprintf(stderr,"\t%cs d - delete stored tag info (no other processing)\n",SWITCH_CHAR); fprintf(stderr,"\t%cs s - skip (ignore) stored tag info (do not read or write tags)\n",SWITCH_CHAR); fprintf(stderr,"\t%cs r - force re-calculation (do not read tag info)\n",SWITCH_CHAR); fprintf(stderr,"\t%cs i - use ID3v2 tag for MP3 gain info\n",SWITCH_CHAR); fprintf(stderr,"\t%cs a - use APE tag for MP3 gain info (default)\n",SWITCH_CHAR); fprintf(stderr,"\t%cu - undo changes made (based on stored tag info)\n",SWITCH_CHAR); fprintf(stderr,"\t%cw - \"wrap\" gain change if gain+change > 255 or gain+change < 0\n",SWITCH_CHAR); #ifdef AACGAIN fprintf(stderr,"\t MP3 only. (use \"%c? wrap\" switch for a complete explanation)\n",SWITCH_CHAR); #else fprintf(stderr,"\t (use \"%c? wrap\" switch for a complete explanation)\n",SWITCH_CHAR); #endif fprintf(stderr,"If you specify %cr and %ca, only the second one will work\n",SWITCH_CHAR,SWITCH_CHAR); fprintf(stderr,"If you do not specify %cc, the program will stop and ask before\n applying gain change to a file that might clip\n",SWITCH_CHAR); fclose(stdout); fclose(stderr); exit(0); } #ifdef AACGAIN void ReadAacTags(AACGainHandle gh, struct MP3GainTagInfo *info) { int p1, p2; if (aac_get_tag_float(gh, replaygain_album_gain, &info->albumGain) == 0) info->haveAlbumGain = !0; if (aac_get_tag_float(gh, replaygain_album_peak, &info->albumPeak) == 0) info->haveAlbumPeak = !0; if (aac_get_tag_int_2(gh, replaygain_album_minmax, &p1, &p2) == 0) { info->albumMinGain = p1; info->albumMaxGain = p2; info->haveAlbumMinMaxGain = !0; } if (aac_get_tag_float(gh, replaygain_track_gain, &info->trackGain) == 0) info->haveTrackGain = !0; if (aac_get_tag_float(gh, replaygain_track_peak, &info->trackPeak) == 0) info->haveTrackPeak = !0; if (aac_get_tag_int_2(gh, replaygain_track_minmax, &p1, &p2) == 0) { info->minGain = p1; info->maxGain = p2; info->haveMinMaxGain = !0; } if (aac_get_tag_int_2(gh, replaygain_undo, &p1, &p2) == 0) { info->undoLeft = p1; info->undoRight = p2; info->haveUndo = !0; } } #endif void dumpTaginfo(struct MP3GainTagInfo *info) { fprintf(stderr, "haveAlbumGain %d albumGain %f\n",info->haveAlbumGain, info->albumGain); fprintf(stderr, "haveAlbumPeak %d albumPeak %f\n",info->haveAlbumPeak, info->albumPeak); fprintf(stderr, "haveAlbumMinMaxGain %d min %d max %d\n",info->haveAlbumMinMaxGain, info->albumMinGain, info->albumMaxGain); fprintf(stderr, "haveTrackGain %d trackGain %f\n",info->haveTrackGain, info->trackGain); fprintf(stderr, "haveTrackPeak %d trackPeak %f\n",info->haveTrackPeak, info->trackPeak); fprintf(stderr, "haveMinMaxGain %d min %d max %d\n",info->haveMinMaxGain, info->minGain, info->maxGain); } #ifdef WIN32 int __cdecl main(int argc, char **argv) { /*make sure this one is standard C declaration*/ #else int main(int argc, char **argv) { #endif MPSTR mp; unsigned long ok; int mode; int crcflag; unsigned char *Xingcheck; unsigned long frame; int nchan; int bitridx; int freqidx; long bytesinframe; double dBchange; double dblGainChange; int intGainChange = 0; int intAlbumGainChange = 0; int nprocsamp; int first = 1; int mainloop; Float_t maxsample; Float_t lsamples[1152]; Float_t rsamples[1152]; unsigned char maxgain; unsigned char mingain; int ignoreClipWarning = 0; int autoClip = 0; int applyTrack = 0; int applyAlbum = 0; int analysisTrack = 0; char analysisError = 0; int fileStart; int databaseFormat = 0; int i; int *fileok; int goAhead; int directGain = 0; int directSingleChannelGain = 0; int directGainVal = 0; int mp3GainMod = 0; double dBGainMod = 0; int mpegver; int sideinfo_len; long gFilesize = 0; int decodeSuccess; struct MP3GainTagInfo *tagInfo; struct MP3GainTagInfo *curTag; struct FileTagsStruct *fileTags; int albumRecalc; double curAlbumGain = 0; double curAlbumPeak = 0; unsigned char curAlbumMinGain = 0; unsigned char curAlbumMaxGain = 0; char chtmp; #ifdef AACGAIN AACGainHandle *aacInfo; #endif gSuccess = 1; if (argc < 2) { errUsage(argv[0]); } maxAmpOnly = 0; saveTime = 0; fileStart = 1; numFiles = 0; for (i = 1; i < argc; i++) { #ifdef WIN32 if ((argv[i][0] == '/')||((argv[i][0] == '-') && (strlen(argv[i])==2))) { /* don't need to force single-character command parameters */ #else if (((argv[i][0] == '/')||(argv[i][0] == '-'))&& (strlen(argv[i])==2)) { #endif fileStart++; switch(argv[i][1]) { case 'a': case 'A': applyTrack = 0; applyAlbum = !0; break; case 'c': case 'C': ignoreClipWarning = !0; break; case 'd': case 'D': if (argv[i][2] != '\0') { dBGainMod = atof(argv[i]+2); } else { if (i+1 < argc) { dBGainMod = atof(argv[i+1]); i++; fileStart++; } else { errUsage(argv[0]); } } break; case 'f': case 'F': Reckless = 1; break; case 'g': case 'G': directGain = !0; directSingleChannelGain = 0; if (argv[i][2] != '\0') { directGainVal = atoi(argv[i]+2); } else { if (i+1 < argc) { directGainVal = atoi(argv[i+1]); i++; fileStart++; } else { errUsage(argv[0]); } } break; case 'h': case 'H': case '?': if ((argv[i][2] == 'w')||(argv[i][2] == 'W')) { wrapExplanation(); } else { if (i+1 < argc) { if ((argv[i+1][0] == 'w')||(argv[i+1][0] =='W')) wrapExplanation(); } else { fullUsage(argv[0]); } } fullUsage(argv[0]); break; case 'k': case 'K': autoClip = !0; break; case 'l': case 'L': directSingleChannelGain = !0; directGain = 0; if (argv[i][2] != '\0') { whichChannel = atoi(argv[i]+2); if (i+1 < argc) { directGainVal = atoi(argv[i+1]); i++; fileStart++; } else { errUsage(argv[0]); } } else { if (i+2 < argc) { whichChannel = atoi(argv[i+1]); i++; fileStart++; directGainVal = atoi(argv[i+1]); i++; fileStart++; } else { errUsage(argv[0]); } } break; case 'm': case 'M': if (argv[i][2] != '\0') { mp3GainMod = atoi(argv[i]+2); } else { if (i+1 < argc) { mp3GainMod = atoi(argv[i+1]); i++; fileStart++; } else { errUsage(argv[0]); } } break; case 'o': case 'O': databaseFormat = !0; break; case 'p': case 'P': saveTime = !0; break; case 'q': case 'Q': QuietMode = !0; break; case 'r': case 'R': applyTrack = !0; applyAlbum = 0; break; case 's': case 'S': chtmp = 0; if (argv[i][2] == '\0') { if (i+1 < argc) { i++; fileStart++; chtmp = argv[i][0]; } else { errUsage(argv[0]); } } else { chtmp = argv[i][2]; } switch (chtmp) { case 'c': case 'C': checkTagOnly = !0; break; case 'd': case 'D': deleteTag = !0; break; case 's': case 'S': skipTag = !0; break; case 'r': case 'R': forceRecalculateTag = !0; break; case 'i': case 'I': useId3 = 1; break; case 'a': case 'A': useId3 = 0; break; default: errUsage(argv[0]); } break; case 't': case 'T': UsingTemp = !0; break; case 'u': case 'U': undoChanges = !0; break; case 'v': case 'V': showVersion(argv[0]); fclose(stdout); fclose(stderr); exit(0); case 'w': case 'W': wrapGain = !0; break; case 'x': case 'X': maxAmpOnly = !0; break; case 'e': case 'E': analysisTrack = !0; break; default: fprintf(stderr,"I don't recognize option %s\n",argv[i]); } } } /* now stored in tagInfo--- maxsample = malloc(sizeof(Float_t) * argc); */ fileok = (int *)malloc(sizeof(int) * argc); /* now stored in tagInfo--- maxgain = malloc(sizeof(unsigned char) * argc); */ /* now stored in tagInfo--- mingain = malloc(sizeof(unsigned char) * argc); */ tagInfo = (struct MP3GainTagInfo *)calloc(argc, sizeof(struct MP3GainTagInfo)); fileTags = (struct FileTagsStruct *)malloc(sizeof(struct FileTagsStruct) * argc); #ifdef AACGAIN aacInfo = (AACGainHandle)malloc(sizeof(AACGainHandle) * argc); #endif if (databaseFormat) { if (checkTagOnly) { fprintf(stdout,"File\tMP3 gain\tdB gain\tMax Amplitude\tMax global_gain\tMin global_gain\tAlbum gain\tAlbum dB gain\tAlbum Max Amplitude\tAlbum Max global_gain\tAlbum Min global_gain\n"); } else if (undoChanges) { fprintf(stdout,"File\tleft global_gain change\tright global_gain change\n"); } else { fprintf(stdout,"File\tMP3 gain\tdB gain\tMax Amplitude\tMax global_gain\tMin global_gain\n"); } fflush(stdout); } /* read all the tags first */ totFiles = argc - fileStart; for (mainloop = fileStart; mainloop < argc; mainloop++) { fileok[mainloop] = 0; curfilename = argv[mainloop]; fileTags[mainloop].apeTag = NULL; fileTags[mainloop].lyrics3tag = NULL; fileTags[mainloop].id31tag = NULL; tagInfo[mainloop].dirty = 0; tagInfo[mainloop].haveAlbumGain = 0; tagInfo[mainloop].haveAlbumPeak = 0; tagInfo[mainloop].haveTrackGain = 0; tagInfo[mainloop].haveTrackPeak = 0; tagInfo[mainloop].haveUndo = 0; tagInfo[mainloop].haveMinMaxGain = 0; tagInfo[mainloop].haveAlbumMinMaxGain = 0; tagInfo[mainloop].recalc = 0; #ifdef AACGAIN //check for aac file; open it if found //note: we try to open aac even if /f (reckless) if (aac_open(curfilename, UsingTemp, saveTime, &aacInfo[mainloop]) != 0) { //in case of any errors, don't continue processing so there is no risk of corrupting //a bad file passError(MP3GAIN_FILEFORMAT_NOTSUPPORTED, 2, curfilename, " is not a valid mp4/m4a file.\n"); exit(1); } #endif if ((!skipTag)&&(!deleteTag)) { #ifdef AACGAIN if (aacInfo[mainloop]) { if (!skipTag) ReadAacTags(aacInfo[mainloop], &(tagInfo[mainloop])); } else #endif { ReadMP3GainAPETag(curfilename,&(tagInfo[mainloop]),&(fileTags[mainloop])); if (useId3) { if (tagInfo[mainloop].haveTrackGain || tagInfo[mainloop].haveAlbumGain || tagInfo[mainloop].haveMinMaxGain || tagInfo[mainloop].haveAlbumMinMaxGain || tagInfo[mainloop].haveUndo) { /* Mark the file dirty to force upgrade to ID3v2 */ tagInfo[mainloop].dirty = 1; } ReadMP3GainID3Tag(curfilename,&(tagInfo[mainloop])); } } /*fprintf(stdout,"Read previous tags from %s\n",curfilename); dumpTaginfo(&(tagInfo[mainloop]));*/ if (forceRecalculateTag) { if (tagInfo[mainloop].haveAlbumGain) { tagInfo[mainloop].dirty = !0; tagInfo[mainloop].haveAlbumGain = 0; } if (tagInfo[mainloop].haveAlbumPeak) { tagInfo[mainloop].dirty = !0; tagInfo[mainloop].haveAlbumPeak = 0; } if (tagInfo[mainloop].haveTrackGain) { tagInfo[mainloop].dirty = !0; tagInfo[mainloop].haveTrackGain = 0; } if (tagInfo[mainloop].haveTrackPeak) { tagInfo[mainloop].dirty = !0; tagInfo[mainloop].haveTrackPeak = 0; } /* NOT Undo information! if (tagInfo[mainloop].haveUndo) { tagInfo[mainloop].dirty = !0; tagInfo[mainloop].haveUndo = 0; } */ if (tagInfo[mainloop].haveMinMaxGain) { tagInfo[mainloop].dirty = !0; tagInfo[mainloop].haveMinMaxGain = 0; } if (tagInfo[mainloop].haveAlbumMinMaxGain) { tagInfo[mainloop].dirty = !0; tagInfo[mainloop].haveAlbumMinMaxGain = 0; } } } } /* check if we need to actually process the file(s) */ albumRecalc = forceRecalculateTag || skipTag ? FULL_RECALC : 0; if ((!skipTag)&&(!deleteTag)&&(!forceRecalculateTag)) { /* we're not automatically recalculating, so check if we already have all the information */ if (argc - fileStart > 1) { curAlbumGain = tagInfo[fileStart].albumGain; curAlbumPeak = tagInfo[fileStart].albumPeak; curAlbumMinGain = tagInfo[fileStart].albumMinGain; curAlbumMaxGain = tagInfo[fileStart].albumMaxGain; } for (mainloop = fileStart; mainloop < argc; mainloop++) { if (!maxAmpOnly) { /* we don't care about these things if we're only looking for max amp */ if (argc - fileStart > 1 && !applyTrack && !analysisTrack) { /* only check album stuff if more than one file in the list */ if (!tagInfo[mainloop].haveAlbumGain) { albumRecalc |= FULL_RECALC; } else if (tagInfo[mainloop].albumGain != curAlbumGain) { albumRecalc |= FULL_RECALC; } } if (!tagInfo[mainloop].haveTrackGain) { tagInfo[mainloop].recalc |= FULL_RECALC; } } if (argc - fileStart > 1 && !applyTrack && !analysisTrack) { /* only check album stuff if more than one file in the list */ if (!tagInfo[mainloop].haveAlbumPeak) { albumRecalc |= AMP_RECALC; } else if (tagInfo[mainloop].albumPeak != curAlbumPeak) { albumRecalc |= AMP_RECALC; } if (!tagInfo[mainloop].haveAlbumMinMaxGain) { albumRecalc |= MIN_MAX_GAIN_RECALC; } else if (tagInfo[mainloop].albumMaxGain != curAlbumMaxGain) { albumRecalc |= MIN_MAX_GAIN_RECALC; } else if (tagInfo[mainloop].albumMinGain != curAlbumMinGain) { albumRecalc |= MIN_MAX_GAIN_RECALC; } } if (!tagInfo[mainloop].haveTrackPeak) { tagInfo[mainloop].recalc |= AMP_RECALC; } if (!tagInfo[mainloop].haveMinMaxGain) { tagInfo[mainloop].recalc |= MIN_MAX_GAIN_RECALC; } } } for (mainloop = fileStart; mainloop < argc; mainloop++) { #ifdef AACGAIN AACGainHandle aacH = aacInfo[mainloop]; #endif memset(&mp, 0, sizeof(mp)); // if the entire Album requires some kind of recalculation, then each track needs it tagInfo[mainloop].recalc |= albumRecalc; curfilename = argv[mainloop]; if (checkTagOnly) { curTag = tagInfo + mainloop; if (curTag->haveTrackGain) { dblGainChange = curTag->trackGain / (5.0 * log10(2.0)); if (fabs(dblGainChange) - (double)((int)(fabs(dblGainChange))) < 0.5) intGainChange = (int)(dblGainChange); else intGainChange = (int)(dblGainChange) + (dblGainChange < 0 ? -1 : 1); } if (curTag->haveAlbumGain) { dblGainChange = curTag->albumGain / (5.0 * log10(2.0)); if (fabs(dblGainChange) - (double)((int)(fabs(dblGainChange))) < 0.5) intAlbumGainChange = (int)(dblGainChange); else intAlbumGainChange = (int)(dblGainChange) + (dblGainChange < 0 ? -1 : 1); } if (!databaseFormat) { fprintf(stdout,"%s\n",argv[mainloop]); if (curTag->haveTrackGain) { fprintf(stdout,"Recommended \"Track\" dB change: %f\n",curTag->trackGain); fprintf(stdout,"Recommended \"Track\" mp3 gain change: %d\n",intGainChange); if (curTag->haveTrackPeak) { if (curTag->trackPeak * (Float_t)(pow(2.0,(double)(intGainChange)/4.0)) > 1.0) { fprintf(stdout,"WARNING: some clipping may occur with this gain change!\n"); } } } if (curTag->haveTrackPeak) fprintf(stdout,"Max PCM sample at current gain: %f\n",curTag->trackPeak * 32768.0); if (curTag->haveMinMaxGain) { fprintf(stdout,"Max mp3 global gain field: %d\n",curTag->maxGain); fprintf(stdout,"Min mp3 global gain field: %d\n",curTag->minGain); } if (curTag->haveAlbumGain) { fprintf(stdout,"Recommended \"Album\" dB change: %f\n",curTag->albumGain); fprintf(stdout,"Recommended \"Album\" mp3 gain change: %d\n",intAlbumGainChange); if (curTag->haveTrackPeak) { if (curTag->trackPeak * (Float_t)(pow(2.0,(double)(intAlbumGainChange)/4.0)) > 1.0) { fprintf(stdout,"WARNING: some clipping may occur with this gain change!\n"); } } } if (curTag->haveAlbumPeak) { fprintf(stdout,"Max Album PCM sample at current gain: %f\n",curTag->albumPeak * 32768.0); } if (curTag->haveAlbumMinMaxGain) { fprintf(stdout,"Max Album mp3 global gain field: %d\n",curTag->albumMaxGain); fprintf(stdout,"Min Album mp3 global gain field: %d\n",curTag->albumMinGain); } fprintf(stdout,"\n"); } else { fprintf(stdout,"%s\t",argv[mainloop]); if (curTag->haveTrackGain) { fprintf(stdout,"%d\t",intGainChange); fprintf(stdout,"%f\t",curTag->trackGain); } else { fprintf(stdout,"NA\tNA\t"); } if (curTag->haveTrackPeak) { fprintf(stdout,"%f\t",curTag->trackPeak * 32768.0); } else { fprintf(stdout,"NA\t"); } if (curTag->haveMinMaxGain) { fprintf(stdout,"%d\t",curTag->maxGain); fprintf(stdout,"%d\t",curTag->minGain); } else { fprintf(stdout,"NA\tNA\t"); } if (curTag->haveAlbumGain) { fprintf(stdout,"%d\t",intAlbumGainChange); fprintf(stdout,"%f\t",curTag->albumGain); } else { fprintf(stdout,"NA\tNA\t"); } if (curTag->haveAlbumPeak) { fprintf(stdout,"%f\t",curTag->albumPeak * 32768.0); } else { fprintf(stdout,"NA\t"); } if (curTag->haveAlbumMinMaxGain) { fprintf(stdout,"%d\t",curTag->albumMaxGain); fprintf(stdout,"%d\n",curTag->albumMinGain); } else { fprintf(stdout,"NA\tNA\n"); } fflush(stdout); } } else if (undoChanges) { directGain = !0; /* so we don't write the tag a second time */ if ((tagInfo[mainloop].haveUndo)&&(tagInfo[mainloop].undoLeft || tagInfo[mainloop].undoRight)) { if ((!QuietMode)&&(!databaseFormat)) fprintf(stderr,"Undoing mp3gain changes (%d,%d) to %s...\n", tagInfo[mainloop].undoLeft, tagInfo[mainloop].undoRight, argv[mainloop]); if (databaseFormat) fprintf(stdout,"%s\t%d\t%d\n", argv[mainloop], tagInfo[mainloop].undoLeft, tagInfo[mainloop].undoRight); changeGainAndTag(argv[mainloop] AACGAIN_ARG(aacH), tagInfo[mainloop].undoLeft, tagInfo[mainloop].undoRight, tagInfo + mainloop, fileTags + mainloop); } else { if (databaseFormat) { fprintf(stdout,"%s\t0\t0\n",argv[mainloop]); } else if (!QuietMode) { if (tagInfo[mainloop].haveUndo) { fprintf(stderr,"No changes to undo in %s\n",argv[mainloop]); } else { fprintf(stderr,"No undo information in %s\n",argv[mainloop]); } } } } else if (directSingleChannelGain) { if (!QuietMode) fprintf(stderr,"Applying gain change of %d to CHANNEL %d of %s...\n",directGainVal,whichChannel,argv[mainloop]); if (whichChannel) { /* do right channel */ if (skipTag) { changeGain(argv[mainloop] AACGAIN_ARG(aacH), 0, directGainVal); } else { changeGainAndTag(argv[mainloop] AACGAIN_ARG(aacH), 0, directGainVal, tagInfo + mainloop, fileTags + mainloop); } } else { /* do left channel */ if (skipTag) { changeGain(argv[mainloop] AACGAIN_ARG(aacH), directGainVal, 0); } else { changeGainAndTag(argv[mainloop] AACGAIN_ARG(aacH), directGainVal, 0, tagInfo + mainloop, fileTags + mainloop); } } if ((!QuietMode) && (gSuccess == 1)) fprintf(stderr,"\ndone\n"); } else if (directGain) { if (!QuietMode) fprintf(stderr,"Applying gain change of %d to %s...\n",directGainVal,argv[mainloop]); if (skipTag) { changeGain(argv[mainloop] AACGAIN_ARG(aacH), directGainVal, directGainVal); } else { changeGainAndTag(argv[mainloop] AACGAIN_ARG(aacH), directGainVal,directGainVal, tagInfo + mainloop, fileTags + mainloop); } if ((!QuietMode) && (gSuccess == 1)) fprintf(stderr,"\ndone\n"); } else if (deleteTag) { #ifdef AACGAIN if (aacH) aac_clear_rg_tags(aacH); else #endif { RemoveMP3GainAPETag(argv[mainloop], saveTime); if (useId3) { RemoveMP3GainID3Tag(argv[mainloop], saveTime); } } if ((!QuietMode)&&(!databaseFormat)) fprintf(stderr,"Deleting tag info of %s...\n", argv[mainloop]); if (databaseFormat) fprintf(stdout,"%s\tNA\tNA\tNA\tNA\tNA\n", argv[mainloop]); } else { if (!databaseFormat) fprintf(stdout,"%s\n",argv[mainloop]); if (tagInfo[mainloop].recalc > 0) { gFilesize = getSizeOfFile(argv[mainloop]); #ifdef AACGAIN if (!aacH) #endif inf = fopen(argv[mainloop],"rb"); } #ifdef AACGAIN if (!aacH&&(inf == NULL)&&(tagInfo[mainloop].recalc > 0)) { #else if ((inf == NULL)&&(tagInfo[mainloop].recalc > 0)) { #endif fprintf(stdout, "Can't open %s for reading\n",argv[mainloop]); fflush(stdout); } else { #ifdef AACGAIN if (!aacH) #endif InitMP3(&mp); if (tagInfo[mainloop].recalc == 0) { maxsample = tagInfo[mainloop].trackPeak * 32768.0; maxgain = tagInfo[mainloop].maxGain; mingain = tagInfo[mainloop].minGain; ok = !0; } else { if (!((tagInfo[mainloop].recalc & FULL_RECALC)||(tagInfo[mainloop].recalc & AMP_RECALC))) { /* only min/max rescan */ maxsample = tagInfo[mainloop].trackPeak * 32768.0; } else { maxsample = 0; } #ifdef AACGAIN if (aacH) { int rc; if (first) { lastfreq = aac_get_sample_rate(aacH); InitGainAnalysis((long)lastfreq); analysisError = 0; first = 0; } else { if (aac_get_sample_rate(aacH) != lastfreq) { lastfreq = aac_get_sample_rate(aacH); ResetSampleFrequency ((long)lastfreq); } } numFiles++; if (maxAmpOnly) rc = aac_compute_peak(aacH, &maxsample, &mingain, &maxgain, QuietMode ? NULL : reportPercentAnalyzed); else rc = aac_compute_gain(aacH, &maxsample, &mingain, &maxgain, QuietMode ? NULL : reportPercentAnalyzed); //in case of any error, bail to avoid corrupting file if (rc != 0) { passError(MP3GAIN_FILEFORMAT_NOTSUPPORTED, 2, curfilename, " is not a valid mp4/m4a file.\n"); exit(1); } ok = !0; } else #endif { BadLayer = 0; LayerSet = Reckless; maxgain = 0; mingain = 255; inbuffer = 0; filepos = 0; bitidx = 0; ok = fillBuffer(0); } } if (ok) { #ifdef AACGAIN if (!aacH && (tagInfo[mainloop].recalc > 0)) { #else if (tagInfo[mainloop].recalc > 0) { #endif wrdpntr = buffer; ok = skipID3v2(); ok = frameSearch(!0); } #ifdef AACGAIN if (!ok && !aacH) { #else if (!ok) { #endif if (!BadLayer) { fprintf(stdout,"Can't find any valid MP3 frames in file %s\n",argv[mainloop]); fflush(stdout); } } else { LayerSet = 1; /* We've found at least one valid layer 3 frame. * Assume any later layer 1 or 2 frames are just * bitstream corruption */ fileok[mainloop] = !0; #ifdef AACGAIN if (!aacH || (tagInfo[mainloop].recalc == 0)) #endif numFiles++; #ifdef AACGAIN if (!aacH && (tagInfo[mainloop].recalc > 0)) { #else if (tagInfo[mainloop].recalc > 0) { #endif mode = (curframe[3] >> 6) & 3; if ((curframe[1] & 0x08) == 0x08) /* MPEG 1 */ sideinfo_len = ((curframe[3] & 0xC0) == 0xC0) ? 4 + 17 : 4 + 32; else /* MPEG 2 */ sideinfo_len = ((curframe[3] & 0xC0) == 0xC0) ? 4 + 9 : 4 + 17; if (!(curframe[1] & 0x01)) sideinfo_len += 2; Xingcheck = curframe + sideinfo_len; //LAME CBR files have "Info" tags, not "Xing" tags if ((Xingcheck[0] == 'X' && Xingcheck[1] == 'i' && Xingcheck[2] == 'n' && Xingcheck[3] == 'g') || (Xingcheck[0] == 'I' && Xingcheck[1] == 'n' && Xingcheck[2] == 'f' && Xingcheck[3] == 'o')) { bitridx = (curframe[2] >> 4) & 0x0F; if (bitridx == 0) { fprintf(stdout, "%s is free format (not currently supported)\n",curfilename); fflush(stdout); ok = 0; } else { mpegver = (curframe[1] >> 3) & 0x03; freqidx = (curframe[2] >> 2) & 0x03; bytesinframe = arrbytesinframe[bitridx] + ((curframe[2] >> 1) & 0x01); wrdpntr = curframe + bytesinframe; ok = frameSearch(0); } } frame = 1; if (!maxAmpOnly) { if (ok) { mpegver = (curframe[1] >> 3) & 0x03; freqidx = (curframe[2] >> 2) & 0x03; if (first) { lastfreq = frequency[mpegver][freqidx]; InitGainAnalysis((long)(lastfreq * 1000.0)); analysisError = 0; first = 0; } else { if (frequency[mpegver][freqidx] != lastfreq) { lastfreq = frequency[mpegver][freqidx]; ResetSampleFrequency ((long)(lastfreq * 1000.0)); } } } } else { analysisError = 0; } while (ok) { bitridx = (curframe[2] >> 4) & 0x0F; if (bitridx == 0) { fprintf(stdout,"%s is free format (not currently supported)\n",curfilename); fflush(stdout); ok = 0; } else { mpegver = (curframe[1] >> 3) & 0x03; crcflag = curframe[1] & 0x01; freqidx = (curframe[2] >> 2) & 0x03; bytesinframe = arrbytesinframe[bitridx] + ((curframe[2] >> 1) & 0x01); mode = (curframe[3] >> 6) & 0x03; nchan = (mode == 3) ? 1 : 2; if (inbuffer >= bytesinframe) { lSamp = lsamples; rSamp = rsamples; maxSamp = &maxsample; maxGain = &maxgain; minGain = &mingain; procSamp = 0; if ((tagInfo[mainloop].recalc & AMP_RECALC) || (tagInfo[mainloop].recalc & FULL_RECALC)) { #ifdef WIN32 #ifndef __GNUC__ __try { /* this is the Windows try/catch equivalent for C. If you want this in some other system, you should be able to use the C++ try/catch mechanism. I've tried to keep all of the code plain C, though. This error only occurs with _very_ corrupt mp3s, so I don't know if you'll think it's worth the trouble */ #endif #endif decodeSuccess = decodeMP3(&mp,curframe,bytesinframe,&nprocsamp); #ifdef WIN32 #ifndef __GNUC__ } __except(1) { fprintf(stderr,"Error analyzing %s. This mp3 has some very corrupt data.\n",curfilename); fclose(stdout); fclose(stderr); exit(1); } #endif #endif } else { /* don't need to actually decode frame, just scan for min/max gain values */ decodeSuccess = !MP3_OK; scanFrameGain();//curframe); } if (decodeSuccess == MP3_OK) { if ((!maxAmpOnly)&&(tagInfo[mainloop].recalc & FULL_RECALC)) { if (AnalyzeSamples(lsamples,rsamples,procSamp/nchan,nchan) == GAIN_ANALYSIS_ERROR) { fprintf(stderr,"Error analyzing further samples (max time reached) \n"); analysisError = !0; ok = 0; } } } } if (!analysisError) { wrdpntr = curframe+bytesinframe; ok = frameSearch(0); } if (!QuietMode) { if ( !(++frame % 200)) { reportPercentAnalyzed((int)(((double)(filepos-(inbuffer-(curframe+bytesinframe-buffer))) * 100.0) / gFilesize),gFilesize); } } } } } if (!QuietMode) fprintf(stderr," \r"); if (tagInfo[mainloop].recalc & FULL_RECALC) { if (maxAmpOnly) dBchange = 0; else dBchange = GetTitleGain(); } else { dBchange = tagInfo[mainloop].trackGain; } if (dBchange == GAIN_NOT_ENOUGH_SAMPLES) { fprintf(stdout,"Not enough samples in %s to do analysis\n",argv[mainloop]); fflush(stdout); numFiles--; } else { /* even if skipTag is on, we'll leave this part running just to store the minpeak and maxpeak */ curTag = tagInfo + mainloop; if (!maxAmpOnly) { if ( /* if we don't already have a tagged track gain OR we have it, but it doesn't match */ !curTag->haveTrackGain || (curTag->haveTrackGain && (fabs(dBchange - curTag->trackGain) >= 0.01)) ) { curTag->dirty = !0; curTag->haveTrackGain = 1; curTag->trackGain = dBchange; } } if (!curTag->haveMinMaxGain || /* if minGain or maxGain doesn't match tag */ (curTag->haveMinMaxGain && (curTag->minGain != mingain || curTag->maxGain != maxgain))) { curTag->dirty = !0; curTag->haveMinMaxGain = !0; curTag->minGain = mingain; curTag->maxGain = maxgain; } if (!curTag->haveTrackPeak || (curTag->haveTrackPeak && (fabs(maxsample - (curTag->trackPeak) * 32768.0) >= 3.3))) { curTag->dirty = !0; curTag->haveTrackPeak = !0; curTag->trackPeak = maxsample / 32768.0; } /* the TAG version of the suggested Track Gain should ALWAYS be based on the 89dB standard. So we don't modify the suggested gain change until this point */ dBchange += dBGainMod; dblGainChange = dBchange / (5.0 * log10(2.0)); if (fabs(dblGainChange) - (double)((int)(fabs(dblGainChange))) < 0.5) intGainChange = (int)(dblGainChange); else intGainChange = (int)(dblGainChange) + (dblGainChange < 0 ? -1 : 1); intGainChange += mp3GainMod; if (databaseFormat) { fprintf(stdout,"%s\t%d\t%f\t%f\t%d\t%d\n",argv[mainloop],intGainChange,dBchange,maxsample,maxgain,mingain); fflush(stdout); } if ((!applyTrack)&&(!applyAlbum)) { if (!databaseFormat) { fprintf(stdout,"Recommended \"Track\" dB change: %f\n",dBchange); fprintf(stdout,"Recommended \"Track\" mp3 gain change: %d\n",intGainChange); if (maxsample * (Float_t)(pow(2.0,(double)(intGainChange)/4.0)) > 32767.0) { fprintf(stdout,"WARNING: some clipping may occur with this gain change!\n"); } fprintf(stdout,"Max PCM sample at current gain: %f\n",maxsample); fprintf(stdout,"Max mp3 global gain field: %d\n",maxgain); fprintf(stdout,"Min mp3 global gain field: %d\n",mingain); fprintf(stdout,"\n"); } } else if (applyTrack) { first = !0; /* don't keep track of Album gain */ if (inf) fclose(inf); inf = NULL; goAhead = !0; if (intGainChange == 0) { fprintf(stdout,"No changes to %s are necessary\n",argv[mainloop]); if (!skipTag && tagInfo[mainloop].dirty) { fprintf(stdout,"...but tag needs update: Writing tag information for %s\n",argv[mainloop]); WriteMP3GainTag(argv[mainloop] AACGAIN_ARG(aacInfo[mainloop]), tagInfo + mainloop, fileTags + mainloop, saveTime); } } else { if (autoClip) { int intMaxNoClipGain = (int)(floor(4.0 * log10(32767.0 / maxsample) / log10(2.0))); if (intGainChange > intMaxNoClipGain) { fprintf(stdout,"Applying auto-clipped mp3 gain change of %d to %s\n(Original suggested gain was %d)\n",intMaxNoClipGain,argv[mainloop],intGainChange); intGainChange = intMaxNoClipGain; } } else if (!ignoreClipWarning) { if (maxsample * (Float_t)(pow(2.0,(double)(intGainChange)/4.0)) > 32767.0) { if (queryUserForClipping(argv[mainloop],intGainChange)) { fprintf(stdout,"Applying mp3 gain change of %d to %s...\n",intGainChange,argv[mainloop]); } else { goAhead = 0; } } } if (goAhead) { fprintf(stdout,"Applying mp3 gain change of %d to %s...\n",intGainChange,argv[mainloop]); if (skipTag) { changeGain(argv[mainloop] AACGAIN_ARG(aacH), intGainChange, intGainChange); } else { changeGainAndTag(argv[mainloop] AACGAIN_ARG(aacH), intGainChange,intGainChange, tagInfo + mainloop, fileTags + mainloop); } } else if (!skipTag && tagInfo[mainloop].dirty) { fprintf(stdout,"Writing tag information for %s\n",argv[mainloop]); WriteMP3GainTag(argv[mainloop] AACGAIN_ARG(aacH), tagInfo + mainloop, fileTags + mainloop, saveTime); } } } } } } #ifdef AACGAIN if (!aacH) #endif ExitMP3(&mp); fflush(stderr); fflush(stdout); if (inf) fclose(inf); inf = NULL; } } } if ((numFiles > 0)&&(!applyTrack)&&(!analysisTrack)) { if (albumRecalc & FULL_RECALC) { if (maxAmpOnly) dBchange = 0; else dBchange = GetAlbumGain(); } else { /* the following if-else is for the weird case where someone applies "Album" gain to a single file, but the file doesn't actually have an Album field */ if (tagInfo[fileStart].haveAlbumGain) dBchange = tagInfo[fileStart].albumGain; else dBchange = tagInfo[fileStart].trackGain; } if (dBchange == GAIN_NOT_ENOUGH_SAMPLES) { fprintf(stdout,"Not enough samples in mp3 files to do analysis\n"); fflush(stdout); } else { Float_t maxmaxsample; unsigned char maxmaxgain; unsigned char minmingain; maxmaxsample = 0; maxmaxgain = 0; minmingain = 255; for (mainloop = fileStart; mainloop < argc; mainloop++) { if (fileok[mainloop]) { if (tagInfo[mainloop].trackPeak > maxmaxsample) maxmaxsample = tagInfo[mainloop].trackPeak; if (tagInfo[mainloop].maxGain > maxmaxgain) maxmaxgain = tagInfo[mainloop].maxGain; if (tagInfo[mainloop].minGain < minmingain) minmingain = tagInfo[mainloop].minGain; } } if ((!skipTag)&&(numFiles > 1 || applyAlbum)) { for (mainloop = fileStart; mainloop < argc; mainloop++) { curTag = tagInfo + mainloop; if (!maxAmpOnly) { if ( /* if we don't already have a tagged track gain OR we have it, but it doesn't match */ !curTag->haveAlbumGain || (curTag->haveAlbumGain && (fabs(dBchange - curTag->albumGain) >= 0.01)) ){ curTag->dirty = !0; curTag->haveAlbumGain = 1; curTag->albumGain = dBchange; } } if (!curTag->haveAlbumMinMaxGain || /* if albumMinGain or albumMaxGain doesn't match tag */ (curTag->haveAlbumMinMaxGain && (curTag->albumMinGain != minmingain || curTag->albumMaxGain != maxmaxgain))) { curTag->dirty = !0; curTag->haveAlbumMinMaxGain = !0; curTag->albumMinGain = minmingain; curTag->albumMaxGain = maxmaxgain; } if (!curTag->haveAlbumPeak || (curTag->haveAlbumPeak && (fabs(maxmaxsample - curTag->albumPeak) >= 0.0001))) { curTag->dirty = !0; curTag->haveAlbumPeak = !0; curTag->albumPeak = maxmaxsample; } } } /* the TAG version of the suggested Album Gain should ALWAYS be based on the 89dB standard. So we don't modify the suggested gain change until this point */ dBchange += dBGainMod; dblGainChange = dBchange / (5.0 * log10(2.0)); if (fabs(dblGainChange) - (double)((int)(fabs(dblGainChange))) < 0.5) intGainChange = (int)(dblGainChange); else intGainChange = (int)(dblGainChange) + (dblGainChange < 0 ? -1 : 1); intGainChange += mp3GainMod; if (databaseFormat) { fprintf(stdout,"\"Album\"\t%d\t%f\t%f\t%d\t%d\n",intGainChange,dBchange,maxmaxsample * 32768.0 ,maxmaxgain,minmingain); fflush(stdout); } if (!applyAlbum) { if (!databaseFormat) { fprintf(stdout,"\nRecommended \"Album\" dB change for all files: %f\n",dBchange); fprintf(stdout,"Recommended \"Album\" mp3 gain change for all files: %d\n",intGainChange); for (mainloop = fileStart; mainloop < argc; mainloop++) { if (fileok[mainloop]) if (tagInfo[mainloop].trackPeak * (Float_t)(pow(2.0,(double)(intGainChange)/4.0)) > 1.0) { fprintf(stdout,"WARNING: with this global gain change, some clipping may occur in file %s\n",argv[mainloop]); } } } } else { /*MAA*/ if (autoClip) { /*MAA*/ int intMaxNoClipGain = (int)(floor(-4.0 * log10(maxmaxsample) / log10(2.0))); /*MAA*/ if (intGainChange > intMaxNoClipGain) { /*MAA*/ fprintf(stdout,"Applying auto-clipped mp3 gain change of %d to album\n(Original suggested gain was %d)\n",intMaxNoClipGain,intGainChange); /*MAA*/ intGainChange = intMaxNoClipGain; /*MAA*/ } /*MAA*/ } for (mainloop = fileStart; mainloop < argc; mainloop++) { if (fileok[mainloop]) { goAhead = !0; if (intGainChange == 0) { fprintf(stdout,"\nNo changes to %s are necessary\n",argv[mainloop]); if (!skipTag && tagInfo[mainloop].dirty) { fprintf(stdout,"...but tag needs update: Writing tag information for %s\n",argv[mainloop]); WriteMP3GainTag(argv[mainloop] AACGAIN_ARG(aacInfo[mainloop]), tagInfo + mainloop, fileTags + mainloop, saveTime); } } else { if (!ignoreClipWarning) { if (tagInfo[mainloop].trackPeak * (Float_t)(pow(2.0,(double)(intGainChange)/4.0)) > 1.0) goAhead = queryUserForClipping(argv[mainloop],intGainChange); } if (goAhead) { fprintf(stdout,"Applying mp3 gain change of %d to %s...\n",intGainChange,argv[mainloop]); if (skipTag) { changeGain(argv[mainloop] AACGAIN_ARG(aacInfo[mainloop]), intGainChange, intGainChange); } else { changeGainAndTag(argv[mainloop] AACGAIN_ARG(aacInfo[mainloop]), intGainChange, intGainChange, tagInfo + mainloop, fileTags + mainloop); } } else if (!skipTag && tagInfo[mainloop].dirty) { fprintf(stdout,"Writing tag information for %s\n",argv[mainloop]); WriteMP3GainTag(argv[mainloop] AACGAIN_ARG(aacInfo[mainloop]), tagInfo + mainloop, fileTags + mainloop, saveTime); } } } } } } } /* update file tags */ if ((!applyTrack)&& (!applyAlbum)&& (!directGain)&& (!directSingleChannelGain)&& (!deleteTag)&& (!skipTag)&& (!checkTagOnly)) { /* if we made changes, we already updated the tags */ for (mainloop = fileStart; mainloop < argc; mainloop++) { if (fileok[mainloop]) { if (tagInfo[mainloop].dirty) { WriteMP3GainTag(argv[mainloop] AACGAIN_ARG(aacInfo[mainloop]), tagInfo + mainloop, fileTags + mainloop, saveTime); } } } } free(tagInfo); /* now stored in tagInfo--- free(maxsample); */ free(fileok); /* now stored in tagInfo--- free(maxgain); */ /* now stored in tagInfo--- free(mingain); */ for (mainloop = fileStart; mainloop < argc; mainloop++) { if (fileTags[mainloop].apeTag) { if (fileTags[mainloop].apeTag->otherFields) { free(fileTags[mainloop].apeTag->otherFields); } free(fileTags[mainloop].apeTag); } if (fileTags[mainloop].lyrics3tag) { free(fileTags[mainloop].lyrics3tag); } if (fileTags[mainloop].id31tag) { free(fileTags[mainloop].id31tag); } #ifdef AACGAIN //close any open aac files if (aacInfo[mainloop]) aac_close(aacInfo[mainloop]); #endif } free(fileTags); #ifdef AACGAIN free(aacInfo); #endif fclose(stdout); fclose(stderr); if (gSuccess) return 0; else return 1; } #endif /* asWIN32DLL */ ./lgpl.txt0000644000175000017500000006350007714631703011752 0ustar rizlarizla GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ./mp3gain.h0000644000175000017500000000376111355415423011760 0ustar rizlarizla/* * ReplayGainAnalysis Heder - DLL for Glen Sawyer's MP3GAIN.C source * Copyright (C) 2002 John Zitterkopf (zitt@bigfoot.com) * (http://www.zittware.com) * * These comments must remain intact in all copies of the source code. * * 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 * * This header for VC++5.0 by John Zitterkopf (zitt@bigfoot.com) * -- blame him for nothing. This work evolves as needed. * * V0.0 - jzitt9/4/2002 * * header needed to eliminate 'changeGain' undefined compiler warning */ #ifndef MP3GAIN_H #define MP3GAIN_H #define MP3GAIN_VERSION "1.5.2" /* jzitt: moved from mp3gain.c */ #define M3G_ERR_CANT_MODIFY_FILE -1 #define M3G_ERR_CANT_MAKE_TMP -2 #define M3G_ERR_NOT_ENOUGH_TMP_SPACE -3 #define M3G_ERR_RENAME_TMP -4 #define M3G_ERR_FILEOPEN -5 #define M3G_ERR_READ -6 #define M3G_ERR_WRITE -7 #define M3G_ERR_TAGFORMAT -8 #include "rg_error.h" #ifdef asWIN32DLL void changeGain(char *filename, int leftgainchange, int rightgainchange); #endif int deleteFile(char *filename); int moveFile(char *currentfilename, char *newfilename); typedef enum { storeTime, setStoredTime } timeAction; void passError(MMRESULT lerrnum, int numStrings, ...); /* Get/Set file datetime stamp */ void fileTime(char *filename, timeAction action); #endif ./apetag.c0000644000175000017500000005223611213776015011657 0ustar rizlarizla#include "apetag.h" #include "mp3gain.h" #include "rg_error.h" #include #include #include #include #include #ifdef WIN32 #include #else #include #endif #ifndef WIN32 #define _stricmp strcasecmp #endif /* WIN32 */ int ReadMP3ID3v1Tag(FILE *fi, unsigned char **tagbuff, long *tag_offset) { char tmp[128]; if ( *tag_offset < 128 ) return 0; if ( fseek(fi, *tag_offset - 128,SEEK_SET) ) return 0; if ( fread(tmp, 1, 128, fi) != 128 ) return 0; if ( memcmp (tmp, "TAG", 3) ) return 0; //we have tag, so store it in buffer if (*tagbuff) free(*tagbuff); *tagbuff = (unsigned char *)malloc(128); memcpy(*tagbuff,tmp,128); *tag_offset -= 128; return 1; } /* static int Lyrics3GetNumber5 ( const unsigned char* string ) { return ( string[0] - '0') * 10000 + ( string[1] - '0') * 1000 + ( string[2] - '0') * 100 + ( string[3] - '0') * 10 + ( string[4] - '0') * 1; } */ static int Lyrics3GetNumber6 ( const unsigned char* string ) { return ( string[0] - '0') * 100000 + ( string[1] - '0') * 10000 + ( string[2] - '0') * 1000 + ( string[3] - '0') * 100 + ( string[4] - '0') * 10 + ( string[5] - '0') * 1; } struct Lyrics3TagFooterStruct { unsigned char Length [6]; unsigned char ID [9]; }; struct Lyrics3TagField { unsigned char ID [3]; unsigned char Length [5]; }; // Reads Lyrics3 v2.0 tag static int ReadMP3Lyrics3v2Tag ( FILE *fp, unsigned char **tagbuff, unsigned long *tagSize, unsigned char **id3tagbuff, long *tag_offset ) { int len; struct Lyrics3TagFooterStruct T; char tmpid3[128]; char tmp[11]; long taglen; if ( *tag_offset < 128 ) return 0; if ( fseek (fp, *tag_offset - 128, SEEK_SET) ) return 0; if ( fread (tmpid3, 1, 128, fp) != 128 ) return 0; // check for id3-tag if ( memcmp (tmpid3, "TAG", 3) ) return 0; //if we have id3-tag, put it in the id3tagbuff if (*id3tagbuff) free(*id3tagbuff); *id3tagbuff = (unsigned char *)malloc(128); memcpy(*id3tagbuff,tmpid3,128); if ( fseek (fp, *tag_offset - 128 - sizeof (T), SEEK_SET) ) return 0; if ( fread (&T, 1, sizeof (T), fp) != sizeof (T) ) return 0; // check for lyrics3 v2.00 tag if ( memcmp (T.ID, "LYRICS200", sizeof (T.ID)) ) return 0; len = Lyrics3GetNumber6 (T.Length); if ( fseek (fp, *tag_offset - 128 - (int)sizeof (T) - len, SEEK_SET) ) return 0; if ( fread (tmp, 1, 11, fp) != 11 ) return 0; if ( memcmp (tmp, "LYRICSBEGIN", 11) ) return 0; taglen = 128 + Lyrics3GetNumber6(T.Length) + sizeof(T); *tag_offset -= taglen; if (*tagbuff != NULL) { free(*tagbuff); } *tagbuff = (unsigned char *)malloc(taglen); fseek(fp,*tag_offset,SEEK_SET); fread(*tagbuff,1,taglen,fp); *tagSize = taglen; return 1; } static unsigned long Read_LE_Uint32_unsigned ( const unsigned char* p ) { return ((unsigned long)p[0] << 0) | ((unsigned long)p[1] << 8) | ((unsigned long)p[2] << 16) | ((unsigned long)p[3] << 24); } static unsigned long Read_LE_Uint32 ( const char* p ) {return Read_LE_Uint32_unsigned((const unsigned char*)p);} static void Write_LE_Uint32 ( char* p, const unsigned long value ) { p[0] = (unsigned char) (value >> 0); p[1] = (unsigned char) (value >> 8); p[2] = (unsigned char) (value >> 16); p[3] = (unsigned char) (value >> 24); } enum { MAX_FIELD_SIZE = 1024*1024 //treat bigger fields as errors }; unsigned long strlen_max(const char * ptr, unsigned long max) { unsigned long n = 0; while (ptr[n] && n < max) n++; return n; } // Reads APE v1.0/2.0 tag int ReadMP3APETag ( FILE *fp, struct MP3GainTagInfo *info, struct APETagStruct **apeTag, long *tag_offset ) { unsigned long vsize; unsigned long isize; unsigned long flags; unsigned long remaining; char* buff; char* p; char* value; char* vp; char* end; struct APETagFooterStruct T; unsigned long TagLen; unsigned long TagCount; unsigned long origTagCount, otherFieldsCount; unsigned long curFieldNum; unsigned long Ver; char* name; int is_info; char tmpString[10]; if ( *tag_offset < (long)(sizeof(T)) ) return 0; if ( fseek(fp,*tag_offset - sizeof(T),SEEK_SET) ) return 0; if ( fread (&T, 1, sizeof(T), fp) != sizeof(T) ) return 0; if ( memcmp (T.ID, "APETAGEX", sizeof(T.ID)) ) return 0; Ver = Read_LE_Uint32 (T.Version); if ( (Ver != 1000) && (Ver != 2000) ) return 0; if ( (TagLen = Read_LE_Uint32 (T.Length)) < sizeof (T) ) return 0; if ( fseek (fp, *tag_offset - TagLen, SEEK_SET) ) return 0; buff = (char *)malloc (TagLen); if ( fread (buff, 1, TagLen - sizeof (T), fp) != (TagLen - sizeof (T)) ) { free (buff); return 0; } if (*apeTag) { if ((*apeTag)->otherFields) free((*apeTag)->otherFields); free(*apeTag); } *apeTag = (struct APETagStruct *)malloc(sizeof(struct APETagStruct)); (*apeTag)->haveHeader = 0; (*apeTag)->otherFields = (unsigned char *)malloc(TagLen - sizeof(T)); (*apeTag)->otherFieldsSize = 0; memcpy(&((*apeTag)->footer),&T,sizeof(T)); origTagCount = TagCount = Read_LE_Uint32 (T.TagCount); otherFieldsCount = 0; end = buff + TagLen - sizeof (T); curFieldNum = 0; for ( p = buff; p < end && TagCount--; ) { if (end - p < 8) break; vsize = Read_LE_Uint32 (p); p += 4; flags = Read_LE_Uint32 (p); p += 4; remaining = (unsigned long) (end - p); isize = strlen_max (p, remaining); if (isize >= remaining || vsize > MAX_FIELD_SIZE || isize + 1 + vsize > remaining) break; name = (char*)malloc(isize+1); memcpy(name, p, isize); name[isize] = 0; value = (char*)malloc(vsize+1); memcpy(value, p+isize+1, vsize); value[vsize] = 0; is_info = 0; { if (!_stricmp (name, "REPLAYGAIN_TRACK_GAIN")) { info->haveTrackGain = !0; info->trackGain = atof(value); } else if (!_stricmp(name,"REPLAYGAIN_TRACK_PEAK")) { info->haveTrackPeak = !0; info->trackPeak = atof(value); } else if (!_stricmp(name,"REPLAYGAIN_ALBUM_GAIN")) { info->haveAlbumGain = !0; info->albumGain = atof(value); } else if (!_stricmp(name,"REPLAYGAIN_ALBUM_PEAK")) { info->haveAlbumPeak = !0; info->albumPeak = atof(value); } else if (!_stricmp(name,"MP3GAIN_UNDO")) { /* value should be something like "+003,+003,W" */ info->haveUndo = !0; vp = value; memcpy(tmpString,vp,4); tmpString[4] = '\0'; info->undoLeft = atoi(tmpString); vp = vp + 5; /* skip the comma, too */ memcpy(tmpString,vp,4); tmpString[4] = '\0'; info->undoRight = atoi(tmpString); vp = vp + 5; /* skip the comma, too */ if ((*vp == 'w')||(*vp == 'W')) { info->undoWrap = !0; } else { info->undoWrap = 0; } } else if (!_stricmp(name,"MP3GAIN_MINMAX")) { /* value should be something like "001,153" */ info->haveMinMaxGain = !0; vp = value; memcpy(tmpString,vp,3); tmpString[3] = '\0'; info->minGain = atoi(tmpString); vp = vp + 4; /* skip the comma, too */ memcpy(tmpString,vp,3); tmpString[3] = '\0'; info->maxGain = atoi(tmpString); } else if (!_stricmp(name,"MP3GAIN_ALBUM_MINMAX")) { /* value should be something like "001,153" */ info->haveAlbumMinMaxGain = !0; vp = value; memcpy(tmpString,vp,3); tmpString[3] = '\0'; info->albumMinGain = atoi(tmpString); vp = vp + 4; /* skip the comma, too */ memcpy(tmpString,vp,3); tmpString[3] = '\0'; info->albumMaxGain = atoi(tmpString); } else { memcpy((*apeTag)->otherFields + (*apeTag)->otherFieldsSize, p - 8, 8 + isize + 1 + vsize); (*apeTag)->otherFieldsSize += 8 + isize + 1 + vsize; otherFieldsCount++; } } if ( isize > 0 && vsize > 0 ) { if (is_info) { } else { } } free(value); free(name); p += isize + 1 + vsize; } free (buff); *tag_offset -= TagLen; (*apeTag)->originalTagSize = TagLen; if ( Read_LE_Uint32 (T.Flags) & (1<<31) ) { // Tag contains header *tag_offset -= sizeof (T); fseek (fp, *tag_offset, SEEK_SET); fread (&((*apeTag)->header),1,sizeof(T),fp); (*apeTag)->haveHeader = !0; (*apeTag)->originalTagSize += sizeof(T); } if (otherFieldsCount != origTagCount) { Write_LE_Uint32((*apeTag)->footer.Length, sizeof(T) + (*apeTag)->otherFieldsSize); Write_LE_Uint32((*apeTag)->footer.TagCount, otherFieldsCount); if ((*apeTag)->haveHeader) { Write_LE_Uint32((*apeTag)->header.Length, sizeof(T) + (*apeTag)->otherFieldsSize); Write_LE_Uint32((*apeTag)->header.TagCount, otherFieldsCount); } } return 1; } int truncate_file (char *filename, long truncLength) { #ifdef WIN32 int fh, result; /* Open a file */ if( (fh = _open(filename, _O_RDWR)) != -1 ) { if( ( result = _chsize( fh, truncLength ) ) == 0 ) { _close(fh); return 1; } else { _close(fh); return 0; } } else { return 0; } #else int fd; fd = open(filename, O_RDWR); if (fd < 0) return 0; if (ftruncate(fd, truncLength)) { close(fd); passError( MP3GAIN_UNSPECIFED_ERROR, 3, "Could not truncate ", filename, "\n"); return 0; } close(fd); return 1; #endif } /** * Read gain information from an APE tag. * * Look for an APE tag at the end of the MP3 file, and extract * gain information from it. Any ID3v1 or Lyrics3v2 tags at the end * of the file are read and stored, but not processed. */ int ReadMP3GainAPETag (char *filename, struct MP3GainTagInfo *info, struct FileTagsStruct *fileTags) { FILE *fi; long tag_offset, offs_bk; fi = fopen(filename, "rb"); if (fi == NULL) return 0; fseek(fi, 0, SEEK_END); tag_offset = ftell(fi); fileTags->lyrics3TagSize = 0; do { offs_bk = tag_offset; ReadMP3APETag ( fi, info, &(fileTags->apeTag), &tag_offset ); ReadMP3Lyrics3v2Tag ( fi, &(fileTags->lyrics3tag), &(fileTags->lyrics3TagSize), &(fileTags->id31tag), &tag_offset ); ReadMP3ID3v1Tag ( fi, &(fileTags->id31tag), &tag_offset ); } while ( offs_bk != tag_offset ); fileTags->tagOffset = tag_offset; fclose(fi); return 1; }; /** * (Re-)Write gain information to an APEv2 tag. * * You need to have already called ReadMP3GainTag and filled in the info * and fileTags structures. */ int WriteMP3GainAPETag (char *filename, struct MP3GainTagInfo *info, struct FileTagsStruct *fileTags, int saveTimeStamp) { FILE *outputFile; unsigned long newTagLength; unsigned long newTagCount; char *newFieldData; char *mp3gainTagData; unsigned long mp3gainTagLength; char valueString[100]; struct APETagFooterStruct newFooter; struct APETagFooterStruct newHeader; if (saveTimeStamp) fileTime(filename, storeTime); /* For the new tag, we'll have a footer _AND_ header (whether or not a header was in the original */ newTagLength = sizeof(struct APETagFooterStruct) * 2; newTagCount = 0; mp3gainTagLength = 0; if (fileTags->apeTag) { /* For the new tag, we'll have the non-MP3Gain fields from the original tag */ newTagLength += fileTags->apeTag->otherFieldsSize; newTagCount += Read_LE_Uint32(fileTags->apeTag->footer.TagCount); } if (info->haveAlbumGain) { /* 8 bytes + "REPLAYGAIN_ALBUM_GAIN" + '/0' + "+2.456789 dB" = 42 bytes */ mp3gainTagLength += 42; newTagCount++; } if (info->haveAlbumPeak) { /* 8 bytes + "REPLAYGAIN_ALBUM_PEAK" + '/0' + "1.345678" = 38 bytes */ mp3gainTagLength += 38; newTagCount++; } if (info->haveTrackGain) { /* 8 bytes + "REPLAYGAIN_TRACK_GAIN" + '/0' + "+2.456789 dB" = 42 bytes */ mp3gainTagLength += 42; newTagCount++; } if (info->haveTrackPeak) { /* 8 bytes + "REPLAYGAIN_TRACK_PEAK" + '/0' + "1.345678" = 38 bytes */ mp3gainTagLength += 38; newTagCount++; } if (info->haveMinMaxGain) { /* 8 bytes + "MP3GAIN_MINMAX" + '/0' + "123,123" = 30 bytes */ mp3gainTagLength += 30; newTagCount++; } if (info->haveAlbumMinMaxGain) { /* 8 bytes + "MP3GAIN_ALBUM_MINMAX" + '/0' + "123,123" = 36 bytes */ mp3gainTagLength += 36; newTagCount++; } if (info->haveUndo) { /* 8 bytes + "MP3GAIN_UNDO" + '/0' + "+123,+123,W" = 32 bytes */ mp3gainTagLength += 32; newTagCount++; } newTagLength += mp3gainTagLength; newFieldData = (char *)malloc(newTagLength - (sizeof(newFooter) + sizeof(newHeader))); mp3gainTagData = newFieldData; if (fileTags->apeTag) { /* Check if the new tag will be shorter than the old tag */ if (fileTags->apeTag->originalTagSize > newTagLength) { /* we'll need to truncate the file */ if (!truncate_file(filename, fileTags->tagOffset)) { return 0; } } memcpy(&newFooter,&(fileTags->apeTag->footer),sizeof(newFooter)); Write_LE_Uint32(newFooter.Length, newTagLength - sizeof(newHeader)); Write_LE_Uint32(newFooter.TagCount, newTagCount); if (fileTags->apeTag->haveHeader) { memcpy(&newHeader,&(fileTags->apeTag->header), sizeof(newHeader)); Write_LE_Uint32(newHeader.Length, newTagLength - sizeof(newFooter)); Write_LE_Uint32(newHeader.TagCount, newTagCount); } else { memcpy(newHeader.ID,"APETAGEX",sizeof(newHeader.ID)); Write_LE_Uint32(newHeader.Version,2000); Write_LE_Uint32(newHeader.Length, newTagLength - sizeof(newFooter)); Write_LE_Uint32(newHeader.TagCount,newTagCount); Write_LE_Uint32(newHeader.Flags,1<<31 | 1<<29); /* tag has header, this _is_ the header */ memset(newHeader.Reserved,0,sizeof(newHeader.Reserved)); /* and don't forget to fix the footer so that it now shows that the tag has a header! */ Write_LE_Uint32(newFooter.Flags, Read_LE_Uint32(newFooter.Flags) | 1<<31); } if (fileTags->apeTag->otherFieldsSize) { memcpy(newFieldData, fileTags->apeTag->otherFields, fileTags->apeTag->otherFieldsSize); mp3gainTagData += fileTags->apeTag->otherFieldsSize; } } else { /* we don't already have an APE tag, so create one from scratch */ memcpy(newHeader.ID,"APETAGEX",sizeof(newHeader.ID)); Write_LE_Uint32(newHeader.Version,2000); Write_LE_Uint32(newHeader.Length, newTagLength - sizeof(newFooter)); Write_LE_Uint32(newHeader.TagCount,newTagCount); Write_LE_Uint32(newHeader.Flags,1<<31 | 1<<29); /* tag has header, this _is_ the header */ memset(newHeader.Reserved,0,sizeof(newHeader.Reserved)); memcpy(newFooter.ID,"APETAGEX",sizeof(newFooter.ID)); Write_LE_Uint32(newFooter.Version,2000); Write_LE_Uint32(newFooter.Length, newTagLength - sizeof(newHeader)); Write_LE_Uint32(newFooter.TagCount,newTagCount); Write_LE_Uint32(newFooter.Flags,1<<31); /* tag has header */ memset(newFooter.Reserved,0,sizeof(newFooter.Reserved)); } if (info->haveMinMaxGain) { /* 8 bytes + "MP3GAIN_MINMAX" + '/0' + "123,123" = 30 bytes */ Write_LE_Uint32(mp3gainTagData,7); mp3gainTagData += 4; Write_LE_Uint32(mp3gainTagData,0); mp3gainTagData += 4; strcpy(mp3gainTagData, "MP3GAIN_MINMAX"); mp3gainTagData += 15; sprintf(mp3gainTagData,"%03d", info->minGain); /* write directly to tag buffer, because we'll replace the trailing null char anyhow */ mp3gainTagData[3] = ','; mp3gainTagData += 4; sprintf(valueString,"%03d", info->maxGain); memcpy(mp3gainTagData, valueString, 3); /* DON'T write trailing null char */ mp3gainTagData += 3; } if (info->haveAlbumMinMaxGain) { /* 8 bytes + "MP3GAIN_ALBUM_MINMAX" + '/0' + "123,123" = 36 bytes */ Write_LE_Uint32(mp3gainTagData,7); mp3gainTagData += 4; Write_LE_Uint32(mp3gainTagData,0); mp3gainTagData += 4; strcpy(mp3gainTagData, "MP3GAIN_ALBUM_MINMAX"); mp3gainTagData += 21; sprintf(mp3gainTagData,"%03d", info->albumMinGain); /* write directly to tag buffer, because we'll replace the trailing null char anyhow */ mp3gainTagData[3] = ','; mp3gainTagData += 4; sprintf(valueString,"%03d", info->albumMaxGain); memcpy(mp3gainTagData, valueString, 3); /* DON'T write trailing null char */ mp3gainTagData += 3; } if (info->haveUndo) { /* 8 bytes + "MP3GAIN_UNDO" + '/0' + "+234,+234,W" = 32 bytes */ Write_LE_Uint32(mp3gainTagData,11); mp3gainTagData += 4; Write_LE_Uint32(mp3gainTagData,0); mp3gainTagData += 4; strcpy(mp3gainTagData, "MP3GAIN_UNDO"); mp3gainTagData += 13; sprintf(mp3gainTagData,"%+04d", info->undoLeft); /* write directly to tag buffer, because we'll replace the trailing null char anyhow */ mp3gainTagData[4] = ','; mp3gainTagData += 5; sprintf(mp3gainTagData,"%+04d", info->undoRight); /* write directly to tag buffer, because we'll replace the trailing null char anyhow */ mp3gainTagData[4] = ','; mp3gainTagData += 5; if (info->undoWrap) { *mp3gainTagData = 'W'; } else { *mp3gainTagData = 'N'; } mp3gainTagData++; } if (info->haveTrackGain) { /* 8 bytes + "REPLAYGAIN_TRACK_GAIN" + '/0' + "+2.456789 dB" = 42 bytes */ Write_LE_Uint32(mp3gainTagData,12); mp3gainTagData += 4; Write_LE_Uint32(mp3gainTagData,0); mp3gainTagData += 4; strcpy(mp3gainTagData, "REPLAYGAIN_TRACK_GAIN"); mp3gainTagData += 22; sprintf(valueString,"%-+9.6f", info->trackGain); memcpy(mp3gainTagData, valueString, 9); mp3gainTagData += 9; memcpy(mp3gainTagData, " dB", 3); mp3gainTagData += 3; } if (info->haveTrackPeak) { /* 8 bytes + "REPLAYGAIN_TRACK_PEAK" + '/0' + "1.345678" = 38 bytes */ Write_LE_Uint32(mp3gainTagData,8); mp3gainTagData += 4; Write_LE_Uint32(mp3gainTagData,0); mp3gainTagData += 4; strcpy(mp3gainTagData, "REPLAYGAIN_TRACK_PEAK"); mp3gainTagData += 22; sprintf(valueString,"%-8.6f", info->trackPeak); memcpy(mp3gainTagData, valueString, 8); mp3gainTagData += 8; } if (info->haveAlbumGain) { /* 8 bytes + "REPLAYGAIN_ALBUM_GAIN" + '/0' + "+2.456789 dB" = 42 bytes */ Write_LE_Uint32(mp3gainTagData,12); mp3gainTagData += 4; Write_LE_Uint32(mp3gainTagData,0); mp3gainTagData += 4; strcpy(mp3gainTagData, "REPLAYGAIN_ALBUM_GAIN"); mp3gainTagData += 22; sprintf(valueString,"%-+9.6f", info->albumGain); memcpy(mp3gainTagData, valueString, 9); mp3gainTagData += 9; memcpy(mp3gainTagData, " dB", 3); mp3gainTagData += 3; } if (info->haveAlbumPeak) { /* 8 bytes + "REPLAYGAIN_ALBUM_PEAK" + '/0' + "1.345678" = 38 bytes */ Write_LE_Uint32(mp3gainTagData,8); mp3gainTagData += 4; Write_LE_Uint32(mp3gainTagData,0); mp3gainTagData += 4; strcpy(mp3gainTagData, "REPLAYGAIN_ALBUM_PEAK"); mp3gainTagData += 22; sprintf(valueString,"%-8.6f", info->albumPeak); memcpy(mp3gainTagData, valueString, 8); mp3gainTagData += 8; } outputFile = fopen(filename,"r+b"); if (outputFile == NULL) { passError( MP3GAIN_UNSPECIFED_ERROR, 3, "\nCan't open ", filename, " for modifying\n"); return 0; } fseek(outputFile,fileTags->tagOffset,SEEK_SET); if (newTagCount > 0) { /* write APE tag */ fwrite(&newHeader,1,sizeof(newHeader),outputFile); fwrite(newFieldData, 1, newTagLength - (sizeof(newFooter) + sizeof(newHeader)), outputFile); fwrite(&newFooter,1,sizeof(newFooter),outputFile); } if (fileTags->lyrics3TagSize > 0) { fwrite(fileTags->lyrics3tag, 1, fileTags->lyrics3TagSize, outputFile); } else if (fileTags->id31tag) { //by definition, Lyrics3 tag includes id3 tag, fwrite(fileTags->id31tag, 1, 128, outputFile); //so only write id3 tag alone if } //no Lyrics3 tag fclose(outputFile); if (saveTimeStamp) fileTime(filename,setStoredTime); free(newFieldData); return 1; }; /** * Remove gain information from the APE tag. */ int RemoveMP3GainAPETag (char *filename, int saveTimeStamp) { struct MP3GainTagInfo info; struct FileTagsStruct fileTags; info.dirty = 0; info.haveAlbumGain = 0; info.haveAlbumPeak = 0; info.haveTrackGain = 0; info.haveTrackPeak = 0; info.haveMinMaxGain = 0; info.haveAlbumMinMaxGain = 0; info.haveUndo = 0; fileTags.apeTag = NULL; fileTags.id31tag = NULL; fileTags.lyrics3tag = NULL; fileTags.lyrics3TagSize = 0; ReadMP3GainAPETag(filename, &info, &fileTags); /* if any MP3Gain tags exist, then we're going to change the tag */ if (info.haveAlbumGain || info.haveAlbumPeak || info.haveTrackGain || info.haveTrackPeak || info.haveMinMaxGain || info.haveAlbumMinMaxGain || info.haveUndo) info.dirty = !0; info.haveAlbumGain = 0; info.haveAlbumPeak = 0; info.haveTrackGain = 0; info.haveTrackPeak = 0; info.haveMinMaxGain = 0; info.haveAlbumMinMaxGain = 0; info.haveUndo = 0; if (info.dirty) WriteMP3GainAPETag(filename, &info, &fileTags, saveTimeStamp); return 1; }; ./mpglibDBL/0000755000175000017500000000000011426352075012040 5ustar rizlarizla./mpglibDBL/huffman.h0000644000175000017500000003733007716027257013653 0ustar rizlarizla/* * huffman tables ... recalcualted to work with my optimzed * decoder scheme (MH) * * probably we could save a few bytes of memory, because the * smaller tables are often the part of a bigger table */ struct newhuff { const unsigned int linbits; const short * const table; }; static const short tab0[] = { 0 }; static const short tab1[] = { -5, -3, -1, 17, 1, 16, 0 }; static const short tab2[] = { -15, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 17, -1, 1, 16, 0 }; static const short tab3[] = { -13, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 16, 17, -1, 1, 0 }; static const short tab5[] = { -29, -25, -23, -15, -7, -5, -3, -1, 51, 35, 50, 49, -3, -1, 19, 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, 0 }; static const short tab6[] = { -25, -19, -13, -9, -5, -3, -1, 51, 3, 35, -1, 50, 48, -1, 19, 49, -3, -1, 34, 2, 18, -3, -1, 33, 32, 1, -1, 17, -1, 16, 0 }; static const short tab7[] = { -69, -65, -57, -39, -29, -17, -11, -7, -3, -1, 85, 69, -1, 84, 83, -1, 53, 68, -3, -1, 37, 82, 21, -5, -1, 81, -1, 5, 52, -1, 80, -1, 67, 51, -5, -3, -1, 36, 66, 20, -1, 65, 64, -11, -7, -3, -1, 4, 35, -1, 50, 3, -1, 19, 49, -3, -1, 48, 34, 18, -5, -1, 33, -1, 2, 32, 17, -1, 1, 16, 0 }; static const short tab8[] = { -65, -63, -59, -45, -31, -19, -13, -7, -5, -3, -1, 85, 84, 69, 83, -3, -1, 53, 68, 37, -3, -1, 82, 5, 21, -5, -1, 81, -1, 52, 67, -3, -1, 80, 51, 36, -5, -3, -1, 66, 20, 65, -3, -1, 4, 64, -1, 35, 50, -9, -7, -3, -1, 19, 49, -1, 3, 48, 34, -1, 2, 32, -1, 18, 33, 17, -3, -1, 1, 16, 0 }; static const short tab9[] = { -63, -53, -41, -29, -19, -11, -5, -3, -1, 85, 69, 53, -1, 83, -1, 84, 5, -3, -1, 68, 37, -1, 82, 21, -3, -1, 81, 52, -1, 67, -1, 80, 4, -7, -3, -1, 36, 66, -1, 51, 64, -1, 20, 65, -5, -3, -1, 35, 50, 19, -1, 49, -1, 3, 48, -5, -3, -1, 34, 2, 18, -1, 33, 32, -3, -1, 17, 1, -1, 16, 0 }; static const short tab10[] = { -125,-121,-111, -83, -55, -35, -21, -13, -7, -3, -1, 119, 103, -1, 118, 87, -3, -1, 117, 102, 71, -3, -1, 116, 86, -1, 101, 55, -9, -3, -1, 115, 70, -3, -1, 85, 84, 99, -1, 39, 114, -11, -5, -3, -1, 100, 7, 112, -1, 98, -1, 69, 53, -5, -1, 6, -1, 83, 68, 23, -17, -5, -1, 113, -1, 54, 38, -5, -3, -1, 37, 82, 21, -1, 81, -1, 52, 67, -3, -1, 22, 97, -1, 96, -1, 5, 80, -19, -11, -7, -3, -1, 36, 66, -1, 51, 4, -1, 20, 65, -3, -1, 64, 35, -1, 50, 3, -3, -1, 19, 49, -1, 48, 34, -7, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, 0 }; static const short tab11[] = { -121,-113, -89, -59, -43, -27, -17, -7, -3, -1, 119, 103, -1, 118, 117, -3, -1, 102, 71, -1, 116, -1, 87, 85, -5, -3, -1, 86, 101, 55, -1, 115, 70, -9, -7, -3, -1, 69, 84, -1, 53, 83, 39, -1, 114, -1, 100, 7, -5, -1, 113, -1, 23, 112, -3, -1, 54, 99, -1, 96, -1, 68, 37, -13, -7, -5, -3, -1, 82, 5, 21, 98, -3, -1, 38, 6, 22, -5, -1, 97, -1, 81, 52, -5, -1, 80, -1, 67, 51, -1, 36, 66, -15, -11, -7, -3, -1, 20, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -5, -3, -1, 3, 48, 34, 33, -5, -1, 18, -1, 2, 32, 17, -3, -1, 1, 16, 0 }; static const short tab12[] = { -115, -99, -73, -45, -27, -17, -9, -5, -3, -1, 119, 103, 118, -1, 87, 117, -3, -1, 102, 71, -1, 116, 101, -3, -1, 86, 55, -3, -1, 115, 85, 39, -7, -3, -1, 114, 70, -1, 100, 23, -5, -1, 113, -1, 7, 112, -1, 54, 99, -13, -9, -3, -1, 69, 84, -1, 68, -1, 6, 5, -1, 38, 98, -5, -1, 97, -1, 22, 96, -3, -1, 53, 83, -1, 37, 82, -17, -7, -3, -1, 21, 81, -1, 52, 67, -5, -3, -1, 80, 4, 36, -1, 66, 20, -3, -1, 51, 65, -1, 35, 50, -11, -7, -5, -3, -1, 64, 3, 48, 19, -1, 49, 34, -1, 18, 33, -7, -5, -3, -1, 2, 32, 0, 17, -1, 1, 16 }; static const short tab13[] = { -509,-503,-475,-405,-333,-265,-205,-153,-115, -83, -53, -35, -21, -13, -9, -7, -5, -3, -1, 254, 252, 253, 237, 255, -1, 239, 223, -3, -1, 238, 207, -1, 222, 191, -9, -3, -1, 251, 206, -1, 220, -1, 175, 233, -1, 236, 221, -9, -5, -3, -1, 250, 205, 190, -1, 235, 159, -3, -1, 249, 234, -1, 189, 219, -17, -9, -3, -1, 143, 248, -1, 204, -1, 174, 158, -5, -1, 142, -1, 127, 126, 247, -5, -1, 218, -1, 173, 188, -3, -1, 203, 246, 111, -15, -7, -3, -1, 232, 95, -1, 157, 217, -3, -1, 245, 231, -1, 172, 187, -9, -3, -1, 79, 244, -3, -1, 202, 230, 243, -1, 63, -1, 141, 216, -21, -9, -3, -1, 47, 242, -3, -1, 110, 156, 15, -5, -3, -1, 201, 94, 171, -3, -1, 125, 215, 78, -11, -5, -3, -1, 200, 214, 62, -1, 185, -1, 155, 170, -1, 31, 241, -23, -13, -5, -1, 240, -1, 186, 229, -3, -1, 228, 140, -1, 109, 227, -5, -1, 226, -1, 46, 14, -1, 30, 225, -15, -7, -3, -1, 224, 93, -1, 213, 124, -3, -1, 199, 77, -1, 139, 184, -7, -3, -1, 212, 154, -1, 169, 108, -1, 198, 61, -37, -21, -9, -5, -3, -1, 211, 123, 45, -1, 210, 29, -5, -1, 183, -1, 92, 197, -3, -1, 153, 122, 195, -7, -5, -3, -1, 167, 151, 75, 209, -3, -1, 13, 208, -1, 138, 168, -11, -7, -3, -1, 76, 196, -1, 107, 182, -1, 60, 44, -3, -1, 194, 91, -3, -1, 181, 137, 28, -43, -23, -11, -5, -1, 193, -1, 152, 12, -1, 192, -1, 180, 106, -5, -3, -1, 166, 121, 59, -1, 179, -1, 136, 90, -11, -5, -1, 43, -1, 165, 105, -1, 164, -1, 120, 135, -5, -1, 148, -1, 119, 118, 178, -11, -3, -1, 27, 177, -3, -1, 11, 176, -1, 150, 74, -7, -3, -1, 58, 163, -1, 89, 149, -1, 42, 162, -47, -23, -9, -3, -1, 26, 161, -3, -1, 10, 104, 160, -5, -3, -1, 134, 73, 147, -3, -1, 57, 88, -1, 133, 103, -9, -3, -1, 41, 146, -3, -1, 87, 117, 56, -5, -1, 131, -1, 102, 71, -3, -1, 116, 86, -1, 101, 115, -11, -3, -1, 25, 145, -3, -1, 9, 144, -1, 72, 132, -7, -5, -1, 114, -1, 70, 100, 40, -1, 130, 24, -41, -27, -11, -5, -3, -1, 55, 39, 23, -1, 113, -1, 85, 7, -7, -3, -1, 112, 54, -1, 99, 69, -3, -1, 84, 38, -1, 98, 53, -5, -1, 129, -1, 8, 128, -3, -1, 22, 97, -1, 6, 96, -13, -9, -5, -3, -1, 83, 68, 37, -1, 82, 5, -1, 21, 81, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -19, -11, -5, -1, 65, -1, 4, 64, -3, -1, 35, 50, 19, -3, -1, 49, 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, 0 }; static const short tab15[] = { -495,-445,-355,-263,-183,-115, -77, -43, -27, -13, -7, -3, -1, 255, 239, -1, 254, 223, -1, 238, -1, 253, 207, -7, -3, -1, 252, 222, -1, 237, 191, -1, 251, -1, 206, 236, -7, -3, -1, 221, 175, -1, 250, 190, -3, -1, 235, 205, -1, 220, 159, -15, -7, -3, -1, 249, 234, -1, 189, 219, -3, -1, 143, 248, -1, 204, 158, -7, -3, -1, 233, 127, -1, 247, 173, -3, -1, 218, 188, -1, 111, -1, 174, 15, -19, -11, -3, -1, 203, 246, -3, -1, 142, 232, -1, 95, 157, -3, -1, 245, 126, -1, 231, 172, -9, -3, -1, 202, 187, -3, -1, 217, 141, 79, -3, -1, 244, 63, -1, 243, 216, -33, -17, -9, -3, -1, 230, 47, -1, 242, -1, 110, 240, -3, -1, 31, 241, -1, 156, 201, -7, -3, -1, 94, 171, -1, 186, 229, -3, -1, 125, 215, -1, 78, 228, -15, -7, -3, -1, 140, 200, -1, 62, 109, -3, -1, 214, 227, -1, 155, 185, -7, -3, -1, 46, 170, -1, 226, 30, -5, -1, 225, -1, 14, 224, -1, 93, 213, -45, -25, -13, -7, -3, -1, 124, 199, -1, 77, 139, -1, 212, -1, 184, 154, -7, -3, -1, 169, 108, -1, 198, 61, -1, 211, 210, -9, -5, -3, -1, 45, 13, 29, -1, 123, 183, -5, -1, 209, -1, 92, 208, -1, 197, 138, -17, -7, -3, -1, 168, 76, -1, 196, 107, -5, -1, 182, -1, 153, 12, -1, 60, 195, -9, -3, -1, 122, 167, -1, 166, -1, 192, 11, -1, 194, -1, 44, 91, -55, -29, -15, -7, -3, -1, 181, 28, -1, 137, 152, -3, -1, 193, 75, -1, 180, 106, -5, -3, -1, 59, 121, 179, -3, -1, 151, 136, -1, 43, 90, -11, -5, -1, 178, -1, 165, 27, -1, 177, -1, 176, 105, -7, -3, -1, 150, 74, -1, 164, 120, -3, -1, 135, 58, 163, -17, -7, -3, -1, 89, 149, -1, 42, 162, -3, -1, 26, 161, -3, -1, 10, 160, 104, -7, -3, -1, 134, 73, -1, 148, 57, -5, -1, 147, -1, 119, 9, -1, 88, 133, -53, -29, -13, -7, -3, -1, 41, 103, -1, 118, 146, -1, 145, -1, 25, 144, -7, -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 71, -7, -3, -1, 40, 130, -1, 24, 129, -7, -3, -1, 116, 8, -1, 128, 86, -3, -1, 101, 55, -1, 115, 70, -17, -7, -3, -1, 39, 114, -1, 100, 23, -3, -1, 85, 113, -3, -1, 7, 112, 54, -7, -3, -1, 99, 69, -1, 84, 38, -3, -1, 98, 22, -3, -1, 6, 96, 53, -33, -19, -9, -5, -1, 97, -1, 83, 68, -1, 37, 82, -3, -1, 21, 81, -3, -1, 5, 80, 52, -7, -3, -1, 67, 36, -1, 66, 51, -1, 65, -1, 20, 4, -9, -3, -1, 35, 50, -3, -1, 64, 3, 19, -3, -1, 49, 48, 34, -9, -7, -3, -1, 18, 33, -1, 2, 32, 17, -3, -1, 1, 16, 0 }; static const short tab16[] = { -509,-503,-461,-323,-103, -37, -27, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 175, -1, 250, 159, -3, -1, 249, 248, 143, -7, -3, -1, 127, 247, -1, 111, 246, 255, -9, -5, -3, -1, 95, 245, 79, -1, 244, 243, -53, -1, 240, -1, 63, -29, -19, -13, -7, -5, -1, 206, -1, 236, 221, 222, -1, 233, -1, 234, 217, -1, 238, -1, 237, 235, -3, -1, 190, 205, -3, -1, 220, 219, 174, -11, -5, -1, 204, -1, 173, 218, -3, -1, 126, 172, 202, -5, -3, -1, 201, 125, 94, 189, 242, -93, -5, -3, -1, 47, 15, 31, -1, 241, -49, -25, -13, -5, -1, 158, -1, 188, 203, -3, -1, 142, 232, -1, 157, 231, -7, -3, -1, 187, 141, -1, 216, 110, -1, 230, 156, -13, -7, -3, -1, 171, 186, -1, 229, 215, -1, 78, -1, 228, 140, -3, -1, 200, 62, -1, 109, -1, 214, 155, -19, -11, -5, -3, -1, 185, 170, 225, -1, 212, -1, 184, 169, -5, -1, 123, -1, 183, 208, 227, -7, -3, -1, 14, 224, -1, 93, 213, -3, -1, 124, 199, -1, 77, 139, -75, -45, -27, -13, -7, -3, -1, 154, 108, -1, 198, 61, -3, -1, 92, 197, 13, -7, -3, -1, 138, 168, -1, 153, 76, -3, -1, 182, 122, 60, -11, -5, -3, -1, 91, 137, 28, -1, 192, -1, 152, 121, -1, 226, -1, 46, 30, -15, -7, -3, -1, 211, 45, -1, 210, 209, -5, -1, 59, -1, 151, 136, 29, -7, -3, -1, 196, 107, -1, 195, 167, -1, 44, -1, 194, 181, -23, -13, -7, -3, -1, 193, 12, -1, 75, 180, -3, -1, 106, 166, 179, -5, -3, -1, 90, 165, 43, -1, 178, 27, -13, -5, -1, 177, -1, 11, 176, -3, -1, 105, 150, -1, 74, 164, -5, -3, -1, 120, 135, 163, -3, -1, 58, 89, 42, -97, -57, -33, -19, -11, -5, -3, -1, 149, 104, 161, -3, -1, 134, 119, 148, -5, -3, -1, 73, 87, 103, 162, -5, -1, 26, -1, 10, 160, -3, -1, 57, 147, -1, 88, 133, -9, -3, -1, 41, 146, -3, -1, 118, 9, 25, -5, -1, 145, -1, 144, 72, -3, -1, 132, 117, -1, 56, 131, -21, -11, -5, -3, -1, 102, 40, 130, -3, -1, 71, 116, 24, -3, -1, 129, 128, -3, -1, 8, 86, 55, -9, -5, -1, 115, -1, 101, 70, -1, 39, 114, -5, -3, -1, 100, 85, 7, 23, -23, -13, -5, -1, 113, -1, 112, 54, -3, -1, 99, 69, -1, 84, 38, -3, -1, 98, 22, -1, 97, -1, 6, 96, -9, -5, -1, 83, -1, 53, 68, -1, 37, 82, -1, 81, -1, 21, 5, -33, -23, -13, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -5, -1, 65, -1, 4, 64, -1, 35, 50, -3, -1, 19, 49, -3, -1, 3, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, 0 }; static const short tab24[] = { -451,-117, -43, -25, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 250, -1, 175, 159, -1, 249, 248, -9, -5, -3, -1, 143, 127, 247, -1, 111, 246, -3, -1, 95, 245, -1, 79, 244, -71, -7, -3, -1, 63, 243, -1, 47, 242, -5, -1, 241, -1, 31, 240, -25, -9, -1, 15, -3, -1, 238, 222, -1, 237, 206, -7, -3, -1, 236, 221, -1, 190, 235, -3, -1, 205, 220, -1, 174, 234, -15, -7, -3, -1, 189, 219, -1, 204, 158, -3, -1, 233, 173, -1, 218, 188, -7, -3, -1, 203, 142, -1, 232, 157, -3, -1, 217, 126, -1, 231, 172, 255,-235, -143, -77, -45, -25, -15, -7, -3, -1, 202, 187, -1, 141, 216, -5, -3, -1, 14, 224, 13, 230, -5, -3, -1, 110, 156, 201, -1, 94, 186, -9, -5, -1, 229, -1, 171, 125, -1, 215, 228, -3, -1, 140, 200, -3, -1, 78, 46, 62, -15, -7, -3, -1, 109, 214, -1, 227, 155, -3, -1, 185, 170, -1, 226, 30, -7, -3, -1, 225, 93, -1, 213, 124, -3, -1, 199, 77, -1, 139, 184, -31, -15, -7, -3, -1, 212, 154, -1, 169, 108, -3, -1, 198, 61, -1, 211, 45, -7, -3, -1, 210, 29, -1, 123, 183, -3, -1, 209, 92, -1, 197, 138, -17, -7, -3, -1, 168, 153, -1, 76, 196, -3, -1, 107, 182, -3, -1, 208, 12, 60, -7, -3, -1, 195, 122, -1, 167, 44, -3, -1, 194, 91, -1, 181, 28, -57, -35, -19, -7, -3, -1, 137, 152, -1, 193, 75, -5, -3, -1, 192, 11, 59, -3, -1, 176, 10, 26, -5, -1, 180, -1, 106, 166, -3, -1, 121, 151, -3, -1, 160, 9, 144, -9, -3, -1, 179, 136, -3, -1, 43, 90, 178, -7, -3, -1, 165, 27, -1, 177, 105, -1, 150, 164, -17, -9, -5, -3, -1, 74, 120, 135, -1, 58, 163, -3, -1, 89, 149, -1, 42, 162, -7, -3, -1, 161, 104, -1, 134, 119, -3, -1, 73, 148, -1, 57, 147, -63, -31, -15, -7, -3, -1, 88, 133, -1, 41, 103, -3, -1, 118, 146, -1, 25, 145, -7, -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 40, -17, -7, -3, -1, 130, 24, -1, 71, 116, -5, -1, 129, -1, 8, 128, -1, 86, 101, -7, -5, -1, 23, -1, 7, 112, 115, -3, -1, 55, 39, 114, -15, -7, -3, -1, 70, 100, -1, 85, 113, -3, -1, 54, 99, -1, 69, 84, -7, -3, -1, 38, 98, -1, 22, 97, -5, -3, -1, 6, 96, 53, -1, 83, 68, -51, -37, -23, -15, -9, -3, -1, 37, 82, -1, 21, -1, 5, 80, -1, 81, -1, 52, 67, -3, -1, 36, 66, -1, 51, 20, -9, -5, -1, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -7, -5, -3, -1, 3, 48, 34, 18, -1, 33, -1, 2, 32, -3, -1, 17, 1, -1, 16, 0 }; static const short tab_c0[] = { -29, -21, -13, -7, -3, -1, 11, 15, -1, 13, 14, -3, -1, 7, 5, 9, -3, -1, 6, 3, -1, 10, 12, -3, -1, 2, 1, -1, 4, 8, 0 }; static const short tab_c1[] = { -15, -7, -3, -1, 15, 14, -1, 13, 12, -3, -1, 11, 10, -1, 9, 8, -7, -3, -1, 7, 6, -1, 5, 4, -3, -1, 3, 2, -1, 1, 0 }; static const struct newhuff ht[] = { { /* 0 */ 0 , tab0 } , { /* 2 */ 0 , tab1 } , { /* 3 */ 0 , tab2 } , { /* 3 */ 0 , tab3 } , { /* 0 */ 0 , tab0 } , { /* 4 */ 0 , tab5 } , { /* 4 */ 0 , tab6 } , { /* 6 */ 0 , tab7 } , { /* 6 */ 0 , tab8 } , { /* 6 */ 0 , tab9 } , { /* 8 */ 0 , tab10 } , { /* 8 */ 0 , tab11 } , { /* 8 */ 0 , tab12 } , { /* 16 */ 0 , tab13 } , { /* 0 */ 0 , tab0 } , { /* 16 */ 0 , tab15 } , { /* 16 */ 1 , tab16 } , { /* 16 */ 2 , tab16 } , { /* 16 */ 3 , tab16 } , { /* 16 */ 4 , tab16 } , { /* 16 */ 6 , tab16 } , { /* 16 */ 8 , tab16 } , { /* 16 */ 10, tab16 } , { /* 16 */ 13, tab16 } , { /* 16 */ 4 , tab24 } , { /* 16 */ 5 , tab24 } , { /* 16 */ 6 , tab24 } , { /* 16 */ 7 , tab24 } , { /* 16 */ 8 , tab24 } , { /* 16 */ 9 , tab24 } , { /* 16 */ 11, tab24 } , { /* 16 */ 13, tab24 } }; static const struct newhuff htc[] = { { /* 1 , 1 , */ 0 , tab_c0 } , { /* 1 , 1 , */ 0 , tab_c1 } }; ./mpglibDBL/l2tables.h0000644000175000017500000002045607451136440013727 0ustar rizlarizla/* * Layer 2 Alloc tables .. * most other tables are calculated on program start (which is (of course) * not ISO-conform) .. * Layer-3 huffman table is in huffman.h */ const struct al_table2 alloc_0[] = { {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767} }; const struct al_table2 alloc_1[] = { {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{3,-3},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255},{10,-511}, {11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {3,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767}, {2,0},{5,3},{7,5},{16,-32767} }; const struct al_table2 alloc_2[] = { {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; const struct al_table2 alloc_3[] = { {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, {4,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127},{9,-255}, {10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191},{15,-16383}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63} }; const struct al_table2 alloc_4[] = { {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, {4,0},{5,3},{7,5},{3,-3},{10,9},{4,-7},{5,-15},{6,-31},{7,-63},{8,-127}, {9,-255},{10,-511},{11,-1023},{12,-2047},{13,-4095},{14,-8191}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {3,0},{5,3},{7,5},{10,9},{4,-7},{5,-15},{6,-31},{7,-63}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9}, {2,0},{5,3},{7,5},{10,9} }; ./mpglibDBL/bitstream.h0000644000175000017500000000262707716027257014222 0ustar rizlarizla/* * MP3 bitstream Output interface for LAME * * Copyright (c) 1999 Takehiro TOMINAGA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. */ #ifndef LAME_BITSTREAM_H #define LAME_BITSTREAM_H #include "util.h" int format_bitstream(lame_global_flags *gfp, int i, int l3_enc[2][2][576], III_scalefac_t scalefac[2][2] ); void flush_bitstream(lame_global_flags *gfp); void add_dummy_byte ( lame_global_flags* const gfp, unsigned char val ); int copy_buffer(unsigned char *buffer,int buffer_size,Bit_stream_struc *bs); void init_bit_stream_w(lame_internal_flags *gfc); void CRC_writeheader (lame_internal_flags *gfc, char *buffer); int compute_flushbits(const lame_global_flags *gfp, int *nbytes); #endif ./mpglibDBL/layer1.c0000644000175000017500000001032407451136440013400 0ustar rizlarizla/* * Mpeg Layer-1 audio decoder * -------------------------- * copyright (c) 1995 by Michael Hipp, All rights reserved. See also 'README' * near unoptimzed ... * * may have a few bugs after last optimization ... * */ /* $Id: layer1.c,v 1.1 2002/03/29 19:14:40 snelg Exp $ */ #ifdef HAVE_CONFIG_H # include #endif #ifdef USE_LAYER_1 #include #include "common.h" #include "decode_i386.h" #ifdef WITH_DMALLOC #include #endif void I_step_one(unsigned int balloc[], unsigned int scale_index[2][SBLIMIT],struct frame *fr) { unsigned int *ba=balloc; unsigned int *sca = (unsigned int *) scale_index; assert ( fr->stereo == 0 || fr->stereo == 1 ); if(fr->stereo) { int i; int jsbound = fr->jsbound; for (i=0;istereo == 0 || fr->stereo == 1 ); if(fr->stereo) { int jsbound = fr->jsbound; register real *f0 = fraction[0]; register real *f1 = fraction[1]; ba = balloc; for (sample=smpb,i=0;idown_sample_sblimit;i<32;i++) fraction[0][i] = fraction[1][i] = 0.0; } else { register real *f0 = fraction[0]; ba = balloc; for (sample=smpb,i=0;idown_sample_sblimit;i<32;i++) fraction[0][i] = 0.0; } } //int do_layer1(struct frame *fr,int outmode,struct audio_info_struct *ai) int do_layer1(PMPSTR mp, unsigned char *pcm_sample,int *pcm_point) { int clip=0; unsigned int balloc[2*SBLIMIT]; unsigned int scale_index[2][SBLIMIT]; real fraction[2][SBLIMIT]; struct frame *fr=&(mp->fr); int i,stereo = fr->stereo; int single = fr->single; fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext<<2)+4 : 32; if(stereo == 1 || single == 3) single = 0; I_step_one(balloc,scale_index,fr); for (i=0;i= 0) { clip += synth_1to1_mono( mp, (real *) fraction[single],pcm_sample,pcm_point); } else { int p1 = *pcm_point; clip += synth_1to1( mp, (real *) fraction[0],0,pcm_sample,&p1); clip += synth_1to1( mp, (real *) fraction[1],1,pcm_sample,pcm_point); } } return clip; } #endif ./mpglibDBL/mpg123.h0000644000175000017500000000511007714631704013223 0ustar rizlarizla#ifndef MPG123_H_INCLUDED #define MPG123_H_INCLUDED #include #ifdef STDC_HEADERS # include #else /*# ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr (), *strrchr (); */ # ifndef HAVE_MEMCPY # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define memmove(d, s, n) bcopy ((s), (d), (n)) # endif #endif #include #if defined(__riscos__) && defined(FPA10) #include "ymath.h" #else #include #endif #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #ifdef REAL_IS_FLOAT # define real float #elif defined(REAL_IS_LONG_DOUBLE) # define real long double #else # define real double #endif #define FALSE 0 #define TRUE 1 #define SBLIMIT 32 #define SSLIMIT 18 #define MPG_MD_STEREO 0 #define MPG_MD_JOINT_STEREO 1 #define MPG_MD_DUAL_CHANNEL 2 #define MPG_MD_MONO 3 #define MAXFRAMESIZE 1792 /* AF: ADDED FOR LAYER1/LAYER2 */ #define SCALE_BLOCK 12 /* Pre Shift fo 16 to 8 bit converter table */ #define AUSHIFT (3) struct frame { int stereo; int jsbound; int single; int lsf; int mpeg25; int header_change; int lay; int error_protection; int bitrate_index; int sampling_frequency; int padding; int extension; int mode; int mode_ext; int copyright; int original; int emphasis; int framesize; /* computed framesize */ /* AF: ADDED FOR LAYER1/LAYER2 */ #if defined(USE_LAYER_2) || defined(USE_LAYER_1) int II_sblimit; struct al_table2 *alloc; int down_sample_sblimit; int down_sample; #endif }; struct gr_info_s { int scfsi; unsigned part2_3_length; unsigned big_values; unsigned scalefac_compress; unsigned block_type; unsigned mixed_block_flag; unsigned table_select[3]; unsigned subblock_gain[3]; unsigned maxband[3]; unsigned maxbandl; unsigned maxb; unsigned region1start; unsigned region2start; unsigned preflag; unsigned scalefac_scale; unsigned count1table_select; real *full_gain[3]; real *pow2gain; }; struct III_sideinfo { unsigned main_data_begin; unsigned private_bits; struct { struct gr_info_s gr[2]; } ch[2]; }; #endif ./mpglibDBL/mpglib.h0000644000175000017500000000236107714631704013471 0ustar rizlarizla#include "encoder.h" struct buf { unsigned char *pnt; long size; long pos; struct buf *next; struct buf *prev; }; struct framebuf { struct buf *buf; long pos; struct frame *next; struct frame *prev; }; typedef struct mpstr_tag { struct buf *head,*tail; int vbr_header; /* 1 if valid Xing vbr header detected */ int num_frames; /* set if vbr header present */ int header_parsed; int side_parsed; int data_parsed; int free_format; /* 1 = free format frame */ int old_free_format; /* 1 = last frame was free format */ int bsize; int framesize; int ssize; int dsize; int fsizeold; int fsizeold_nopadding; struct frame fr; unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */ real hybrid_block[2][2][SBLIMIT*SSLIMIT]; int hybrid_blc[2]; unsigned long header; int bsnum; real synth_buffs[2][2][0x110]; int synth_bo; int sync_bitstream; } MPSTR, *PMPSTR; #if ( defined(_MSC_VER) || defined(__BORLANDC__) ) typedef int BOOL; /* windef.h contains the same definition */ #else #define BOOL int #endif #define MP3_ERR -1 #define MP3_OK 0 #define MP3_NEED_MORE 1 ./mpglibDBL/decode_i386.c0000644000175000017500000001420707716027257014214 0ustar rizlarizla/* * Mpeg Layer-1,2,3 audio decoder * ------------------------------ * copyright (c) 1995,1996,1997 by Michael Hipp, All rights reserved. * See also 'README' * * slighlty optimized for machines without autoincrement/decrement. * The performance is highly compiler dependend. Maybe * the decode.c version for 'normal' processor may be faster * even for Intel processors. */ /* $Id: decode_i386.c,v 1.3 2003/08/12 00:02:55 snelg Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #ifdef STDC_HEADERS # include # include #else /*# ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr (), *strrchr (); */ # ifndef HAVE_MEMCPY # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define memmove(d, s, n) bcopy ((s), (d), (n)) # endif #endif #if defined(__riscos__) && defined(FPA10) #include "ymath.h" #else #include #endif #include "decode_i386.h" #include "dct64_i386.h" #include "tabinit.h" #include "interface.h" #ifdef WITH_DMALLOC #include #endif Float_t *lSamp; Float_t *rSamp; Float_t *maxSamp; unsigned char maxAmpOnly; int procSamp; int synth_1to1_mono(PMPSTR mp, real *bandPtr,int *pnt) { int ret; int pnt1 = 0; ret = synth_1to1(mp,bandPtr,0,&pnt1); *pnt += 64; return ret; } int synth_1to1(PMPSTR mp, real *bandPtr,int channel,int *pnt) { /* static const int step = 2; */ int bo; Float_t *dsamp; real mSamp = 0; real *b0,(*buf)[0x110]; int clip = 0; int bo1; bo = mp->synth_bo; if(!channel) { dsamp = lSamp; bo--; bo &= 0xf; buf = mp->synth_buffs[0]; } else { dsamp = rSamp; buf = mp->synth_buffs[1]; } if(bo & 0x1) { b0 = buf[0]; bo1 = bo; dct64(buf[1]+((bo+1)&0xf),buf[0]+bo,bandPtr); } else { b0 = buf[1]; bo1 = bo+1; dct64(buf[0]+bo,buf[1]+bo+1,bandPtr); } mp->synth_bo = bo; if (maxAmpOnly) { { register int j; real *window = decwin + 16 - bo1; for (j=16;j;j--,b0+=0x10,window+=0x20) { real sum; sum = window[0x0] * b0[0x0]; sum -= window[0x1] * b0[0x1]; sum += window[0x2] * b0[0x2]; sum -= window[0x3] * b0[0x3]; sum += window[0x4] * b0[0x4]; sum -= window[0x5] * b0[0x5]; sum += window[0x6] * b0[0x6]; sum -= window[0x7] * b0[0x7]; sum += window[0x8] * b0[0x8]; sum -= window[0x9] * b0[0x9]; sum += window[0xA] * b0[0xA]; sum -= window[0xB] * b0[0xB]; sum += window[0xC] * b0[0xC]; sum -= window[0xD] * b0[0xD]; sum += window[0xE] * b0[0xE]; sum -= window[0xF] * b0[0xF]; if (sum > mSamp) { mSamp = sum; } else if ((-sum) > mSamp) { mSamp = (-sum); } } { real sum; sum = window[0x0] * b0[0x0]; sum += window[0x2] * b0[0x2]; sum += window[0x4] * b0[0x4]; sum += window[0x6] * b0[0x6]; sum += window[0x8] * b0[0x8]; sum += window[0xA] * b0[0xA]; sum += window[0xC] * b0[0xC]; sum += window[0xE] * b0[0xE]; if (sum > mSamp) { mSamp = sum; } else if ((-sum) > mSamp) { mSamp = (-sum); } b0-=0x10,window-=0x20; } window += bo1<<1; for (j=15;j;j--,b0-=0x10,window-=0x20) { real sum; sum = -window[-0x1] * b0[0x0]; sum -= window[-0x2] * b0[0x1]; sum -= window[-0x3] * b0[0x2]; sum -= window[-0x4] * b0[0x3]; sum -= window[-0x5] * b0[0x4]; sum -= window[-0x6] * b0[0x5]; sum -= window[-0x7] * b0[0x6]; sum -= window[-0x8] * b0[0x7]; sum -= window[-0x9] * b0[0x8]; sum -= window[-0xA] * b0[0x9]; sum -= window[-0xB] * b0[0xA]; sum -= window[-0xC] * b0[0xB]; sum -= window[-0xD] * b0[0xC]; sum -= window[-0xE] * b0[0xD]; sum -= window[-0xF] * b0[0xE]; sum -= window[-0x0] * b0[0xF]; if (sum > mSamp) { mSamp = sum; } else if ((-sum) > mSamp) { mSamp = (-sum); } } } } else { { register int j; real *window = decwin + 16 - bo1; for (j=16;j;j--,b0+=0x10,window+=0x20) { real sum; sum = window[0x0] * b0[0x0]; sum -= window[0x1] * b0[0x1]; sum += window[0x2] * b0[0x2]; sum -= window[0x3] * b0[0x3]; sum += window[0x4] * b0[0x4]; sum -= window[0x5] * b0[0x5]; sum += window[0x6] * b0[0x6]; sum -= window[0x7] * b0[0x7]; sum += window[0x8] * b0[0x8]; sum -= window[0x9] * b0[0x9]; sum += window[0xA] * b0[0xA]; sum -= window[0xB] * b0[0xB]; sum += window[0xC] * b0[0xC]; sum -= window[0xD] * b0[0xD]; sum += window[0xE] * b0[0xE]; sum -= window[0xF] * b0[0xF]; *dsamp++ = (Float_t)sum; procSamp++; if (sum > mSamp) { mSamp = sum; } else if ((-sum) > mSamp) { mSamp = (-sum); } } { real sum; sum = window[0x0] * b0[0x0]; sum += window[0x2] * b0[0x2]; sum += window[0x4] * b0[0x4]; sum += window[0x6] * b0[0x6]; sum += window[0x8] * b0[0x8]; sum += window[0xA] * b0[0xA]; sum += window[0xC] * b0[0xC]; sum += window[0xE] * b0[0xE]; *dsamp++ = (Float_t)sum; procSamp++; if (sum > mSamp) { mSamp = sum; } else if ((-sum) > mSamp) { mSamp = (-sum); } b0-=0x10,window-=0x20; } window += bo1<<1; for (j=15;j;j--,b0-=0x10,window-=0x20) { real sum; sum = -window[-0x1] * b0[0x0]; sum -= window[-0x2] * b0[0x1]; sum -= window[-0x3] * b0[0x2]; sum -= window[-0x4] * b0[0x3]; sum -= window[-0x5] * b0[0x4]; sum -= window[-0x6] * b0[0x5]; sum -= window[-0x7] * b0[0x6]; sum -= window[-0x8] * b0[0x7]; sum -= window[-0x9] * b0[0x8]; sum -= window[-0xA] * b0[0x9]; sum -= window[-0xB] * b0[0xA]; sum -= window[-0xC] * b0[0xB]; sum -= window[-0xD] * b0[0xC]; sum -= window[-0xE] * b0[0xD]; sum -= window[-0xF] * b0[0xE]; sum -= window[-0x0] * b0[0xF]; *dsamp++ = (Float_t)sum; procSamp++; if (sum > mSamp) { mSamp = sum; } else if ((-sum) > mSamp) { mSamp = (-sum); } } } } *pnt += 128; if ((Float_t)mSamp > *maxSamp) *maxSamp = mSamp; if (!channel) lSamp = dsamp; else rSamp = dsamp; return clip; } ./mpglibDBL/machine.h0000644000175000017500000000741407714631704013627 0ustar rizlarizla/* * Machine dependent defines/includes for LAME. * * Copyright (c) 1999 A.L. Faber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. */ #ifndef LAME_MACHINE_H #define LAME_MACHINE_H #include #ifdef STDC_HEADERS # include # include #else /*# ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr (), *strrchr (); */ # ifndef HAVE_MEMCPY # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define memmove(d, s, n) bcopy ((s), (d), (n)) # endif #endif #if defined(__riscos__) && defined(FPA10) # include "ymath.h" #else # include #endif #include #ifdef HAVE_ERRNO_H # include #endif #ifdef HAVE_FCNTL_H # include #endif #if defined(macintosh) # include # include #else # include # include #endif /* * 3 different types of pow() functions: * - table lookup * - pow() * - exp() on some machines this is claimed to be faster than pow() */ #define POW20(x) pow20[x] //#define POW20(x) pow(2.0,((double)(x)-210)*.25) //#define POW20(x) exp( ((double)(x)-210)*(.25*LOG2) ) #define IPOW20(x) ipow20[x] //#define IPOW20(x) exp( -((double)(x)-210)*.1875*LOG2 ) //#define IPOW20(x) pow(2.0,-((double)(x)-210)*.1875) /* in case this is used without configure */ #ifndef inline # define inline #endif /* compatibility */ #define INLINE inline #if defined(_MSC_VER) # undef inline # define inline _inline #elif defined(__SASC) || defined(__GNUC__) /* if __GNUC__ we always want to inline, not only if the user requests it */ # undef inline # define inline __inline #endif #if defined(_MSC_VER) # pragma warning( disable : 4244 ) //# pragma warning( disable : 4305 ) #endif /* * FLOAT for variables which require at least 32 bits * FLOAT8 for variables which require at least 64 bits * * On some machines, 64 bit will be faster than 32 bit. Also, some math * routines require 64 bit float, so setting FLOAT=float will result in a * lot of conversions. */ #if ( defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) ) # define WIN32_LEAN_AND_MEAN # include #else # ifndef FLOAT typedef float FLOAT; # ifdef FLT_MAX # define FLOAT_MAX FLT_MAX # else # define FLOAT_MAX 1e99 /* approx */ # endif # endif #endif #ifndef FLOAT8 /* NOTE: RH: 7/00: if FLOAT8=float, it breaks resampling and VBR code */ typedef double FLOAT8; # ifdef DBL_MAX # define FLOAT8_MAX DBL_MAX # else # define FLOAT8_MAX 1e99 /* approx */ # endif #else # ifdef FLT_MAX # define FLOAT8_MAX FLT_MAX # else # define FLOAT8_MAX 1e99 /* approx */ # endif #endif /* Various integer types */ #if defined _WIN32 && !defined __CYGWIN__ typedef unsigned char u_char; #elif defined __DECALPHA__ // do nothing #elif defined OS_AMIGAOS // do nothing #elif defined __DJGPP__ typedef unsigned char u_char; #elif !defined __GNUC__ || defined __STRICT_ANSI__ typedef unsigned char u_char; #else // do nothing #endif /* sample_t must be floating point, at least 32 bits */ typedef FLOAT sample_t; typedef sample_t stereo_t [2]; #endif /* end of machine.h */ ./mpglibDBL/encoder.h0000644000175000017500000000652407716027257013647 0ustar rizlarizla/* * encoder.h include file * * Copyright (c) 2000 Mark Taylor * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. */ #ifndef LAME_ENCODER_H #define LAME_ENCODER_H /*********************************************************************** * * encoder and decoder delays * ***********************************************************************/ /* * layer III enc->dec delay: 1056 (1057?) (observed) * layer II enc->dec delay: 480 (481?) (observed) * * polyphase 256-16 (dec or enc) = 240 * mdct 256+32 (9*32) (dec or enc) = 288 * total: 512+16 * * My guess is that delay of polyphase filterbank is actualy 240.5 * (there are technical reasons for this, see postings in mp3encoder). * So total Encode+Decode delay = ENCDELAY + 528 + 1 */ /* * ENCDELAY The encoder delay. * * Minimum allowed is MDCTDELAY (see below) * * The first 96 samples will be attenuated, so using a value less than 96 * will result in corrupt data for the first 96-ENCDELAY samples. * * suggested: 576 * set to 1160 to sync with FhG. */ #define ENCDELAY 576 #define POSTDELAY 288 /* * delay of the MDCT used in mdct.c * original ISO routines had a delay of 528! * Takehiro's routines: */ #define MDCTDELAY 48 #define FFTOFFSET (224+MDCTDELAY) /* * Most decoders, including the one we use, have a delay of 528 samples. */ #define DECDELAY 528 /* number of subbands */ #define SBLIMIT 32 /* parition bands bands */ #define CBANDS 64 /* number of critical bands/scale factor bands where masking is computed*/ #define SBPSY_l 21 #define SBPSY_s 12 /* total number of scalefactor bands encoded */ #define SBMAX_l 22 #define SBMAX_s 13 /* FFT sizes */ #define BLKSIZE 1024 #define HBLKSIZE (BLKSIZE/2 + 1) #define BLKSIZE_s 256 #define HBLKSIZE_s (BLKSIZE_s/2 + 1) /* #define switch_pe 1800 */ #define NORM_TYPE 0 #define START_TYPE 1 #define SHORT_TYPE 2 #define STOP_TYPE 3 /* * Mode Extention: * When we are in stereo mode, there are 4 possible methods to store these * two channels. The stereo modes -m? are using a subset of them. * * -ms: MPG_MD_LR_LR * -mj: MPG_MD_LR_LR and MPG_MD_MS_LR * -mf: MPG_MD_MS_LR * -mi: all */ #define MPG_MD_LR_LR 0 #define MPG_MD_LR_I 1 #define MPG_MD_MS_LR 2 #define MPG_MD_MS_I 3 #include "machine.h" #include "lame.h" int lame_encode_mp3_frame ( lame_global_flags* const gfp, sample_t* inbuf_l, sample_t* inbuf_r, unsigned char* mp3buf, int mp3buf_size ); #endif /* LAME_ENCODER_H */ ./mpglibDBL/lame.h0000644000175000017500000007644207716027257013154 0ustar rizlarizla/* * Interface to MP3 LAME encoding engine * * Copyright (c) 1999 Mark Taylor * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* $Id: lame.h,v 1.2 2003/08/12 00:02:55 snelg Exp $ */ #ifndef LAME_LAME_H #define LAME_LAME_H #include #include #if defined(__cplusplus) extern "C" { #endif #if defined(WIN32) #undef CDECL #define CDECL _cdecl #else #define CDECL #endif typedef enum vbr_mode_e { vbr_off=0, vbr_mt, vbr_rh, vbr_abr, vbr_mtrh, vbr_max_indicator, /* Don't use this! It's used for sanity checks. */ vbr_default=vbr_rh /* change this to change the default VBR mode of LAME */ } vbr_mode; /* MPEG modes */ typedef enum MPEG_mode_e { STEREO = 0, JOINT_STEREO, DUAL_CHANNEL, /* LAME doesn't supports this! */ MONO, NOT_SET, MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ } MPEG_mode; /* Padding types */ typedef enum Padding_type_e { PAD_NO = 0, PAD_ALL, PAD_ADJUST, PAD_MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ } Padding_type; struct lame_global_struct; typedef struct lame_global_struct lame_global_flags; typedef lame_global_flags *lame_t; /*********************************************************************** * * The LAME API * These functions should be called, in this order, for each * MP3 file to be encoded * ***********************************************************************/ /* * REQUIRED: * initialize the encoder. sets default for all encoder paramters, * returns -1 if some malloc()'s failed * otherwise returns 0 */ lame_global_flags * CDECL lame_init(void); /* obsolete version */ int CDECL lame_init_old(lame_global_flags *); /* * OPTIONAL: * set as needed to override defaults */ /******************************************************************** * input stream description ***********************************************************************/ // number of samples. default = 2^32-1 int CDECL lame_set_num_samples(lame_global_flags *, unsigned long); unsigned long CDECL lame_get_num_samples(const lame_global_flags *); // input sample rate in Hz. default = 44100hz int CDECL lame_set_in_samplerate(lame_global_flags *, int); int CDECL lame_get_in_samplerate(const lame_global_flags *); // number of channels in input stream. default=2 int CDECL lame_set_num_channels(lame_global_flags *, int); int CDECL lame_get_num_channels(const lame_global_flags *); // scale the input by this amount before encoding. default=0 (disabled) // (not used by decoding routines) int CDECL lame_set_scale(lame_global_flags *, float); float CDECL lame_get_scale(const lame_global_flags *); // output sample rate in Hz. default = 0, which means LAME picks best value // based on the amount of compression. MPEG only allows: // MPEG1 32, 44.1, 48khz // MPEG2 16, 22.05, 24 // MPEG2.5 8, 11.025, 12 // (not used by decoding routines) int CDECL lame_set_out_samplerate(lame_global_flags *, int); int CDECL lame_get_out_samplerate(const lame_global_flags *); /******************************************************************** * general control parameters ***********************************************************************/ // 1=cause LAME to collect data for an MP3 frame analzyer. default=0 int CDECL lame_set_analysis(lame_global_flags *, int); int CDECL lame_get_analysis(const lame_global_flags *); // 1 = write a Xing VBR header frame. // default = 1 for VBR/ABR modes, 0 for CBR mode // this variable must have been added by a Hungarian notation Windows programmer :-) int CDECL lame_set_bWriteVbrTag(lame_global_flags *, int); int CDECL lame_get_bWriteVbrTag(const lame_global_flags *); // 1=decode only. use lame/mpglib to convert mp3/ogg to wav. default=0 int CDECL lame_set_decode_only(lame_global_flags *, int); int CDECL lame_get_decode_only(const lame_global_flags *); // 1=encode a Vorbis .ogg file. default=0 int CDECL lame_set_ogg(lame_global_flags *, int); int CDECL lame_get_ogg(const lame_global_flags *); // internal algorithm selection. True quality is determined by the bitrate // but this variable will effect quality by selecting expensive or cheap algorithms. // quality=0..9. 0=best (very slow). 9=worst. // recommended: 2 near-best quality, not too slow // 5 good quality, fast // 7 ok quality, really fast int CDECL lame_set_quality(lame_global_flags *, int); int CDECL lame_get_quality(const lame_global_flags *); // mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono // default: lame picks based on compression ration and input channels int CDECL lame_set_mode(lame_global_flags *, MPEG_mode); MPEG_mode CDECL lame_get_mode(const lame_global_flags *); // mode_automs. Us a M/S mode with a switching threshold based on // compression ratio // default = 0 (disabled) int CDECL lame_set_mode_automs(lame_global_flags *, int); int CDECL lame_get_mode_automs(const lame_global_flags *); // force_ms. Force M/S for all frames. For testing only. // default = 0 (disabled) int CDECL lame_set_force_ms(lame_global_flags *, int); int CDECL lame_get_force_ms(const lame_global_flags *); // use free_format? default = 0 (disabled) int CDECL lame_set_free_format(lame_global_flags *, int); int CDECL lame_get_free_format(const lame_global_flags *); /* * OPTIONAL: * Set printf like error/debug/message reporting functions. * The second argument has to be a pointer to a function which looks like * void my_debugf(const char *format, va_list ap) * { * (void) vfprintf(stdout, format, ap); * } * If you use NULL as the value of the pointer in the set function, the * lame buildin function will be used (prints to stderr). * To quiet any output you have to replace the body of the example function * with just "return;" and use it in the set function. */ int CDECL lame_set_errorf(lame_global_flags *, void (*func)(const char *, va_list)); int CDECL lame_set_debugf(lame_global_flags *, void (*func)(const char *, va_list)); int CDECL lame_set_msgf (lame_global_flags *, void (*func)(const char *, va_list)); /* set one of brate compression ratio. default is compression ratio of 11. */ int CDECL lame_set_brate(lame_global_flags *, int); int CDECL lame_get_brate(const lame_global_flags *); int CDECL lame_set_compression_ratio(lame_global_flags *, float); float CDECL lame_get_compression_ratio(const lame_global_flags *); /******************************************************************** * frame params ***********************************************************************/ // mark as copyright. default=0 int CDECL lame_set_copyright(lame_global_flags *, int); int CDECL lame_get_copyright(const lame_global_flags *); // mark as original. default=1 int CDECL lame_set_original(lame_global_flags *, int); int CDECL lame_get_original(const lame_global_flags *); // error_protection. Use 2 bytes from each fraome for CRC checksum. default=0 int CDECL lame_set_error_protection(lame_global_flags *, int); int CDECL lame_get_error_protection(const lame_global_flags *); // padding_type. 0=pad no frames 1=pad all frames 2=adjust padding(default) int CDECL lame_set_padding_type(lame_global_flags *, Padding_type); Padding_type CDECL lame_get_padding_type(const lame_global_flags *); // MP3 'private extension' bit Meaningless int CDECL lame_set_extension(lame_global_flags *, int); int CDECL lame_get_extension(const lame_global_flags *); // enforce strict ISO complience. default=0 int CDECL lame_set_strict_ISO(lame_global_flags *, int); int CDECL lame_get_strict_ISO(const lame_global_flags *); /******************************************************************** * quantization/noise shaping ***********************************************************************/ // disable the bit reservoir. For testing only. default=0 int CDECL lame_set_disable_reservoir(lame_global_flags *, int); int CDECL lame_get_disable_reservoir(const lame_global_flags *); // select a different "best quantization" function. default=0 int CDECL lame_set_experimentalX(lame_global_flags *, int); int CDECL lame_get_experimentalX(const lame_global_flags *); // another experimental option. for testing only int CDECL lame_set_experimentalY(lame_global_flags *, int); int CDECL lame_get_experimentalY(const lame_global_flags *); // another experimental option. for testing only int CDECL lame_set_experimentalZ(lame_global_flags *, int); int CDECL lame_get_experimentalZ(const lame_global_flags *); // Naoki's psycho acoustic model. default=0 int CDECL lame_set_exp_nspsytune(lame_global_flags *, int); int CDECL lame_get_exp_nspsytune(const lame_global_flags *); /******************************************************************** * VBR control ***********************************************************************/ // Types of VBR. default = vbr_off = CBR int CDECL lame_set_VBR(lame_global_flags *, vbr_mode); vbr_mode CDECL lame_get_VBR(const lame_global_flags *); // VBR quality level. 0=highest 9=lowest int CDECL lame_set_VBR_q(lame_global_flags *, int); int CDECL lame_get_VBR_q(const lame_global_flags *); // Ignored except for VBR=vbr_abr (ABR mode) int CDECL lame_set_VBR_mean_bitrate_kbps(lame_global_flags *, int); int CDECL lame_get_VBR_mean_bitrate_kbps(const lame_global_flags *); int CDECL lame_set_VBR_min_bitrate_kbps(lame_global_flags *, int); int CDECL lame_get_VBR_min_bitrate_kbps(const lame_global_flags *); int CDECL lame_set_VBR_max_bitrate_kbps(lame_global_flags *, int); int CDECL lame_get_VBR_max_bitrate_kbps(const lame_global_flags *); // 1=stricetly enforce VBR_min_bitrate. Normally it will be violated for // analog silence int CDECL lame_set_VBR_hard_min(lame_global_flags *, int); int CDECL lame_get_VBR_hard_min(const lame_global_flags *); /******************************************************************** * Filtering control ***********************************************************************/ // freq in Hz to apply lowpass. Default = 0 = lame chooses. -1 = disabled int CDECL lame_set_lowpassfreq(lame_global_flags *, int); int CDECL lame_get_lowpassfreq(const lame_global_flags *); // width of transition band, in Hz. Default = one polyphase filter band int CDECL lame_set_lowpasswidth(lame_global_flags *, int); int CDECL lame_get_lowpasswidth(const lame_global_flags *); // freq in Hz to apply highpass. Default = 0 = lame chooses. -1 = disabled int CDECL lame_set_highpassfreq(lame_global_flags *, int); int CDECL lame_get_highpassfreq(const lame_global_flags *); // width of transition band, in Hz. Default = one polyphase filter band int CDECL lame_set_highpasswidth(lame_global_flags *, int); int CDECL lame_get_highpasswidth(const lame_global_flags *); /******************************************************************** * psycho acoustics and other arguments which you should not change * unless you know what you are doing ***********************************************************************/ // only use ATH for masking int CDECL lame_set_ATHonly(lame_global_flags *, int); int CDECL lame_get_ATHonly(const lame_global_flags *); // only use ATH for short blocks int CDECL lame_set_ATHshort(lame_global_flags *, int); int CDECL lame_get_ATHshort(const lame_global_flags *); // disable ATH int CDECL lame_set_noATH(lame_global_flags *, int); int CDECL lame_get_noATH(const lame_global_flags *); // select ATH formula int CDECL lame_set_ATHtype(lame_global_flags *, int); int CDECL lame_get_ATHtype(const lame_global_flags *); // lower ATH by this many db int CDECL lame_set_ATHlower(lame_global_flags *, float); float CDECL lame_get_ATHlower(const lame_global_flags *); // select adaptive ATH type int CDECL lame_set_adjust_type( lame_global_flags *, int); int CDECL lame_get_adjust_type( const lame_global_flags *); // select adaptive ATH level adjustment scheme int CDECL lame_set_adapt_thres_type( lame_global_flags *, int); int CDECL lame_get_adapt_thres_type( const lame_global_flags *); // adjust (in dB) the point below which adaptive ATH level adjustment occurs int CDECL lame_set_adapt_thres_level( lame_global_flags *, float); float CDECL lame_get_adapt_thres_level( const lame_global_flags* ); // predictability limit (ISO tonality formula) int CDECL lame_set_cwlimit(lame_global_flags *, int); int CDECL lame_get_cwlimit(const lame_global_flags *); // allow blocktypes to differ between channels? // default: 0 for jstereo, 1 for stereo int CDECL lame_set_allow_diff_short(lame_global_flags *, int); int CDECL lame_get_allow_diff_short(const lame_global_flags *); // use temporal masking effect (default = 1) int CDECL lame_set_useTemporal(lame_global_flags *, int); int CDECL lame_get_useTemporal(const lame_global_flags *); // disable short blocks int CDECL lame_set_no_short_blocks(lame_global_flags *, int); int CDECL lame_get_no_short_blocks(const lame_global_flags *); // force short blocks int CDECL lame_set_force_short_blocks(lame_global_flags *, int); int CDECL lame_get_force_short_blocks(const lame_global_flags *); /* Input PCM is emphased PCM (for instance from one of the rarely emphased CDs), it is STRONGLY not recommended to use this, because psycho does not take it into account, and last but not least many decoders ignore these bits */ int CDECL lame_set_emphasis(lame_global_flags *, int); int CDECL lame_get_emphasis(const lame_global_flags *); /************************************************************************/ /* internal variables, cannot be set... */ /* provided because they may be of use to calling application */ /************************************************************************/ // version 0=MPEG-2 1=MPEG-1 (2=MPEG-2.5) int CDECL lame_get_version(const lame_global_flags *); // encoder delay int CDECL lame_get_encoder_delay(const lame_global_flags *); // padding appended to the input to make sure decoder can fully decode // all input. Note that this value can only be calculated during the // call to lame_encoder_flush(). Before lame_encoder_flush() has // been called, the value of encoder_padding = 0. int CDECL lame_get_encoder_padding(const lame_global_flags *); // size of MPEG frame int CDECL lame_get_framesize(const lame_global_flags *); // number of PCM samples buffered, but not yet encoded to mp3 data. int CDECL lame_get_mf_samples_to_encode( const lame_global_flags* gfp ); // size (bytes) of mp3 data buffered, but not yet encoded. // this is the number of bytes which would be output by a call to // lame_encode_flush_nogap. NOTE: lame_encode_flush() will return // more bytes than this because it will encode the reamining buffered // PCM samples before flushing the mp3 buffers. int CDECL lame_get_size_mp3buffer( const lame_global_flags* gfp ); // number of frames encoded so far int CDECL lame_get_frameNum(const lame_global_flags *); // lame's estimate of the total number of frames to be encoded // only valid if calling program set num_samples int CDECL lame_get_totalframes(const lame_global_flags *); /* * REQUIRED: * sets more internal configuration based on data provided above. * returns -1 if something failed. */ int CDECL lame_init_params(lame_global_flags *); /* * OPTIONAL: * get the version number, in a string. of the form: * "3.63 (beta)" or just "3.63". */ const char* CDECL get_lame_version ( void ); const char* CDECL get_lame_short_version ( void ); const char* CDECL get_lame_very_short_version ( void ); const char* CDECL get_psy_version ( void ); const char* CDECL get_mp3x_version ( void ); const char* CDECL get_lame_url ( void ); /* * OPTIONAL: * get the version numbers in numerical form. */ typedef struct { /* generic LAME version */ int major; int minor; int alpha; /* 0 if not an alpha version */ int beta; /* 0 if not a beta version */ /* version of the psy model */ int psy_major; int psy_minor; int psy_alpha; /* 0 if not an alpha version */ int psy_beta; /* 0 if not a beta version */ /* compile time features */ const char *features; /* Don't make assumptions about the contents! */ } lame_version_t; void CDECL get_lame_version_numerical ( lame_version_t *const ); /* * OPTIONAL: * print internal lame configuration to message handler */ void CDECL lame_print_config(const lame_global_flags* gfp); void CDECL lame_print_internals( const lame_global_flags *gfp); /* * input pcm data, output (maybe) mp3 frames. * This routine handles all buffering, resampling and filtering for you. * * return code number of bytes output in mp3buf. Can be 0 * -1: mp3buf was too small * -2: malloc() problem * -3: lame_init_params() not called * -4: psycho acoustic problems * -5: ogg cleanup encoding error * -6: ogg frame encoding error * * The required mp3buf_size can be computed from num_samples, * samplerate and encoding rate, but here is a worst case estimate: * * mp3buf_size in bytes = 1.25*num_samples + 7200 * * I think a tighter bound could be: (mt, March 2000) * MPEG1: * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512 * MPEG2: * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256 * * but test first if you use that! * * set mp3buf_size = 0 and LAME will not check if mp3buf_size is * large enough. * * NOTE: * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels * will be averaged into the L channel before encoding only the L channel * This will overwrite the data in buffer_l[] and buffer_r[]. * */ int CDECL lame_encode_buffer ( lame_global_flags* gfp, /* global context handle */ const short int buffer_l [], /* PCM data for left channel */ const short int buffer_r [], /* PCM data for right channel */ const int nsamples, /* number of samples per channel */ unsigned char* mp3buf, /* pointer to encoded MP3 stream */ const int mp3buf_size ); /* number of valid octets in this stream */ /* * as above, but input has L & R channel data interleaved. * NOTE: * num_samples = number of samples in the L (or R) * channel, not the total number of samples in pcm[] */ int CDECL lame_encode_buffer_interleaved( lame_global_flags* gfp, /* global context handlei */ short int pcm[], /* PCM data for left and right channel, interleaved */ int num_samples, /* number of samples per channel, _not_ number of samples in pcm[] */ unsigned char* mp3buf, /* pointer to encoded MP3 stream */ int mp3buf_size ); /* number of valid octets in this stream */ /* as lame_encode_buffer, but for 'float's */ int CDECL lame_encode_buffer_float( lame_global_flags* gfp, /* global context handle */ const float buffer_l [], /* PCM data for left channel */ const float buffer_r [], /* PCM data for right channel */ const int nsamples, /* number of samples per channel */ unsigned char* mp3buf, /* pointer to encoded MP3 stream */ const int mp3buf_size ); /* number of valid octets in this stream */ /* as lame_encode_buffer, but for int's */ int CDECL lame_encode_buffer_int( lame_global_flags* gfp, /* global context handle */ const int buffer_l [], /* PCM data for left channel */ const int buffer_r [], /* PCM data for right channel */ const int nsamples, /* number of samples per channel */ unsigned char* mp3buf, /* pointer to encoded MP3 stream */ const int mp3buf_size ); /* number of valid octets in this stream */ /* as lame_encode_buffer, but for long's */ int CDECL lame_encode_buffer_long( lame_global_flags* gfp, /* global context handle */ const long buffer_l [], /* PCM data for left channel */ const long buffer_r [], /* PCM data for right channel */ const int nsamples, /* number of samples per channel */ unsigned char* mp3buf, /* pointer to encoded MP3 stream */ const int mp3buf_size ); /* number of valid octets in this stream */ /* * REQUIRED: * lame_encode_flush will flush the intenal PCM buffers, padding with * 0's to make sure the final frame is complete, and then flush * the internal MP3 buffers, and thus may return a * final few mp3 frames. 'mp3buf' should be at least 7200 bytes long * to hold all possible emitted data. * * will also write id3v1 tags (if any) into the bitstream * * return code = number of bytes output to mp3buf. Can be 0 */ int CDECL lame_encode_flush( lame_global_flags * gfp, /* global context handle */ unsigned char* mp3buf, /* pointer to encoded MP3 stream */ int size); /* number of valid octets in this stream */ /* * OPTIONAL: * lame_encode_flush_nogap will flush the internal mp3 buffers and pad * the last frame with ancillary data so it is a complete mp3 frame. * * 'mp3buf' should be at least 7200 bytes long * to hold all possible emitted data. * * After a call to this routine, the outputed mp3 data is complete, but * you may continue to encode new PCM samples and write future mp3 data * to a different file. The two mp3 files will play back with no gaps * if they are concatenated together. * * This routine will NOT write id3v1 tags into the bitstream. * * return code = number of bytes output to mp3buf. Can be 0 */ int CDECL lame_encode_flush_nogap( lame_global_flags * gfp, /* global context handle */ unsigned char* mp3buf, /* pointer to encoded MP3 stream */ int size); /* number of valid octets in this stream */ /* * OPTIONAL: * Normally, this is called by lame_init_params(). It writes id3v2 and * Xing headers into the front of the bitstream, and sets frame counters * and bitrate histogram data to 0. You can also call this after * lame_encode_flush_nogap(). */ int CDECL lame_init_bitstream( lame_global_flags * gfp); /* global context handle */ /* * OPTIONAL: some simple statistics * a bitrate histogram to visualize the distribution of used frame sizes * a stereo mode histogram to visualize the distribution of used stereo * modes, useful in joint-stereo mode only * 0: LR left-right encoded * 1: LR-I left-right and intensity encoded (currently not supported) * 2: MS mid-side encoded * 3: MS-I mid-side and intensity encoded (currently not supported) * * attention: don't call them after lame_encode_finish * suggested: lame_encode_flush -> lame_*_hist -> lame_close */ void CDECL lame_bitrate_hist( const lame_global_flags *const gfp, int bitrate_count[14] ); void CDECL lame_bitrate_kbps( const lame_global_flags *const gfp, int bitrate_kbps [14] ); void CDECL lame_stereo_mode_hist( const lame_global_flags *const gfp, int stereo_mode_count[4] ); void CDECL lame_bitrate_stereo_mode_hist ( const lame_global_flags* gfp, int bitrate_stmode_count [14] [4] ); /* * OPTIONAL: * lame_mp3_tags_fid will append a Xing VBR tag to the mp3 file with file * pointer fid. These calls perform forward and backwards seeks, so make * sure fid is a real file. Make sure lame_encode_flush has been called, * and all mp3 data has been written to the file before calling this * function. * NOTE: * if VBR tags are turned off by the user, or turned off by LAME because * the output is not a regular file, this call does nothing */ void CDECL lame_mp3_tags_fid(lame_global_flags *,FILE* fid); /* * REQUIRED: * final call to free all remaining buffers */ int CDECL lame_close (lame_global_flags *); /* * OBSOLETE: * lame_encode_finish combines lame_encode_flush() and lame_close() in * one call. However, once this call is made, the statistics routines * will no longer work because the data will have been cleared */ int CDECL lame_encode_finish( lame_global_flags* gfp, unsigned char* mp3buf, int size ); /********************************************************************* * * decoding * * a simple interface to mpglib, part of mpg123, is also included if * libmp3lame is compiled with HAVE_MPGLIB * *********************************************************************/ typedef struct { int header_parsed; /* 1 if header was parsed and following data was computed */ int stereo; /* number of channels */ int samplerate; /* sample rate */ int bitrate; /* bitrate */ int mode; /* mp3 frame type */ int mode_ext; /* mp3 frame type */ int framesize; /* number of samples per mp3 frame */ /* this data is only computed if mpglib detects a Xing VBR header */ unsigned long nsamp; /* number of samples in mp3 file. */ int totalframes; /* total number of frames in mp3 file */ /* this data is not currently computed by the mpglib routines */ int framenum; /* frames decoded counter */ } mp3data_struct; /* required call to initialize decoder */ int CDECL lame_decode_init(void); /********************************************************************* * input 1 mp3 frame, output (maybe) pcm data. * lame_decode() return code: * -1: error * 0: need more data * n>0: size of pcm output *********************************************************************/ int CDECL lame_decode( unsigned char * mp3buf, int len, short pcm_l[], short pcm_r[] ); /* same as lame_decode, and also returns mp3 header data */ int CDECL lame_decode_headers( unsigned char* mp3buf, int len, short pcm_l[], short pcm_r[], mp3data_struct* mp3data ); /* same as lame_decode, but returns at most one frame */ int CDECL lame_decode1( unsigned char* mp3buf, int len, short pcm_l[], short pcm_r[] ); /* same as lame_decode1, but returns at most one frame and mp3 header data */ int CDECL lame_decode1_headers( unsigned char* mp3buf, int len, short pcm_l[], short pcm_r[], mp3data_struct* mp3data ); /********************************************************************* * * id3tag stuff * *********************************************************************/ /* * id3tag.h -- Interface to write ID3 version 1 and 2 tags. * * Copyright (C) 2000 Don Melton. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. */ /* utility to obtain alphabetically sorted list of genre names with numbers */ extern void id3tag_genre_list( void (*handler)(int, const char *, void *), void* cookie); extern void id3tag_init (lame_global_flags *gfp); /* force addition of version 2 tag */ extern void id3tag_add_v2 (lame_global_flags *gfp); /* add only a version 1 tag */ extern void id3tag_v1_only (lame_global_flags *gfp); /* add only a version 2 tag */ extern void id3tag_v2_only (lame_global_flags *gfp); /* pad version 1 tag with spaces instead of nulls */ extern void id3tag_space_v1 (lame_global_flags *gfp); /* pad version 2 tag with extra 128 bytes */ extern void id3tag_pad_v2 (lame_global_flags *gfp); extern void id3tag_set_title( lame_global_flags* gfp, const char* title ); extern void id3tag_set_artist( lame_global_flags* gfp, const char* artist ); extern void id3tag_set_album( lame_global_flags* gfp, const char* album ); extern void id3tag_set_year( lame_global_flags* gfp, const char* year ); extern void id3tag_set_comment( lame_global_flags* gfp, const char* comment ); extern void id3tag_set_track( lame_global_flags* gfp, const char* track ); /* return non-zero result if genre name or number is invalid */ extern int id3tag_set_genre( lame_global_flags* gfp, const char* genre ); /*********************************************************************** * * list of valid bitrates [kbps] & sample frequencies [Hz]. * first index: 0: MPEG-2 values (sample frequencies 16...24 kHz) * 1: MPEG-1 values (sample frequencies 32...48 kHz) * 2: MPEG-2.5 values (sample frequencies 8...12 kHz) ***********************************************************************/ extern const int bitrate_table [3] [16]; extern const int samplerate_table [3] [ 4]; /* maximum size of mp3buffer needed if you encode at most 1152 samples for each call to lame_encode_buffer. see lame_encode_buffer() below (LAME_MAXMP3BUFFER is now obsolete) */ #define LAME_MAXMP3BUFFER 16384 #if defined(__cplusplus) } #endif #endif /* LAME_LAME_H */ ./mpglibDBL/layer2.c0000644000175000017500000002174507451136440013412 0ustar rizlarizla/* * Mpeg Layer-2 audio decoder * -------------------------- * copyright (c) 1995 by Michael Hipp, All rights reserved. See also 'README' * */ /* $Id: layer2.c,v 1.1 2002/03/29 19:14:40 snelg Exp $ */ #ifdef HAVE_CONFIG_H # include #endif #ifdef USE_LAYER_2 #include "common.h" #include "layer2.h" #include "l2tables.h" #include "decode_i386.h" #ifdef WITH_DMALLOC #include #endif static int grp_3tab[32 * 3] = { 0, }; /* used: 27 */ static int grp_5tab[128 * 3] = { 0, }; /* used: 125 */ static int grp_9tab[1024 * 3] = { 0, }; /* used: 729 */ void init_layer2(void) { static const double mulmul[27] = { 0.0 , -2.0/3.0 , 2.0/3.0 , 2.0/7.0 , 2.0/15.0 , 2.0/31.0, 2.0/63.0 , 2.0/127.0 , 2.0/255.0 , 2.0/511.0 , 2.0/1023.0 , 2.0/2047.0 , 2.0/4095.0 , 2.0/8191.0 , 2.0/16383.0 , 2.0/32767.0 , 2.0/65535.0 , -4.0/5.0 , -2.0/5.0 , 2.0/5.0, 4.0/5.0 , -8.0/9.0 , -4.0/9.0 , -2.0/9.0 , 2.0/9.0 , 4.0/9.0 , 8.0/9.0 }; static const int base[3][9] = { { 1 , 0, 2 , } , { 17, 18, 0 , 19, 20 , } , { 21, 1, 22, 23, 0, 24, 25, 2, 26 } }; int i,j,k,l,len; real *table; static const int tablen[3] = { 3 , 5 , 9 }; static int *itable,*tables[3] = { grp_3tab , grp_5tab , grp_9tab }; for(i=0;i<3;i++) { itable = tables[i]; len = tablen[i]; for(j=0;jstereo-1; int sblimit = fr->II_sblimit; int jsbound = fr->jsbound; int sblimit2 = fr->II_sblimit<alloc; int i; static unsigned int scfsi_buf[64]; unsigned int *scfsi,*bita; int sc,step; bita = bit_alloc; if(stereo) { for (i=jsbound;i;i--,alloc1+=(1<bits); *bita++ = (char) getbits(step); } for (i=sblimit-jsbound;i;i--,alloc1+=(1<bits); bita[1] = bita[0]; bita+=2; } bita = bit_alloc; scfsi=scfsi_buf; for (i=sblimit2;i;i--) if (*bita++) *scfsi++ = (char) getbits_fast(2); } else /* mono */ { for (i=sblimit;i;i--,alloc1+=(1<bits); bita = bit_alloc; scfsi=scfsi_buf; for (i=sblimit;i;i--) if (*bita++) *scfsi++ = (char) getbits_fast(2); } bita = bit_alloc; scfsi=scfsi_buf; for (i=sblimit2;i;i--) if (*bita++) switch (*scfsi++) { case 0: *scale++ = getbits_fast(6); *scale++ = getbits_fast(6); *scale++ = getbits_fast(6); break; case 1 : *scale++ = sc = getbits_fast(6); *scale++ = sc; *scale++ = getbits_fast(6); break; case 2: *scale++ = sc = getbits_fast(6); *scale++ = sc; *scale++ = sc; break; default: /* case 3 */ *scale++ = getbits_fast(6); *scale++ = sc = getbits_fast(6); *scale++ = sc; break; } } void II_step_two(unsigned int *bit_alloc,real fraction[2][4][SBLIMIT],int *scale,struct frame *fr,int x1) { int i,j,k,ba; int stereo = fr->stereo; int sblimit = fr->II_sblimit; int jsbound = fr->jsbound; struct al_table2 *alloc2,*alloc1 = fr->alloc; unsigned int *bita=bit_alloc; int d1,step; for (i=0;ibits; for (j=0;jbits; if( (d1=alloc2->d) < 0) { real cm=muls[k][scale[x1]]; fraction[j][0][i] = ((real) ((int)getbits(k) + d1)) * cm; fraction[j][1][i] = ((real) ((int)getbits(k) + d1)) * cm; fraction[j][2][i] = ((real) ((int)getbits(k) + d1)) * cm; } else { static int *table[] = { 0,0,0,grp_3tab,0,grp_5tab,0,0,0,grp_9tab }; unsigned int idx,*tab,m=scale[x1]; idx = (unsigned int) getbits(k); tab = (unsigned int *) (table[d1] + idx + idx + idx); fraction[j][0][i] = muls[*tab++][m]; fraction[j][1][i] = muls[*tab++][m]; fraction[j][2][i] = muls[*tab][m]; } scale+=3; } else fraction[j][0][i] = fraction[j][1][i] = fraction[j][2][i] = 0.0; } } for (i=jsbound;ibits; bita++; /* channel 1 and channel 2 bitalloc are the same */ if ( (ba=*bita++) ) { k=(alloc2 = alloc1+ba)->bits; if( (d1=alloc2->d) < 0) { real cm; cm=muls[k][scale[x1+3]]; fraction[1][0][i] = (fraction[0][0][i] = (real) ((int)getbits(k) + d1) ) * cm; fraction[1][1][i] = (fraction[0][1][i] = (real) ((int)getbits(k) + d1) ) * cm; fraction[1][2][i] = (fraction[0][2][i] = (real) ((int)getbits(k) + d1) ) * cm; cm=muls[k][scale[x1]]; fraction[0][0][i] *= cm; fraction[0][1][i] *= cm; fraction[0][2][i] *= cm; } else { static int *table[] = { 0,0,0,grp_3tab,0,grp_5tab,0,0,0,grp_9tab }; unsigned int idx,*tab,m1,m2; m1 = scale[x1]; m2 = scale[x1+3]; idx = (unsigned int) getbits(k); tab = (unsigned int *) (table[d1] + idx + idx + idx); fraction[0][0][i] = muls[*tab][m1]; fraction[1][0][i] = muls[*tab++][m2]; fraction[0][1][i] = muls[*tab][m1]; fraction[1][1][i] = muls[*tab++][m2]; fraction[0][2][i] = muls[*tab][m1]; fraction[1][2][i] = muls[*tab][m2]; } scale+=6; } else { fraction[0][0][i] = fraction[0][1][i] = fraction[0][2][i] = fraction[1][0][i] = fraction[1][1][i] = fraction[1][2][i] = 0.0; } /* should we use individual scalefac for channel 2 or is the current way the right one , where we just copy channel 1 to channel 2 ?? The current 'strange' thing is, that we throw away the scalefac values for the second channel ...!! -> changed .. now we use the scalefac values of channel one !! */ } // if(sblimit > (fr->down_sample_sblimit) ) // sblimit = fr->down_sample_sblimit; for(i=sblimit;ilsf) table = 4; else table = translate[fr->sampling_frequency][2-fr->stereo][fr->bitrate_index]; sblim = sblims[table]; fr->alloc = (struct al_table2*)tables[table]; fr->II_sblimit = sblim; } int do_layer2( PMPSTR mp,unsigned char *pcm_sample,int *pcm_point) //int do_layer2(struct frame *fr,int outmode,struct audio_info_struct *ai) { int clip=0; int i,j; real fraction[2][4][SBLIMIT]; /* pick_table clears unused subbands */ unsigned int bit_alloc[64]; int scale[192]; struct frame *fr=&(mp->fr); int stereo = fr->stereo; int single = fr->single; II_select_table(fr); fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext<<2)+4 : fr->II_sblimit; if(stereo == 1 || single == 3) single = 0; II_step_one(bit_alloc, scale, fr); for (i=0;i>2); for (j=0;j<3;j++) { if(single >= 0) { clip += synth_1to1_mono(mp, fraction[single][j],pcm_sample,pcm_point); } else { int p1 = *pcm_point; clip += synth_1to1(mp, fraction[0][j],0,pcm_sample,&p1); clip += synth_1to1(mp, fraction[1][j],1,pcm_sample,pcm_point); } } } return clip; } #endif ./mpglibDBL/tabinit.c0000644000175000017500000001115107716027257013645 0ustar rizlarizla/* $Id: tabinit.c,v 1.2 2003/08/12 00:02:55 snelg Exp $ */ #ifdef HAVE_CONFIG_H # include #endif #include #include "tabinit.h" #include "mpg123.h" #ifdef WITH_DMALLOC #include #endif real decwin[512+32]; static real cos64[16],cos32[8],cos16[4],cos8[2],cos4[1]; real *pnts[] = { cos64,cos32,cos16,cos8,cos4 }; const double dewin[512] = { 0.000000000,-0.000015259,-0.000015259,-0.000015259, -0.000015259,-0.000015259,-0.000015259,-0.000030518, -0.000030518,-0.000030518,-0.000030518,-0.000045776, -0.000045776,-0.000061035,-0.000061035,-0.000076294, -0.000076294,-0.000091553,-0.000106812,-0.000106812, -0.000122070,-0.000137329,-0.000152588,-0.000167847, -0.000198364,-0.000213623,-0.000244141,-0.000259399, -0.000289917,-0.000320435,-0.000366211,-0.000396729, -0.000442505,-0.000473022,-0.000534058,-0.000579834, -0.000625610,-0.000686646,-0.000747681,-0.000808716, -0.000885010,-0.000961304,-0.001037598,-0.001113892, -0.001205444,-0.001296997,-0.001388550,-0.001480103, -0.001586914,-0.001693726,-0.001785278,-0.001907349, -0.002014160,-0.002120972,-0.002243042,-0.002349854, -0.002456665,-0.002578735,-0.002685547,-0.002792358, -0.002899170,-0.002990723,-0.003082275,-0.003173828, -0.003250122,-0.003326416,-0.003387451,-0.003433228, -0.003463745,-0.003479004,-0.003479004,-0.003463745, -0.003417969,-0.003372192,-0.003280640,-0.003173828, -0.003051758,-0.002883911,-0.002700806,-0.002487183, -0.002227783,-0.001937866,-0.001617432,-0.001266479, -0.000869751,-0.000442505, 0.000030518, 0.000549316, 0.001098633, 0.001693726, 0.002334595, 0.003005981, 0.003723145, 0.004486084, 0.005294800, 0.006118774, 0.007003784, 0.007919312, 0.008865356, 0.009841919, 0.010848999, 0.011886597, 0.012939453, 0.014022827, 0.015121460, 0.016235352, 0.017349243, 0.018463135, 0.019577026, 0.020690918, 0.021789551, 0.022857666, 0.023910522, 0.024932861, 0.025909424, 0.026840210, 0.027725220, 0.028533936, 0.029281616, 0.029937744, 0.030532837, 0.031005859, 0.031387329, 0.031661987, 0.031814575, 0.031845093, 0.031738281, 0.031478882, 0.031082153, 0.030517578, 0.029785156, 0.028884888, 0.027801514, 0.026535034, 0.025085449, 0.023422241, 0.021575928, 0.019531250, 0.017257690, 0.014801025, 0.012115479, 0.009231567, 0.006134033, 0.002822876, -0.000686646,-0.004394531,-0.008316040,-0.012420654, -0.016708374,-0.021179199,-0.025817871,-0.030609131, -0.035552979,-0.040634155,-0.045837402,-0.051132202, -0.056533813,-0.061996460,-0.067520142,-0.073059082, -0.078628540,-0.084182739,-0.089706421,-0.095169067, -0.100540161,-0.105819702,-0.110946655,-0.115921021, -0.120697021,-0.125259399,-0.129562378,-0.133590698, -0.137298584,-0.140670776,-0.143676758,-0.146255493, -0.148422241,-0.150115967,-0.151306152,-0.151962280, -0.152069092,-0.151596069,-0.150497437,-0.148773193, -0.146362305,-0.143264771,-0.139450073,-0.134887695, -0.129577637,-0.123474121,-0.116577148,-0.108856201, -0.100311279,-0.090927124,-0.080688477,-0.069595337, -0.057617187,-0.044784546,-0.031082153,-0.016510010, -0.001068115, 0.015228271, 0.032379150, 0.050354004, 0.069168091, 0.088775635, 0.109161377, 0.130310059, 0.152206421, 0.174789429, 0.198059082, 0.221984863, 0.246505737, 0.271591187, 0.297210693, 0.323318481, 0.349868774, 0.376800537, 0.404083252, 0.431655884, 0.459472656, 0.487472534, 0.515609741, 0.543823242, 0.572036743, 0.600219727, 0.628295898, 0.656219482, 0.683914185, 0.711318970, 0.738372803, 0.765029907, 0.791213989, 0.816864014, 0.841949463, 0.866363525, 0.890090942, 0.913055420, 0.935195923, 0.956481934, 0.976852417, 0.996246338, 1.014617920, 1.031936646, 1.048156738, 1.063217163, 1.077117920, 1.089782715, 1.101211548, 1.111373901, 1.120223999, 1.127746582, 1.133926392, 1.138763428, 1.142211914, 1.144287109, 1.144989014 }; void make_decode_tables(long scaleval) { int i,j,k,kr,divv; real *table,*costab; for(i=0;i<5;i++) { kr=0x10>>i; divv=0x40>>i; costab = pnts[i]; for(k=0;k #endif #include #include #include #include "common.h" #include "interface.h" #include "tabinit.h" #include "layer3.h" #include "VbrTag.h" #ifdef USE_LAYER_1 #include "layer1.h" #endif #ifdef USE_LAYER_2 #include "layer2.h" #endif #ifdef WITH_DMALLOC #include #endif BOOL InitMP3( PMPSTR mp) { memset(mp,0,sizeof(MPSTR)); mp->framesize = 0; mp->num_frames = 0; mp->vbr_header=0; mp->header_parsed=0; mp->side_parsed=0; mp->data_parsed=0; mp->free_format=0; mp->old_free_format=0; mp->ssize = 0; mp->dsize=0; mp->fsizeold = -1; mp->bsize = 0; mp->head = mp->tail = NULL; mp->fr.single = -1; mp->bsnum = 0; wordpointer = mp->bsspace[mp->bsnum] + 512; mp->synth_bo = 1; mp->sync_bitstream = 1; make_decode_tables(32767); init_layer3(SBLIMIT); #ifdef USE_LAYER_2 init_layer2(); #endif return !0; } void ExitMP3( PMPSTR mp) { struct buf *b,*bn; b = mp->tail; while(b) { free(b->pnt); bn = b->next; free(b); b = bn; } } static struct buf *addbuf( PMPSTR mp, unsigned char *ibuf,int size) { struct buf *nbuf; nbuf = (struct buf*) malloc( sizeof(struct buf) ); if(!nbuf) { fprintf(stderr,"Out of memory!\n"); return NULL; } nbuf->pnt = (unsigned char*) malloc((size_t)size); if(!nbuf->pnt) { free(nbuf); return NULL; } nbuf->size = size; memcpy(nbuf->pnt,ibuf,(size_t)size); nbuf->next = NULL; nbuf->prev = mp->head; nbuf->pos = 0; if(!mp->tail) { mp->tail = nbuf; } else { mp->head->next = nbuf; } mp->head = nbuf; mp->bsize += size; return nbuf; } void remove_buf(PMPSTR mp) { struct buf *buff = mp->tail; mp->tail = buff->next; if(mp->tail) mp->tail->prev = NULL; else { mp->tail = mp->head = NULL; } free(buff->pnt); free(buff); } static int read_buf_byte(PMPSTR mp) { unsigned int b; int pos; pos = mp->tail->pos; while(pos >= mp->tail->size) { remove_buf(mp); if(!mp->tail) { fprintf(stderr,"Fatal error! tried to read past mp buffer\n"); fclose(stdout); fclose(stderr); exit(1); } pos = mp->tail->pos; } b = mp->tail->pnt[pos]; mp->bsize--; mp->tail->pos++; return b; } static void read_head(PMPSTR mp) { unsigned long head; head = read_buf_byte(mp); head <<= 8; head |= read_buf_byte(mp); head <<= 8; head |= read_buf_byte(mp); head <<= 8; head |= read_buf_byte(mp); mp->header = head; } void copy_mp(PMPSTR mp,int size,unsigned char *ptr) { int len = 0; while(len < size) { int nlen; int blen = mp->tail->size - mp->tail->pos; if( (size - len) <= blen) { nlen = size-len; } else { nlen = blen; } memcpy(ptr+len,mp->tail->pnt+mp->tail->pos,(size_t)nlen); len += nlen; mp->tail->pos += nlen; mp->bsize -= nlen; if(mp->tail->pos == mp->tail->size) { remove_buf(mp); } } } char VBRTag[5] = "Xing"; static int ExtractI4(unsigned char *buf) { int x; /* big endian extract */ x = buf[0]; x <<= 8; x |= buf[1]; x <<= 8; x |= buf[2]; x <<= 8; x |= buf[3]; return x; } const int bitrate_table [3] [16] = { { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, }; const int samplerate_table [3] [4] = { { 22050, 24000, 16000, -1 }, { 44100, 48000, 32000, -1 }, { 11025, 12000, 8000, -1 }, }; int GetVbrTag(VBRTAGDATA *pTagData, unsigned char *buf) { int i, head_flags; int h_bitrate,h_id, h_mode, h_sr_index; /* get Vbr header data */ pTagData->flags = 0; /* get selected MPEG header data */ h_id = (buf[1] >> 3) & 1; h_sr_index = (buf[2] >> 2) & 3; h_mode = (buf[3] >> 6) & 3; h_bitrate = ((buf[2]>>4)&0xf); h_bitrate = bitrate_table[h_id][h_bitrate]; /* determine offset of header */ if( h_id ) { /* mpeg1 */ if( h_mode != 3 ) buf+=(32+4); else buf+=(17+4); } else { /* mpeg2 */ if( h_mode != 3 ) buf+=(17+4); else buf+=(9+4); } if( buf[0] != VBRTag[0] ) return 0; /* fail */ if( buf[1] != VBRTag[1] ) return 0; /* header not found*/ if( buf[2] != VBRTag[2] ) return 0; if( buf[3] != VBRTag[3] ) return 0; buf+=4; pTagData->h_id = h_id; pTagData->samprate = samplerate_table[h_id][h_sr_index]; if( h_id == 0 ) pTagData->samprate >>= 1; head_flags = pTagData->flags = ExtractI4(buf); buf+=4; /* get flags */ if( head_flags & FRAMES_FLAG ) { pTagData->frames = ExtractI4(buf); buf+=4; } if( head_flags & BYTES_FLAG ) { pTagData->bytes = ExtractI4(buf); buf+=4; } if( head_flags & TOC_FLAG ) { if( pTagData->toc != NULL ) { for(i=0;itoc[i] = buf[i]; } buf+=NUMTOCENTRIES; } pTagData->vbr_scale = -1; if( head_flags & VBR_SCALE_FLAG ) { pTagData->vbr_scale = ExtractI4(buf); buf+=4; } pTagData->headersize = ((h_id+1)*72000*h_bitrate) / pTagData->samprate; #ifdef DEBUG_VBRTAG DEBUGF("\n\n********************* VBR TAG INFO *****************\n"); DEBUGF("tag :%s\n",VBRTag); DEBUGF("head_flags :%d\n",head_flags); DEBUGF("bytes :%d\n",pTagData->bytes); DEBUGF("frames :%d\n",pTagData->frames); DEBUGF("VBR Scale :%d\n",pTagData->vbr_scale); DEBUGF("toc:\n"); if( pTagData->toc != NULL ) { for(i=0;itoc[i])); } } DEBUGF("\n***************** END OF VBR TAG INFO ***************\n"); #endif return 1; /* success */ } // traverse mp data structure without changing it // (just like sync_buffer) // pull out 48 bytes // call vbr header check code from LAME // if we find a header, parse it and also compute the VBR header size // if no header, do nothing. // // bytes = number of bytes before MPEG header. skip this many bytes // before starting to read // return value: number of bytes in VBR header, including syncword int check_vbr_header(PMPSTR mp,int bytes) { int i,pos; struct buf *ibuf=mp->tail; unsigned char xing[48]; VBRTAGDATA pTagData; pos = ibuf->pos; // skip to valid header for (i=0; i= ibuf->size) { ibuf = ibuf->next; pos = ibuf->pos; if(!ibuf) return -1; /* fatal error */ } ++pos; } // now read 48 bytes for (i=0; i<48; ++i) { while(pos >= ibuf->size) { ibuf = ibuf->next; pos = ibuf->pos; if(!ibuf) return -1; /* fatal error */ } xing[i] = ibuf->pnt[pos]; ++pos; } /* check first 48 bytes for Xing header */ mp->vbr_header = GetVbrTag(&pTagData,xing); if (mp->vbr_header) { mp->num_frames=pTagData.frames; // fprintf(stderr,"\rmpglib: Xing VBR header dectected. MP3 file has %i frames\n", pTagData.frames); return pTagData.headersize; } return 0; } int sync_buffer(PMPSTR mp,int free_match) { /* traverse mp structure without modifing pointers, looking * for a frame valid header. * if free_format, valid header must also have the same * samplerate. * return number of bytes in mp, before the header * return -1 if header is not found */ unsigned int b[4]={0,0,0,0}; int i,h,pos; struct buf *buff=mp->tail; pos = buff->pos; for (i=0; ibsize; i++) { /* get 4 bytes */ b[0]=b[1]; b[1]=b[2]; b[2]=b[3]; while(pos >= buff->size) { buff = buff->next; pos = buff->pos; if(!buff) { return -1; /* not enough data to read 4 bytes */ } } b[3] = buff->pnt[pos]; ++pos; if (i>=3) { struct frame *fr = &mp->fr; unsigned long head; head = b[0]; head <<= 8; head |= b[1]; head <<= 8; head |= b[2]; head <<= 8; head |= b[3]; h = head_check(head,fr->lay); if (h && free_match) { /* just to be even more thorough, match the sample rate */ int mode,stereo,sampling_frequency,mpeg25,lsf; if( head & (1<<20) ) { lsf = (head & (1<<19)) ? 0x0 : 0x1; mpeg25 = 0; } else { lsf = 1; mpeg25 = 1; } mode = ((head>>6)&0x3); stereo = (mode == MPG_MD_MONO) ? 1 : 2; if(mpeg25) sampling_frequency = 6 + ((head>>10)&0x3); else sampling_frequency = ((head>>10)&0x3) + (lsf*3); h = ((stereo==fr->stereo) && (lsf==fr->lsf) && (mpeg25==fr->mpeg25) && (sampling_frequency == fr->sampling_frequency)); } if (h) { return i-3; } } } return -1; } int decodeMP3( PMPSTR mp,unsigned char *in,int isize,int *done) { int i,iret,bits,bytes; if(in) { if(addbuf(mp,in,isize) == NULL) { return MP3_ERR; } } /* First decode header */ if(!mp->header_parsed) { if (mp->fsizeold==-1 || mp->sync_bitstream) { int vbrbytes; mp->sync_bitstream=0; /* This is the very first call. sync with anything */ /* bytes= number of bytes before header */ bytes=sync_buffer(mp,0); /* now look for Xing VBR header */ if (mp->bsize >= bytes+48 ) { /* vbrbytes = number of bytes in entire vbr header */ vbrbytes=check_vbr_header(mp,bytes); } else { /* not enough data to look for Xing header */ return MP3_NEED_MORE; } if (mp->vbr_header) { /* do we have enough data to parse entire Xing header? */ if (bytes+vbrbytes > mp->bsize) return MP3_NEED_MORE; /* read in Xing header. Buffer data in case it * is used by a non zero main_data_begin for the next * frame, but otherwise dont decode Xing header */ for (i=0; i0) { /* there were some extra bytes in front of header. * bitstream problem, but we are now resynced * should try to buffer previous data in case new * frame has nonzero main_data_begin, but we need * to make sure we do not overflow buffer */ int size; // fprintf(stderr,"bitstream problem: resyncing...\n"); mp->old_free_format=0; mp->sync_bitstream=1; /* skip some bytes, buffer the rest */ size = (int) (wordpointer - (mp->bsspace[mp->bsnum]+512)); if (size > MAXFRAMESIZE) { /* wordpointer buffer is trashed. probably cant recover, but try anyway */ // fprintf(stderr,"mpglib: wordpointer trashed. size=%i (%i) bytes=%i \n", // size,MAXFRAMESIZE,bytes); size=0; wordpointer = mp->bsspace[mp->bsnum]+512; } /* buffer contains 'size' data right now we want to add 'bytes' worth of data, but do not exceed MAXFRAMESIZE, so we through away 'i' bytes */ i = (size+bytes)-MAXFRAMESIZE; for (; i>0; --i) { --bytes; read_buf_byte(mp); } copy_mp(mp,bytes,wordpointer); mp->fsizeold += bytes; } read_head(mp); decode_header(&mp->fr,mp->header); mp->header_parsed=1; mp->framesize = mp->fr.framesize; mp->free_format = (mp->framesize==0); if(mp->fr.lsf) mp->ssize = (mp->fr.stereo == 1) ? 9 : 17; else mp->ssize = (mp->fr.stereo == 1) ? 17 : 32; if (mp->fr.error_protection) mp->ssize += 2; mp->bsnum = 1-mp->bsnum; /* toggle buffer */ wordpointer = mp->bsspace[mp->bsnum] + 512; bitindex = 0; /* for very first header, never parse rest of data */ if (mp->fsizeold==-1) return MP3_NEED_MORE; } /* now decode side information */ if (!mp->side_parsed) { /* Layer 3 only */ if (mp->fr.lay==3) { if (mp->bsize < mp->ssize) return MP3_NEED_MORE; copy_mp(mp,mp->ssize,wordpointer); if(mp->fr.error_protection) getbits(16); bits=do_layer3_sideinfo(&mp->fr); if (bits == -32767) { ExitMP3(mp); InitMP3(mp); return MP3_ERR; } /* bits = actual number of bits needed to parse this frame */ /* can be negative, if all bits needed are in the reservoir */ if (bits<0) bits=0; /* read just as many bytes as necessary before decoding */ mp->dsize = (bits+7)/8; /* this will force mpglib to read entire frame before decoding */ /* mp->dsize= mp->framesize - mp->ssize;*/ } else { /* Layers 1 and 2 */ /* check if there is enough input data */ if(mp->fr.framesize > mp->bsize) return MP3_NEED_MORE; /* takes care that the right amount of data is copied into wordpointer */ mp->dsize=mp->fr.framesize; mp->ssize=0; } mp->side_parsed=1; } /* now decode main data */ iret=MP3_NEED_MORE; if (!mp->data_parsed ) { if(mp->dsize > mp->bsize) { return MP3_NEED_MORE; } copy_mp(mp,mp->dsize,wordpointer); *done = 0; //do_layer3(&mp->fr,(unsigned char *) out,done); iret=MP3_OK; switch (mp->fr.lay) { #ifdef USE_LAYER_1 case 1: if(mp->fr.error_protection) getbits(16); do_layer1(mp,(unsigned char *) out,done); break; #endif #ifdef USE_LAYER_2 case 2: if(mp->fr.error_protection) getbits(16); do_layer2(mp,(unsigned char *) out,done); break; #endif case 3: if (do_layer3(mp,done)) { iret = MP3_ERR; } break; default: fprintf(stderr,"invalid layer %d\n",mp->fr.lay); } wordpointer = mp->bsspace[mp->bsnum] + 512 + mp->ssize + mp->dsize; mp->data_parsed=1; } /* remaining bits are ancillary data, or reservoir for next frame * If free format, scan stream looking for next frame to determine * mp->framesize */ if (mp->free_format) { if (mp->old_free_format) { /* free format. bitrate must not vary */ mp->framesize=mp->fsizeold_nopadding + (mp->fr.padding); }else{ bytes=sync_buffer(mp,1); if (bytes<0) return iret; mp->framesize = bytes + mp->ssize+mp->dsize; mp->fsizeold_nopadding= mp->framesize - mp->fr.padding; /* fprintf(stderr,"freeformat bitstream: estimated bitrate=%ikbs \n", 8*(4+mp->framesize)*freqs[mp->fr.sampling_frequency]/ (1000*576*(2-mp->fr.lsf))); */ } } /* buffer the ancillary data and reservoir for next frame */ bytes = mp->framesize-(mp->ssize+mp->dsize); if (bytes > mp->bsize) { return iret; } if (bytes>0) { int size; copy_mp(mp,bytes,wordpointer); wordpointer += bytes; size = (int) (wordpointer - (mp->bsspace[mp->bsnum]+512)); if (size > MAXFRAMESIZE) { fprintf(stderr,"fatal error. MAXFRAMESIZE not large enough.\n"); } } /* the above frame is completey parsed. start looking for next frame */ mp->fsizeold = mp->framesize; mp->old_free_format = mp->free_format; mp->framesize =0; mp->header_parsed=0; mp->side_parsed=0; mp->data_parsed=0; return iret; } ./mpglibDBL/layer3.c0000644000175000017500000013006407716027257013417 0ustar rizlarizla/* * Mpeg Layer-3 audio decoder * -------------------------- * copyright (c) 1995,1996,1997 by Michael Hipp. * All rights reserved. See also 'README' */ /* $Id: layer3.c,v 1.3 2003/08/12 00:02:55 snelg Exp $ */ #ifdef HAVE_CONFIG_H # include #endif #include #include "common.h" #include "huffman.h" #include "encoder.h" #include "decode_i386.h" #ifdef WITH_DMALLOC #include #endif #define MPEG1 unsigned char *maxGain; unsigned char *minGain; static real ispow[8207]; static real aa_ca[8],aa_cs[8]; static real COS1[12][6]; static real win[4][36]; static real win1[4][36]; static real gainpow2[256+118+4]; static real COS9[9]; static real COS6_1,COS6_2; static real tfcos36[9]; static real tfcos12[3]; struct bandInfoStruct { short longIdx[23]; short longDiff[22]; short shortIdx[14]; short shortDiff[13]; }; int longLimit[9][23]; int shortLimit[9][14]; const struct bandInfoStruct bandInfo[9] = { /* MPEG 1.0 */ { {0,4,8,12,16,20,24,30,36,44,52,62,74, 90,110,134,162,196,238,288,342,418,576}, {4,4,4,4,4,4,6,6,8, 8,10,12,16,20,24,28,34,42,50,54, 76,158}, {0,4*3,8*3,12*3,16*3,22*3,30*3,40*3,52*3,66*3, 84*3,106*3,136*3,192*3}, {4,4,4,4,6,8,10,12,14,18,22,30,56} } , { {0,4,8,12,16,20,24,30,36,42,50,60,72, 88,106,128,156,190,230,276,330,384,576}, {4,4,4,4,4,4,6,6,6, 8,10,12,16,18,22,28,34,40,46,54, 54,192}, {0,4*3,8*3,12*3,16*3,22*3,28*3,38*3,50*3,64*3, 80*3,100*3,126*3,192*3}, {4,4,4,4,6,6,10,12,14,16,20,26,66} } , { {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576} , {4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102, 26} , {0,4*3,8*3,12*3,16*3,22*3,30*3,42*3,58*3,78*3,104*3,138*3,180*3,192*3} , {4,4,4,4,6,8,12,16,20,26,34,42,12} } , /* MPEG 2.0 */ { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 } , {0,4*3,8*3,12*3,18*3,24*3,32*3,42*3,56*3,74*3,100*3,132*3,174*3,192*3} , {4,4,4,6,6,8,10,14,18,26,32,42,18 } } , /* docs: 332. mpg123: 330 */ { {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,332,394,464,540,576}, {6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36 } , {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,136*3,180*3,192*3} , {4,4,4,6,8,10,12,14,18,24,32,44,12 } } , { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 }, {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,134*3,174*3,192*3}, {4,4,4,6,8,10,12,14,18,24,30,40,18 } } , /* MPEG 2.5 */ { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, {4,4,4,6,8,10,12,14,18,24,30,40,18} }, { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, {4,4,4,6,8,10,12,14,18,24,30,40,18} }, { {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576}, {12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2}, {0, 24, 48, 72,108,156,216,288,372,480,486,492,498,576}, {8,8,8,12,16,20,24,28,36,2,2,2,26} } , }; static int mapbuf0[9][152]; static int mapbuf1[9][156]; static int mapbuf2[9][44]; static int *map[9][3]; static int *mapend[9][3]; static unsigned int n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */ static unsigned int i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */ static real tan1_1[16],tan2_1[16],tan1_2[16],tan2_2[16]; static real pow1_1[2][16],pow2_1[2][16],pow1_2[2][16],pow2_2[2][16]; static unsigned int get1bit(void) { unsigned char rval; rval = *wordpointer << bitindex; bitindex++; wordpointer += (bitindex>>3); bitindex &= 7; return rval>>7; } /* * init tables for layer-3 */ void init_layer3(int down_sample_sblimit) { int i,j,k; for(i=-256;i<118+4;i++) gainpow2[i+256] = pow((double)2.0,-0.25 * (double) (i+210) ); for(i=0;i<8207;i++) ispow[i] = pow((double)i,(double)4.0/3.0); for (i=0;i<8;i++) { static double Ci[8]={-0.6,-0.535,-0.33,-0.185,-0.095,-0.041,-0.0142,-0.0037}; double sq=sqrt(1.0+Ci[i]*Ci[i]); aa_cs[i] = 1.0/sq; aa_ca[i] = Ci[i]/sq; } for(i=0;i<18;i++) { win[0][i] = win[1][i] = 0.5 * sin( M_PI / 72.0 * (double) (2*(i+0) +1) ) / cos ( M_PI * (double) (2*(i+0) +19) / 72.0 ); win[0][i+18] = win[3][i+18] = 0.5 * sin( M_PI / 72.0 * (double) (2*(i+18)+1) ) / cos ( M_PI * (double) (2*(i+18)+19) / 72.0 ); } for(i=0;i<6;i++) { win[1][i+18] = 0.5 / cos ( M_PI * (double) (2*(i+18)+19) / 72.0 ); win[3][i+12] = 0.5 / cos ( M_PI * (double) (2*(i+12)+19) / 72.0 ); win[1][i+24] = 0.5 * sin( M_PI / 24.0 * (double) (2*i+13) ) / cos ( M_PI * (double) (2*(i+24)+19) / 72.0 ); win[1][i+30] = win[3][i] = 0.0; win[3][i+6 ] = 0.5 * sin( M_PI / 24.0 * (double) (2*i+1) ) / cos ( M_PI * (double) (2*(i+6 )+19) / 72.0 ); } for(i=0;i<9;i++) COS9[i] = cos( M_PI / 18.0 * (double) i); for(i=0;i<9;i++) tfcos36[i] = 0.5 / cos ( M_PI * (double) (i*2+1) / 36.0 ); for(i=0;i<3;i++) tfcos12[i] = 0.5 / cos ( M_PI * (double) (i*2+1) / 12.0 ); COS6_1 = cos( M_PI / 6.0 * (double) 1); COS6_2 = cos( M_PI / 6.0 * (double) 2); for(i=0;i<12;i++) { win[2][i] = 0.5 * sin( M_PI / 24.0 * (double) (2*i+1) ) / cos ( M_PI * (double) (2*i+7) / 24.0 ); for(j=0;j<6;j++) COS1[i][j] = cos( M_PI / 24.0 * (double) ((2*i+7)*(2*j+1)) ); } for(j=0;j<4;j++) { static int len[4] = { 36,36,12,36 }; for(i=0;i 0) { if( i & 1 ) p1 = pow(base,(i+1.0)*0.5); else p2 = pow(base,i*0.5); } pow1_1[j][i] = p1; pow2_1[j][i] = p2; pow1_2[j][i] = M_SQRT2 * p1; pow2_2[j][i] = M_SQRT2 * p2; } } for(j=0;j<9;j++) { struct bandInfoStruct *bi = (struct bandInfoStruct *)&bandInfo[j]; int *mp; int cb,lwin; short *bdf; mp = map[j][0] = mapbuf0[j]; bdf = bi->longDiff; for(i=0,cb = 0; cb < 8 ; cb++,i+=*bdf++) { *mp++ = (*bdf) >> 1; *mp++ = i; *mp++ = 3; *mp++ = cb; } bdf = bi->shortDiff+3; for(cb=3;cb<13;cb++) { int l = (*bdf++) >> 1; for(lwin=0;lwin<3;lwin++) { *mp++ = l; *mp++ = i + lwin; *mp++ = lwin; *mp++ = cb; } i += 6*l; } mapend[j][0] = mp; mp = map[j][1] = mapbuf1[j]; bdf = bi->shortDiff+0; for(i=0,cb=0;cb<13;cb++) { int l = (*bdf++) >> 1; for(lwin=0;lwin<3;lwin++) { *mp++ = l; *mp++ = i + lwin; *mp++ = lwin; *mp++ = cb; } i += 6*l; } mapend[j][1] = mp; mp = map[j][2] = mapbuf2[j]; bdf = bi->longDiff; for(cb = 0; cb < 22 ; cb++) { *mp++ = (*bdf++) >> 1; *mp++ = cb; } mapend[j][2] = mp; } for(j=0;j<9;j++) { for(i=0;i<23;i++) { longLimit[j][i] = (bandInfo[j].longIdx[i] - 1 + 8) / 18 + 1; if(longLimit[j][i] > (down_sample_sblimit) ) longLimit[j][i] = down_sample_sblimit; } for(i=0;i<14;i++) { shortLimit[j][i] = (bandInfo[j].shortIdx[i] - 1) / 18 + 1; if(shortLimit[j][i] > (down_sample_sblimit) ) shortLimit[j][i] = down_sample_sblimit; } } for(i=0;i<5;i++) { for(j=0;j<6;j++) { for(k=0;k<6;k++) { int n = k + j * 6 + i * 36; i_slen2[n] = i|(j<<3)|(k<<6)|(3<<12); } } } for(i=0;i<4;i++) { for(j=0;j<4;j++) { for(k=0;k<4;k++) { int n = k + j * 4 + i * 16; i_slen2[n+180] = i|(j<<3)|(k<<6)|(4<<12); } } } for(i=0;i<4;i++) { for(j=0;j<3;j++) { int n = j + i * 3; i_slen2[n+244] = i|(j<<3) | (5<<12); n_slen2[n+500] = i|(j<<3) | (2<<12) | (1<<15); } } for(i=0;i<5;i++) { for(j=0;j<5;j++) { for(k=0;k<4;k++) { int l; for(l=0;l<4;l++) { int n = l + k * 4 + j * 16 + i * 80; n_slen2[n] = i|(j<<3)|(k<<6)|(l<<9)|(0<<12); } } } } for(i=0;i<5;i++) { for(j=0;j<5;j++) { for(k=0;k<4;k++) { int n = k + j * 4 + i * 20; n_slen2[n+400] = i|(j<<3)|(k<<6)|(1<<12); } } } } /* * read additional side information */ #ifdef MPEG1 static int III_get_side_info_1(struct III_sideinfo *si,int stereo, int ms_stereo,long sfreq,int single) { int ch, gr; int powdiff = (single == 3) ? 4 : 0; si->main_data_begin = getbits(9); if (stereo == 1) si->private_bits = getbits_fast(5); else si->private_bits = getbits_fast(3); for (ch=0; chch[ch].gr[0].scfsi = -1; si->ch[ch].gr[1].scfsi = getbits_fast(4); } for (gr=0; gr<2; gr++) { for (ch=0; chch[ch].gr[gr]); gr_infos->part2_3_length = getbits(12); gr_infos->big_values = getbits_fast(9); if(gr_infos->big_values > 288) { // fprintf(stderr,"big_values too large! %i\n",gr_infos->big_values); //gr_infos->big_values = 288; return 0; } { unsigned int qss = getbits_fast(8); if ((unsigned char)qss > *maxGain) *maxGain = (unsigned char)qss; if ((unsigned char)qss < *minGain) *minGain = (unsigned char)qss; gr_infos->pow2gain = gainpow2+256 - qss + powdiff; } if(ms_stereo) gr_infos->pow2gain += 2; gr_infos->scalefac_compress = getbits_fast(4); /* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */ if(get1bit()) { int i; gr_infos->block_type = getbits_fast(2); gr_infos->mixed_block_flag = get1bit(); gr_infos->table_select[0] = getbits_fast(5); gr_infos->table_select[1] = getbits_fast(5); /* * table_select[2] not needed, because there is no region2, * but to satisfy some verifications tools we set it either. */ gr_infos->table_select[2] = 0; for(i=0;i<3;i++) { unsigned int sbg = (getbits_fast(3)<<3); gr_infos->full_gain[i] = gr_infos->pow2gain + sbg; } if(gr_infos->block_type == 0) { // fprintf(stderr,"Blocktype == 0 and window-switching == 1 not allowed.\n"); return 0; /* error seems to be very good recoverable, so don't exit */ /* exit(1); */ } /* region_count/start parameters are implicit in this case. */ gr_infos->region1start = 36>>1; gr_infos->region2start = 576>>1; } else { int i,r0c,r1c; for (i=0; i<3; i++) gr_infos->table_select[i] = getbits_fast(5); r0c = getbits_fast(4); r1c = getbits_fast(3); gr_infos->region1start = bandInfo[sfreq].longIdx[r0c+1] >> 1 ; gr_infos->region2start = bandInfo[sfreq].longIdx[r0c+1+r1c+1] >> 1; gr_infos->block_type = 0; gr_infos->mixed_block_flag = 0; } gr_infos->preflag = get1bit(); gr_infos->scalefac_scale = get1bit(); gr_infos->count1table_select = get1bit(); } } return 1; } #endif /* * Side Info for MPEG 2.0 / LSF */ static int III_get_side_info_2(struct III_sideinfo *si,int stereo, int ms_stereo,long sfreq,int single) { int ch; int powdiff = (single == 3) ? 4 : 0; si->main_data_begin = getbits(8); if (stereo == 1) si->private_bits = get1bit(); else si->private_bits = getbits_fast(2); for (ch=0; chch[ch].gr[0]); unsigned int qss; gr_infos->part2_3_length = getbits(12); gr_infos->big_values = getbits_fast(9); if(gr_infos->big_values > 288) { // fprintf(stderr,"big_values too large! %i\n",gr_infos->big_values); //gr_infos->big_values = 288; return 0; } qss=getbits_fast(8); if ((unsigned char)qss > *maxGain) *maxGain = (unsigned char)qss; if ((unsigned char)qss < *minGain) *minGain = (unsigned char)qss; gr_infos->pow2gain = gainpow2+256 - qss + powdiff; if(ms_stereo) gr_infos->pow2gain += 2; gr_infos->scalefac_compress = getbits(9); /* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */ if(get1bit()) { int i; gr_infos->block_type = getbits_fast(2); gr_infos->mixed_block_flag = get1bit(); gr_infos->table_select[0] = getbits_fast(5); gr_infos->table_select[1] = getbits_fast(5); /* * table_select[2] not needed, because there is no region2, * but to satisfy some verifications tools we set it either. */ gr_infos->table_select[2] = 0; for(i=0;i<3;i++) { unsigned int sbg = (getbits_fast(3)<<3); gr_infos->full_gain[i] = gr_infos->pow2gain + sbg; } if(gr_infos->block_type == 0) { // fprintf(stderr,"Blocktype == 0 and window-switching == 1 not allowed.\n"); return 0; /* error seems to be very good recoverable, so don't exit */ /* exit(1); */ } /* region_count/start parameters are implicit in this case. */ /* check this again! */ if(gr_infos->block_type == 2) gr_infos->region1start = 36>>1; else if(sfreq == 8) /* check this for 2.5 and sfreq=8 */ gr_infos->region1start = 108>>1; else gr_infos->region1start = 54>>1; gr_infos->region2start = 576>>1; } else { int i,r0c,r1c; for (i=0; i<3; i++) gr_infos->table_select[i] = getbits_fast(5); r0c = getbits_fast(4); r1c = getbits_fast(3); gr_infos->region1start = bandInfo[sfreq].longIdx[r0c+1] >> 1 ; gr_infos->region2start = bandInfo[sfreq].longIdx[r0c+1+r1c+1] >> 1; gr_infos->block_type = 0; gr_infos->mixed_block_flag = 0; } gr_infos->scalefac_scale = get1bit(); gr_infos->count1table_select = get1bit(); } return 1; } /* * read scalefactors */ #ifdef MPEG1 static int III_get_scale_factors_1(int *scf,struct gr_info_s *gr_infos) { static const unsigned char slen[2][16] = { {0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4}, {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3} }; int numbits; int num0 = slen[0][gr_infos->scalefac_compress]; int num1 = slen[1][gr_infos->scalefac_compress]; if (gr_infos->block_type == 2) { int i=18; numbits = (num0 + num1) * 18; if (gr_infos->mixed_block_flag) { for (i=8;i;i--) *scf++ = getbits_fast(num0); i = 9; numbits -= num0; /* num0 * 17 + num1 * 18 */ } for (;i;i--) *scf++ = getbits_fast(num0); for (i = 18; i; i--) *scf++ = getbits_fast(num1); *scf++ = 0; *scf++ = 0; *scf++ = 0; /* short[13][0..2] = 0 */ } else { int i; int scfsi = gr_infos->scfsi; if(scfsi < 0) { /* scfsi < 0 => granule == 0 */ for(i=11;i;i--) *scf++ = getbits_fast(num0); for(i=10;i;i--) *scf++ = getbits_fast(num1); numbits = (num0 + num1) * 10 + num0; } else { numbits = 0; if(!(scfsi & 0x8)) { for (i=6;i;i--) *scf++ = getbits_fast(num0); numbits += num0 * 6; } else { scf += 6; } if(!(scfsi & 0x4)) { for (i=5;i;i--) *scf++ = getbits_fast(num0); numbits += num0 * 5; } else { scf += 5; } if(!(scfsi & 0x2)) { for(i=5;i;i--) *scf++ = getbits_fast(num1); numbits += num1 * 5; } else { scf += 5; } if(!(scfsi & 0x1)) { for (i=5;i;i--) *scf++ = getbits_fast(num1); numbits += num1 * 5; } else { scf += 5; } } *scf++ = 0; /* no l[21] in original sources */ } return numbits; } #endif static int III_get_scale_factors_2(int *scf,struct gr_info_s *gr_infos,int i_stereo) { unsigned char *pnt; int i,j; unsigned int slen; int n = 0; int numbits = 0; static const unsigned char stab[3][6][4] = { { { 6, 5, 5,5 } , { 6, 5, 7,3 } , { 11,10,0,0} , { 7, 7, 7,0 } , { 6, 6, 6,3 } , { 8, 8,5,0} } , { { 9, 9, 9,9 } , { 9, 9,12,6 } , { 18,18,0,0} , {12,12,12,0 } , {12, 9, 9,6 } , { 15,12,9,0} } , { { 6, 9, 9,9 } , { 6, 9,12,6 } , { 15,18,0,0} , { 6,15,12,0 } , { 6,12, 9,6 } , { 6,18,9,0} } }; if(i_stereo) /* i_stereo AND second channel -> do_layer3() checks this */ slen = i_slen2[gr_infos->scalefac_compress>>1]; else slen = n_slen2[gr_infos->scalefac_compress]; gr_infos->preflag = (slen>>15) & 0x1; n = 0; if( gr_infos->block_type == 2 ) { n++; if(gr_infos->mixed_block_flag) n++; } pnt = (unsigned char *)stab[n][(slen>>12)&0x7]; for(i=0;i<4;i++) { int num = slen & 0x7; slen >>= 3; if(num) { for(j=0;j<(int)(pnt[i]);j++) *scf++ = getbits_fast(num); numbits += pnt[i] * num; } else { for(j=0;j<(int)(pnt[i]);j++) *scf++ = 0; } } n = (n << 1) + 1; for(i=0;iscalefac_scale; real *xrpnt = (real *) xr; int l[3],l3; int part2remain = gr_infos->part2_3_length - part2bits; int *me; { int i; for(i=(&xr[SBLIMIT][0]-xrpnt)>>1;i>0;i--) { *xrpnt++ = 0.0; *xrpnt++ = 0.0; } xrpnt = (real *) xr; } { int bv = gr_infos->big_values; int region1 = gr_infos->region1start; int region2 = gr_infos->region2start; l3 = ((576>>1)-bv)>>1; /* * we may lose the 'odd' bit here !! * check this later again */ if(bv <= region1) { l[0] = bv; l[1] = 0; l[2] = 0; } else { l[0] = region1; if(bv <= region2) { l[1] = bv - l[0]; l[2] = 0; } else { l[1] = region2 - l[0]; l[2] = bv - region2; } } } if(gr_infos->block_type == 2) { /* * decoding with short or mixed mode BandIndex table */ int i,max[4]; int step=0,lwin=0,cb=0; register real v = 0.0; register int *m,mc; if(gr_infos->mixed_block_flag) { max[3] = -1; max[0] = max[1] = max[2] = 2; m = map[sfreq][0]; me = mapend[sfreq][0]; } else { max[0] = max[1] = max[2] = max[3] = -1; /* max[3] not really needed in this case */ m = map[sfreq][1]; me = mapend[sfreq][1]; } mc = 0; for(i=0;i<2;i++) { int lp = l[i]; struct newhuff *h = (struct newhuff *)(ht+gr_infos->table_select[i]); for(;lp;lp--,mc--) { register int x,y; if( (!mc) ) { mc = *m++; xrpnt = ((real *) xr) + (*m++); lwin = *m++; cb = *m++; if(lwin == 3) { v = gr_infos->pow2gain[(*scf++) << shift]; step = 1; } else { v = gr_infos->full_gain[lwin][(*scf++) << shift]; step = 3; } } { register short *val = (short *)h->table; while((y=*val++)<0) { if (get1bit()) val -= y; part2remain--; } x = y >> 4; y &= 0xf; } if(x == 15) { max[lwin] = cb; part2remain -= h->linbits+1; x += getbits((int)h->linbits); if(get1bit()) *xrpnt = -ispow[x] * v; else *xrpnt = ispow[x] * v; } else if(x) { max[lwin] = cb; if(get1bit()) *xrpnt = -ispow[x] * v; else *xrpnt = ispow[x] * v; part2remain--; } else *xrpnt = 0.0; xrpnt += step; if(y == 15) { max[lwin] = cb; part2remain -= h->linbits+1; y += getbits((int)h->linbits); if(get1bit()) *xrpnt = -ispow[y] * v; else *xrpnt = ispow[y] * v; } else if(y) { max[lwin] = cb; if(get1bit()) *xrpnt = -ispow[y] * v; else *xrpnt = ispow[y] * v; part2remain--; } else *xrpnt = 0.0; xrpnt += step; } } for(;l3 && (part2remain > 0);l3--) { struct newhuff *h = (struct newhuff *)(htc+gr_infos->count1table_select); register short *val = (short *)h->table,a; while((a=*val++)<0) { part2remain--; if(part2remain < 0) { part2remain++; a = 0; break; } if (get1bit()) val -= a; } for(i=0;i<4;i++) { if(!(i & 1)) { if(!mc) { mc = *m++; xrpnt = ((real *) xr) + (*m++); lwin = *m++; cb = *m++; if(lwin == 3) { v = gr_infos->pow2gain[(*scf++) << shift]; step = 1; } else { v = gr_infos->full_gain[lwin][(*scf++) << shift]; step = 3; } } mc--; } if( (a & (0x8>>i)) ) { max[lwin] = cb; part2remain--; if(part2remain < 0) { part2remain++; break; } if(get1bit()) *xrpnt = -v; else *xrpnt = v; } else *xrpnt = 0.0; xrpnt += step; } } while( m < me ) { if(!mc) { mc = *m++; xrpnt = ((real *) xr) + *m++; if( (*m++) == 3) step = 1; else step = 3; m++; /* cb */ } mc--; *xrpnt = 0.0; xrpnt += step; *xrpnt = 0.0; xrpnt += step; /* we could add a little opt. here: * if we finished a band for window 3 or a long band * further bands could copied in a simple loop without a * special 'map' decoding */ } gr_infos->maxband[0] = max[0]+1; gr_infos->maxband[1] = max[1]+1; gr_infos->maxband[2] = max[2]+1; gr_infos->maxbandl = max[3]+1; { int rmax = max[0] > max[1] ? max[0] : max[1]; rmax = (rmax > max[2] ? rmax : max[2]) + 1; gr_infos->maxb = rmax ? shortLimit[sfreq][rmax] : longLimit[sfreq][max[3]+1]; } } else { /* * decoding with 'long' BandIndex table (block_type != 2) */ int *pretab = (int *)(gr_infos->preflag ? pretab1 : pretab2); int i,max = -1; int cb = 0; register int *m = map[sfreq][2]; register real v = 0.0; register int mc = 0; #if 0 me = mapend[sfreq][2]; #endif /* * long hash table values */ for(i=0;i<3;i++) { int lp = l[i]; struct newhuff *h = (struct newhuff *)(ht+gr_infos->table_select[i]); for(;lp;lp--,mc--) { int x,y; if(!mc) { mc = *m++; v = gr_infos->pow2gain[((*scf++) + (*pretab++)) << shift]; cb = *m++; } { register short *val = (short *)h->table; while((y=*val++)<0) { if (get1bit()) val -= y; part2remain--; } x = y >> 4; y &= 0xf; } if (x == 15) { max = cb; part2remain -= h->linbits+1; x += getbits((int)h->linbits); if(get1bit()) *xrpnt++ = -ispow[x] * v; else *xrpnt++ = ispow[x] * v; } else if(x) { max = cb; if(get1bit()) *xrpnt++ = -ispow[x] * v; else *xrpnt++ = ispow[x] * v; part2remain--; } else *xrpnt++ = 0.0; if (y == 15) { max = cb; part2remain -= h->linbits+1; y += getbits((int)h->linbits); if(get1bit()) *xrpnt++ = -ispow[y] * v; else *xrpnt++ = ispow[y] * v; } else if(y) { max = cb; if(get1bit()) *xrpnt++ = -ispow[y] * v; else *xrpnt++ = ispow[y] * v; part2remain--; } else *xrpnt++ = 0.0; } } /* * short (count1table) values */ for(;l3 && (part2remain > 0);l3--) { struct newhuff *h = (struct newhuff *)(htc+gr_infos->count1table_select); register short *val = (short *)h->table,a; while((a=*val++)<0) { part2remain--; if(part2remain < 0) { part2remain++; a = 0; break; } if (get1bit()) val -= a; } for(i=0;i<4;i++) { if(!(i & 1)) { if(!mc) { mc = *m++; cb = *m++; v = gr_infos->pow2gain[((*scf++) + (*pretab++)) << shift]; } mc--; } if ( (a & (0x8>>i)) ) { max = cb; part2remain--; if(part2remain < 0) { part2remain++; break; } if(get1bit()) *xrpnt++ = -v; else *xrpnt++ = v; } else *xrpnt++ = 0.0; } } /* * zero part */ for(i=(&xr[SBLIMIT][0]-xrpnt)>>1;i;i--) { *xrpnt++ = 0.0; *xrpnt++ = 0.0; } gr_infos->maxbandl = max+1; gr_infos->maxb = longLimit[sfreq][gr_infos->maxbandl]; } while( part2remain > 16 ) { getbits(16); /* Dismiss stuffing Bits */ part2remain -= 16; } if(part2remain > 0) getbits(part2remain); else if(part2remain < 0) { // fprintf(stderr,"mpg123: Can't rewind stream by %d bits!\n",-part2remain); return -1; /* -> error */ } return 0; } /* * III_stereo: calculate real channel values for Joint-I-Stereo-mode */ static void III_i_stereo(real xr_buf[2][SBLIMIT][SSLIMIT],int *scalefac, struct gr_info_s *gr_infos,int sfreq,int ms_stereo,int lsf) { real (*xr)[SBLIMIT*SSLIMIT] = (real (*)[SBLIMIT*SSLIMIT] ) xr_buf; struct bandInfoStruct *bi = (struct bandInfoStruct *)&bandInfo[sfreq]; real *tabl1,*tabl2; if(lsf) { int p = gr_infos->scalefac_compress & 0x1; if(ms_stereo) { tabl1 = pow1_2[p]; tabl2 = pow2_2[p]; } else { tabl1 = pow1_1[p]; tabl2 = pow2_1[p]; } } else { if(ms_stereo) { tabl1 = tan1_2; tabl2 = tan2_2; } else { tabl1 = tan1_1; tabl2 = tan2_1; } } if (gr_infos->block_type == 2) { int lwin,do_l = 0; if( gr_infos->mixed_block_flag ) do_l = 1; for (lwin=0;lwin<3;lwin++) /* process each window */ { /* get first band with zero values */ int is_p,sb,idx,sfb = gr_infos->maxband[lwin]; /* sfb is minimal 3 for mixed mode */ if(sfb > 3) do_l = 0; for(;sfb<12;sfb++) { is_p = scalefac[sfb*3+lwin-gr_infos->mixed_block_flag]; /* scale: 0-15 */ if(is_p != 7) { real t1,t2; sb = bi->shortDiff[sfb]; idx = bi->shortIdx[sfb] + lwin; t1 = tabl1[is_p]; t2 = tabl2[is_p]; for (; sb > 0; sb--,idx+=3) { real v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } } #if 1 /* in the original: copy 10 to 11 , here: copy 11 to 12 maybe still wrong??? (copy 12 to 13?) */ is_p = scalefac[11*3+lwin-gr_infos->mixed_block_flag]; /* scale: 0-15 */ sb = bi->shortDiff[12]; idx = bi->shortIdx[12] + lwin; #else is_p = scalefac[10*3+lwin-gr_infos->mixed_block_flag]; /* scale: 0-15 */ sb = bi->shortDiff[11]; idx = bi->shortIdx[11] + lwin; #endif if(is_p != 7) { real t1,t2; t1 = tabl1[is_p]; t2 = tabl2[is_p]; for ( ; sb > 0; sb--,idx+=3 ) { real v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } } /* end for(lwin; .. ; . ) */ if (do_l) { /* also check l-part, if ALL bands in the three windows are 'empty' * and mode = mixed_mode */ int sfb = gr_infos->maxbandl; int idx = bi->longIdx[sfb]; for ( ; sfb<8; sfb++ ) { int sb = bi->longDiff[sfb]; int is_p = scalefac[sfb]; /* scale: 0-15 */ if(is_p != 7) { real t1,t2; t1 = tabl1[is_p]; t2 = tabl2[is_p]; for ( ; sb > 0; sb--,idx++) { real v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } else idx += sb; } } } else /* ((gr_infos->block_type != 2)) */ { int sfb = gr_infos->maxbandl; int is_p,idx = bi->longIdx[sfb]; for ( ; sfb<21; sfb++) { int sb = bi->longDiff[sfb]; is_p = scalefac[sfb]; /* scale: 0-15 */ if(is_p != 7) { real t1,t2; t1 = tabl1[is_p]; t2 = tabl2[is_p]; for ( ; sb > 0; sb--,idx++) { real v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } else idx += sb; } is_p = scalefac[20]; /* copy l-band 20 to l-band 21 */ if(is_p != 7) { int sb; real t1 = tabl1[is_p],t2 = tabl2[is_p]; for ( sb = bi->longDiff[21]; sb > 0; sb--,idx++ ) { real v = xr[0][idx]; xr[0][idx] = v * t1; xr[1][idx] = v * t2; } } } /* ... */ } static void III_antialias(real xr[SBLIMIT][SSLIMIT],struct gr_info_s *gr_infos) { int sblim; if(gr_infos->block_type == 2) { if(!gr_infos->mixed_block_flag) return; sblim = 1; } else { sblim = gr_infos->maxb-1; } /* 31 alias-reduction operations between each pair of sub-bands */ /* with 8 butterflies between each pair */ { int sb; real *xr1=(real *) xr[1]; for(sb=sblim;sb;sb--,xr1+=10) { int ss; real *cs=aa_cs,*ca=aa_ca; real *xr2 = xr1; for(ss=7;ss>=0;ss--) { /* upper and lower butterfly inputs */ register real bu = *--xr2,bd = *xr1; *xr2 = (bu * (*cs) ) - (bd * (*ca) ); *xr1++ = (bd * (*cs++) ) + (bu * (*ca++) ); } } } } /* DCT insipired by Jeff Tsay's DCT from the maplay package this is an optimized version with manual unroll. References: [1] S. Winograd: "On Computing the Discrete Fourier Transform", Mathematics of Computation, Volume 32, Number 141, January 1978, Pages 175-199 */ static void dct36(real *inbuf,real *o1,real *o2,real *wintab,real *tsbuf) { { register real *in = inbuf; in[17]+=in[16]; in[16]+=in[15]; in[15]+=in[14]; in[14]+=in[13]; in[13]+=in[12]; in[12]+=in[11]; in[11]+=in[10]; in[10]+=in[9]; in[9] +=in[8]; in[8] +=in[7]; in[7] +=in[6]; in[6] +=in[5]; in[5] +=in[4]; in[4] +=in[3]; in[3] +=in[2]; in[2] +=in[1]; in[1] +=in[0]; in[17]+=in[15]; in[15]+=in[13]; in[13]+=in[11]; in[11]+=in[9]; in[9] +=in[7]; in[7] +=in[5]; in[5] +=in[3]; in[3] +=in[1]; { #define MACRO0(v) { \ real tmp; \ out2[9+(v)] = (tmp = sum0 + sum1) * w[27+(v)]; \ out2[8-(v)] = tmp * w[26-(v)]; } \ sum0 -= sum1; \ ts[SBLIMIT*(8-(v))] = out1[8-(v)] + sum0 * w[8-(v)]; \ ts[SBLIMIT*(9+(v))] = out1[9+(v)] + sum0 * w[9+(v)]; #define MACRO1(v) { \ real sum0,sum1; \ sum0 = tmp1a + tmp2a; \ sum1 = (tmp1b + tmp2b) * tfcos36[(v)]; \ MACRO0(v); } #define MACRO2(v) { \ real sum0,sum1; \ sum0 = tmp2a - tmp1a; \ sum1 = (tmp2b - tmp1b) * tfcos36[(v)]; \ MACRO0(v); } register const real *c = COS9; register real *out2 = o2; register real *w = wintab; register real *out1 = o1; register real *ts = tsbuf; real ta33,ta66,tb33,tb66; ta33 = in[2*3+0] * c[3]; ta66 = in[2*6+0] * c[6]; tb33 = in[2*3+1] * c[3]; tb66 = in[2*6+1] * c[6]; { real tmp1a,tmp2a,tmp1b,tmp2b; tmp1a = in[2*1+0] * c[1] + ta33 + in[2*5+0] * c[5] + in[2*7+0] * c[7]; tmp1b = in[2*1+1] * c[1] + tb33 + in[2*5+1] * c[5] + in[2*7+1] * c[7]; tmp2a = in[2*0+0] + in[2*2+0] * c[2] + in[2*4+0] * c[4] + ta66 + in[2*8+0] * c[8]; tmp2b = in[2*0+1] + in[2*2+1] * c[2] + in[2*4+1] * c[4] + tb66 + in[2*8+1] * c[8]; MACRO1(0); MACRO2(8); } { real tmp1a,tmp2a,tmp1b,tmp2b; tmp1a = ( in[2*1+0] - in[2*5+0] - in[2*7+0] ) * c[3]; tmp1b = ( in[2*1+1] - in[2*5+1] - in[2*7+1] ) * c[3]; tmp2a = ( in[2*2+0] - in[2*4+0] - in[2*8+0] ) * c[6] - in[2*6+0] + in[2*0+0]; tmp2b = ( in[2*2+1] - in[2*4+1] - in[2*8+1] ) * c[6] - in[2*6+1] + in[2*0+1]; MACRO1(1); MACRO2(7); } { real tmp1a,tmp2a,tmp1b,tmp2b; tmp1a = in[2*1+0] * c[5] - ta33 - in[2*5+0] * c[7] + in[2*7+0] * c[1]; tmp1b = in[2*1+1] * c[5] - tb33 - in[2*5+1] * c[7] + in[2*7+1] * c[1]; tmp2a = in[2*0+0] - in[2*2+0] * c[8] - in[2*4+0] * c[2] + ta66 + in[2*8+0] * c[4]; tmp2b = in[2*0+1] - in[2*2+1] * c[8] - in[2*4+1] * c[2] + tb66 + in[2*8+1] * c[4]; MACRO1(2); MACRO2(6); } { real tmp1a,tmp2a,tmp1b,tmp2b; tmp1a = in[2*1+0] * c[7] - ta33 + in[2*5+0] * c[1] - in[2*7+0] * c[5]; tmp1b = in[2*1+1] * c[7] - tb33 + in[2*5+1] * c[1] - in[2*7+1] * c[5]; tmp2a = in[2*0+0] - in[2*2+0] * c[4] + in[2*4+0] * c[8] + ta66 - in[2*8+0] * c[2]; tmp2b = in[2*0+1] - in[2*2+1] * c[4] + in[2*4+1] * c[8] + tb66 - in[2*8+1] * c[2]; MACRO1(3); MACRO2(5); } { real sum0,sum1; sum0 = in[2*0+0] - in[2*2+0] + in[2*4+0] - in[2*6+0] + in[2*8+0]; sum1 = (in[2*0+1] - in[2*2+1] + in[2*4+1] - in[2*6+1] + in[2*8+1] ) * tfcos36[4]; MACRO0(4); } } } } /* * new DCT12 */ static void dct12(real *in,real *rawout1,real *rawout2,register real *wi,register real *ts) { #define DCT12_PART1 \ in5 = in[5*3]; \ in5 += (in4 = in[4*3]); \ in4 += (in3 = in[3*3]); \ in3 += (in2 = in[2*3]); \ in2 += (in1 = in[1*3]); \ in1 += (in0 = in[0*3]); \ \ in5 += in3; in3 += in1; \ \ in2 *= COS6_1; \ in3 *= COS6_1; \ #define DCT12_PART2 \ in0 += in4 * COS6_2; \ \ in4 = in0 + in2; \ in0 -= in2; \ \ in1 += in5 * COS6_2; \ \ in5 = (in1 + in3) * tfcos12[0]; \ in1 = (in1 - in3) * tfcos12[2]; \ \ in3 = in4 + in5; \ in4 -= in5; \ \ in2 = in0 + in1; \ in0 -= in1; { real in0,in1,in2,in3,in4,in5; register real *out1 = rawout1; ts[SBLIMIT*0] = out1[0]; ts[SBLIMIT*1] = out1[1]; ts[SBLIMIT*2] = out1[2]; ts[SBLIMIT*3] = out1[3]; ts[SBLIMIT*4] = out1[4]; ts[SBLIMIT*5] = out1[5]; DCT12_PART1 { real tmp0,tmp1 = (in0 - in4); { real tmp2 = (in1 - in5) * tfcos12[1]; tmp0 = tmp1 + tmp2; tmp1 -= tmp2; } ts[(17-1)*SBLIMIT] = out1[17-1] + tmp0 * wi[11-1]; ts[(12+1)*SBLIMIT] = out1[12+1] + tmp0 * wi[6+1]; ts[(6 +1)*SBLIMIT] = out1[6 +1] + tmp1 * wi[1]; ts[(11-1)*SBLIMIT] = out1[11-1] + tmp1 * wi[5-1]; } DCT12_PART2 ts[(17-0)*SBLIMIT] = out1[17-0] + in2 * wi[11-0]; ts[(12+0)*SBLIMIT] = out1[12+0] + in2 * wi[6+0]; ts[(12+2)*SBLIMIT] = out1[12+2] + in3 * wi[6+2]; ts[(17-2)*SBLIMIT] = out1[17-2] + in3 * wi[11-2]; ts[(6+0)*SBLIMIT] = out1[6+0] + in0 * wi[0]; ts[(11-0)*SBLIMIT] = out1[11-0] + in0 * wi[5-0]; ts[(6+2)*SBLIMIT] = out1[6+2] + in4 * wi[2]; ts[(11-2)*SBLIMIT] = out1[11-2] + in4 * wi[5-2]; } in++; { real in0,in1,in2,in3,in4,in5; register real *out2 = rawout2; DCT12_PART1 { real tmp0,tmp1 = (in0 - in4); { real tmp2 = (in1 - in5) * tfcos12[1]; tmp0 = tmp1 + tmp2; tmp1 -= tmp2; } out2[5-1] = tmp0 * wi[11-1]; out2[0+1] = tmp0 * wi[6+1]; ts[(12+1)*SBLIMIT] += tmp1 * wi[1]; ts[(17-1)*SBLIMIT] += tmp1 * wi[5-1]; } DCT12_PART2 out2[5-0] = in2 * wi[11-0]; out2[0+0] = in2 * wi[6+0]; out2[0+2] = in3 * wi[6+2]; out2[5-2] = in3 * wi[11-2]; ts[(12+0)*SBLIMIT] += in0 * wi[0]; ts[(17-0)*SBLIMIT] += in0 * wi[5-0]; ts[(12+2)*SBLIMIT] += in4 * wi[2]; ts[(17-2)*SBLIMIT] += in4 * wi[5-2]; } in++; { real in0,in1,in2,in3,in4,in5; register real *out2 = rawout2; out2[12]=out2[13]=out2[14]=out2[15]=out2[16]=out2[17]=0.0; DCT12_PART1 { real tmp0,tmp1 = (in0 - in4); { real tmp2 = (in1 - in5) * tfcos12[1]; tmp0 = tmp1 + tmp2; tmp1 -= tmp2; } out2[11-1] = tmp0 * wi[11-1]; out2[6 +1] = tmp0 * wi[6+1]; out2[0+1] += tmp1 * wi[1]; out2[5-1] += tmp1 * wi[5-1]; } DCT12_PART2 out2[11-0] = in2 * wi[11-0]; out2[6 +0] = in2 * wi[6+0]; out2[6 +2] = in3 * wi[6+2]; out2[11-2] = in3 * wi[11-2]; out2[0+0] += in0 * wi[0]; out2[5-0] += in0 * wi[5-0]; out2[0+2] += in4 * wi[2]; out2[5-2] += in4 * wi[5-2]; } } /* * III_hybrid */ static void III_hybrid( PMPSTR mp, real fsIn[SBLIMIT][SSLIMIT],real tsOut[SSLIMIT][SBLIMIT], int ch,struct gr_info_s *gr_infos) { real *tspnt = (real *) tsOut; real (*block)[2][SBLIMIT*SSLIMIT] = mp->hybrid_block; int *blc = mp->hybrid_blc; real *rawout1,*rawout2; int bt; int sb = 0; { int b = blc[ch]; rawout1=block[b][ch]; b=-b+1; rawout2=block[b][ch]; blc[ch] = b; } if(gr_infos->mixed_block_flag) { sb = 2; dct36(fsIn[0],rawout1,rawout2,win[0],tspnt); dct36(fsIn[1],rawout1+18,rawout2+18,win1[0],tspnt+1); rawout1 += 36; rawout2 += 36; tspnt += 2; } bt = gr_infos->block_type; if(bt == 2) { for (; sb<(int)gr_infos->maxb; sb+=2,tspnt+=2,rawout1+=36,rawout2+=36) { dct12(fsIn[sb],rawout1,rawout2,win[2],tspnt); dct12(fsIn[sb+1],rawout1+18,rawout2+18,win1[2],tspnt+1); } } else { for (; sb<(int)gr_infos->maxb; sb+=2,tspnt+=2,rawout1+=36,rawout2+=36) { dct36(fsIn[sb],rawout1,rawout2,win[bt],tspnt); dct36(fsIn[sb+1],rawout1+18,rawout2+18,win1[bt],tspnt+1); } } for(;sbstereo; int single = fr->single; int ms_stereo; int sfreq = fr->sampling_frequency; int granules; int ch,gr,databits; if(stereo == 1) { /* stream is mono */ single = 0; } if(fr->mode == MPG_MD_JOINT_STEREO) { ms_stereo = fr->mode_ext & 0x2; } else ms_stereo = 0; if(fr->lsf) { granules = 1; if (!(III_get_side_info_2(&sideinfo,stereo,ms_stereo,sfreq,single))) return -32767; } else { granules = 2; #ifdef MPEG1 if (!(III_get_side_info_1(&sideinfo,stereo,ms_stereo,sfreq,single))) return -32767; #else fprintf(stderr,"Not supported\n"); #endif } databits=0; for (gr=0 ; gr < granules ; ++gr) { for (ch=0; ch < stereo ; ++ch) { struct gr_info_s *gr_infos = &(sideinfo.ch[ch].gr[gr]); databits += gr_infos->part2_3_length; } } return databits-8*sideinfo.main_data_begin; } int do_layer3( PMPSTR mp,int *pcm_point) { int gr, ch, ss,clip=0; int scalefacs[2][39]; /* max 39 for short[13][3] mode, mixed: 38, long: 22 */ // struct III_sideinfo sideinfo; struct frame *fr=&(mp->fr); int stereo = fr->stereo; int single = fr->single; int ms_stereo,i_stereo; int sfreq = fr->sampling_frequency; int stereo1,granules; if(set_pointer(mp, (int)sideinfo.main_data_begin) == MP3_ERR) return -32767; if(stereo == 1) { /* stream is mono */ stereo1 = 1; single = 0; } else if(single >= 0) /* stream is stereo, but force to mono */ stereo1 = 1; else stereo1 = 2; if(fr->mode == MPG_MD_JOINT_STEREO) { ms_stereo = fr->mode_ext & 0x2; i_stereo = fr->mode_ext & 0x1; } else ms_stereo = i_stereo = 0; if(fr->lsf) { granules = 1; } else { granules = 2; } for (gr=0;grlsf) part2bits = III_get_scale_factors_2(scalefacs[0],gr_infos,0); else { #ifdef MPEG1 part2bits = III_get_scale_factors_1(scalefacs[0],gr_infos); #else fprintf(stderr,"Not supported\n"); #endif } if(III_dequantize_sample(hybridIn[0], scalefacs[0],gr_infos,sfreq,part2bits)) return 0; } if(stereo == 2) { struct gr_info_s *gr_infos = &(sideinfo.ch[1].gr[gr]); long part2bits; if(fr->lsf) part2bits = III_get_scale_factors_2(scalefacs[1],gr_infos,i_stereo); else { #ifdef MPEG1 part2bits = III_get_scale_factors_1(scalefacs[1],gr_infos); #else fprintf(stderr,"Not supported\n"); #endif } if(III_dequantize_sample(hybridIn[1],scalefacs[1],gr_infos,sfreq,part2bits)) return 0; if(ms_stereo) { int i; for(i=0;ilsf); if(ms_stereo || i_stereo || (single == 3) ) { if(gr_infos->maxb > sideinfo.ch[0].gr[gr].maxb) sideinfo.ch[0].gr[gr].maxb = gr_infos->maxb; else gr_infos->maxb = sideinfo.ch[0].gr[gr].maxb; } switch(single) { case 3: { register int i; register real *in0 = (real *) hybridIn[0],*in1 = (real *) hybridIn[1]; for(i=0;i<(int)(SSLIMIT*gr_infos->maxb);i++,in0++) *in0 = (*in0 + *in1++); /* *0.5 done by pow-scale */ } break; case 1: { register int i; register real *in0 = (real *) hybridIn[0],*in1 = (real *) hybridIn[1]; for(i=0;i<(int)(SSLIMIT*gr_infos->maxb);i++) *in0++ = *in1++; } break; } } for(ch=0;ch= 0) { clip += synth_1to1_mono(mp, hybridOut[0][ss],pcm_point); } else { int p1 = *pcm_point; clip += synth_1to1(mp, hybridOut[0][ss],0,&p1); clip += synth_1to1(mp, hybridOut[1][ss],1,pcm_point); } } } return 0; } ./mpglibDBL/common.c0000644000175000017500000001723210173230675013500 0ustar rizlarizla/* $Id: common.c,v 1.4 2005/01/18 15:56:45 snelg Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #ifdef HAVE_FCNTL_H #include #endif #ifdef macintosh #include #include #else #include #include #endif #include "common.h" #ifdef WITH_DMALLOC #include #endif #ifdef __BEOS__ #include #endif /* __BEOS__ */ // In C++ the array first must be prototyped, why ? extern const int tabsel_123 [2] [3] [16]; const int tabsel_123 [2] [3] [16] = { { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } }; const long freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000 }; int bitindex; unsigned char *wordpointer; unsigned char *pcm_sample; int pcm_point = 0; #if defined( USE_LAYER_1 ) || defined ( USE_LAYER_2 ) real muls[27][64]; #endif #if 0 static void get_II_stuff(struct frame *fr) { static const int translate [3] [2] [16] = /* char ? */ { { { 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0 } , { 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0 } } , { { 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 } , { 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0 } } , { { 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0 } , { 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0 } } }; int table,sblim; static const struct al_table2 *tables[5] = { alloc_0, alloc_1, alloc_2, alloc_3 , alloc_4 }; static int sblims[5] = { 27 , 30 , 8, 12 , 30 }; if(fr->lsf) table = 4; else table = translate[fr->sampling_frequency][2-fr->stereo][fr->bitrate_index]; sblim = sblims[table]; fr->alloc = tables[table]; fr->II_sblimit = sblim; } #endif #define HDRCMPMASK 0xfffffd00 int head_check(unsigned long head,int check_layer) { /* look for a valid header. if check_layer > 0, then require that nLayer = check_layer. */ /* bits 13-14 = layer 3 */ int nLayer=4-((head>>17)&3); if( (head & 0xffe00000) != 0xffe00000) { /* syncword */ return FALSE; } #if 0 if(!((head>>17)&3)) { /* bits 13-14 = layer 3 */ return FALSE; } #endif if (3 != nLayer) { #if defined (USE_LAYER_1) || defined (USE_LAYER_2) if (4==nLayer) return FALSE; #else return FALSE; #endif } if (check_layer>0) { if (nLayer != check_layer) return FALSE; } if( ((head>>12)&0xf) == 0xf) { /* bits 16,17,18,19 = 1111 invalid bitrate */ return FALSE; } if( ((head>>10)&0x3) == 0x3 ) { /* bits 20,21 = 11 invalid sampling freq */ return FALSE; } return TRUE; } /* * the code a header and write the information * into the frame structure */ int decode_header(struct frame *fr,unsigned long newhead) { if( newhead & (1<<20) ) { fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1; fr->mpeg25 = 0; } else { fr->lsf = 1; fr->mpeg25 = 1; } fr->lay = 4-((newhead>>17)&3); if( ((newhead>>10)&0x3) == 0x3) { fprintf(stderr,"Stream error\n"); fclose(stdout); fclose(stderr); exit(1); } if(fr->mpeg25) { fr->sampling_frequency = 6 + ((newhead>>10)&0x3); } else fr->sampling_frequency = ((newhead>>10)&0x3) + (fr->lsf*3); fr->error_protection = ((newhead>>16)&0x1)^0x1; if(fr->mpeg25) /* allow Bitrate change for 2.5 ... */ fr->bitrate_index = ((newhead>>12)&0xf); fr->bitrate_index = ((newhead>>12)&0xf); fr->padding = ((newhead>>9)&0x1); fr->extension = ((newhead>>8)&0x1); fr->mode = ((newhead>>6)&0x3); fr->mode_ext = ((newhead>>4)&0x3); fr->copyright = ((newhead>>3)&0x1); fr->original = ((newhead>>2)&0x1); fr->emphasis = newhead & 0x3; fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; switch(fr->lay) { #ifdef USE_LAYER_1 case 1: fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; fr->framesize /= freqs[fr->sampling_frequency]; fr->framesize = ((fr->framesize+fr->padding)<<2)-4; fr->down_sample=0; fr->down_sample_sblimit = SBLIMIT>>(fr->down_sample); break; #endif #ifdef USE_LAYER_2 case 2: fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; fr->framesize /= freqs[fr->sampling_frequency]; fr->framesize += fr->padding - 4; fr->down_sample=0; fr->down_sample_sblimit = SBLIMIT>>(fr->down_sample); break; #endif case 3: #if 0 fr->do_layer = do_layer3; if(fr->lsf) ssize = (fr->stereo == 1) ? 9 : 17; else ssize = (fr->stereo == 1) ? 17 : 32; #endif #if 0 if(fr->error_protection) ssize += 2; #endif if (fr->bitrate_index==0) fr->framesize=0; else{ fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; fr->framesize /= freqs[fr->sampling_frequency]<<(fr->lsf); fr->framesize = fr->framesize + fr->padding - 4; } break; default: fprintf(stderr,"Sorry, layer %d not supported\n",fr->lay); return (0); } /* print_header(fr); */ return 1; } #if 1 void print_header(struct frame *fr) { static const char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" }; static const char *layers[4] = { "Unknown" , "I", "II", "III" }; fprintf(stderr,"MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n", fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), layers[fr->lay],freqs[fr->sampling_frequency], modes[fr->mode],fr->mode_ext,fr->framesize+4); fprintf(stderr,"Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n", fr->stereo,fr->copyright?"Yes":"No", fr->original?"Yes":"No",fr->error_protection?"Yes":"No", fr->emphasis); fprintf(stderr,"Bitrate: %d Kbits/s, Extension value: %d\n", tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],fr->extension); } void print_header_compact(struct frame *fr) { static const char *modes[4] = { "stereo", "joint-stereo", "dual-channel", "mono" }; static const char *layers[4] = { "Unknown" , "I", "II", "III" }; fprintf(stderr,"MPEG %s layer %s, %d kbit/s, %ld Hz %s\n", fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), layers[fr->lay], tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index], freqs[fr->sampling_frequency], modes[fr->mode]); } #endif unsigned int getbits(int number_of_bits) { unsigned long rval; if(!number_of_bits) return 0; { rval = wordpointer[0]; rval <<= 8; rval |= wordpointer[1]; rval <<= 8; rval |= wordpointer[2]; rval <<= bitindex; rval &= 0xffffff; bitindex += number_of_bits; rval >>= (24-number_of_bits); wordpointer += (bitindex>>3); bitindex &= 7; } return rval; } unsigned int getbits_fast(int number_of_bits) { unsigned long rval; { rval = wordpointer[0]; rval <<= 8; rval |= wordpointer[1]; rval <<= bitindex; rval &= 0xffff; bitindex += number_of_bits; rval >>= (16-number_of_bits); wordpointer += (bitindex>>3); bitindex &= 7; } return rval; } int set_pointer( PMPSTR mp, long backstep) { unsigned char *bsbufold; if(mp->fsizeold < 0 && backstep > 0) { // fprintf(stderr,"Can't step back %ld!\n",backstep); return MP3_ERR; } bsbufold = mp->bsspace[1-mp->bsnum] + 512; wordpointer -= backstep; if (backstep) memcpy(wordpointer,bsbufold+mp->fsizeold-backstep,(size_t)backstep); bitindex = 0; return MP3_OK; } ./mpglibDBL/dct64_i386.h0000644000175000017500000000161607716027257013722 0ustar rizlarizla/* ** Copyright (C) 2000 Albert L. Faber ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef MPGLIB_DCT64_I386_H_INCLUDED #define MPGLIB_DCT64_I386_H_INCLUDED #include "common.h" void dct64( real *a,real *b,real *c); #endif ./mpglibDBL/layer3.h0000644000175000017500000000165207714631704013420 0ustar rizlarizla/* ** Copyright (C) 2000 Albert L. Faber ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef LAYER3_H_INCLUDED #define LAYER3_H_INCLUDED void init_layer3(int); int do_layer3_sideinfo(struct frame *fr); int do_layer3( PMPSTR mp,int *pcm_point); #endif ./mpglibDBL/layer1.h0000644000175000017500000000163007451136440013405 0ustar rizlarizla/* ** Copyright (C) 2000 Albert L. Faber ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef LAYER1_H_INCLUDED #define LAYER1_H_INCLUDED int do_layer1(PMPSTR mp, unsigned char *pcm_sample,int *pcm_point); #endif ./mpglibDBL/VbrTag.h0000644000175000017500000000545107716027257013413 0ustar rizlarizla/* * Xing VBR tagging for LAME. * * Copyright (c) 1999 A.L. Faber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. */ #ifndef LAME_VRBTAG_H #define LAME_VRBTAG_H #include "lame.h" #include "config.h" /* ----------------------------------------------------------- * A Vbr header may be present in the ancillary * data field of the first frame of an mp3 bitstream * The Vbr header (optionally) contains * frames total number of audio frames in the bitstream * bytes total number of bytes in the bitstream * toc table of contents * toc (table of contents) gives seek points * for random access * the ith entry determines the seek point for * i-percent duration * seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes * e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes */ #define FRAMES_FLAG 0x0001 #define BYTES_FLAG 0x0002 #define TOC_FLAG 0x0004 #define VBR_SCALE_FLAG 0x0008 #define NUMTOCENTRIES 100 #define FRAMES_AND_BYTES (FRAMES_FLAG | BYTES_FLAG) /*structure to receive extracted header */ /* toc may be NULL*/ typedef struct { int h_id; /* from MPEG header, 0=MPEG2, 1=MPEG1 */ int samprate; /* determined from MPEG header */ int flags; /* from Vbr header data */ int frames; /* total bit stream frames from Vbr header data */ int bytes; /* total bit stream bytes from Vbr header data*/ int vbr_scale; /* encoded vbr scale from Vbr header data*/ unsigned char toc[NUMTOCENTRIES]; /* may be NULL if toc not desired*/ int headersize; /* size of VBR header, in bytes */ } VBRTAGDATA; int CheckVbrTag(unsigned char *buf); int GetVbrTag(VBRTAGDATA *pTagData, unsigned char *buf); int SeekPoint(unsigned char TOC[NUMTOCENTRIES], int file_bytes, float percent); int InitVbrTag(lame_global_flags *gfp); int PutVbrTag(lame_global_flags *gfp,FILE *fid,int nVbrScale); int PutLameVBR(lame_global_flags *gfp, FILE *fpStream, u_char *pbtStreamBuffer, uint32_t id3v2size, uint16_t crc); void AddVbrFrame(lame_global_flags *gfp); void ReportLameTagProgress(lame_global_flags *gfp,int nStart); #endif ./mpglibDBL/interface.h0000644000175000017500000000251707714631704014162 0ustar rizlarizla/* ** Copyright (C) 2000 Albert L. Faber ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INTERFACE_H_INCLUDED #define INTERFACE_H_INCLUDED #include "common.h" #include "../gain_analysis.h" #if defined(__cplusplus) extern "C" { #endif extern Float_t *lSamp; extern Float_t *rSamp; extern Float_t *maxSamp; extern unsigned char *maxGain; extern unsigned char *minGain; extern unsigned char maxAmpOnly; extern int procSamp; BOOL InitMP3(PMPSTR mp); int decodeMP3(PMPSTR mp,unsigned char *inmemory,int inmemsize,int *done); void ExitMP3(PMPSTR mp); /* added remove_buf to support mpglib seeking */ void remove_buf(PMPSTR mp); #if defined(__cplusplus) } #endif #endif ./mpglibDBL/decode_i386.h0000644000175000017500000000172207714631704014213 0ustar rizlarizla/* ** Copyright (C) 2000 Albert L. Faber ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef DECODE_I386_H_INCLUDED #define DECODE_I386_H_INCLUDED #include "common.h" int synth_1to1_mono(PMPSTR mp, real *bandPtr,int *pnt); int synth_1to1(PMPSTR mp, real *bandPtr,int channel,int *pnt); #endif ./mpglibDBL/dct64_i386.c0000644000175000017500000002273107716027257013716 0ustar rizlarizla/* * Discrete Cosine Tansform (DCT) for subband synthesis * optimized for machines with no auto-increment. * The performance is highly compiler dependend. Maybe * the dct64.c version for 'normal' processor may be faster * even for Intel processors. */ /* $Id: dct64_i386.c,v 1.2 2003/08/12 00:02:55 snelg Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include "dct64_i386.h" #include "tabinit.h" #ifdef WITH_DMALLOC #include #endif static void dct64_1(real *out0,real *out1,real *b1,real *b2,real *samples) { { register real *costab = pnts[0]; b1[0x00] = samples[0x00] + samples[0x1F]; b1[0x1F] = (samples[0x00] - samples[0x1F]) * costab[0x0]; b1[0x01] = samples[0x01] + samples[0x1E]; b1[0x1E] = (samples[0x01] - samples[0x1E]) * costab[0x1]; b1[0x02] = samples[0x02] + samples[0x1D]; b1[0x1D] = (samples[0x02] - samples[0x1D]) * costab[0x2]; b1[0x03] = samples[0x03] + samples[0x1C]; b1[0x1C] = (samples[0x03] - samples[0x1C]) * costab[0x3]; b1[0x04] = samples[0x04] + samples[0x1B]; b1[0x1B] = (samples[0x04] - samples[0x1B]) * costab[0x4]; b1[0x05] = samples[0x05] + samples[0x1A]; b1[0x1A] = (samples[0x05] - samples[0x1A]) * costab[0x5]; b1[0x06] = samples[0x06] + samples[0x19]; b1[0x19] = (samples[0x06] - samples[0x19]) * costab[0x6]; b1[0x07] = samples[0x07] + samples[0x18]; b1[0x18] = (samples[0x07] - samples[0x18]) * costab[0x7]; b1[0x08] = samples[0x08] + samples[0x17]; b1[0x17] = (samples[0x08] - samples[0x17]) * costab[0x8]; b1[0x09] = samples[0x09] + samples[0x16]; b1[0x16] = (samples[0x09] - samples[0x16]) * costab[0x9]; b1[0x0A] = samples[0x0A] + samples[0x15]; b1[0x15] = (samples[0x0A] - samples[0x15]) * costab[0xA]; b1[0x0B] = samples[0x0B] + samples[0x14]; b1[0x14] = (samples[0x0B] - samples[0x14]) * costab[0xB]; b1[0x0C] = samples[0x0C] + samples[0x13]; b1[0x13] = (samples[0x0C] - samples[0x13]) * costab[0xC]; b1[0x0D] = samples[0x0D] + samples[0x12]; b1[0x12] = (samples[0x0D] - samples[0x12]) * costab[0xD]; b1[0x0E] = samples[0x0E] + samples[0x11]; b1[0x11] = (samples[0x0E] - samples[0x11]) * costab[0xE]; b1[0x0F] = samples[0x0F] + samples[0x10]; b1[0x10] = (samples[0x0F] - samples[0x10]) * costab[0xF]; } { register real *costab = pnts[1]; b2[0x00] = b1[0x00] + b1[0x0F]; b2[0x0F] = (b1[0x00] - b1[0x0F]) * costab[0]; b2[0x01] = b1[0x01] + b1[0x0E]; b2[0x0E] = (b1[0x01] - b1[0x0E]) * costab[1]; b2[0x02] = b1[0x02] + b1[0x0D]; b2[0x0D] = (b1[0x02] - b1[0x0D]) * costab[2]; b2[0x03] = b1[0x03] + b1[0x0C]; b2[0x0C] = (b1[0x03] - b1[0x0C]) * costab[3]; b2[0x04] = b1[0x04] + b1[0x0B]; b2[0x0B] = (b1[0x04] - b1[0x0B]) * costab[4]; b2[0x05] = b1[0x05] + b1[0x0A]; b2[0x0A] = (b1[0x05] - b1[0x0A]) * costab[5]; b2[0x06] = b1[0x06] + b1[0x09]; b2[0x09] = (b1[0x06] - b1[0x09]) * costab[6]; b2[0x07] = b1[0x07] + b1[0x08]; b2[0x08] = (b1[0x07] - b1[0x08]) * costab[7]; b2[0x10] = b1[0x10] + b1[0x1F]; b2[0x1F] = (b1[0x1F] - b1[0x10]) * costab[0]; b2[0x11] = b1[0x11] + b1[0x1E]; b2[0x1E] = (b1[0x1E] - b1[0x11]) * costab[1]; b2[0x12] = b1[0x12] + b1[0x1D]; b2[0x1D] = (b1[0x1D] - b1[0x12]) * costab[2]; b2[0x13] = b1[0x13] + b1[0x1C]; b2[0x1C] = (b1[0x1C] - b1[0x13]) * costab[3]; b2[0x14] = b1[0x14] + b1[0x1B]; b2[0x1B] = (b1[0x1B] - b1[0x14]) * costab[4]; b2[0x15] = b1[0x15] + b1[0x1A]; b2[0x1A] = (b1[0x1A] - b1[0x15]) * costab[5]; b2[0x16] = b1[0x16] + b1[0x19]; b2[0x19] = (b1[0x19] - b1[0x16]) * costab[6]; b2[0x17] = b1[0x17] + b1[0x18]; b2[0x18] = (b1[0x18] - b1[0x17]) * costab[7]; } { register real *costab = pnts[2]; b1[0x00] = b2[0x00] + b2[0x07]; b1[0x07] = (b2[0x00] - b2[0x07]) * costab[0]; b1[0x01] = b2[0x01] + b2[0x06]; b1[0x06] = (b2[0x01] - b2[0x06]) * costab[1]; b1[0x02] = b2[0x02] + b2[0x05]; b1[0x05] = (b2[0x02] - b2[0x05]) * costab[2]; b1[0x03] = b2[0x03] + b2[0x04]; b1[0x04] = (b2[0x03] - b2[0x04]) * costab[3]; b1[0x08] = b2[0x08] + b2[0x0F]; b1[0x0F] = (b2[0x0F] - b2[0x08]) * costab[0]; b1[0x09] = b2[0x09] + b2[0x0E]; b1[0x0E] = (b2[0x0E] - b2[0x09]) * costab[1]; b1[0x0A] = b2[0x0A] + b2[0x0D]; b1[0x0D] = (b2[0x0D] - b2[0x0A]) * costab[2]; b1[0x0B] = b2[0x0B] + b2[0x0C]; b1[0x0C] = (b2[0x0C] - b2[0x0B]) * costab[3]; b1[0x10] = b2[0x10] + b2[0x17]; b1[0x17] = (b2[0x10] - b2[0x17]) * costab[0]; b1[0x11] = b2[0x11] + b2[0x16]; b1[0x16] = (b2[0x11] - b2[0x16]) * costab[1]; b1[0x12] = b2[0x12] + b2[0x15]; b1[0x15] = (b2[0x12] - b2[0x15]) * costab[2]; b1[0x13] = b2[0x13] + b2[0x14]; b1[0x14] = (b2[0x13] - b2[0x14]) * costab[3]; b1[0x18] = b2[0x18] + b2[0x1F]; b1[0x1F] = (b2[0x1F] - b2[0x18]) * costab[0]; b1[0x19] = b2[0x19] + b2[0x1E]; b1[0x1E] = (b2[0x1E] - b2[0x19]) * costab[1]; b1[0x1A] = b2[0x1A] + b2[0x1D]; b1[0x1D] = (b2[0x1D] - b2[0x1A]) * costab[2]; b1[0x1B] = b2[0x1B] + b2[0x1C]; b1[0x1C] = (b2[0x1C] - b2[0x1B]) * costab[3]; } { register real const cos0 = pnts[3][0]; register real const cos1 = pnts[3][1]; b2[0x00] = b1[0x00] + b1[0x03]; b2[0x03] = (b1[0x00] - b1[0x03]) * cos0; b2[0x01] = b1[0x01] + b1[0x02]; b2[0x02] = (b1[0x01] - b1[0x02]) * cos1; b2[0x04] = b1[0x04] + b1[0x07]; b2[0x07] = (b1[0x07] - b1[0x04]) * cos0; b2[0x05] = b1[0x05] + b1[0x06]; b2[0x06] = (b1[0x06] - b1[0x05]) * cos1; b2[0x08] = b1[0x08] + b1[0x0B]; b2[0x0B] = (b1[0x08] - b1[0x0B]) * cos0; b2[0x09] = b1[0x09] + b1[0x0A]; b2[0x0A] = (b1[0x09] - b1[0x0A]) * cos1; b2[0x0C] = b1[0x0C] + b1[0x0F]; b2[0x0F] = (b1[0x0F] - b1[0x0C]) * cos0; b2[0x0D] = b1[0x0D] + b1[0x0E]; b2[0x0E] = (b1[0x0E] - b1[0x0D]) * cos1; b2[0x10] = b1[0x10] + b1[0x13]; b2[0x13] = (b1[0x10] - b1[0x13]) * cos0; b2[0x11] = b1[0x11] + b1[0x12]; b2[0x12] = (b1[0x11] - b1[0x12]) * cos1; b2[0x14] = b1[0x14] + b1[0x17]; b2[0x17] = (b1[0x17] - b1[0x14]) * cos0; b2[0x15] = b1[0x15] + b1[0x16]; b2[0x16] = (b1[0x16] - b1[0x15]) * cos1; b2[0x18] = b1[0x18] + b1[0x1B]; b2[0x1B] = (b1[0x18] - b1[0x1B]) * cos0; b2[0x19] = b1[0x19] + b1[0x1A]; b2[0x1A] = (b1[0x19] - b1[0x1A]) * cos1; b2[0x1C] = b1[0x1C] + b1[0x1F]; b2[0x1F] = (b1[0x1F] - b1[0x1C]) * cos0; b2[0x1D] = b1[0x1D] + b1[0x1E]; b2[0x1E] = (b1[0x1E] - b1[0x1D]) * cos1; } { register real const cos0 = pnts[4][0]; b1[0x00] = b2[0x00] + b2[0x01]; b1[0x01] = (b2[0x00] - b2[0x01]) * cos0; b1[0x02] = b2[0x02] + b2[0x03]; b1[0x03] = (b2[0x03] - b2[0x02]) * cos0; b1[0x02] += b1[0x03]; b1[0x04] = b2[0x04] + b2[0x05]; b1[0x05] = (b2[0x04] - b2[0x05]) * cos0; b1[0x06] = b2[0x06] + b2[0x07]; b1[0x07] = (b2[0x07] - b2[0x06]) * cos0; b1[0x06] += b1[0x07]; b1[0x04] += b1[0x06]; b1[0x06] += b1[0x05]; b1[0x05] += b1[0x07]; b1[0x08] = b2[0x08] + b2[0x09]; b1[0x09] = (b2[0x08] - b2[0x09]) * cos0; b1[0x0A] = b2[0x0A] + b2[0x0B]; b1[0x0B] = (b2[0x0B] - b2[0x0A]) * cos0; b1[0x0A] += b1[0x0B]; b1[0x0C] = b2[0x0C] + b2[0x0D]; b1[0x0D] = (b2[0x0C] - b2[0x0D]) * cos0; b1[0x0E] = b2[0x0E] + b2[0x0F]; b1[0x0F] = (b2[0x0F] - b2[0x0E]) * cos0; b1[0x0E] += b1[0x0F]; b1[0x0C] += b1[0x0E]; b1[0x0E] += b1[0x0D]; b1[0x0D] += b1[0x0F]; b1[0x10] = b2[0x10] + b2[0x11]; b1[0x11] = (b2[0x10] - b2[0x11]) * cos0; b1[0x12] = b2[0x12] + b2[0x13]; b1[0x13] = (b2[0x13] - b2[0x12]) * cos0; b1[0x12] += b1[0x13]; b1[0x14] = b2[0x14] + b2[0x15]; b1[0x15] = (b2[0x14] - b2[0x15]) * cos0; b1[0x16] = b2[0x16] + b2[0x17]; b1[0x17] = (b2[0x17] - b2[0x16]) * cos0; b1[0x16] += b1[0x17]; b1[0x14] += b1[0x16]; b1[0x16] += b1[0x15]; b1[0x15] += b1[0x17]; b1[0x18] = b2[0x18] + b2[0x19]; b1[0x19] = (b2[0x18] - b2[0x19]) * cos0; b1[0x1A] = b2[0x1A] + b2[0x1B]; b1[0x1B] = (b2[0x1B] - b2[0x1A]) * cos0; b1[0x1A] += b1[0x1B]; b1[0x1C] = b2[0x1C] + b2[0x1D]; b1[0x1D] = (b2[0x1C] - b2[0x1D]) * cos0; b1[0x1E] = b2[0x1E] + b2[0x1F]; b1[0x1F] = (b2[0x1F] - b2[0x1E]) * cos0; b1[0x1E] += b1[0x1F]; b1[0x1C] += b1[0x1E]; b1[0x1E] += b1[0x1D]; b1[0x1D] += b1[0x1F]; } out0[0x10*16] = b1[0x00]; out0[0x10*12] = b1[0x04]; out0[0x10* 8] = b1[0x02]; out0[0x10* 4] = b1[0x06]; out0[0x10* 0] = b1[0x01]; out1[0x10* 0] = b1[0x01]; out1[0x10* 4] = b1[0x05]; out1[0x10* 8] = b1[0x03]; out1[0x10*12] = b1[0x07]; b1[0x08] += b1[0x0C]; out0[0x10*14] = b1[0x08]; b1[0x0C] += b1[0x0a]; out0[0x10*10] = b1[0x0C]; b1[0x0A] += b1[0x0E]; out0[0x10* 6] = b1[0x0A]; b1[0x0E] += b1[0x09]; out0[0x10* 2] = b1[0x0E]; b1[0x09] += b1[0x0D]; out1[0x10* 2] = b1[0x09]; b1[0x0D] += b1[0x0B]; out1[0x10* 6] = b1[0x0D]; b1[0x0B] += b1[0x0F]; out1[0x10*10] = b1[0x0B]; out1[0x10*14] = b1[0x0F]; b1[0x18] += b1[0x1C]; out0[0x10*15] = b1[0x10] + b1[0x18]; out0[0x10*13] = b1[0x18] + b1[0x14]; b1[0x1C] += b1[0x1a]; out0[0x10*11] = b1[0x14] + b1[0x1C]; out0[0x10* 9] = b1[0x1C] + b1[0x12]; b1[0x1A] += b1[0x1E]; out0[0x10* 7] = b1[0x12] + b1[0x1A]; out0[0x10* 5] = b1[0x1A] + b1[0x16]; b1[0x1E] += b1[0x19]; out0[0x10* 3] = b1[0x16] + b1[0x1E]; out0[0x10* 1] = b1[0x1E] + b1[0x11]; b1[0x19] += b1[0x1D]; out1[0x10* 1] = b1[0x11] + b1[0x19]; out1[0x10* 3] = b1[0x19] + b1[0x15]; b1[0x1D] += b1[0x1B]; out1[0x10* 5] = b1[0x15] + b1[0x1D]; out1[0x10* 7] = b1[0x1D] + b1[0x13]; b1[0x1B] += b1[0x1F]; out1[0x10* 9] = b1[0x13] + b1[0x1B]; out1[0x10*11] = b1[0x1B] + b1[0x17]; out1[0x10*13] = b1[0x17] + b1[0x1F]; out1[0x10*15] = b1[0x1F]; } /* * the call via dct64 is a trick to force GCC to use * (new) registers for the b1,b2 pointer to the bufs[xx] field */ void dct64( real *a,real *b,real *c) { real bufs[0x40]; dct64_1(a,b,bufs,bufs+0x20,c); } ./mpglibDBL/common.h0000644000175000017500000000260607716027257013515 0ustar rizlarizla/* ** Copyright (C) 2000 Albert L. Faber ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef COMMON_H_INCLUDED #define COMMON_H_INCLUDED #include "mpg123.h" #include "mpglib.h" extern const int tabsel_123[2][3][16]; extern const long freqs[9]; extern unsigned char *wordpointer; extern int bitindex; #if defined( USE_LAYER_1 ) || defined ( USE_LAYER_2 ) extern real muls[27][64]; #endif int head_check(unsigned long head,int check_layer); int decode_header(struct frame *fr,unsigned long newhead); void print_header(struct frame *fr); void print_header_compact(struct frame *fr); unsigned int getbits(int number_of_bits); unsigned int getbits_fast(int number_of_bits); int set_pointer( PMPSTR mp, long backstep); #endif ./mpglibDBL/layer2.h0000644000175000017500000000230507451136440013406 0ustar rizlarizla/* ** Copyright (C) 2000 Albert L. Faber ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef USE_LAYER_2 #ifndef LAYER2_H_INCLUDED #define LAYER2_H_INCLUDED struct al_table2 { short bits; short d; }; void init_layer2(void); void II_step_one(unsigned int *bit_alloc,int *scale,struct frame *fr); void II_step_two(unsigned int *bit_alloc,real fraction[2][4][SBLIMIT],int *scale,struct frame *fr,int x1); int do_layer2( PMPSTR mp,unsigned char *pcm_sample,int *pcm_point); #endif #endif ./mpglibDBL/README0000644000175000017500000000332407714631704012726 0ustar rizlarizlaMP3 library ----------- Version 0.2a --some modifications made by Glen Sawyer for use with MP3Gain. --In particular, I changed it so that these routines pass back --the raw double decoded values instead of rounding (and clipping) --them to 16-bit integers. This decoder is a 'light' version (thrown out all unnecessay parts) from the mpg123 package. I made this for a company. Currently only Layer3 is enabled to save some space. Layer1,2 isn't tested at all. The interface will not change significantly. A backport to the mpg123 package is planed. compiled and tested only on Solaris 2.6 main.c contains a simple demo application for library. COPYING: you may use this source under LGPL terms! (Yes, I switched to LGPL for the _mpglib_ part!) PLEASE NOTE: This software may contain patented algorithms (at least patented in some countries). It may be not allowed to sell/use products based on this source code in these countries. Check this out first! COPYRIGHT of MP3 music: Please note, that the duplicating of copyrighted music without explicit permission violates the rights of the owner. SENDING PATCHES: The current version is under LGPL. Please consider this when sending patches or changes. I also want to have the freedom to sell the code to companies that cannot or do not want to use the code under LGPL. So, if you send me significant patches, I need your explicit permission to do this. Of course, there will always be the LGPLed open source version of the 100% same code. In the case you cannot accept this: the code is free, it's your freedom to distribute your changes again under LGPL. FEEDBACK: I'm interessted to here from you, when you use this package as part of another project. ./mpglibDBL/config.h0000644000175000017500000000360107714631704013462 0ustar rizlarizla/* The number of bytes in a double. */ #define SIZEOF_DOUBLE 8 /* The number of bytes in a float. */ #define SIZEOF_FLOAT 4 /* The number of bytes in a int. */ #define SIZEOF_INT 4 /* The number of bytes in a long. */ #define SIZEOF_LONG 4 /* The number of bytes in a long double. */ #define SIZEOF_LONG_DOUBLE 12 /* The number of bytes in a short. */ #define SIZEOF_SHORT 2 /* The number of bytes in a unsigned int. */ #define SIZEOF_UNSIGNED_INT 4 /* The number of bytes in a unsigned long. */ #define SIZEOF_UNSIGNED_LONG 4 /* The number of bytes in a unsigned short. */ #define SIZEOF_UNSIGNED_SHORT 2 /* Define if you have the ANSI C header files. */ #define STDC_HEADERS /* Define if you have the header file. */ #define HAVE_ERRNO_H /* Define if you have the header file. */ #define HAVE_FCNTL_H /* Define if you have the header file. */ #define HAVE_LIMITS_H /* Name of package */ #define PACKAGE "lame" /* Version number of package */ #define VERSION "3.90" /* Define if compiler has function prototypes */ #define PROTOTYPES 1 /* enable VBR bitrate histogram */ #define BRHIST 1 /* IEEE754 compatible machine */ #define TAKEHIRO_IEEE754_HACK 1 /* #define HAVE_STRCHR */ #ifndef HAVE_MEMCPY #define HAVE_MEMCPY #endif #if defined(_MSC_VER) typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef float float32_t; typedef double float64_t; #elif defined (__GNUC__) #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int #define uint64_t unsigned long long #endif typedef long double ieee854_float80_t; typedef double ieee754_float64_t; typedef float ieee754_float32_t; #define LAME_LIBRARY_BUILD ./mpglibDBL/lame-analysis.h0000644000175000017500000000521607451136440014753 0ustar rizlarizla/* * GTK plotting routines source file * * Copyright (c) 1999 Mark Taylor * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. */ #ifndef LAME_GTKANAL_H #define LAME_GTKANAL_H #include "encoder.h" #define READ_AHEAD 10 /* number of frames to read ahead */ #define MAXMPGLAG READ_AHEAD /* if the mpg123 lag becomes bigger than this we have to stop */ #define NUMBACK 6 /* number of frames we can back up */ #define NUMPINFO (NUMBACK+READ_AHEAD+1) typedef struct { int frameNum; /* current frame number */ int frameNum123; int num_samples; /* number of pcm samples read for this frame */ double frametime; /* starting time of frame, in seconds */ double pcmdata[2][1600]; double pcmdata2[2][1152+1152-DECDELAY]; double xr[2][2][576]; double mpg123xr[2][2][576]; double ms_ratio[2]; double ms_ener_ratio[2]; /* L,R, M and S values */ double energy[2][4][BLKSIZE]; double pe[2][4]; double thr[2][4][SBMAX_l]; double en[2][4][SBMAX_l]; double thr_s[2][4][3*SBMAX_s]; double en_s[2][4][3*SBMAX_s]; double ers[2][4]; double sfb[2][2][SBMAX_l]; double sfb_s[2][2][3*SBMAX_s]; double LAMEsfb[2][2][SBMAX_l]; double LAMEsfb_s[2][2][3*SBMAX_s]; int LAMEqss[2][2]; int qss[2][2]; int big_values[2][2]; int sub_gain[2][2][3]; double xfsf[2][2][SBMAX_l]; double xfsf_s[2][2][3*SBMAX_s]; int over[2][2]; double tot_noise[2][2]; double max_noise[2][2]; double over_noise[2][2]; int blocktype[2][2]; int scalefac_scale[2][2]; int preflag[2][2]; int mpg123blocktype[2][2]; int mixed[2][2]; int mainbits[2][2]; int sfbits[2][2]; int LAMEmainbits[2][2]; int LAMEsfbits[2][2]; int framesize,stereo,js,ms_stereo,i_stereo,emph,bitrate,sampfreq,maindata; int crc,padding; int scfsi[2],mean_bits,resvsize; int totbits; } plotting_data; extern plotting_data *pinfo; #endif ./mpglibDBL/tabinit.h0000644000175000017500000000167207716027260013653 0ustar rizlarizla/* ** Copyright (C) 2000 Albert L. Faber ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef MPGLIB_TABINIT_H_INCLUDED #define MPGLIB_TABINIT_H_INCLUDED #include "mpg123.h" extern real decwin[512+32]; extern real *pnts[5]; void make_decode_tables(long scale); #endif ./apetag.h0000644000175000017500000000400710116405646011655 0ustar rizlarizla#ifndef APETAG_H #define APETAG_H #include struct MP3GainTagInfo { int haveTrackGain; int haveTrackPeak; int haveAlbumGain; int haveAlbumPeak; int haveUndo; int haveMinMaxGain; int haveAlbumMinMaxGain; double trackGain; double trackPeak; double albumGain; double albumPeak; int undoLeft; int undoRight; int undoWrap; /* undoLeft and undoRight will be the same 95% of the time. mp3gain DOES have a command-line switch to adjust the gain on just one channel, though. The "undoWrap" field indicates whether or not "wrapping" was turned on when the mp3 was adjusted */ unsigned char minGain; unsigned char maxGain; unsigned char albumMinGain; unsigned char albumMaxGain; /* minGain and maxGain are the current minimum and maximum values of the "global gain" fields in the frames of the mp3 file */ int dirty; /* flag if data changes after loaded from file */ int recalc; /* Used to signal if recalculation is required */ }; struct APEFieldStruct { unsigned long vsize; unsigned long isize; unsigned long flags; char *name; char *value; }; struct APETagFooterStruct { char ID [8]; char Version [4]; char Length [4]; char TagCount [4]; char Flags [4]; char Reserved [8]; }; struct APETagStruct { unsigned long originalTagSize; int haveHeader; struct APETagFooterStruct header; struct APETagFooterStruct footer; unsigned char *otherFields; /* i.e. other than MP3Gain */ unsigned long otherFieldsSize; }; struct FileTagsStruct { long tagOffset; struct APETagStruct *apeTag; unsigned char *lyrics3tag; unsigned long lyrics3TagSize; unsigned char *id31tag; }; int ReadMP3GainAPETag (char *filename, struct MP3GainTagInfo *info, struct FileTagsStruct *fileTags); int WriteMP3GainAPETag (char *filename, struct MP3GainTagInfo *info, struct FileTagsStruct *fileTags, int saveTimeStamp); int RemoveMP3GainAPETag (char *filename, int saveTimeStamp); #endif ./mp3gain.vcproj0000755000175000017500000001446011213773524013037 0ustar rizlarizla ./replaygaindll.def0000644000175000017500000000116207714631703013556 0ustar rizlarizlaLIBRARY replaygain.DLL DESCRIPTION 'ReplayGain.DLL Windows Dynamic Link Library' EXPORTS ; ReplayGain Exposures InitGainAnalysis @1 InitGainAnalysisAsInt @8 ResetSampleFrequency @9 AnalyzeSamples @2 AnalyzeSamplesInterleaved @5 GetRadioGain @3 GetTitleGain @6 GetAudiophileGain @4 GetAlbumGain @7 GetDLLVersion @10 ; MP3 Gain Exposures (leave room, start at ordinal 100) ChangeGainOfMP3File @100 StopMP3GainProcessing @101 ; Error Reporting (leave room, start at ordinal 300) GetMP3GainError @300 GetMP3GainErrorStr @301 attachmsgpump @302 GetMP3GainErrorStrLen @303./mp3gain.sln0000755000175000017500000000155711213773524012333 0ustar rizlarizla Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mp3gain", "mp3gain.vcproj", "{B16A1BFF-6ADE-4705-AE72-079C0312DC23}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {B16A1BFF-6ADE-4705-AE72-079C0312DC23}.Debug|Win32.ActiveCfg = Debug|Win32 {B16A1BFF-6ADE-4705-AE72-079C0312DC23}.Debug|Win32.Build.0 = Debug|Win32 {B16A1BFF-6ADE-4705-AE72-079C0312DC23}.Release|Win32.ActiveCfg = Release|Win32 {B16A1BFF-6ADE-4705-AE72-079C0312DC23}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ./gain_analysis.h0000644000175000017500000000376611216260715013246 0ustar rizlarizla/* * ReplayGainAnalysis - analyzes input samples and give the recommended dB change * Copyright (C) 2001-2009 David Robinson and Glen Sawyer * * 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 * * concept and filter values by David Robinson (David@Robinson.org) * -- blame him if you think the idea is flawed * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA * -- blame him if you think this runs too slowly, or the coding is otherwise flawed * * For an explanation of the concepts and the basic algorithms involved, go to: * http://www.replaygain.org/ */ #ifndef GAIN_ANALYSIS_H #define GAIN_ANALYSIS_H #include #define GAIN_NOT_ENOUGH_SAMPLES -24601 #define GAIN_ANALYSIS_ERROR 0 #define GAIN_ANALYSIS_OK 1 #define INIT_GAIN_ANALYSIS_ERROR 0 #define INIT_GAIN_ANALYSIS_OK 1 #ifdef __cplusplus extern "C" { #endif typedef double Float_t; // Type used for filtering int InitGainAnalysis ( long samplefreq ); int AnalyzeSamples ( const Float_t* left_samples, const Float_t* right_samples, size_t num_samples, int num_channels ); int ResetSampleFrequency ( long samplefreq ); Float_t GetTitleGain ( void ); Float_t GetAlbumGain ( void ); #ifdef __cplusplus } #endif #endif /* GAIN_ANALYSIS_H */ ./mp3gain.dsp0000644000175000017500000003624211216260716012316 0ustar rizlarizla# Microsoft Developer Studio Project File - Name="mp3gain" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=mp3gain - Win32 DebugDLL !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "mp3gain.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "mp3gain.mak" CFG="mp3gain - Win32 DebugDLL" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "mp3gain - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "mp3gain - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "mp3gain - Win32 ReleaseDLL" (based on "Win32 (x86) Console Application") !MESSAGE "mp3gain - Win32 DebugDLL" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName ""$/analysis", SCAAAAAA" # PROP Scc_LocalPath "." CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "mp3gain - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" MTL=midl.exe # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W4 /GX /Zi /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "HAVE_MEMCPY" /D "NOANALYSIS" /D "HAVE_STRCHR" /U "asWIN32DLL" /YX /FD /c # SUBTRACT CPP /WX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 setargv.obj /nologo /subsystem:console /map /debug /machine:I386 /OPT:REF # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" MTL=midl.exe # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "HAVE_MEMCPY" /D "NOANALYSIS" /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 setargv.obj /nologo /subsystem:console /incremental:no /map /debug /machine:I386 /pdbtype:sept !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseDLL" # PROP BASE Intermediate_Dir "ReleaseDLL" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseDLL" # PROP Intermediate_Dir "ReleaseDLL" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" MTL=midl.exe # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c # ADD CPP /nologo /MD /W4 /GX /Zi /O2 /Ob2 /D "NDEBUG" /D "asWIN32DLL" /D "WIN32" /D "_WINDOWS" /D "HAVE_MEMCPY" /D "NOANALYSIS" /FR /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 # ADD LINK32 user32.lib /nologo /base:"0x60000000" /subsystem:windows /dll /map /debug /machine:I386 /nodefaultlib:"LIBC" /def:"replaygaindll.def" /out:"ReleaseDLL/replaygain.dll" /OPT:REF # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "DebugDLL" # PROP BASE Intermediate_Dir "DebugDLL" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "DebugDLL" # PROP Intermediate_Dir "DebugDLL" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" MTL=midl.exe # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD BASE CPP /nologo /Zp1 /MD /W3 /GX /Zi /Od /D "WIN32" /D "_WINDOWS" /FR /FD /c # ADD CPP /nologo /MD /W4 /GX /Zi /Od /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "HAVE_MEMCPY" /D "NOANALYSIS" /D "asWIN32DLL" /FR /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /map /debug /machine:I386 /def:"replaygaindll.def" # SUBTRACT BASE LINK32 /verbose /pdb:none # ADD LINK32 user32.lib /nologo /base:"0x60000000" /subsystem:windows /dll /incremental:yes /map /debug /machine:I386 /nodefaultlib:"LIBC" /def:"replaygaindll.def" /out:"DebugDLL/replaygain.dll" # SUBTRACT LINK32 /verbose /pdb:none !ENDIF # Begin Target # Name "mp3gain - Win32 Release" # Name "mp3gain - Win32 Debug" # Name "mp3gain - Win32 ReleaseDLL" # Name "mp3gain - Win32 DebugDLL" # Begin Group "Source Files" # PROP Default_Filter ".c" # Begin Source File SOURCE=.\apetag.c # End Source File # Begin Source File SOURCE=.\id3tag.c # End Source File # Begin Source File SOURCE=.\mpglibDBL\common.c !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\dct64_i386.c !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\decode_i386.c !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\gain_analysis.c # End Source File # Begin Source File SOURCE=.\mpglibDBL\interface.c !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\layer3.c !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mp3gain.c # End Source File # Begin Source File SOURCE=.\replaygaindll.c !IF "$(CFG)" == "mp3gain - Win32 Release" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" !ENDIF # End Source File # Begin Source File SOURCE=.\rg_error.c # End Source File # Begin Source File SOURCE=.\mpglibDBL\tabinit.c !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter ".h" # Begin Source File SOURCE=.\apetag.h # End Source File # Begin Source File SOURCE=.\id3tag.h # End Source File # Begin Source File SOURCE=.\mpglibDBL\bitstream.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\common.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\config.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\dct64_i386.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\decode_i386.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\encoder.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\gain_analysis.h # End Source File # Begin Source File SOURCE=.\mpglibDBL\huffman.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\interface.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\lame.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\layer3.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\machine.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mp3gain.h # End Source File # Begin Source File SOURCE=.\mpglibDBL\mpg123.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\mpglib.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\resource.h !IF "$(CFG)" == "mp3gain - Win32 Release" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" !ENDIF # End Source File # Begin Source File SOURCE=.\rg_error.h # End Source File # Begin Source File SOURCE=.\mpglibDBL\tabinit.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=.\mpglibDBL\VbrTag.h !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter ".rc" # Begin Source File SOURCE=.\replaygaindll.def !IF "$(CFG)" == "mp3gain - Win32 Release" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" !ENDIF # End Source File # Begin Source File SOURCE=.\replaygainversion.rc !IF "$(CFG)" == "mp3gain - Win32 Release" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" !ENDIF # End Source File # Begin Source File SOURCE=.\VerInfo.rc !IF "$(CFG)" == "mp3gain - Win32 Release" !ELSEIF "$(CFG)" == "mp3gain - Win32 Debug" !ELSEIF "$(CFG)" == "mp3gain - Win32 ReleaseDLL" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "mp3gain - Win32 DebugDLL" # PROP Exclude_From_Build 1 !ENDIF # End Source File # End Group # End Target # End Project ./replaygaindll.c0000644000175000017500000001416607714631703013252 0ustar rizlarizla/* * ReplayGainAnalysis DLL Wrapper - DLL Wrapper for Glen Sawyer's headers * Copyright (C) 2002 John Zitterkopf (zitt@bigfoot.com) * (http://www.zittware.com) * * These comments must remain intact in all copies of the source code. * * 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 * * concept and filter values by David Robinson (David@Robinson.org) * -- blame him if you think the idea is flawed * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA * -- blame him if you think this runs too slowly, or the coding is otherwise flawed * DLL Wrapper code for VC++5.0 by John Zitterkopf (zitt@bigfoot.com) * -- blame him for nothing. This work evolves as needed. * * For an explanation of the concepts and the basic algorithms involved, go to: * http://www.replaygain.org/ * * V1.0 - jzitt * * Based on V1.0 header source provided by Glen Sawyer * * Attempts to maintain some backward capability with V0.9 of the same source. * * V1.2.1 - jzitt 9/4/2002 * * Incorporates V1.2.1 MP3Gain sources. * * Adds MP3GAIN capabilities to DLL. */ /*define below tells sourcecode that we are compiling as a Win32 DLL*/ #ifndef asWIN32DLL #define asWIN32DLL #endif #include #include "gain_analysis.h" #include "mp3gain.h" #include "rg_error.h" /*jzitt*/ #define MAXSAMPLES 2400 BOOL APIENTRY DllMain(HANDLE hModule, unsigned long dwReason, LPVOID lpReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: mp3gainerrstr = NULL; break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: if (mp3gainerrstr != NULL) { free(mp3gainerrstr); mp3gainerrstr = NULL; } break; } return TRUE; UNREFERENCED_PARAMETER(lpReserved); UNREFERENCED_PARAMETER(hModule); } int AnalyzeSamplesInterleaved(char *samples, long num_samples, int num_channels) { double leftbuf[MAXSAMPLES], rightbuf[MAXSAMPLES]; long i; long totSamples = num_samples; long nSamples = num_samples; signed short int *samp = (signed short int *)samples; int result = GAIN_ANALYSIS_ERROR; /* NOTES: * leftbuf and rightbuf are arrays of doubles * samp is a short (16-bit) integer * inf is the input file * totSamples is the total number of samples remaining in the input file * MAXSAMPLES is the maximum number of samples to send to AnalyzeSamples at once */ while (totSamples > 0) { if (totSamples > MAXSAMPLES) nSamples = MAXSAMPLES; else nSamples = totSamples; if (num_channels == 2) { for (i = 0; i < nSamples; i++) { leftbuf[i] = *samp++; /* default conversion from short to double */ rightbuf[i] = *samp++; } result = AnalyzeSamples(leftbuf,rightbuf,nSamples,2); if (result != GAIN_ANALYSIS_OK) return result; } //end stereo else { /* Just one channel (mono) */ for (i = 0; i < nSamples; i++) { leftbuf[i] = *samp++; } result = AnalyzeSamples(leftbuf,NULL,nSamples,1); if (result != GAIN_ANALYSIS_OK) return result; } //end just mono totSamples -= nSamples; } //end while return result; } double GetRadioGain() { return GetTitleGain(); } double GetAudiophileGain() { return GetAlbumGain(); } int InitGainAnalysisAsInt( int samplingFreq ) { return InitGainAnalysis( samplingFreq ); } char *thFilename; int thGainchange; DWORD WINAPI changeGainThread( LPVOID lpParam ) { changeGain(thFilename, thGainchange, thGainchange); return 0; UNREFERENCED_PARAMETER(lpParam); } unsigned int __stdcall ChangeGainOfMP3File(char *filename, int gainchange) { DWORD dwThreadID; HANDLE hThread; MSG msg; mp3gainerr = MP3GAIN_NOERROR; blnCancel = 0; if (mp3gainerrstr != NULL) { free(mp3gainerrstr); mp3gainerrstr = NULL; } thFilename = filename; thGainchange = gainchange; hThread = CreateThread(NULL,0,changeGainThread,NULL,0,&dwThreadID); if (hThread == NULL) return MP3GAIN_UNSPECIFED_ERROR; while ((MsgWaitForMultipleObjects(1, &hThread, FALSE, INFINITE, QS_ALLINPUT)) == (WAIT_OBJECT_0 + 1)) { while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg); } CloseHandle(hThread); return mp3gainerr; } unsigned int __stdcall GetMP3GainError() { return mp3gainerr; } long __stdcall GetMP3GainErrorStrLen() { if ((mp3gainerr == MP3GAIN_NOERROR) || (mp3gainerrstr == NULL)) return 0; return strlen(mp3gainerrstr); } char * __stdcall GetMP3GainErrorStr( char * buffer, int buflen ) { if (buflen < 1) { //strcpy(buffer,'\0'); return NULL;//buffer; } if ((mp3gainerr == MP3GAIN_NOERROR) || (mp3gainerrstr == NULL)) { buffer[0] = '\0'; return buffer; } buffer[buflen-1] = '\0'; //don't assume buffer has extra byte at the end //for null terminator return strncpy( buffer, mp3gainerrstr, buflen-1 ); } void __stdcall StopMP3GainProcessing() { blnCancel = !0; } int __stdcall attachmsgpump(HANDLE ahwnd, UINT percentdonemsg, UINT errmsg) { apphandle = 0; apppercentdonemsg = 0; apperrmsg = 0; if (ahwnd != 0) { apphandle = ahwnd; apppercentdonemsg = percentdonemsg; apperrmsg = errmsg; } /*printf("Hi, John!\n"); MessageBox( 0, "Hi, John!\n", "ReplayGainDLL\n", MB_OK ); */ return(MP3GAIN_NOERROR); //return success } char * GetDLLVersion( char * buffer, int buflen ) { if (buflen < 1) { //strcpy(buffer,'\0'); return NULL;//buffer; } buffer[buflen] = '\0'; return strncpy( buffer, MP3GAIN_VERSION, buflen-1 ); }./resource.h0000644000175000017500000000402307714631703012246 0ustar rizlarizla//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by replaygainversion.rc /* * ReplayGainAnalysis DLL Wrapper - DLL Wrapper for Glen Sawyer's headers * Copyright (C) 2002 John Zitterkopf (zitt@bigfoot.com) * (http://www.zittware.com) * * These comments must remain intact in all copies of the source code. * * 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 * * concept and filter values by David Robinson (David@Robinson.org) * -- blame him if you think the idea is flawed * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA * -- blame him if you think this runs too slowly, or the coding is otherwise flawed * DLL Wrapper code for VC++5.0 by John Zitterkopf (zitt@bigfoot.com) * * For an explanation of the concepts and the basic algorithms involved, go to: * http://www.replaygain.org/ * * V1.0 - jzitt * * Based on V1.0 header source provided by Glen Sawyer * * Attempts to maintain some backward capability with V0.9 of the same source. */ // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif ./replaygainversion.rc0000644000175000017500000000510107714631703014333 0ustar rizlarizla//Microsoft Developer Studio generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 #ifndef _MAC ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 1,3,1,0 PRODUCTVERSION 1,3,1,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "Comments", "Replay Gain DLL \r\nBased on David Robinson's www.replaygain.org idea \r\nand C++ headers by Glen Sawyer.\0" VALUE "CompanyName", "Zittware\0" VALUE "FileDescription", "Replay Gain DLL\0" VALUE "FileVersion", "1, 3, 1, 0\0" VALUE "InternalName", "replaygain\0" VALUE "LegalCopyright", "Copyright © 2002 by John Zitterkopf\0" VALUE "LegalTrademarks", "ALL RIGHTS RESERVED\0" VALUE "OriginalFilename", "replaygain.dll\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "Zittware Replay Gain DLL\0" VALUE "ProductVersion", "1, 3, 1, 0\0" VALUE "SpecialBuild", "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif // !_MAC #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED ./gain_analysis.c0000644000175000017500000005341711216260715013237 0ustar rizlarizla/* * ReplayGainAnalysis - analyzes input samples and give the recommended dB change * Copyright (C) 2001-2009 David Robinson and Glen Sawyer * Improvements and optimizations added by Frank Klemm, and by Marcel Müller * * 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 * * concept and filter values by David Robinson (David@Robinson.org) * -- blame him if you think the idea is flawed * original coding by Glen Sawyer (mp3gain@hotmail.com) * -- blame him if you think this runs too slowly, or the coding is otherwise flawed * * lots of code improvements by Frank Klemm ( http://www.uni-jena.de/~pfk/mpp/ ) * -- credit him for all the _good_ programming ;) * * * For an explanation of the concepts and the basic algorithms involved, go to: * http://www.replaygain.org/ */ /* * Here's the deal. Call * * InitGainAnalysis ( long samplefreq ); * * to initialize everything. Call * * AnalyzeSamples ( const Float_t* left_samples, * const Float_t* right_samples, * size_t num_samples, * int num_channels ); * * as many times as you want, with as many or as few samples as you want. * If mono, pass the sample buffer in through left_samples, leave * right_samples NULL, and make sure num_channels = 1. * * GetTitleGain() * * will return the recommended dB level change for all samples analyzed * SINCE THE LAST TIME you called GetTitleGain() OR InitGainAnalysis(). * * GetAlbumGain() * * will return the recommended dB level change for all samples analyzed * since InitGainAnalysis() was called and finalized with GetTitleGain(). * * Pseudo-code to process an album: * * Float_t l_samples [4096]; * Float_t r_samples [4096]; * size_t num_samples; * unsigned int num_songs; * unsigned int i; * * InitGainAnalysis ( 44100 ); * for ( i = 1; i <= num_songs; i++ ) { * while ( ( num_samples = getSongSamples ( song[i], left_samples, right_samples ) ) > 0 ) * AnalyzeSamples ( left_samples, right_samples, num_samples, 2 ); * fprintf ("Recommended dB change for song %2d: %+6.2f dB\n", i, GetTitleGain() ); * } * fprintf ("Recommended dB change for whole album: %+6.2f dB\n", GetAlbumGain() ); */ /* * So here's the main source of potential code confusion: * * The filters applied to the incoming samples are IIR filters, * meaning they rely on up to number of previous samples * AND up to number of previous filtered samples. * * I set up the AnalyzeSamples routine to minimize memory usage and interface * complexity. The speed isn't compromised too much (I don't think), but the * internal complexity is higher than it should be for such a relatively * simple routine. * * Optimization/clarity suggestions are welcome. */ #include #include #include #include #include "gain_analysis.h" typedef unsigned short Uint16_t; typedef signed short Int16_t; typedef unsigned int Uint32_t; typedef signed int Int32_t; #define YULE_ORDER 10 #define BUTTER_ORDER 2 #define YULE_FILTER filterYule #define BUTTER_FILTER filterButter #define RMS_PERCENTILE 0.95 // percentile which is louder than the proposed level #define MAX_SAMP_FREQ 96000. // maximum allowed sample frequency [Hz] #define RMS_WINDOW_TIME 0.050 // Time slice size [s] #define STEPS_per_dB 100. // Table entries per dB #define MAX_dB 120. // Table entries for 0...MAX_dB (normal max. values are 70...80 dB) #define MAX_ORDER (BUTTER_ORDER > YULE_ORDER ? BUTTER_ORDER : YULE_ORDER) #define MAX_SAMPLES_PER_WINDOW (size_t) (MAX_SAMP_FREQ * RMS_WINDOW_TIME + 1) // max. Samples per Time slice #define PINK_REF 64.82 //298640883795 // calibration value Float_t linprebuf [MAX_ORDER * 2]; Float_t* linpre; // left input samples, with pre-buffer Float_t lstepbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; Float_t* lstep; // left "first step" (i.e. post first filter) samples Float_t loutbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; Float_t* lout; // left "out" (i.e. post second filter) samples Float_t rinprebuf [MAX_ORDER * 2]; Float_t* rinpre; // right input samples ... Float_t rstepbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; Float_t* rstep; Float_t routbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; Float_t* rout; long sampleWindow; // number of samples required to reach number of milliseconds required for RMS window long totsamp; double lsum; double rsum; int freqindex; int first; static Uint32_t A [(size_t)(STEPS_per_dB * MAX_dB)]; static Uint32_t B [(size_t)(STEPS_per_dB * MAX_dB)]; // for each filter: // [0] 48 kHz, [1] 44.1 kHz, [2] 32 kHz, [3] 24 kHz, [4] 22050 Hz, [5] 16 kHz, [6] 12 kHz, [7] is 11025 Hz, [8] 8 kHz #ifdef WIN32 #ifndef __GNUC__ #pragma warning ( disable : 4305 ) #endif #endif static const Float_t ABYule[12][2*YULE_ORDER + 1] = { {0.006471345933032, -7.22103125152679, -0.02567678242161, 24.7034187975904, 0.049805860704367, -52.6825833623896, -0.05823001743528, 77.4825736677539, 0.040611847441914, -82.0074753444205, -0.010912036887501, 63.1566097101925, -0.00901635868667, -34.889569769245, 0.012448886238123, 13.2126852760198, -0.007206683749426, -3.09445623301669, 0.002167156433951, 0.340344741393305, -0.000261819276949}, {0.015415414474287, -7.19001570087017, -0.07691359399407, 24.4109412087159, 0.196677418516518, -51.6306373580801, -0.338855114128061, 75.3978476863163, 0.430094579594561, -79.4164552507386, -0.415015413747894, 61.0373661948115, 0.304942508151101, -33.7446462547014, -0.166191795926663, 12.8168791146274, 0.063198189938739, -3.01332198541437, -0.015003978694525, 0.223619893831468, 0.001748085184539}, {0.021776466467053, -5.74819833657784, -0.062376961003801, 16.246507961894, 0.107731165328514, -29.9691822642542, -0.150994515142316, 40.027597579378, 0.170334807313632, -40.3209196052655, -0.157984942890531, 30.8542077487718, 0.121639833268721, -17.5965138737281, -0.074094040816409, 7.10690214103873, 0.031282852041061, -1.82175564515191, -0.00755421235941, 0.223619893831468, 0.00117925454213 }, {0.03857599435200, -3.84664617118067, -0.02160367184185, 7.81501653005538, -0.00123395316851, -11.34170355132042, -0.00009291677959, 13.05504219327545, -0.01655260341619, -12.28759895145294, 0.02161526843274, 9.48293806319790, -0.02074045215285, -5.87257861775999, 0.00594298065125, 2.75465861874613, 0.00306428023191, -0.86984376593551, 0.00012025322027, 0.13919314567432, 0.00288463683916 }, {0.05418656406430, -3.47845948550071, -0.02911007808948, 6.36317777566148, -0.00848709379851, -8.54751527471874, -0.00851165645469, 9.47693607801280, -0.00834990904936, -8.81498681370155, 0.02245293253339, 6.85401540936998, -0.02596338512915, -4.39470996079559, 0.01624864962975, 2.19611684890774, -0.00240879051584, -0.75104302451432, 0.00674613682247, 0.13149317958808, -0.00187763777362 }, {0.15457299681924, -2.37898834973084, -0.09331049056315, 2.84868151156327, -0.06247880153653, -2.64577170229825, 0.02163541888798, 2.23697657451713, -0.05588393329856, -1.67148153367602, 0.04781476674921, 1.00595954808547, 0.00222312597743, -0.45953458054983, 0.03174092540049, 0.16378164858596, -0.01390589421898, -0.05032077717131, 0.00651420667831, 0.02347897407020, -0.00881362733839 }, {0.30296907319327, -1.61273165137247, -0.22613988682123, 1.07977492259970, -0.08587323730772, -0.25656257754070, 0.03282930172664, -0.16276719120440, -0.00915702933434, -0.22638893773906, -0.02364141202522, 0.39120800788284, -0.00584456039913, -0.22138138954925, 0.06276101321749, 0.04500235387352, -0.00000828086748, 0.02005851806501, 0.00205861885564, 0.00302439095741, -0.02950134983287 }, {0.33642304856132, -1.49858979367799, -0.25572241425570, 0.87350271418188, -0.11828570177555, 0.12205022308084, 0.11921148675203, -0.80774944671438, -0.07834489609479, 0.47854794562326, -0.00469977914380, -0.12453458140019, -0.00589500224440, -0.04067510197014, 0.05724228140351, 0.08333755284107, 0.00832043980773, -0.04237348025746, -0.01635381384540, 0.02977207319925, -0.01760176568150 }, {0.44915256608450, -0.62820619233671, -0.14351757464547, 0.29661783706366, -0.22784394429749, -0.37256372942400, -0.01419140100551, 0.00213767857124, 0.04078262797139, -0.42029820170918, -0.12398163381748, 0.22199650564824, 0.04097565135648, 0.00613424350682, 0.10478503600251, 0.06747620744683, -0.01863887810927, 0.05784820375801, -0.03193428438915, 0.03222754072173, 0.00541907748707 }, {0.56619470757641, -1.04800335126349, -0.75464456939302, 0.29156311971249, 0.16242137742230, -0.26806001042947, 0.16744243493672, 0.00819999645858, -0.18901604199609, 0.45054734505008, 0.30931782841830, -0.33032403314006, -0.27562961986224, 0.06739368333110, 0.00647310677246, -0.04784254229033, 0.08647503780351, 0.01639907836189, -0.03788984554840, 0.01807364323573, -0.00588215443421 }, {0.58100494960553, -0.51035327095184, -0.53174909058578, -0.31863563325245, -0.14289799034253, -0.20256413484477, 0.17520704835522, 0.14728154134330, 0.02377945217615, 0.38952639978999, 0.15558449135573, -0.23313271880868, -0.25344790059353, -0.05246019024463, 0.01628462406333, -0.02505961724053, 0.06920467763959, 0.02442357316099, -0.03721611395801, 0.01818801111503, -0.00749618797172 }, {0.53648789255105, -0.25049871956020, -0.42163034350696, -0.43193942311114, -0.00275953611929, -0.03424681017675, 0.04267842219415, -0.04678328784242, -0.10214864179676, 0.26408300200955, 0.14590772289388, 0.15113130533216, -0.02459864859345, -0.17556493366449, -0.11202315195388, -0.18823009262115, -0.04060034127000, 0.05477720428674, 0.04788665548180, 0.04704409688120, -0.02217936801134 } }; static const Float_t ABButter[12][2*BUTTER_ORDER + 1] = { {0.99308203517541, -1.98611621154089, -1.98616407035082, 0.986211929160751, 0.99308203517541 }, {0.992472550461293,-1.98488843762334, -1.98494510092258, 0.979389350028798, 0.992472550461293}, {0.989641019334721,-1.97917472731008, -1.97928203866944, 0.979389350028798, 0.989641019334721}, {0.98621192462708, -1.97223372919527, -1.97242384925416, 0.97261396931306, 0.98621192462708 }, {0.98500175787242, -1.96977855582618, -1.97000351574484, 0.97022847566350, 0.98500175787242 }, {0.97938932735214, -1.95835380975398, -1.95877865470428, 0.95920349965459, 0.97938932735214 }, {0.97531843204928, -1.95002759149878, -1.95063686409857, 0.95124613669835, 0.97531843204928 }, {0.97316523498161, -1.94561023566527, -1.94633046996323, 0.94705070426118, 0.97316523498161 }, {0.96454515552826, -1.92783286977036, -1.92909031105652, 0.93034775234268, 0.96454515552826 }, {0.96009142950541, -1.91858953033784, -1.92018285901082, 0.92177618768381, 0.96009142950541 }, {0.95856916599601, -1.91542108074780, -1.91713833199203, 0.91885558323625, 0.95856916599601 }, {0.94597685600279, -1.88903307939452, -1.89195371200558, 0.89487434461664, 0.94597685600279 } }; #ifdef WIN32 #ifndef __GNUC__ #pragma warning ( default : 4305 ) #endif #endif // When calling these filter procedures, make sure that ip[-order] and op[-order] point to real data! // If your compiler complains that "'operation on 'output' may be undefined", you can // either ignore the warnings or uncomment the three "y" lines (and comment out the indicated line) static void filterYule (const Float_t* input, Float_t* output, size_t nSamples, const Float_t* kernel) { while (nSamples--) { *output = 1e-10 /* 1e-10 is a hack to avoid slowdown because of denormals */ + input [0] * kernel[0] - output[-1] * kernel[1] + input [-1] * kernel[2] - output[-2] * kernel[3] + input [-2] * kernel[4] - output[-3] * kernel[5] + input [-3] * kernel[6] - output[-4] * kernel[7] + input [-4] * kernel[8] - output[-5] * kernel[9] + input [-5] * kernel[10] - output[-6] * kernel[11] + input [-6] * kernel[12] - output[-7] * kernel[13] + input [-7] * kernel[14] - output[-8] * kernel[15] + input [-8] * kernel[16] - output[-9] * kernel[17] + input [-9] * kernel[18] - output[-10]* kernel[19] + input [-10]* kernel[20]; ++output; ++input; } } static void filterButter (const Float_t* input, Float_t* output, size_t nSamples, const Float_t* kernel) { while (nSamples--) { *output = input [0] * kernel[0] - output[-1] * kernel[1] + input [-1] * kernel[2] - output[-2] * kernel[3] + input [-2] * kernel[4]; ++output; ++input; } } // returns a INIT_GAIN_ANALYSIS_OK if successful, INIT_GAIN_ANALYSIS_ERROR if not int ResetSampleFrequency ( long samplefreq ) { int i; // zero out initial values for ( i = 0; i < MAX_ORDER; i++ ) linprebuf[i] = lstepbuf[i] = loutbuf[i] = rinprebuf[i] = rstepbuf[i] = routbuf[i] = 0.; switch ( (int)(samplefreq) ) { case 96000: freqindex = 0; break; case 88200: freqindex = 1; break; case 64000: freqindex = 2; break; case 48000: freqindex = 3; break; case 44100: freqindex = 4; break; case 32000: freqindex = 5; break; case 24000: freqindex = 6; break; case 22050: freqindex = 7; break; case 16000: freqindex = 8; break; case 12000: freqindex = 9; break; case 11025: freqindex = 10; break; case 8000: freqindex = 11; break; default: return INIT_GAIN_ANALYSIS_ERROR; } sampleWindow = (int) ceil (samplefreq * RMS_WINDOW_TIME); lsum = 0.; rsum = 0.; totsamp = 0; memset ( A, 0, sizeof(A) ); return INIT_GAIN_ANALYSIS_OK; } int InitGainAnalysis ( long samplefreq ) { if (ResetSampleFrequency(samplefreq) != INIT_GAIN_ANALYSIS_OK) { return INIT_GAIN_ANALYSIS_ERROR; } linpre = linprebuf + MAX_ORDER; rinpre = rinprebuf + MAX_ORDER; lstep = lstepbuf + MAX_ORDER; rstep = rstepbuf + MAX_ORDER; lout = loutbuf + MAX_ORDER; rout = routbuf + MAX_ORDER; memset ( B, 0, sizeof(B) ); return INIT_GAIN_ANALYSIS_OK; } // returns GAIN_ANALYSIS_OK if successful, GAIN_ANALYSIS_ERROR if not static __inline double fsqr(const double d) { return d*d; } int AnalyzeSamples ( const Float_t* left_samples, const Float_t* right_samples, size_t num_samples, int num_channels ) { const Float_t* curleft; const Float_t* curright; long batchsamples; long cursamples; long cursamplepos; int i; if ( num_samples == 0 ) return GAIN_ANALYSIS_OK; cursamplepos = 0; batchsamples = (long)num_samples; switch ( num_channels) { case 1: right_samples = left_samples; case 2: break; default: return GAIN_ANALYSIS_ERROR; } if ( num_samples < MAX_ORDER ) { memcpy ( linprebuf + MAX_ORDER, left_samples , num_samples * sizeof(Float_t) ); memcpy ( rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t) ); } else { memcpy ( linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t) ); memcpy ( rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t) ); } while ( batchsamples > 0 ) { cursamples = batchsamples > sampleWindow-totsamp ? sampleWindow - totsamp : batchsamples; if ( cursamplepos < MAX_ORDER ) { curleft = linpre+cursamplepos; curright = rinpre+cursamplepos; if (cursamples > MAX_ORDER - cursamplepos ) cursamples = MAX_ORDER - cursamplepos; } else { curleft = left_samples + cursamplepos; curright = right_samples + cursamplepos; } YULE_FILTER ( curleft , lstep + totsamp, cursamples, ABYule[freqindex]); YULE_FILTER ( curright, rstep + totsamp, cursamples, ABYule[freqindex]); BUTTER_FILTER ( lstep + totsamp, lout + totsamp, cursamples, ABButter[freqindex]); BUTTER_FILTER ( rstep + totsamp, rout + totsamp, cursamples, ABButter[freqindex]); curleft = lout + totsamp; // Get the squared values curright = rout + totsamp; i = cursamples % 16; while (i--) { lsum += fsqr(*curleft++); rsum += fsqr(*curright++); } i = cursamples / 16; while (i--) { lsum += fsqr(curleft[0]) + fsqr(curleft[1]) + fsqr(curleft[2]) + fsqr(curleft[3]) + fsqr(curleft[4]) + fsqr(curleft[5]) + fsqr(curleft[6]) + fsqr(curleft[7]) + fsqr(curleft[8]) + fsqr(curleft[9]) + fsqr(curleft[10]) + fsqr(curleft[11]) + fsqr(curleft[12]) + fsqr(curleft[13]) + fsqr(curleft[14]) + fsqr(curleft[15]); curleft += 16; rsum += fsqr(curright[0]) + fsqr(curright[1]) + fsqr(curright[2]) + fsqr(curright[3]) + fsqr(curright[4]) + fsqr(curright[5]) + fsqr(curright[6]) + fsqr(curright[7]) + fsqr(curright[8]) + fsqr(curright[9]) + fsqr(curright[10]) + fsqr(curright[11]) + fsqr(curright[12]) + fsqr(curright[13]) + fsqr(curright[14]) + fsqr(curright[15]); curright += 16; } batchsamples -= cursamples; cursamplepos += cursamples; totsamp += cursamples; if ( totsamp == sampleWindow ) { // Get the Root Mean Square (RMS) for this set of samples double val = STEPS_per_dB * 10. * log10 ( (lsum+rsum) / totsamp * 0.5 + 1.e-37 ); int ival = (int) val; if ( ival < 0 ) ival = 0; if ( ival >= (int)(sizeof(A)/sizeof(*A)) ) ival = sizeof(A)/sizeof(*A) - 1; A [ival]++; lsum = rsum = 0.; memmove ( loutbuf , loutbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); memmove ( routbuf , routbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); memmove ( lstepbuf, lstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); memmove ( rstepbuf, rstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); totsamp = 0; } if ( totsamp > sampleWindow ) // somehow I really screwed up: Error in programming! Contact author about totsamp > sampleWindow return GAIN_ANALYSIS_ERROR; } if ( num_samples < MAX_ORDER ) { memmove ( linprebuf, linprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) ); memmove ( rinprebuf, rinprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) ); memcpy ( linprebuf + MAX_ORDER - num_samples, left_samples, num_samples * sizeof(Float_t) ); memcpy ( rinprebuf + MAX_ORDER - num_samples, right_samples, num_samples * sizeof(Float_t) ); } else { memcpy ( linprebuf, left_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) ); memcpy ( rinprebuf, right_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) ); } return GAIN_ANALYSIS_OK; } static Float_t analyzeResult ( Uint32_t* Array, size_t len ) { Uint32_t elems; Int32_t upper; size_t i; elems = 0; for ( i = 0; i < len; i++ ) elems += Array[i]; if ( elems == 0 ) return GAIN_NOT_ENOUGH_SAMPLES; upper = (Int32_t) ceil (elems * (1. - RMS_PERCENTILE)); for ( i = len; i-- > 0; ) { if ( (upper -= Array[i]) <= 0 ) break; } return (Float_t) ((Float_t)PINK_REF - (Float_t)i / (Float_t)STEPS_per_dB); } Float_t GetTitleGain ( void ) { Float_t retval; int i; retval = analyzeResult ( A, sizeof(A)/sizeof(*A) ); for ( i = 0; i < (int)(sizeof(A)/sizeof(*A)); i++ ) { B[i] += A[i]; A[i] = 0; } for ( i = 0; i < MAX_ORDER; i++ ) linprebuf[i] = lstepbuf[i] = loutbuf[i] = rinprebuf[i] = rstepbuf[i] = routbuf[i] = 0.f; totsamp = 0; lsum = rsum = 0.; return retval; } Float_t GetAlbumGain ( void ) { return analyzeResult ( B, sizeof(B)/sizeof(*B) ); } /* end of gain_analysis.c */ ./id3tag.h0000644000175000017500000000040511213773524011567 0ustar rizlarizla#ifndef ID3TAG_H #define ID3TAG_H int ReadMP3GainID3Tag(char *filename, struct MP3GainTagInfo *info); int WriteMP3GainID3Tag(char *filename, struct MP3GainTagInfo *info, int saveTimeStamp); int RemoveMP3GainID3Tag(char *filename, int saveTimeStamp); #endif ./Makefile0000644000175000017500000000317511426351713011710 0ustar rizlarizla# # Quick 'n dirty unix Makefile # # Mike Oliphant (oliphant@gtk.org) # CC?= gcc CFLAGS+= -Wall -DHAVE_MEMCPY # all known MS Windows OS define the ComSpec environment variable ifdef ComSpec ifndef OSTYPE OSTYPE = win endif EXE_EXT = .exe else EXE_EXT = endif ifneq ($(OSTYPE),beos) INSTALL_PATH= /usr/local/bin else INSTALL_PATH= $(HOME)/config/bin endif # BeOS doesn't have libm (it's all in libroot) ifneq ($(OSTYPE),beos) LIBS= -lm else # BeOS: without this it wants to use bcopy() :^) CFLAGS+= -DHAVE_MEMCPY endif ifeq ($(OSTYPE),win) # gnu windows resource compiler WINDRES = windres endif OBJS= mp3gain.o apetag.o id3tag.o gain_analysis.o rg_error.o \ mpglibDBL/common.o mpglibDBL/dct64_i386.o \ mpglibDBL/decode_i386.o mpglibDBL/interface.o \ mpglibDBL/layer3.o mpglibDBL/tabinit.o ifeq ($(OSTYPE),win) RC_OBJ = VerInfo.o endif all: mp3gain $(RC_OBJ): $(WINDRES) $(RC_OBJ:.o=.rc) $(RC_OBJ) mp3gain: $(RC_OBJ) $(OBJS) $(CC) $(LDFLAGS) -o mp3gain $(OBJS) $(RC_OBJ) $(LIBS) ifeq ($(OSTYPE),beos) mimeset -f mp3gain$(EXE_EXT) endif install: mp3gain ifneq ($(OSTYPE),win) cp -p mp3gain$(EXE_EXT) "$(INSTALL_PATH)" ifeq ($(OSTYPE),beos) mimeset -f "$(INSTALL_PATH)/mp3gain$(EXE_EXT)" endif else @echo install target is not implemented on windows endif uninstall: ifneq ($(OSTYPE),win) -rm -f "$(INSTALL_PATH)/mp3gain$(EXE_EXT)" else @echo uninstall target is not implemented on windows endif clean: -rm -rf mp3gain$(EXE_EXT) mp3gain.zip $(OBJS) $(RC_OBJ) dist: clean ifneq ($(OSTYPE),win) ifneq ($(OSTYPE),beos) zip -r mp3gain.zip * -x "CVS/*" "*/CVS/*" endif else @echo dist target is not implemented on windows and beos endif ./mp3gain.dsw0000644000175000017500000000124507714631703012326 0ustar rizlarizlaMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "mp3gain"=.\mp3gain.dsp - Package Owner=<4> Package=<5> {{{ begin source code control "$/CLI", ECAAAAAA . end source code control }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ begin source code control "$/", aaaaaaaa . end source code control }}} Package=<3> {{{ }}} ############################################################################### ./id3tag.c0000644000175000017500000010533711222217111011555 0ustar rizlarizla/** * Handling of Replay Gain information in ID3v2 tags. * * We store Replay Gain data in RVA2 frames inside the ID3v2.4 tag. * Album and track gain are written as two separate frames. * We use the RVA2 frame as follows: * * Identification string: either "track" or "album"; * Channel number: always 1 (master volume); * Volume adjustment: recommended gain relative to 89 dB standard; * Bits representing peak: always 16; * Peak volume: max absolute sample value relative to full scale * * The meaning of the RVA2 peak volume field is not specified in ID3v2.4. * We follow the interpretation of QuodLibet/mutagen: Peak volume is the * maximum absolute sample value relative to full scale, before application * of the volume adjustment, stored as an unsigned fixed point value with * 1 integer bit and (peakbits-1) fractional bits. * * In addition to standard Replay Gain data, we also store mp3gain-specific * fields in TXXX frames. The description string of such frames starts with * "MP3GAIN_". These frames are only needed when mp3gain updates the encoded * audio volume in MP3 stream (-r and -a command line options). * * We read tag data in ID3v2.2, ID3v2.3 or ID3v2.4 format, from either * the beginning or the end of the file. Extended tag headers are ignored * and removed; compressed frames are ignored but preserved. No workarounds * are attempted for invalid ID3v2.4 tags. * * When writing/updating tag data, we always write a single ID3v2.4 tag * at the beginning of the file, fully unsynchronized. If the original * file had an ID3v2.2 or ID3v2.3 tag, it is upgraded to ID3v2.4. If the * original file had only an appended tag, it is moved to the beginning of * the file. If the original file contained multiple tags, we update only * the first tag and ignore the rest (this is bad, but it's probably a * rare case). If the original file had only an ID3v1 tag, it is copied * to a new ID3v2 tag and the ID3v1 tag is left as it was. * * See: http://www.id3.org/id3v2.4.0-structure * http://www.id3.org/id3v2.4.0-frames */ #include #include #include #include #include "apetag.h" #include "id3tag.h" #include "mp3gain.h" #ifdef WIN32 #define strcasecmp(x,y) _stricmp(x,y) #endif #define DBG(x) /*#define DBG(x) (printf x)*/ #define TAGFL_UNSYNC (0x80) #define TAGFL_EXTHDR (0x40) #define TAGFL_EXPR (0x20) #define TAGFL_FOOTER (0x10) #define FRAMEFL_BAD (0x00f0) #define FRAMEFL_TAGALTER (0x4000) #define FRAMEFL_GROUP (0x0040) #define FRAMEFL_COMPR (0x0008) #define FRAMEFL_CRYPT (0x0004) #define FRAMEFL_UNSYNC (0x0002) #define FRAMEFL_DLEN (0x0001) #define SYNCSAFE_INT_BAD (0xffffffff) struct ID3v2TagStruct { unsigned long offset; /* offset of tag in file */ unsigned long length; /* total length of ID3v2 tag, including header/footer */ unsigned int version; /* ID3v2 version */ unsigned int flags; /* tag flags */ struct ID3v2FrameStruct *frames; /* linked list of frames */ }; struct ID3v2FrameStruct { struct ID3v2FrameStruct *next; /* pointer to next frame */ char frameid[4]; /* frame ID */ unsigned int flags; /* frame flags */ unsigned long len; /* length of frame, excluding header */ unsigned long hskip; /* length of flag parameters */ unsigned char *data; /* pointer to data, excluding header */ }; struct upgrade_id3v22_struct { char id_v22[3]; char id_new[4]; }; static const struct upgrade_id3v22_struct upgrade_id3v22_table[] = { { "BUF", "RBUF" }, { "CNT", "PCNT" }, { "COM", "COMM" }, { "CRA", "AENC" }, { "ETC", "ETCO" }, { "EQU", "EQUA" }, { "GEO", "GEOB" }, { "IPL", "IPLS" }, { "LNK", "LINK" }, { "MCI", "MCDI" }, { "MLL", "MLLT" }, { "PIC", "APIC" /* NOTE: incompatible format */ }, { "POP", "POPM" }, { "REV", "RVRB" }, { "RVA", "RVAD" }, { "SLT", "SYLT" }, { "STC", "SYTC" }, { "TAL", "TALB" }, { "TBP", "TBPM" }, { "TCM", "TCOM" }, { "TCO", "TCON" }, { "TCR", "TCOP" }, { "TDA", "TDAT" }, { "TDY", "TDLY" }, { "TEN", "TENC" }, { "TFT", "TFLT" }, { "TIM", "TIME" }, { "TKE", "TKEY" }, { "TLA", "TLAN" }, { "TLE", "TLEN" }, { "TMT", "TMED" }, { "TOA", "TOPE" }, { "TOF", "TOFN" }, { "TOL", "TOLY" }, { "TOR", "TORY" }, { "TOT", "TOAL" }, { "TP1", "TPE1" }, { "TP2", "TPE2" }, { "TP3", "TPE3" }, { "TP4", "TPE4" }, { "TPA", "TPOS" }, { "TPB", "TPUB" }, { "TRC", "TSRC" }, { "TRD", "TRDA" }, { "TRK", "TRCK" }, { "TSI", "TSIZ" }, { "TSS", "TSSE" }, { "TT1", "TIT1" }, { "TT2", "TIT2" }, { "TT3", "TIT3" }, { "TXT", "TEXT" }, { "TXX", "TXXX" }, { "TYE", "TYER" }, { "UFI", "UFID" }, { "ULT", "USLT" }, { "WAF", "WOAF" }, { "WAR", "WOAR" }, { "WAS", "WOAS" }, { "WCM", "WCOM" }, { "WCP", "WCOP" }, { "WPB", "WPUB" }, { "WXX", "WXXX" }, { "\0\0\0", "\0\0\0\0" } }; /** * Decode a 4-byte unsigned integer. */ static __inline unsigned long id3_get_int32(const unsigned char *p) { return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; } /** * Decode a 4-byte unsigned synchsafe integer. */ static __inline unsigned long id3_get_syncsafe_int(const unsigned char *p) { if ((p[0] | p[1] | p[2] | p[3]) & 0x80) return SYNCSAFE_INT_BAD; return (p[0] << 21) | (p[1] << 14) | (p[2] << 7) | p[3]; } /** * Write a 4-byte unsigned synchsafe integer. */ static __inline void id3_put_syncsafe_int(unsigned char *p, unsigned long i) { p[0] = (i >> 21) & 0x7f; p[1] = (i >> 14) & 0x7f; p[2] = (i >> 7) & 0x7f; p[3] = i & 0x7f; } /** * Decode srclen bytes of unsynchronized data from src into dest. * Return the number of bytes written into dest. * * The buffer pointed to by dest must be large enough to hold the decoded data. * The decoded data will never be longer than the unsynchronized data. * Decoding may be performed in-place by specifying dest equal to src. * * If dest == NULL, decoded data are not stored but the decoded length is * still computed and returned. */ static unsigned long id3_get_unsync_data(unsigned char *dest, const unsigned char *src, unsigned long srclen) { unsigned long k = 0, i; for (i = 0; i < srclen; i++) { if (dest) dest[k] = src[i]; k++; if (src[i] == 0xff && i + 1 < srclen && src[i+1] == 0x00) i++; } return k; } /** * Encode srclen bytes of data from src, writing the unsynchronized version * into dest. Return the number of bytes written into dest. * * The buffer pointed to by dest must be large enough to hold the * unsynchronized data. * * If dest == NULL, unsynchronized data are not stored but the unsynchronized * length is still computed and returned. * * If the returned length is equal to srclen, unsynchronization is not * needed for these data. */ static unsigned long id3_put_unsync_data(unsigned char *dest, const unsigned char *src, unsigned long srclen) { unsigned long k = 0, i; for (i = 0; i < srclen; i++) { if (dest) dest[k] = src[i]; k++; if (src[i] == 0xff && (i + 1 == srclen || src[i+1] == 0x00 || (src[i+1] & 0xe0) == 0xe0)) { if (dest) dest[k] = 0x00; k++; } } return k; } /** * Release memory associated with a chain of frame structures. */ static void id3_release_frames(struct ID3v2FrameStruct *frame) { struct ID3v2FrameStruct *tframe; while (frame) { tframe = frame; frame = frame->next; free(tframe->data); free(tframe); } } /** * Construct an ID3v2 frame according to specified format and parameters. * * The format string contains one character per field in the frame: * 's' stores a string without null-termination (expects const char *) * 'b' stores a single byte (expects unsigned int) * 'h' stores a 16-bit big-endian integer (expects unsigned int) * * Return a newly allocated ID3v2FrameStruct, or NULL if the format * is invalid. */ static struct ID3v2FrameStruct * id3_make_frame(const char *frameid, const char *format, ...) { va_list ap; struct ID3v2FrameStruct *frame; unsigned long j, k; unsigned int i; const char *p, *s; va_start(ap, format); k = 0; for (p = format; *p; p++) { switch (*p) { case 's': /* string */ s = va_arg(ap, const char *); k += strlen(s); break; case 'b': /* byte */ i = va_arg(ap, unsigned int); k += 1; break; case 'h': /* 16-bit integer */ i = va_arg(ap, unsigned int); k += 2; break; default: va_end(ap); return NULL; } } va_end(ap); frame = malloc(sizeof(struct ID3v2FrameStruct)); frame->next = NULL; strncpy(frame->frameid, frameid, 4); frame->flags = 0; frame->len = k; frame->hskip = 0; frame->data = malloc(k); va_start(ap, format); k = 0; for (p = format; *p; p++) { switch (*p) { case 's': /* string */ s = va_arg(ap, const char *); j = strlen(s); memcpy(frame->data + k, s, j); k += j; break; case 'b': /* byte */ i = va_arg(ap, unsigned int); frame->data[k] = i; k += 1; break; case 'h': /* 16-bit integer */ i = va_arg(ap, unsigned int); frame->data[k] = (i >> 8) & 0xff; frame->data[k+1] = i & 0xff; k += 2; break; default: va_end(ap); return NULL; } } va_end(ap); return frame; } /** * Decode an RVA2 frame (only track/album gain, only master channel). * * Store gain information in the info structure, unless info == NULL. * Return 1 if the frame is an RVA2 frame with track/album gain, 0 otherwise. */ static int id3_decode_rva2_frame(const struct ID3v2FrameStruct *frame, struct MP3GainTagInfo *info) { unsigned long p; int is_album_gain, channel, peakbits; double gain, peak; /* Ignore non-RVA2 frames. */ if (memcmp(frame->frameid, "RVA2", 4) != 0) return 0; p = frame->hskip; /* Check identification string; we understand only "track" and "album". */ if (p + 6 <= frame->len && (memcmp(frame->data + p, "track\0", 6) == 0 || memcmp(frame->data + p, "TRACK\0", 6) == 0)) { is_album_gain = 0; p += 6; } else if (p + 6 <= frame->len && (memcmp(frame->data + p, "album\0", 6) == 0 || memcmp(frame->data + p, "ALBUM\0", 6) == 0)) { is_album_gain = 1; p += 6; } else { return 0; } /* Process per-channel data. */ while (p + 4 <= frame->len) { /* * p+0 : channel number * p+1, p+2 : 16-bit signed BE int = adjustment * 512 * p+3 : nr of bits representing peak * p+4 ... : unsigned multibyte BE int = peak sample * 2**(peakbits-1) */ channel = frame->data[p]; gain = (double)(((signed char)(frame->data[p+1]) << 8) | frame->data[p+2]) / 512.0; peakbits = frame->data[p+3]; if (p + 4 + (peakbits + 7) / 8 > frame->len) break; peak = 0; if (peakbits > 0) peak += (double)(frame->data[p+4]); if (peakbits > 8) peak += (double)(frame->data[p+5]) / 256.0; if (peakbits > 16) peak += (double)(frame->data[p+6]) / 65536.0; if (peakbits > 0) peak = peak / (double)(1 << ((peakbits - 1) & 7)); p += 4 + (peakbits + 7) / 8; if (channel == 1) { /* channel == master volume channel */ if (info) { if (is_album_gain) { info->haveAlbumGain = 1; info->albumGain = gain; info->haveAlbumPeak = (peakbits > 0); info->albumPeak = peak; } else { info->haveTrackGain = 1; info->trackGain = gain; info->haveTrackPeak = (peakbits > 0); info->trackPeak = peak; } } } } return 1; } /** * Create an RVA2 frame, track or album gain, master channel. * Return a newly allocated ID3v2FrameStruct. */ static struct ID3v2FrameStruct * id3_make_rva2_frame(int is_album_gain, double gain, int have_peak, double peak) { const char *ident; int g; unsigned int p; /* * identification: string = "track" or "album" * channel type: byte = 1 (master volume) * volume adjustment: int16 = gain * 512 * peak bits: byte = 16 (or 0 if no peak information) * peak: uint16 = peak * 32768 */ ident = (is_album_gain) ? "album" : "track"; g = (gain <= -64) ? -32768 : (gain >= 64) ? 32767 : (int)(gain * 512); if (g < -32768) g = -32768; if (g > 32767) g = 32767; if (have_peak) { p = (peak <= 0) ? 0 : (peak >= 2) ? 65535 : (unsigned int)(peak * 32768); if (p > 65535) p = 65535; return id3_make_frame("RVA2", "sbbhbh", ident, 0, 1, g, 16, p); } else { return id3_make_frame("RVA2", "sbbhb", ident, 0, 1, g, 0); } } /** * Decode a mp3gain-specific TXXX frame, either "MP3GAIN_UNDO" or * "MP3GAIN_MINMAX" or "MP3GAIN_ALBUM_MINMAX". * * Store gain information in the info structure, unless info == NULL. * Return 1 if the frame is a mp3gain-specific TXXX frame, 0 otherwise. */ static int id3_decode_mp3gain_frame(const struct ID3v2FrameStruct *frame, struct MP3GainTagInfo *info) { unsigned long p, k; char buf[64]; int f1, f2; char f3; /* Ignore non-TXXX frames. */ if (memcmp(frame->frameid, "TXXX", 4) != 0) return 0; p = frame->hskip; /* Check text encoding; we understand only 0 (ISO-8859-1) and 3 (UTF-8). */ if (p >= frame->len || (frame->data[p] != 0 && frame->data[p] != 3)) return 0; p++; /* Copy character data to temporary buffer. */ k = (frame->len - p + 1 < sizeof(buf)) ? (frame->len - p) : (sizeof(buf) - 2); memcpy(buf, frame->data + p, k); buf[k] = '\0'; /* terminate the value string */ buf[k+1] = '\0'; /* ensure buf contains two terminated strings, even for invalid frame data */ /* Check identification string. */ if (strcasecmp(buf, "MP3GAIN_UNDO") == 0) { /* value should be something like "+003,+003,W" */ if (sscanf(buf + strlen(buf) + 1, "%d,%d,%c", &f1, &f2, &f3) == 3 && info != NULL) { info->haveUndo = 1; info->undoLeft = f1; info->undoRight = f2; info->undoWrap = (f3 == 'w' || f3 == 'W'); } return 1; } else if (strcasecmp(buf, "MP3GAIN_MINMAX") == 0) { /* value should be something like "001,153" */ if (sscanf(buf + strlen(buf) + 1, "%d,%d", &f1, &f2) == 2 && info != NULL) { info->haveMinMaxGain = 1; info->minGain = f1; info->maxGain = f2; } return 1; } else if (strcasecmp(buf, "MP3GAIN_ALBUM_MINMAX") == 0) { /* value should be something like "001,153" */ if (sscanf(buf + strlen(buf) + 1, "%d,%d", &f1, &f2) == 2 && info != NULL) { info->haveAlbumMinMaxGain = 1; info->albumMinGain = f1; info->albumMaxGain = f2; } return 1; } return 0; } /** * Read an ID3v2 tag from the current position in the MP3 file. * * Return 1 on success, 0 if no tag is found, or a negative error code * if the tag can not be processed. */ static int id3_parse_v2_tag(FILE *f, struct ID3v2TagStruct *tag) { unsigned char buf[12], frameid[4]; unsigned int fflags; unsigned long dlen, flen, fhskip, p, k; unsigned char *tagdata; struct ID3v2FrameStruct *frame, **pframe; /* Read header */ tag->offset = ftell(f); if (fread(buf, 1, 10, f) != 10) return 0; /* Check 'ID3' signature. */ if (memcmp(buf, "ID3", 3) != 0) return 0; DBG(("DEBUG: Found ID3v2 tag at offset %lu\n", tag->offset)); /* Check version and flags. */ switch (buf[3]) { case 2: /* ID3v2.2 */ if (buf[5] & (~(TAGFL_UNSYNC))) return M3G_ERR_TAGFORMAT; /* unknown flags */ break; case 3: /* ID3v2.3 */ if (buf[5] & (~(TAGFL_UNSYNC | TAGFL_EXTHDR | TAGFL_EXPR))) return M3G_ERR_TAGFORMAT; /* unknown flags */ break; case 4: /* ID3v2.4 */ if (buf[5] & (~(TAGFL_UNSYNC | TAGFL_EXTHDR | TAGFL_EXPR | TAGFL_FOOTER))) return M3G_ERR_TAGFORMAT; /* unknown flags */ break; default: return M3G_ERR_TAGFORMAT; /* unknown version */ } /* Check length. */ dlen = id3_get_syncsafe_int(buf + 6); if (dlen == SYNCSAFE_INT_BAD) return M3G_ERR_TAGFORMAT; /* Fill tag structure. */ tag->flags = buf[5]; tag->version = (buf[3] << 8) | buf[4]; tag->length = 10 + dlen + ((tag->flags & TAGFL_FOOTER) ? 10 : 0); tag->frames = NULL; DBG((" version=%04x length=%lu flags=%02x\n", tag->version, tag->length, tag->flags)); /* Read rest of the tag. */ tagdata = malloc(dlen); if (fread(tagdata, 1, dlen, f) != dlen) goto badtag; /* If this is an unsynced v2.2 or v2.3 tag, decode it now. */ if ((tag->version >> 8) != 4 && (tag->flags & TAGFL_UNSYNC) != 0) { dlen = id3_get_unsync_data(tagdata, tagdata, dlen); } /* Skip extended header. */ p = 0; if ((tag->flags & TAGFL_EXTHDR) != 0) { DBG((" skip extended header\n")); if (p + 6 > dlen) goto badtag; if ((tag->version >> 8) == 4) { /* Skip ID3v2.4 extended header */ k = id3_get_syncsafe_int(tagdata + p); if (k == SYNCSAFE_INT_BAD || k > dlen) goto badtag; p += k; } else if ((tag->version >> 8) == 3) { /* Skip ID3v2.3 extended header */ k = id3_get_int32(tagdata + p); if (k > dlen) goto badtag; p += 4 + k; } } /* Scan frames. */ pframe = &(tag->frames); while (p < dlen && tagdata[p] != '\0') { /* Decode frame header. */ switch (tag->version >> 8) { case 2: /* ID3v2.2 */ if (p + 5 > dlen) goto badtag; memset(frameid, 0, 4); for (k = 0; upgrade_id3v22_table[k].id_new[0]; k++) { if (memcmp(tagdata + p, upgrade_id3v22_table[k].id_v22, 3) == 0) { memcpy(frameid, upgrade_id3v22_table[k].id_new, 4); break; } } flen = (tagdata[p+3] << 16) | (tagdata[p+4] << 8) | tagdata[p+5]; fflags = 0; if (flen > dlen) goto badtag; p += 6; break; case 3: /* ID3v2.3 */ if (p + 10 > dlen) goto badtag; memcpy(frameid, tagdata + p, 4); flen = id3_get_int32(tagdata + p + 4); fflags = (tagdata[p+8] << 7) & 0xff00; if (tagdata[p+9] & 0x80) fflags |= FRAMEFL_COMPR | FRAMEFL_DLEN; if (tagdata[p+9] & 0x40) fflags |= FRAMEFL_CRYPT; if (tagdata[p+9] & 0x20) fflags |= FRAMEFL_GROUP; if (tagdata[p+9] & 0x1f) fflags |= FRAMEFL_BAD; if (flen > dlen) goto badtag; p += 10; break; case 4: /* ID3v2.4 */ if (p + 10 > dlen) goto badtag; memcpy(frameid, tagdata + p, 4); flen = id3_get_syncsafe_int(tagdata + p + 4); fflags = (tagdata[p+8] << 8) | tagdata[p+9]; if (flen == SYNCSAFE_INT_BAD || flen > dlen) goto badtag; p += 10; break; default: /* unreachable */ goto badtag; } if (p + flen > dlen) goto badtag; DBG((" got frameid=%.4s fflags=%04x\n", frameid, fflags)); /* Drop unsupported frame types. */ if (frameid[0] == '\0' || memcmp(frameid, "RVAD", 4) == 0 || memcmp(frameid, "RGAD", 4) == 0 || memcmp(frameid, "XRVA", 4) == 0) { DBG((" drop unsupported frame\n")); p += flen; continue; } /* Drop v2.3 frames which we can not upgrade. */ if ((tag->version >> 8) == 3 && (fflags & (FRAMEFL_CRYPT | FRAMEFL_BAD)) != 0) { DBG((" drop non-upgradable frame\n")); p += flen; continue; } /* Drop frames that are too short for their flags. */ fhskip = (fflags & FRAMEFL_GROUP ? 1 : 0) + (fflags & FRAMEFL_CRYPT ? 1 : 0) + (fflags & FRAMEFL_DLEN ? 4 : 0); if (fhskip > flen) { DBG((" drop short frame\n")); p += flen; continue; } /* Drop v2.2 PIC frames that are too short. */ if ((tag->version >> 8) == 2 && memcmp(frameid, "APIC", 4) == 0 && flen < 6) { DBG((" drop short PIC frame\n")); p += flen; continue; } /* Rename TYER (Year) to TDRC (Recording time) */ if (memcmp(frameid, "TYER", 4) == 0) memcpy(frameid, "TDRC", 4); /* Drop frames that want to be dropped on tag alteration. */ if (fflags & FRAMEFL_TAGALTER) { DBG((" drop FRAMEFL_TAGALTER frame\n")); p += flen; continue; } /* Allocate frame structure. */ frame = malloc(sizeof(struct ID3v2FrameStruct)); frame->next = NULL; memcpy(frame->frameid, frameid, 4); frame->flags = fflags; frame->hskip = fhskip; *pframe = frame; pframe = &(frame->next); /* Copy frame data. */ if ((tag->version >> 8) == 4 && (fflags & FRAMEFL_UNSYNC) != 0) { /* This frame is unsynchronized; decode it now. */ frame->data = malloc(flen); k = id3_get_unsync_data(frame->data, tagdata + p, flen); frame->len = k; p += flen; } else if ((tag->version >> 8) == 2 && memcmp(frameid, "APIC", 4) == 0) { /* APIC frame format differs from PIC frame format */ frame->data = malloc(flen + 12); frame->data[0] = tagdata[p]; k = 1; if (memcmp(tagdata + p + 1, "PNG", 3) == 0) { memcpy(frame->data + k, "image/png", strlen("image/png") + 1); k += strlen("image/png") + 1; } else if (memcmp(tagdata + p + 1, "JPG", 3) == 0) { memcpy(frame->data + k, "image/jpeg", strlen("image/jpeg") + 1); k += strlen("image/jpeg") + 1; } else if (tagdata[p+1] == '\0') { memcpy(frame->data + k, tagdata + p + 1, 3); frame->data[k+3] = '\0'; k += 4; } memcpy(frame->data + k, tagdata + p + 4, flen - 4); frame->len = k + flen - 4; p += flen; } else { /* Normal case, just copy the data. */ frame->data = malloc(flen); memcpy(frame->data, tagdata + p, flen); frame->len = flen; p += flen; } /* Reorder flag parameters of upgraded v2.3 frames. */ if ((tag->version >> 8) == 3 && (fflags & FRAMEFL_DLEN) != 0) { k = id3_get_int32(frame->data); if (fflags & FRAMEFL_GROUP) { frame->data[0] = frame->data[4]; id3_put_syncsafe_int(frame->data + 1, k); } else { id3_put_syncsafe_int(frame->data, k); } } } if (p > dlen) goto badtag; free(tagdata); return 1; badtag: free(tagdata); id3_release_frames(tag->frames); return M3G_ERR_TAGFORMAT; } /** * Write an ID3v2 tag at the current position in the MP3 file. * * Tags are always written in ID3v2.4 format. * Tags are always written completely unsynchronized, * without extended header, padded up to an integer multiple of 2 KB. * We don't write a tag footer (not supported by QuodLibet). * * Return 1 on success, 0 if the tag contains no frames, * or a negative error code. */ static int id3_write_tag(FILE *f, struct ID3v2TagStruct *tag) { unsigned long dlen, p, k; unsigned char *tagdata; struct ID3v2FrameStruct *frame; DBG(("DEBUG: Writing ID3v2 tag\n")); /* Do not write a tag with zero frames. */ if (tag->frames == NULL) return 0; /* Compute raw total length of tag. */ dlen = 10; /* tag header */ for (frame = tag->frames; frame; frame = frame->next) { dlen += 10; dlen += id3_put_unsync_data(NULL, frame->data, frame->len); } dlen = (dlen + 2047) & (~2047); /* padding */ DBG((" length=%lu\n", dlen)); /* Allocate buffer and fill with zeros. */ tagdata = calloc(dlen, sizeof(unsigned char)); /* Prepare tag header. */ tagdata[0] = 'I'; tagdata[1] = 'D'; tagdata[2] = '3'; tagdata[3] = 4; tagdata[4] = 0; tagdata[5] = TAGFL_UNSYNC | (tag->flags & TAGFL_EXPR); id3_put_syncsafe_int(tagdata + 6, dlen - 10); p = 10; /* Prepare frames. */ for (frame = tag->frames; frame; frame = frame->next) { unsigned long fflags = frame->flags & (~FRAMEFL_UNSYNC); memcpy(tagdata + p, frame->frameid, 4); k = id3_put_unsync_data(tagdata + p + 10, frame->data, frame->len); id3_put_syncsafe_int(tagdata + p + 4, k); if (k != frame->len) fflags |= FRAMEFL_UNSYNC; tagdata[p+8] = (fflags >> 8) & 0xff; tagdata[p+9] = fflags & 0xff; p += 10 + k; DBG((" write frameid=%.4s length=%lu\n", frame->frameid, 10 + k)); } /* Write the whole thing. */ if (fwrite(tagdata, 1, dlen, f) != dlen) { free(tagdata); return M3G_ERR_WRITE; } free(tagdata); return 1; } /** * Read an ID3v1 tag from the current position in the MP3 file. * * Return 1 on success, 0 if no tag is found. */ static int id3_parse_v1_tag(FILE *f, struct ID3v2TagStruct *tag) { unsigned char buf[128]; char sbuf[32]; struct ID3v2FrameStruct **pframe; /* Read tag */ tag->offset = ftell(f); if (fread(buf, 1, 128, f) != 128) return 0; /* Check 'TAG' signature. */ if (memcmp(buf, "TAG", 3) != 0) return 0; DBG(("DEBUG: Found ID3v1 tag at offset %lu\n", tag->offset)); /* Convert ID3v1 data to ID3v2.4 */ tag->length = 128; tag->version = 0; tag->flags = 0; tag->frames = NULL; pframe = &(tag->frames); /* Add title field (offset 3, len 30). */ if (buf[3] != '\0') { memcpy(sbuf, buf + 3, 30); sbuf[30] = '\0'; *pframe = id3_make_frame("TIT2", "bs", 0, sbuf); pframe = &((*pframe)->next); } /* Add artist field (offset 33, len 30). */ if (buf[33] != '\0') { memcpy(sbuf, buf + 33, 30); sbuf[30] = '\0'; *pframe = id3_make_frame("TPE1", "bs", 0, sbuf); pframe = &((*pframe)->next); } /* Add album field (offset 63, len 30). */ if (buf[63] != '\0') { memcpy(sbuf, buf + 63, 30); sbuf[30] = '\0'; *pframe = id3_make_frame("TALB", "bs", 0, sbuf); pframe = &((*pframe)->next); } /* Add release year (offset 93, len 4). */ if (buf[93] >= '0' && buf[93] <= '9' && buf[94] >= '0' && buf[94] <= '9' && buf[95] >= '0' && buf[95] <= '9' && buf[96] >= '0' && buf[96] <= '9') { memcpy(sbuf, buf + 93, 4); sbuf[4] = '\0'; *pframe = id3_make_frame("TDRC", "bs", 0, sbuf); pframe = &((*pframe)->next); } /* Add comment (offset 97, len 30). */ if (buf[97] != '\0') { memcpy(sbuf, buf + 97, 30); sbuf[30] = '\0'; /* assume ISO-8859-1, unknown language, no description */ *pframe = id3_make_frame("COMM", "bssbs", 0, "XXX", "", 0, sbuf); pframe = &((*pframe)->next); } /* Add track number (offset 126, len 1). */ if (buf[125] == '\0' && buf[126] != 0) { sprintf(sbuf, "%u", buf[126]); *pframe = id3_make_frame("TRCK", "bs", 0, sbuf); pframe = &((*pframe)->next); } return 1; } /** * Search for an ID3v2 tag at the beginning and end of the file. * If no ID3v2 tag is found, search for an ID3v1 tag at the end * of the file. * * Return 1 on success, 0 if no tag is found, or a negative error code * if the tag can not be processed. */ static int id3_search_tag(FILE *f, struct ID3v2TagStruct *tag) { unsigned char buf[32]; unsigned long pos, k, id3v1_pos = 0; int j, ret; /* Look for ID3v2 at the beginning of the file. */ fseek(f, 0, SEEK_SET); ret = id3_parse_v2_tag(f, tag); if (ret == 0) { /* Look for ID3v2 at the end of the file. */ fseek(f, 0, SEEK_END); pos = ftell(f); while (pos > 128) { /* Test for ID3v2 footer */ fseek(f, pos - 10, SEEK_SET); if (fread(buf, 1, 10, f) != 10) return M3G_ERR_READ; if (memcmp(buf, "3DI", 3) == 0 && buf[3] == 4 && ((buf[6] | buf[7] | buf[8] | buf[9]) & 0x80) == 0) { /* Parse ID3v2.4 tag */ k = id3_get_syncsafe_int(buf + 6); if (20 + k < pos) { pos -= 20 + k; fseek(f, pos, SEEK_SET); ret = id3_parse_v2_tag(f, tag); break; } } /* Test for ID3v1/Lyrics3v2 tag */ fseek(f, pos - 128, SEEK_SET); if (fread(buf, 1, 3, f) != 3) return M3G_ERR_READ; if (memcmp(buf, "TAG", 3) == 0) { /* Skip over ID3v1 tag and continue */ pos -= 128; DBG(("DEBUG: Skipping ID3v1 tag at offset %lu\n", pos)); id3v1_pos = pos; /* Test for Lyrics3v2 tag */ if (pos > 26) { fseek(f, pos - 15, SEEK_SET); if (fread(buf, 1, 15, f) != 15) return M3G_ERR_READ; if (memcmp(buf + 6, "LYRICS200", 9) == 0) { /* Skip over Lyrics tag */ k = 0; for (j = 0; j < 6; j++) { if (buf[j] < '0' || buf[j] > '9') { k = 0; break; } k = 10 * k + (buf[j] - '0'); } if (k >= 11 && k + 15 < pos) { pos -= k + 15; DBG(("DEBUG: Skipping Lyrics3v2 tag at offset %lu\n", pos)); } } } continue; } /* Test for APE tag */ fseek(f, pos - 32, SEEK_SET); if (fread(buf, 1, 32, f) != 32) return M3G_ERR_READ; if (memcmp(buf, "APETAGEX", 8) == 0) { /* Skip over APE tag and continue */ k = buf[12] | (buf[13] << 8) | (buf[14] << 16) | (buf[15] << 24); /* tag length */ if (buf[23] & 0x80) k += 32; /* tag header present */ if (k >= 32 && k < pos) { pos -= k; DBG(("DEBUG: Skipping APE tag at offset %lu\n", pos)); continue; } } /* No more tags to skip. */ break; } } if (ret == 0 && id3v1_pos != 0) { /* Read ID3v1 at the end of the file. */ fseek(f, id3v1_pos, SEEK_SET); ret = id3_parse_v1_tag(f, tag); } return ret; } /** * Seek to offset in inf and copy count bytes to the current * position in outf. If count == -1, copy until the end of the file. * * Return 1 on success, otherwise a negative error code. */ static int id3_copy_data(FILE *inf, FILE *outf, long offset, long count) { const long bufsize = 65536; char *buf; size_t k; int ret; ret = 1; buf = malloc(bufsize); if (fseek(inf, offset, SEEK_SET)) ret = M3G_ERR_READ; while (ret == 1 && count != 0) { k = (count > 0 && count < bufsize) ? count : bufsize; k = fread(buf, 1, k, inf); if (k == 0) { if (!feof(inf) || count > 0) ret = M3G_ERR_READ; break; } if (fwrite(buf, 1, k, outf) != k) { ret = M3G_ERR_WRITE; break; } if (count > 0) count -= k; } free(buf); return ret; } /** * Read gain information from an ID3v2 tag. */ int ReadMP3GainID3Tag(char *filename, struct MP3GainTagInfo *info) { FILE *f; struct ID3v2TagStruct tag; struct ID3v2FrameStruct *frame; int ret; f = fopen(filename, "rb"); if (f == NULL) { passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Could not open ", filename, "\n"); return M3G_ERR_FILEOPEN; } ret = id3_search_tag(f, &tag); fclose(f); if (ret == M3G_ERR_READ) { passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error reading ", filename, "\n"); } if (ret == 1) { /* Got the tag; extract gain information from the RVA2/TXXX frames. */ frame = tag.frames; while (frame) { id3_decode_rva2_frame(frame, info); id3_decode_mp3gain_frame(frame, info); frame = frame->next; } id3_release_frames(tag.frames); } return ret; } /** * (Re-)Write gain information to an ID3v2 tag. * * Writes or updates an ID3v2.4 tag at the beginning of the file. * If the file does not yet contain an ID3v2 tag, a new tag is created, * copying basic fields from an ID3v1 tag if present. * If the file contains an ID3v2.2 or ID3v2.3 tag, it is rewritten as ID3v2.4. * * Since modifications are made at the beginning of the file, the entire * file is rewritten to a temporary file and then moved in place of the * old file. */ int WriteMP3GainID3Tag(char *filename, struct MP3GainTagInfo *info, int saveTimeStamp) { char sbuf[32]; char *tmpfilename; FILE *f, *outf; struct ID3v2TagStruct tag; struct ID3v2FrameStruct *frame, **pframe; int ret, need_update; if (saveTimeStamp) fileTime(filename, storeTime); f = fopen(filename, "rb"); if (f == NULL) { passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Could not open ", filename, "\n"); return M3G_ERR_FILEOPEN; } ret = id3_search_tag(f, &tag); switch (ret) { case M3G_ERR_READ: passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error reading ", filename, "\n"); break; case M3G_ERR_TAGFORMAT: passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Unsupported ID3v2 tag in ", filename, "\n"); break; } if (ret < 0) { /* Error. */ fclose(f); return ret; } if (ret == 0) { /* No ID3v2 or ID3v1 tag found in the file; create a new tag. */ tag.offset = 0; tag.length = 0; tag.version = 0; tag.flags = 0; tag.frames = NULL; } /* Kill existing replaygain frames. */ need_update = 0; pframe = &(tag.frames); while ((frame = *pframe)) { if (id3_decode_rva2_frame(frame, NULL) == 1 || id3_decode_mp3gain_frame(frame, NULL) == 1) { /* This is a ReplayGain frame; kill it. */ need_update = 1; *pframe = frame->next; free(frame->data); free(frame); } else { pframe = &((*pframe)->next); } } /* Append new replaygain frames. */ if (info->haveTrackGain) { need_update = 1; frame = id3_make_rva2_frame(0, info->trackGain, info->haveTrackPeak, info->trackPeak); *pframe = frame; pframe = &(frame->next); } if (info->haveAlbumGain) { need_update = 1; frame = id3_make_rva2_frame(1, info->albumGain, info->haveAlbumPeak, info->albumPeak); *pframe = frame; pframe = &(frame->next); } /* Append mp3gain-specific frames. */ if (info->haveMinMaxGain) { need_update = 1; sprintf(sbuf, "%03d,%03d", info->minGain, info->maxGain); frame = id3_make_frame("TXXX", "bsbs", 0, "MP3GAIN_MINMAX", 0, sbuf); *pframe = frame; pframe = &(frame->next); } if (info->haveAlbumMinMaxGain) { need_update = 1; sprintf(sbuf, "%03d,%03d", info->albumMinGain, info->albumMaxGain); frame = id3_make_frame("TXXX", "bsbs", 0, "MP3GAIN_ALBUM_MINMAX", 0, sbuf); *pframe = frame; pframe = &(frame->next); } if (info->haveUndo) { need_update = 1; sprintf(sbuf, "%+04d,%+04d,%c", info->undoLeft, info->undoRight, info->undoWrap ? 'W' : 'N'); frame = id3_make_frame("TXXX", "bsbs", 0, "MP3GAIN_UNDO", 0, sbuf); *pframe = frame; pframe = &(frame->next); } if (!need_update) { /* No need to change MP3 file. */ fclose(f); id3_release_frames(tag.frames); return 0; } /* Create temporary file. */ tmpfilename = malloc(strlen(filename) + 5); strcpy(tmpfilename, filename); strcat(tmpfilename, ".TMP"); outf = fopen(tmpfilename, "wb"); if (outf == NULL) { passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Can not create temporary file ", tmpfilename, "\n"); fclose(f); free(tmpfilename); id3_release_frames(tag.frames); return M3G_ERR_CANT_MAKE_TMP; } /* Write new ID3v2 tag. */ ret = id3_write_tag(outf, &tag); /* Write rest of MP3 file. */ if (ret >= 0) { if (tag.version == 0) { /* The original file has no ID3v2 tag; copy everything. */ ret = id3_copy_data(f, outf, 0, -1); } else { /* The original file has an ID3v2 tag; copy everything except the original tag. */ ret = id3_copy_data(f, outf, 0, tag.offset); if (ret >= 0) ret = id3_copy_data(f, outf, tag.offset + tag.length, -1); } } fclose(outf); fclose(f); id3_release_frames(tag.frames); switch (ret) { case M3G_ERR_READ: passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error reading ", filename, "\n"); break; case M3G_ERR_WRITE: passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error writing ", tmpfilename, "\n"); break; } if (ret < 0) { /* Delete temp file after error. */ remove(tmpfilename); free(tmpfilename); return ret; } /* Replace original file. */ #ifdef WIN32 /* "rename" function in WIN32 does _not_ replace existing destination file, so we have to manually remove it first */ if (remove(filename) != 0) { passError(MP3GAIN_UNSPECIFED_ERROR, 5, "Can not rename ", tmpfilename, " to ", filename, "\n"); ret = M3G_ERR_RENAME_TMP; /* Do NOT remove the temp file itself, just in case the "remove(filename)" function only _temporarily_ failed, and the original file will disappear soon, such as when all handles on the file are closed. If it does disappear and we also delete the tmp file, then the file is completely gone... */ free(tmpfilename); } #endif ret = 1; if (rename(tmpfilename, filename)) { remove(tmpfilename); passError(MP3GAIN_UNSPECIFED_ERROR, 5, "Can not rename ", tmpfilename, " to ", filename, "\n"); ret = M3G_ERR_RENAME_TMP; } else { if (saveTimeStamp) fileTime(filename, setStoredTime); } free(tmpfilename); return ret; } /** * Remove gain information from the ID3v2 tag. * Return 1 on success, 0 if no changes are needed, or a negative error code. */ int RemoveMP3GainID3Tag(char *filename, int saveTimeStamp) { struct MP3GainTagInfo info; info.haveAlbumGain = 0; info.haveAlbumPeak = 0; info.haveTrackGain = 0; info.haveTrackPeak = 0; info.haveMinMaxGain = 0; info.haveAlbumMinMaxGain = 0; info.haveUndo = 0; return WriteMP3GainID3Tag(filename, &info, saveTimeStamp); } ./VerInfo.rc0000644000175000017500000000471411355415423012146 0ustar rizlarizla//Microsoft Developer Studio generated resource script. // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 #ifndef _MAC ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 1,5,0,2 PRODUCTVERSION 1,5,0,2 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x1L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "ProductName", "mp3gain\0" VALUE "Author", "Glen Sawyer\0" VALUE "FileDescription", "mp3 volume normalizer\0" VALUE "LegalCopyright", "Copyright © 2001-2009 Glen Sawyer\0" VALUE "OriginalFilename", "mp3gain.exe\0" VALUE "FileVersion", "1, 5, 0, 2\0" VALUE "ProductVersion", "1, 5, 0, 2\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif // !_MAC #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED ./rg_error.c0000644000175000017500000000511211422242326012221 0ustar rizlarizla/* * ReplayGainAnalysis Error Reporting * Handles error reporting for mp3gain in either standalone or DLL form. * * Copyright (C) 2002 John Zitterkopf (zitt@bigfoot.com) * (http://www.zittware.com) * * These comments must remain intact in all copies of the source code. * * 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 * * based on code by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA * * Error code for VC++5.0 by John Zitterkopf (zitt@bigfoot.com) * -- blame him for nothing. This work evolves as needed. * * V1.0 - jzitt * * initial release based on V1.2.3 sources */ #include "rg_error.h" #ifndef asWIN32DLL extern int gSuccess; #endif void DoError( char * localerrstr, MMRESULT localerrnum ) { #ifndef asWIN32DLL gSuccess = 0; fprintf(stdout, "%s", localerrstr); #else //send message to DLL's parent mp3gainerr = localerrnum; if (mp3gainerrstr != NULL) { free(mp3gainerrstr); mp3gainerrstr = NULL; } mp3gainerrstr = malloc(strlen(localerrstr) + 1); strcpy(mp3gainerrstr,localerrstr); if ( (apphandle != 0) && ( apperrmsg != 0 ) ) { SendMessage(apphandle, apperrmsg, localerrnum, (LPARAM) localerrstr); } #endif } void DoUnkError( char * localerrstr) { DoError( localerrstr, MP3GAIN_UNSPECIFED_ERROR ); } #ifdef asWIN32DLL /*the sendpercentdone sends a windows message to the calling app with the progress into the file (pdone). The calling app acknowledges the message by returning an LRESULT. LRESULT = 0 means continue processing the file. LRESULT != 0 means abort processing this file. */ LRESULT sendpercentdone( int pdone, long filesize ) { //send message to DLL's parent if ( (apphandle != 0) && ( apppercentdonemsg != 0 ) ) { return !(SendNotifyMessage(apphandle, apppercentdonemsg, pdone, filesize)); } else return(0); //no calling app defined, send by 0 to continue } #endif ./rg_error.h0000644000175000017500000000437610026661330012240 0ustar rizlarizla/* * ReplayGainAnalysis Error Reporting Header * Handles error reporting for mp3gain in either standalone or DLL form. * * Copyright (C) 2002 John Zitterkopf (zitt@bigfoot.com) * (http://www.zittware.com) * * These comments must remain intact in all copies of the source code. * * 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 * * based on code by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA * * Error code for VC++5.0 by John Zitterkopf (zitt@bigfoot.com) * -- blame him for nothing. This work evolves as needed. * * V1.0 - jzitt * * initial release based on V1.2.3 */ #ifndef RG_ERROR_H #define RG_ERROR_H #include #ifdef asWIN32DLL #include #include MMRESULT mp3gainerr; char * mp3gainerrstr; BOOL blnCancel; HANDLE apphandle; //holds calling app's window handle int apppercentdonemsg; //holds calling apps message number for percent done int apperrmsg; //holds calling apps message number for errors LRESULT sendpercentdone( int pdone, long filesize ); #else /*asWIN32DLL*/ #include #define MMSYSERR_NOERROR 0 #define MMSYSERR_ERROR 01 #define WAVERR_BADFORMAT 32 typedef unsigned int MMRESULT; #endif /*asWIN32DLL*/ #define MP3GAIN_NOERROR MMSYSERR_NOERROR #define MP3GAIN_UNSPECIFED_ERROR MMSYSERR_ERROR #define MP3GAIN_FILEFORMAT_NOTSUPPORTED WAVERR_BADFORMAT #define MP3GAIN_CANCELLED 2006 void DoUnkError( char * localerrstr); void DoError( char * localerrstr, MMRESULT localerrnum ); #endif