mppenc-1.16/0000755000175000017500000000000010525730167012207 5ustar bencerbencermppenc-1.16/CMakeLists.txt0000644000175000017500000000031510525176503014744 0ustar bencerbencerCMAKE_MINIMUM_REQUIRED(VERSION 2.4) project(mppenc C) set(CMAKE_VERBOSE_MAKEFILE false) if(NOT MSVC) set(CMAKE_C_FLAGS "-O2 -ffast-math -fomit-frame-pointer -pipe") endif(NOT MSVC) add_subdirectory(src) mppenc-1.16/win32/0000755000175000017500000000000010525730167013151 5ustar bencerbencermppenc-1.16/win32/mppenc.sln0000644000175000017500000000155410522734510015147 0ustar bencerbencer Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mppenc", "mppenc.vcproj", "{15082E34-9324-469F-8423-F995B4814A37}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {15082E34-9324-469F-8423-F995B4814A37}.Debug|Win32.ActiveCfg = Debug|Win32 {15082E34-9324-469F-8423-F995B4814A37}.Debug|Win32.Build.0 = Debug|Win32 {15082E34-9324-469F-8423-F995B4814A37}.Release|Win32.ActiveCfg = Release|Win32 {15082E34-9324-469F-8423-F995B4814A37}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal mppenc-1.16/win32/mppenc.vcproj0000644000175000017500000001413010524423665015660 0ustar bencerbencer mppenc-1.16/src/0000755000175000017500000000000010525730167012776 5ustar bencerbencermppenc-1.16/src/psy.c0000644000175000017500000013513110522734510013752 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ /* * Prediction * Short-Block-detection with smooth inset * revise CalcMSThreshold * /dev/audio for Windows too * revise PNS/IS * CVS with smoother inset * several files per call * revise ANS with changing SCFs * No IS * PNS estimation very rough, also IS should be used to reduce data rate in the side channel * ANS problems at Frame boundaries when resolution changes * ANS problems at Subframe boundaries when SCF changes * CVS+ with smoother transition ---------------------------------------- Optimize Tabelle[18] (use second table) CVS+ - ANS is disregarded during the search for the best Res - ANS messes up if res changes (each 36 samples) and/or SCF changes (each 12 samples) - PNS not in difference signal - implement IS in decoder - Experimental Quantizer with complete energy preservation - 1D, calculated - 2D, calculated - 2D, manually modified, coeffs set to 1.f */ #include "mppenc.h" /* V A R I A B L E S */ /* further switches for the psymodel */ unsigned int CVD_used; // global flag for ClearVoiceDetection float varLtq; // variable threshold in quiet unsigned int tmpMask_used; // global flag for temporal masking float ShortThr; // Factor to calculate the masking threshold with transients float minSMR; // minimum SMR for all subbands float a [PART_LONG]; float b [PART_LONG]; float c [PART_LONG]; float d [PART_LONG]; // Integrations for tmpMask static float Xsave_L [3 * 512]; static float Xsave_R [3 * 512]; // FFT-Amplitudes L/R static float Ysave_L [3 * 512]; static float Ysave_R [3 * 512]; // FFT-Phases L/R float T_L [PART_LONG]; float T_R [PART_LONG]; // time-constants for tmpMask float pre_erg_L[2][PART_SHORT]; float pre_erg_R[2][PART_SHORT]; // Preecho-control short float PreThr_L [PART_LONG]; float PreThr_R [PART_LONG]; // for Pre-Echo-control L/R float tmp_Mask_L [PART_LONG]; float tmp_Mask_R [PART_LONG]; // for Post-Masking L/R int Vocal_L [MAX_CVD_LINE + 4]; int Vocal_R [MAX_CVD_LINE + 4]; // FFT-Line belongs to harmonic? /* F U N C T I O N S */ // Resets Arrays void Init_Psychoakustik ( void ) { int i; ENTER(200); // generate FFT lookup-tables with largest FFT-size of 1024 Init_FFT (); // setting pre-echo variables to Ltq for ( i = 0; i < PART_LONG; i++ ) { pre_erg_L [0][i/3] = pre_erg_R [0][i/3] = pre_erg_L [1][i/3] = pre_erg_R [1][i/3] = tmp_Mask_L [i] = tmp_Mask_R [i] = PreThr_L [i] = PreThr_R [i] = partLtq [i]; } // initializing arrays with zero memset ( Xsave_L, 0, sizeof Xsave_L ); memset ( Xsave_R, 0, sizeof Xsave_R ); memset ( Ysave_L, 0, sizeof Ysave_L ); memset ( Ysave_R, 0, sizeof Ysave_R ); memset ( a, 0, sizeof a ); memset ( b, 0, sizeof b ); memset ( c, 0, sizeof c ); memset ( d, 0, sizeof d ); memset ( T_L, 0, sizeof T_L ); memset ( T_R, 0, sizeof T_R ); memset ( Vocal_L, 0, sizeof Vocal_L ); memset ( Vocal_R, 0, sizeof Vocal_R ); LEAVE(200); return; } // VBRmode 1: Adjustment of all SMRs via a factor (offset of SMRoffset dB) // VBRmode 2: SMRs have a minimum of minSMR dB static void RaiseSMR_Signal ( const int MaxBand, float* signal, float tmp ) { int Band; float z = 0.; for ( Band = MaxBand; Band >= 0; Band-- ) { if ( z < signal [Band] ) z = signal [Band]; if ( z > tmp ) z = tmp; if ( signal [Band] < z ) signal [Band] = z; } } void RaiseSMR ( const int MaxBand, SMRTyp* smr ) { float tmp = POW10 ( 0.1 * minSMR ); ENTER(201); RaiseSMR_Signal ( MaxBand, smr->L, tmp ); RaiseSMR_Signal ( MaxBand, smr->R, tmp ); RaiseSMR_Signal ( MaxBand, smr->M, tmp ); RaiseSMR_Signal ( MaxBand, smr->S, 0.5 * tmp ); LEAVE(201); return; } // input : *smr // output: *smr, *ms, *x (only the entries for L/R contain relevant data) // Check if either M/S- or L/R-coding has a lower perceptual entropy // Choose the better mode, copy the appropriate data into the // arrays that belong to L and R and set the ms-Flag accordingly. void MS_LR_Entscheidung ( const int MaxBand, unsigned char* ms, SMRTyp* smr, SubbandFloatTyp* x ) { int Band; int n; float PE_MS; float PE_LR; float tmpM; float tmpS; float* l; float* r; ENTER(202); for ( Band = 0; Band <= MaxBand; Band++ ) { // calculate perceptual entropy PE_LR = PE_MS = 1.f; if (smr->L[Band] > 1.) PE_LR *= smr->L[Band]; if (smr->R[Band] > 1.) PE_LR *= smr->R[Band]; if (smr->M[Band] > 1.) PE_MS *= smr->M[Band]; if (smr->S[Band] > 1.) PE_MS *= smr->S[Band]; if ( PE_MS < PE_LR ) { ms[Band] = 1; // calculate M/S-signal and copies it to L/R-array l = x[Band].L; r = x[Band].R; for ( n = 0; n < 36; n++, l++, r++ ) { tmpM = (*l + *r) * 0.5f; tmpS = (*l - *r) * 0.5f; *l = tmpM; *r = tmpS; } // copy M/S - SMR to L/R-fields smr->L[Band] = smr->M[Band]; smr->R[Band] = smr->S[Band]; } else { ms[Band] = 0; } } LEAVE(202); return; } // input : FFT-spectrums *spec0 und *spec1 // output: energy in the individual subbands *erg0 and *erg1 // With Butfly[], you can calculate the results of aliasing during calculation // of subband energy from the FFT-spectrums. static void SubbandEnergy ( const int MaxBand, float* erg0, float* erg1, const float* spec0, const float* spec1 ) { int n; int k; int alias; float tmp0; float tmp1; ENTER(203); // Is this here correct for FFT-based data or is this calculation rule only for MDCTs??? for ( k = 0; k <= MaxBand; k++ ) { // subband index tmp0 = tmp1 = 0.f; for ( n = 0; n < 16; n++, spec0++, spec1++ ) { // spectral index tmp0 += *spec0; tmp1 += *spec1; // Consideration of Aliasing between the subbands if ( n < +sizeof(Butfly)/sizeof(*Butfly) && k != 0 ) { alias = -1 - (n<<1); tmp0 += Butfly [n] * (spec0[alias] - *spec0); tmp1 += Butfly [n] * (spec1[alias] - *spec1); } else if ( n > 15-sizeof(Butfly)/sizeof(*Butfly) && k != 31 ) { alias = 31 - (n<<1); tmp0 += Butfly [15-n] * (spec0[alias] - *spec0); tmp1 += Butfly [15-n] * (spec1[alias] - *spec1); } } *erg0++ = tmp0; *erg1++ = tmp1; } LEAVE(203); return; } // input : FFT-Spectrums *spec0 and *spec1 // output: energy in the individual partitions *erg0 and *erg1 static void PartitionEnergy ( float* erg0, float* erg1, const float* spec0, const float* spec1 ) { unsigned int n; unsigned int k; float e0; float e1; ENTER(204); #if 000000 for ( n = 0; n < PART_LONG; n++ ) { k = wh[n] - wl[n]; e0 = *spec0++; e1 = *spec1++; while ( k-- ) { e0 += *spec0++; e1 += *spec1++; } *erg0++ = e0; *erg1++ = e1; } #else n = 0; for ( ; n < 23; n++ ) { // 11 or 23 k = wh[n] - wl[n]; e0 = *spec0++; e1 = *spec1++; while ( k-- ) { e0 += *spec0++; e1 += *spec1++; } *erg0++ = e0; *erg1++ = e1; } for ( ; n < 48; n++ ) { // 37 ... 46, 48, 57 k = wh[n] - wl[n]; e0 = sqrt (*spec0++); e1 = sqrt (*spec1++); while ( k-- ) { e0 += sqrt (*spec0++); e1 += sqrt (*spec1++); } *erg0++ = e0*e0 * iw[n]; *erg1++ = e1*e1 * iw[n]; } for ( ; n < PART_LONG; n++ ) { k = wh[n] - wl[n]; e0 = *spec0++; e1 = *spec1++; while ( k-- ) { e0 += *spec0++; e1 += *spec1++; } *erg0++ = e0; *erg1++ = e1; } #endif LEAVE(204); return; } // input : FFT-Spectrums *spec0, *spec1 and unpredictability *cw0 and *cw1 // output: weighted energy in the individual partitions *erg0, *erg1 static void WeightedPartitionEnergy ( float* erg0, float* erg1, const float* spec0, const float* spec1, const float* cw0, const float* cw1 ) { unsigned int n; unsigned int k; float e0; float e1; ENTER(205); #if 000000 for ( n = 0; n < PART_LONG; n++ ) { e0 = *spec0++ * *cw0++; e1 = *spec1++ * *cw1++; k = wh[n] - wl[n]; while ( k-- ) { e0 += *spec0++ * *cw0++; e1 += *spec1++ * *cw1++; } *erg0++ = e0; *erg1++ = e1; } #else n = 0; for ( ; n < 23; n++ ) { e0 = *spec0++ * *cw0++; e1 = *spec1++ * *cw1++; k = wh[n] - wl[n]; while ( k-- ) { e0 += *spec0++ * *cw0++; e1 += *spec1++ * *cw1++; } *erg0++ = e0; *erg1++ = e1; } for ( ; n < 48; n++ ) { e0 = sqrt (*spec0++ * *cw0++); e1 = sqrt (*spec1++ * *cw1++); k = wh[n] - wl[n]; while ( k-- ) { e0 += sqrt (*spec0++ * *cw0++); e1 += sqrt (*spec1++ * *cw1++); } *erg0++ = e0*e0 * iw[n]; *erg1++ = e1*e1 * iw[n]; } for ( ; n < PART_LONG; n++ ) { e0 = *spec0++ * *cw0++; e1 = *spec1++ * *cw1++; k = wh[n] - wl[n]; while ( k-- ) { e0 += *spec0++ * *cw0++; e1 += *spec1++ * *cw1++; } *erg0++ = e0; *erg1++ = e1; } #endif LEAVE(205); return; } // input : masking thresholds, first half of the arrays *shaped0 and *shaped1 // output: masking thresholds, second half of the arrays *shaped0 and *shaped1 // Considering the result of aliasing via InvButfly[] // The input *thr0, *thr1 is gathered via address calculation from *shaped0, *shaped1 static void AdaptThresholds ( const int MaxLine, float* shaped0, float* shaped1 ) { int n; int mod; int alias; float tmp; const float* invb = InvButfly; const float* thr0 = shaped0 - 512; const float* thr1 = shaped1 - 512; float tmp0; float tmp1; ENTER(206); // should be able to optimize it with coasting. [ 9 ] + n * [ 7 + 7 + 2 ] + [ 7 ] // Schleife Schl Schl Ausr Schleife for ( n = 0; n < MaxLine; n++, thr0++, thr1++ ) { mod = n & 15; // n%16 tmp0 = *thr0; tmp1 = *thr1; if ( mod < +sizeof(InvButfly)/sizeof(*InvButfly) && n > 12 ) { alias = -1 - (mod<<1); tmp = thr0[alias] * invb[mod]; if ( tmp < tmp0 ) tmp0 = tmp; tmp = thr1[alias] * invb[mod]; if ( tmp < tmp1 ) tmp1 = tmp; } else if ( mod > 15-sizeof(InvButfly)/sizeof(*InvButfly) && n < 499 ) { alias = 31 - (mod<<1); tmp = thr0[alias] * invb[15-mod]; if ( tmp < tmp0 ) tmp0 = tmp; tmp = thr1[alias] * invb[15-mod]; if ( tmp < tmp1 ) tmp1 = tmp; } *shaped0++ = tmp0; *shaped1++ = tmp1; } LEAVE(206); return; } #include "fastmath.h" // input : current spectrum in the form of power *spec and phase *phase, // the last two earlier spectrums are at position // 512 and 1024 of the corresponding Input-Arrays. // Array *vocal, which can mark an FFT_Linie as harmonic // output: current amplitude *amp and unpredictability *cw static void CalcUnpred ( const int MaxLine, const float* spec, const float* phase, const int* vocal, float* amp0, float* phs0, float* cw ) { int n; float amp; float tmp; #define amp1 ((amp0) + 512) // amp[ 512...1023] contains data of frame-1 #define amp2 ((amp0) + 1024) // amp[1024...1535] contains data of frame-2 #define phs1 ((phs0) + 512) // phs[ 512...1023] contains data of frame-1 #define phs2 ((phs0) + 1024) // phs[1024...1535] contains data of frame-2 ENTER(207); for ( n = 0; n < MaxLine; n++ ) { tmp = COSF ((phs0[n] = phase[n]) - 2*phs1[n] + phs2[n]); // copy phase to output-array, predict phase and calculate predictive error amp0[n] = SQRTF (spec[n]); // calculate and set amplitude amp = 2*amp1[n] - amp2[n]; // predict amplitude // calculate unpredictability cw[n] = SQRTF (spec[n] + amp * (amp - 2*amp0[n] * tmp)) / (amp0[n] + FABS(amp)); } // postprocessing of harmonic FFT-lines (*cw is set to CVD_UNPRED) if ( CVD_used && vocal != NULL ) { for ( n = 0; n < MAX_CVD_LINE; n++, cw++, vocal++ ) if ( *vocal != 0 && *cw > CVD_UNPRED * 0.01 * *vocal ) *cw = CVD_UNPRED * 0.01 * *vocal; } LEAVE(207); return; } #undef amp1 #undef amp2 #undef phs1 #undef phs2 // input : Energy *erg, calibrated energy *werg // output: spread energy *res, spread weighted energy *wres // SPRD describes the spreading function as calculated in psy_tab.c static void SpreadingSignal ( const float* erg, const float* werg, float* res, float* wres ) { int n; int k; int start; int stop; const float* sprd; float e; float ew; ENTER(208); for (k=0; k static float AdaptLtq ( const float* erg0, const float* erg1 ) { static float loud = 0.f; float* weight = Loudness; float sum = 0.f; int n; // calculate loudness for ( n = 0; n < PART_LONG; n++ ) sum += (*erg0++ + *erg1++) * *weight++; // Utilization of the time constants (fast drop of Ltq T=5, slow rise of Ltq T=20) //loud = (sum < loud) ? (4 * sum + loud)*0.2f : (19 * loud + sum)*0.05f; loud = 0.98 * loud + 0.02 * (0.5 * sum); // calculate dynamic offset for threshold in quiet, 0...+20 dB, at 96 dB loudness, an offset of 20 dB is assumed return 1.f + varLtq * loud * 5.023772e-08f; } // input : simultaneous masking threshold *frqthr, // previous masking threshold *tmpthr, // Integrations *a (short-time) and *b (long-time) // output: tracked Integrations *a and *b, time constant *tau static void CalcTemporalThreshold ( float* a, float* b, float* tau, float* frqthr, float* tmpthr ) { int n; float tmp; ENTER(220); for ( n = 0; n < PART_LONG; n++ ) { // following calculations relative to threshold in quiet frqthr[n] *= invLtq[n]; tmpthr[n] *= invLtq[n]; // new post-masking 'tmp' via time constant tau, if old post-masking > Ltq (=1) tmp = tmpthr[n] > 1.f ? POW ( tmpthr[n], tau[n] ) : 1.f; // calculate time constant for post-masking in next frame, // if new time constant has to be calculated (new tmpMask < frqMask) a[n] += 0.5f * (frqthr[n] - a[n]); // short time integrator b[n] += 0.15f * (frqthr[n] - b[n]); // long time integrator if (tmp < frqthr[n]) tau[n] = a[n] <= b[n] ? 0.8f : 0.2f + b[n] / a[n] * 0.6f; // use post-masking of (Re-Normalization) tmpthr[n] = maxf (frqthr[n], tmp) * partLtq[n]; } LEAVE(220); return; } // input : L/R-Masking thresholds in Partitions *thrL, *thrR // L/R-Subband energies *ergL, *ergR // M/S-Subband energies *ergM, *ergS // output: M/S-Masking thresholds in Partitions *thrM, *thrS static void CalcMSThreshold ( const float* const ergL, const float* const ergR, const float* const ergM, const float* const ergS, float* const thrL, float* const thrR, float* const thrM, float* const thrS ) { int n; float norm; float tmp; // All hardcoded numbers here should be pulled from somewhere, // the "4.", the -2 dB, the 0.0625 and the 0.9375, as well as all bands where this is done for ( n = 0; n < PART_LONG; n++ ) { // estimate M/S thresholds out of L/R thresholds and M/S and L/R energies thrS[n] = thrM[n] = maxf (ergM[n], ergS[n]) / maxf (ergL[n], ergR[n]) * minf (thrL[n], thrR[n]); switch ( MS_Channelmode ) { // preserve 'near-mid' signal components case 3: if ( n > 0 ) { double ratioMS = ergM[n] > ergS[n] ? ergS[n] / ergM[n] : ergM[n] / ergS[n]; double ratioLR = ergL[n] > ergR[n] ? ergR[n] / ergL[n] : ergL[n] / ergR[n]; if ( ratioMS < ratioLR ) { // MS if ( ergM[n] > ergS[n] ) thrS[n] = thrL[n] = thrR[n] = 1.e18f; else thrM[n] = thrL[n] = thrR[n] = 1.e18f; } else { // LR if ( ergL[n] > ergR[n] ) thrR[n] = thrM[n] = thrS[n] = 1.e18f; else thrL[n] = thrM[n] = thrS[n] = 1.e18f; } } break; case 4: if ( n > 0 ) { double ratioMS = ergM[n] > ergS[n] ? ergS[n] / ergM[n] : ergM[n] / ergS[n]; double ratioLR = ergL[n] > ergR[n] ? ergR[n] / ergL[n] : ergL[n] / ergR[n]; if ( ratioMS < ratioLR ) { // MS if ( ergM[n] > ergS[n] ) thrS[n] = 1.e18f; else thrM[n] = 1.e18f; } else { // LR if ( ergL[n] > ergR[n] ) thrR[n] = 1.e18f; else thrL[n] = 1.e18f; } } break; case 5: thrS[n] *= 2.; // +3 dB break; case 6: break; default: fprintf ( stderr, "Unknown stereo mode\n"); case 10: if ( 4. * ergL[n] > ergR[n] && ergL[n] < 4. * ergR[n] ) {// Energy between both channels differs by less than 6 dB norm = 0.70794578f * iw[n]; // -1.5 dB * iwidth if ( ergM[n] > ergS[n] ) { tmp = ergS[n] * norm; if ( thrS[n] > tmp ) thrS[n] = MS2SPAT1 * thrS[n] + (1.f-MS2SPAT1) * tmp; // raises masking threshold by up to 3 dB } else if ( ergS[n] > ergM[n] ) { tmp = ergM[n] * norm; if ( thrM[n] > tmp ) thrM[n] = MS2SPAT1 * thrM[n] + (1.f-MS2SPAT1) * tmp; } } break; case 11: if ( 4. * ergL[n] > ergR[n] && ergL[n] < 4. * ergR[n] ) {// Energy between both channels differs by less than 6 dB norm = 0.63095734f * iw[n]; // -2.0 dB * iwidth if ( ergM[n] > ergS[n] ) { tmp = ergS[n] * norm; if ( thrS[n] > tmp ) thrS[n] = MS2SPAT2 * thrS[n] + (1.f-MS2SPAT2) * tmp; // raises masking threshold by up to 6 dB } else if ( ergS[n] > ergM[n] ) { tmp = ergM[n] * norm; if ( thrM[n] > tmp ) thrM[n] = MS2SPAT2 * thrM[n] + (1.f-MS2SPAT2) * tmp; } } break; case 12: if ( 4. * ergL[n] > ergR[n] && ergL[n] < 4. * ergR[n] ) {// Energy between both channels differs by less than 6 dB norm = 0.56234133f * iw[n]; // -2.5 dB * iwidth if ( ergM[n] > ergS[n] ) { tmp = ergS[n] * norm; if ( thrS[n] > tmp ) thrS[n] = MS2SPAT3 * thrS[n] + (1.f-MS2SPAT3) * tmp; // raises masking threshold by up to 9 dB } else if ( ergS[n] > ergM[n] ) { tmp = ergM[n] * norm; if ( thrM[n] > tmp ) thrM[n] = MS2SPAT3 * thrM[n] + (1.f-MS2SPAT3) * tmp; } } break; case 13: if ( 4. * ergL[n] > ergR[n] && ergL[n] < 4. * ergR[n] ) {// Energy between both channels differs by less than 6 dB norm = 0.50118723f * iw[n]; // -3.0 dB * iwidth if ( ergM[n] > ergS[n] ) { tmp = ergS[n] * norm; if ( thrS[n] > tmp ) thrS[n] = MS2SPAT4 * thrS[n] + (1.f-MS2SPAT4) * tmp; // raises masking threshold by up to 12 dB } else if ( ergS[n] > ergM[n] ) { tmp = ergM[n] * norm; if ( thrM[n] > tmp ) thrM[n] = MS2SPAT4 * thrM[n] + (1.f-MS2SPAT4) * tmp; } } break; case 15: if ( 4. * ergL[n] > ergR[n] && ergL[n] < 4. * ergR[n] ) {// Energy between both channels differs by less than 6 dB norm = 0.50118723f * iw[n]; // -3.0 dB * iwidth if ( ergM[n] > ergS[n] ) { tmp = ergS[n] * norm; if ( thrS[n] > tmp ) thrS[n] = tmp; // raises masking threshold by up to +oo dB an } else if ( ergS[n] > ergM[n] ) { tmp = ergM[n] * norm; if ( thrM[n] > tmp ) thrM[n] = tmp; } } break; case 22: if ( 4. * ergL[n] > ergR[n] && ergL[n] < 4. * ergR[n] ) {// Energy between both channels differs by less than 6 dB norm = 0.56234133f * iw[n]; // -2.5 dB * iwidth if ( ergM[n] > ergS[n] ) { tmp = ergS[n] * norm; if ( thrS[n] > tmp ) thrS[n] = maxf (tmp, ergM[n]*iw[n]*0.025); // +/- 1.414° } else if ( ergS[n] > ergM[n] ) { tmp = ergM[n] * norm; if ( thrM[n] > tmp ) thrM[n] = maxf (tmp, ergS[n]*iw[n]*0.025); // +/- 1.414° } } break; } } return; } // input : Masking thresholds in Partitions *partThr0, *partThr1 // level of threshold in quiet *ltq in FFT-resolution // output: Masking thresholds in FFT-resolution *thr0, *thr1 // inline, because it's called 4x static void ApplyLtq ( float* thr0, float* thr1, const float* partThr0, const float* partThr1, const float AdaptedLTQ, int MSflag ) { int n; int k; float ltq; float tmp; float ms = MSflag ? 0.125f * AdaptedLTQ : 0.25f * AdaptedLTQ ; for ( n = 0; n < PART_LONG; n++ ) { for ( k = wl[n]; k <= wh[n]; k++, thr0++, thr1++ ) { // threshold in quiet (Partition) #if 0 ltq = AdaptedLTQ * fftLtq [k]; *thr0 = maxf ( partThr0 [n], ltq ); *thr1 = maxf ( partThr1 [n], ltq ); #else // Applies a much more gentle ATH rolloff + 6 dB more dynamic ltq = sqrt (ms * fftLtq [k]); tmp = sqrt (partThr0 [n]) + ltq; *thr0 = tmp * tmp; tmp = sqrt (partThr1 [n]) + ltq; *thr1 = tmp * tmp; #endif } } return; } // input : Subband energies *erg0, *erg1 // Masking thresholds in FFT-resolution *thr0, *thr1 // output: SMR per Subband *smr0, *smr1 static void CalculateSMR ( const int MaxBand, const float* erg0, const float* erg1, const float* thr0, const float* thr1, float* smr0, float* smr1 ) { int n; int k; float tmp0; float tmp1; // calculation of the masked thresholds in the subbands for (n = 0; n <= MaxBand; n++ ) { tmp0 = *thr0++; tmp1 = *thr1++; for (k=1; k<16; ++k, ++thr0, ++thr1) { if (*thr0 < tmp0) tmp0 = *thr0; if (*thr1 < tmp1) tmp1 = *thr1; } *smr0++ = 0.0625f * *erg0++ / tmp0; *smr1++ = 0.0625f * *erg1++ / tmp1; } return; } // input : energy spectrums erg[4][128] (4 delayed FFTs) // Energy of the last short block *preerg in short partitions // PreechoFac declares allowed traved of the masking threshold // output: masking threshold *thr in short partitions // Energy of the last short block *preerg in short partitions #if 0 static void CalcShortThreshold ( const float erg [] [128], const float PreechoFac, float* thr, float preerg[2][PART_SHORT], int* transient ) { const int* lo = wl_short; // lower FFT-index const int* hi = wh_short; // upper FFT-index const float* iwidth = iw_short; // inverse partition-width int k; int n; int m; float tmp; float enrg; float th; const float* ep; for ( k = 0; k < PART_SHORT; k++, lo++, hi++ ) { transient[k] = 0; th = 1.e20f; for ( n = 0; n < 4; n++ ) { ep = erg[n] + *lo; m = *hi - *lo; enrg = *ep++; while (m--) enrg += *ep++; // preecho prevention tmp = enrg; if (preerg[0][k] < enrg) enrg = preerg[0][k]; preerg[0][k] = tmp; // is signal transient? if (tmp > TransDetect*enrg) transient[k] = 1; // assume short threshold = engr*PreechoFac th = minf (th, enrg*PreechoFac); } thr[k] = th * *iwidth++; } return; } #else static void CalcShortThreshold ( float erg [4] [128], const float ShortThr, float* thr, float old_erg [2][PART_SHORT], int* transient ) { const int* index_lo = wl_short; // lower FFT-index const int* index_hi = wh_short; // upper FFT-index const float* iwidth = iw_short; // inverse partition-width int k; int n; int m; float new_erg; float th; const float* ep; for ( k = 0; k < PART_SHORT; k++ ) { transient [k] = 0; th = old_erg [0][k]; for ( n = 0; n < 4; n++ ) { ep = erg[n] + index_lo [k]; m = index_hi [k] - index_lo [k]; new_erg = *ep++; while (m--) new_erg += *ep++; // e = Short_Partition-energy in piece n if ( new_erg > old_erg [0][k] ) { // bigger than the old? if ( new_erg > old_erg [0][k] * TransDetect || new_erg > old_erg [1][k] * TransDetect*2 ) // is signal transient? transient [k] = 1; } else { th = minf ( th, new_erg ); // assume short threshold = engr*PreechoFac } old_erg [1][k] = old_erg [0][k]; old_erg [0][k] = new_erg; // save the current one } thr [k] = th * ShortThr * *iwidth++; // pull out and multiply only when transient[k]=1 } return; } #endif // input : previous simultaneous masking threshold *preThr, // current simultaneous masking threshold *simThr // output: update of *preThr for next call, // current masking threshold *partThr static void PreechoControl ( float* partThr0, float* preThr0, const float* simThr0, float* partThr1, float* preThr1, const float* simThr1 ) { int n; for ( n = 0; n < PART_LONG; n++ ) { *partThr0++ = minf ( *simThr0, *preThr0 * PREFAC_LONG); *partThr1++ = minf ( *simThr1, *preThr1 * PREFAC_LONG); *preThr0++ = *simThr0++; *preThr1++ = *simThr1++; } return; } void TransientenCalc ( int* T, const int* TL, const int* TR ) { int i; int x1; int x2; memset ( T, 0, 32*sizeof(*T) ); for ( i = 0; i < PART_SHORT; i++ ) if ( TL[i] || TR[i] ) { x1 = wl_short[i] >> 2; x2 = wh_short[i] >> 2; while ( x1 <= x2 ) T [x1++] = 1; } } // input : PCM-Data *data // output: SMRs for the input data SMRTyp Psychoakustisches_Modell ( const int MaxBand, const PCMDataTyp* data, int* TransientL, int* TransientR ) { float Xi_L[32], Xi_R[32]; // acoustic pressure per Subband L/R float Xi_M[32], Xi_S[32]; // acoustic pressure per Subband M/S float cw_L[512], cw_R[512]; // unpredictability (only L/R) float erg0[512], erg1[512]; // holds energy spectrum of long FFT float phs0[512], phs1[512]; // holds phase spectrum of long FFT float Thr_L[2*512], Thr_R[2*512]; // masking thresholds L/R, second half for triangle swap float Thr_M[2*512], Thr_S[2*512]; // masking thresholds M/S, second half for triangle swap float F_256[4][128]; // holds energies of short FFTs (L/R only) float Xerg[1024]; // holds energy spectrum of very long FFT float Ls_L[PART_LONG], Ls_R[PART_LONG]; // acoustic pressure in Partition L/R float Ls_M[PART_LONG], Ls_S[PART_LONG]; // acoustic pressure per each partition M/S float PartThr_L[PART_LONG], PartThr_R[PART_LONG]; // masking thresholds L/R (Partition) float PartThr_M[PART_LONG], PartThr_S[PART_LONG]; // masking thresholds M/S (Partition) float sim_Mask_L[PART_LONG], sim_Mask_R[PART_LONG]; // simultaneous masking (only L/R) float clow_L[PART_LONG], clow_R[PART_LONG]; // spread, weighted energy (only L/R) float cLs_L[PART_LONG], cLs_R[PART_LONG]; // weighted partition energy (only L/R) float shortThr_L[PART_SHORT],shortThr_R[PART_SHORT]; // threshold for short FFT (only L/R) int n; int MaxLine = (MaxBand+1)*16; // set FFT-resolution according to MaxBand SMRTyp SMR0; SMRTyp SMR1; // holds SMR's for first and second Analysis int isvoc_L = 0; int isvoc_R = 0; float factorLTQ = 1.f; // Offset after variable LTQ ENTER(50); // 'ClearVocalDetection'-Process if ( CVD_used ) { memset ( Vocal_L, 0, sizeof Vocal_L ); memset ( Vocal_R, 0, sizeof Vocal_R ); // left channel PowSpec2048 ( &data->L[0], Xerg ); isvoc_L = CVD2048 ( Xerg, Vocal_L ); // right channel PowSpec2048 ( &data->R[0], Xerg ); isvoc_R = CVD2048 ( Xerg, Vocal_R ); } // calculation of the spectral energy via FFT PolarSpec1024 ( &data->L[0], erg0, phs0 ); // left PolarSpec1024 ( &data->R[0], erg1, phs1 ); // right // calculation of the acoustic pressures per each subband for L/R-signals SubbandEnergy ( MaxBand, Xi_L, Xi_R, erg0, erg1 ); // calculation of the acoustic pressures per each partition PartitionEnergy ( Ls_L, Ls_R, erg0, erg1 ); // calculate the predictability of the signal // left memmove ( Xsave_L+512, Xsave_L, 1024*sizeof(float) ); memmove ( Ysave_L+512, Ysave_L, 1024*sizeof(float) ); CalcUnpred ( MaxLine, erg0, phs0, isvoc_L ? Vocal_L : NULL, Xsave_L, Ysave_L, cw_L ); // right memmove ( Xsave_R+512, Xsave_R, 1024*sizeof(float) ); memmove ( Ysave_R+512, Ysave_R, 1024*sizeof(float) ); CalcUnpred ( MaxLine, erg1, phs1, isvoc_R ? Vocal_R : NULL, Xsave_R, Ysave_R, cw_R ); // calculation of the weighted acoustic pressures per each partition WeightedPartitionEnergy ( cLs_L, cLs_R, erg0, erg1, cw_L, cw_R ); // Spreading Signal & weighted unpredictability-signal // left memset ( clow_L , 0, sizeof clow_L ); memset ( sim_Mask_L, 0, sizeof sim_Mask_L ); SpreadingSignal ( Ls_L, cLs_L, sim_Mask_L, clow_L ); // right memset ( clow_R , 0, sizeof clow_R ); memset ( sim_Mask_R, 0, sizeof sim_Mask_R ); SpreadingSignal ( Ls_R, cLs_R, sim_Mask_R, clow_R ); // Offset depending on tonality ApplyTonalityOffset ( sim_Mask_L, sim_Mask_R, clow_L, clow_R ); // handling of transient signals // calculate four short FFTs (left) PowSpec256 ( &data->L[ 0+SHORTFFT_OFFSET], F_256[0] ); PowSpec256 ( &data->L[144+SHORTFFT_OFFSET], F_256[1] ); PowSpec256 ( &data->L[288+SHORTFFT_OFFSET], F_256[2] ); PowSpec256 ( &data->L[432+SHORTFFT_OFFSET], F_256[3] ); // calculate short Threshold CalcShortThreshold ( F_256, ShortThr, shortThr_L, pre_erg_L, TransientL ); // calculate four short FFTs (right) PowSpec256 ( &data->R[ 0+SHORTFFT_OFFSET], F_256[0] ); PowSpec256 ( &data->R[144+SHORTFFT_OFFSET], F_256[1] ); PowSpec256 ( &data->R[288+SHORTFFT_OFFSET], F_256[2] ); PowSpec256 ( &data->R[432+SHORTFFT_OFFSET], F_256[3] ); // calculate short Threshold CalcShortThreshold ( F_256, ShortThr, shortThr_R, pre_erg_R, TransientR ); // dynamic adjustment of the threshold in quiet to the loudness of the current sequence if ( varLtq > 0. ) factorLTQ = AdaptLtq ( Ls_L, Ls_R ); // utilization of the temporal post-masking if ( tmpMask_used ) { CalcTemporalThreshold ( a, b, T_L, sim_Mask_L, tmp_Mask_L ); CalcTemporalThreshold ( c, d, T_R, sim_Mask_R, tmp_Mask_R ); memcpy ( sim_Mask_L, tmp_Mask_L, sizeof sim_Mask_L ); memcpy ( sim_Mask_R, tmp_Mask_R, sizeof sim_Mask_R ); } // transient signal? for ( n = 0; n < PART_SHORT; n++ ) { if ( TransientL [n] ) { sim_Mask_L [3*n ] = minf ( sim_Mask_L [3*n ], shortThr_L [n] ); sim_Mask_L [3*n+1] = minf ( sim_Mask_L [3*n+1], shortThr_L [n] ); sim_Mask_L [3*n+2] = minf ( sim_Mask_L [3*n+2], shortThr_L [n] ); } if ( TransientR[n] ) { sim_Mask_R [3*n ] = minf ( sim_Mask_R [3*n ], shortThr_R [n] ); sim_Mask_R [3*n+1] = minf ( sim_Mask_R [3*n+1], shortThr_R [n] ); sim_Mask_R [3*n+2] = minf ( sim_Mask_R [3*n+2], shortThr_R [n] ); } } // Pre-Echo control PreechoControl ( PartThr_L, PreThr_L, sim_Mask_L, PartThr_R, PreThr_R, sim_Mask_R ); // utilization of the threshold in quiet ApplyLtq ( Thr_L, Thr_R, PartThr_L, PartThr_R, factorLTQ, 0 ); // Consideration of aliasing between the subbands (noise is smeared) // In: Thr[0..511], Out: Thr[512...1023] AdaptThresholds ( MaxLine, Thr_L+512, Thr_R+512 ); memmove ( Thr_L, Thr_L+512, 512*sizeof(float) ); memmove ( Thr_R, Thr_R+512, 512*sizeof(float) ); // calculation of the Signal-to-Mask-Ratio CalculateSMR ( MaxBand, Xi_L, Xi_R, Thr_L, Thr_R, SMR0.L, SMR0.R ); /***************************************************************************************/ /***************************************************************************************/ if ( MS_Channelmode > 0 ) { // calculation of the spectral energy via FFT PowSpec1024 ( &data->M[0], erg0 ); // mid PowSpec1024 ( &data->S[0], erg1 ); // side // calculation of the acoustic pressures per each subband for M/S-signals SubbandEnergy ( MaxBand, Xi_M, Xi_S, erg0, erg1 ); // calculation of the acoustic pressures per each partition PartitionEnergy ( Ls_M, Ls_S, erg0, erg1 ); // calculate masking thresholds for M/S CalcMSThreshold ( Ls_L, Ls_R, Ls_M, Ls_S, PartThr_L, PartThr_R, PartThr_M, PartThr_S ); ApplyLtq ( Thr_M, Thr_S, PartThr_M, PartThr_S, factorLTQ, 1 ); // Consideration of aliasing between the subbands (noise is smeared) // In: Thr[0..511], Out: Thr[512...1023] AdaptThresholds ( MaxLine, Thr_M+512, Thr_S+512 ); memmove ( Thr_M, Thr_M+512, 512*sizeof(float) ); memmove ( Thr_S, Thr_S+512, 512*sizeof(float) ); // calculation of the Signal-to-Mask-Ratio CalculateSMR ( MaxBand, Xi_M, Xi_S, Thr_M, Thr_S, SMR0.M, SMR0.S ); } if ( NS_Order > 0 ) { // providing the Noise Shaping thresholds memcpy ( ANSspec_L, Thr_L, sizeof ANSspec_L ); memcpy ( ANSspec_R, Thr_R, sizeof ANSspec_R ); memcpy ( ANSspec_M, Thr_M, sizeof ANSspec_M ); memcpy ( ANSspec_S, Thr_S, sizeof ANSspec_S ); } /***************************************************************************************/ /***************************************************************************************/ // //-------- second model calculation via shifted FFT ------------------------ // // calculation of the spectral power via FFT PolarSpec1024 ( &data->L[576], erg0, phs0 ); // left PolarSpec1024 ( &data->R[576], erg1, phs1 ); // right // calculation of the acoustic pressures per each subband for L/R-signals SubbandEnergy ( MaxBand, Xi_L, Xi_R, erg0, erg1 ); // calculation of the acoustic pressures per each partition PartitionEnergy ( Ls_L, Ls_R, erg0, erg1 ); // calculate the predictability of the signal // left memmove ( Xsave_L+512, Xsave_L, 1024*sizeof(float) ); memmove ( Ysave_L+512, Ysave_L, 1024*sizeof(float) ); CalcUnpred ( MaxLine, erg0, phs0, isvoc_L ? Vocal_L : NULL, Xsave_L, Ysave_L, cw_L ); // right memmove ( Xsave_R+512, Xsave_R, 1024*sizeof(float) ); memmove ( Ysave_R+512, Ysave_R, 1024*sizeof(float) ); CalcUnpred ( MaxLine, erg1, phs1, isvoc_R ? Vocal_R : NULL, Xsave_R, Ysave_R, cw_R ); // calculation of the weighted acoustic pressure per each partition WeightedPartitionEnergy ( cLs_L, cLs_R, erg0, erg1, cw_L, cw_R ); // Spreading Signal & weighted unpredictability-signal // left memset ( clow_L , 0, sizeof clow_L ); memset ( sim_Mask_L, 0, sizeof sim_Mask_L ); SpreadingSignal ( Ls_L, cLs_L, sim_Mask_L, clow_L ); // right memset ( clow_R , 0, sizeof clow_R ); memset ( sim_Mask_R, 0, sizeof sim_Mask_R ); SpreadingSignal ( Ls_R, cLs_R, sim_Mask_R, clow_R ); // Offset depending on tonality ApplyTonalityOffset ( sim_Mask_L, sim_Mask_R, clow_L, clow_R ); // Handling of transient signals // calculate four short FFTs (left) PowSpec256 ( &data->L[ 576+SHORTFFT_OFFSET], F_256[0] ); PowSpec256 ( &data->L[ 720+SHORTFFT_OFFSET], F_256[1] ); PowSpec256 ( &data->L[ 864+SHORTFFT_OFFSET], F_256[2] ); PowSpec256 ( &data->L[1008+SHORTFFT_OFFSET], F_256[3] ); // calculate short Threshold CalcShortThreshold ( F_256, ShortThr, shortThr_L, pre_erg_L, TransientL ); // calculate four short FFTs (right) PowSpec256 ( &data->R[ 576+SHORTFFT_OFFSET], F_256[0] ); PowSpec256 ( &data->R[ 720+SHORTFFT_OFFSET], F_256[1] ); PowSpec256 ( &data->R[ 864+SHORTFFT_OFFSET], F_256[2] ); PowSpec256 ( &data->R[1008+SHORTFFT_OFFSET], F_256[3] ); // calculate short Threshold CalcShortThreshold ( F_256, ShortThr, shortThr_R, pre_erg_R, TransientR ); // dynamic adjustment of threshold in quiet to loudness of the current sequence if ( varLtq > 0. ) factorLTQ = AdaptLtq ( Ls_L, Ls_R ); // utilization of temporal post-masking if (tmpMask_used) { CalcTemporalThreshold ( a, b, T_L, sim_Mask_L, tmp_Mask_L ); CalcTemporalThreshold ( c, d, T_R, sim_Mask_R, tmp_Mask_R ); memcpy ( sim_Mask_L, tmp_Mask_L, sizeof sim_Mask_L ); memcpy ( sim_Mask_R, tmp_Mask_R, sizeof sim_Mask_R ); } // transient signal? for ( n = 0; n < PART_SHORT; n++ ) { if ( TransientL[n] ) { sim_Mask_L [3*n ] = minf ( sim_Mask_L [3*n ], shortThr_L [n] ); sim_Mask_L [3*n+1] = minf ( sim_Mask_L [3*n+1], shortThr_L [n] ); sim_Mask_L [3*n+2] = minf ( sim_Mask_L [3*n+2], shortThr_L [n] ); } if ( TransientR[n] ) { sim_Mask_R [3*n ] = minf ( sim_Mask_R [3*n ], shortThr_R [n] ); sim_Mask_R [3*n+1] = minf ( sim_Mask_R [3*n+1], shortThr_R [n] ); sim_Mask_R [3*n+2] = minf ( sim_Mask_R [3*n+2], shortThr_R [n] ); } } // Pre-Echo control PreechoControl ( PartThr_L, PreThr_L, sim_Mask_L, PartThr_R, PreThr_R, sim_Mask_R ); // utilization of threshold in quiet ApplyLtq ( Thr_L, Thr_R, PartThr_L, PartThr_R, factorLTQ, 0 ); // Consideration of aliasing between the subbands (noise is smeared) // In: Thr[0..511], Out: Thr[512...1023] AdaptThresholds ( MaxLine, Thr_L+512, Thr_R+512 ); memmove ( Thr_L, Thr_L+512, 512*sizeof(float) ); memmove ( Thr_R, Thr_R+512, 512*sizeof(float) ); // calculation of the Signal-to-Mask-Ratio CalculateSMR ( MaxBand, Xi_L, Xi_R, Thr_L, Thr_R, SMR1.L, SMR1.R ); /***************************************************************************************/ /***************************************************************************************/ if ( MS_Channelmode > 0 ) { // calculation of the spectral energy via FFT PowSpec1024 ( &data->M[576], erg0 ); // mid PowSpec1024 ( &data->S[576], erg1 ); // side // calculation of the acoustic pressure per each subband for M/S-signals SubbandEnergy ( MaxBand, Xi_M, Xi_S, erg0, erg1 ); // calculation of the acoustic pressure per each partition PartitionEnergy ( Ls_M, Ls_S, erg0, erg1 ); // calculate masking thresholds for M/S CalcMSThreshold ( Ls_L, Ls_R, Ls_M, Ls_S, PartThr_L, PartThr_R, PartThr_M, PartThr_S ); ApplyLtq ( Thr_M, Thr_S, PartThr_M, PartThr_S, factorLTQ, 1 ); // Consideration of aliasing between the subbands (noise is smeared) // In: Thr[0..511], Out: Thr[512...1023] AdaptThresholds ( MaxLine, Thr_M+512, Thr_S+512 ); memmove ( Thr_M, Thr_M+512, 512*sizeof(float) ); memmove ( Thr_S, Thr_S+512, 512*sizeof(float) ); // calculation of the Signal-to-Mask-Ratio CalculateSMR ( MaxBand, Xi_M, Xi_S, Thr_M, Thr_S, SMR1.M, SMR1.S ); } /***************************************************************************************/ /***************************************************************************************/ if ( NS_Order > 0 ) { for ( n = 0; n < MAX_ANS_LINES; n++ ) { // providing Noise Shaping thresholds ANSspec_L [n] = minf ( ANSspec_L [n], Thr_L [n] ); ANSspec_R [n] = minf ( ANSspec_R [n], Thr_R [n] ); ANSspec_M [n] = minf ( ANSspec_M [n], Thr_M [n] ); ANSspec_S [n] = minf ( ANSspec_S [n], Thr_S [n] ); } } for ( n = 0; n <= MaxBand; n++ ) { // choose 'worst case'-SMR from shifted analysis windows SMR0.L[n] = maxf ( SMR0.L[n], SMR1.L[n] ); SMR0.R[n] = maxf ( SMR0.R[n], SMR1.R[n] ); SMR0.M[n] = maxf ( SMR0.M[n], SMR1.M[n] ); SMR0.S[n] = maxf ( SMR0.S[n], SMR1.S[n] ); } LEAVE(50); return SMR0; } mppenc-1.16/src/fft_routines.c0000644000175000017500000002074410522734510015651 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" #define CX0 -1. #define CX1 0.5 #define SX1 -1. #define SX2 (2./9/ 1) #define SX3 (2./9/ 4) #define SX4 (2./9/ 10) #define SX5 (2./9/ 20) #define SX6 (2./9/ 35) #define SX7 (2./9/ 56) #define SX8 (2./9/ 84) #define SX9 (2./9/120) #define SX10 (2./9/165) #ifdef EXTRA_DECONV # define DECONV \ { \ tmp = (CX0*aix[0] + CX1*aix[2]) * (1./(CX0*CX0+CX1*CX1)); \ aix[ 0] -= CX0*tmp; \ aix[ 2] -= CX1*tmp; \ tmp = (SX1*aix[3] + SX2*aix[5] + SX3*aix[7] + SX4*aix[9] + SX5*aix[11]) * (1./(SX1*SX1+SX2*SX2+SX3*SX3+SX4*SX4+SX5*SX5)); \ aix[ 3] -= SX1*tmp; \ aix[ 5] -= SX2*tmp; \ aix[ 7] -= SX3*tmp; \ aix[ 9] -= SX4*tmp; \ aix[11] -= SX5*tmp; \ } #elif 0 # define DECONV \ { \ float A[20]; \ int i; \ memcpy (A, aix, 20*sizeof(aix)); \ tmp = (CX0*aix[0] + CX1*aix[2]) * (1./(CX0*CX0+CX1*CX1)); \ aix[ 0] -= CX0*tmp; \ aix[ 2] -= CX1*tmp; \ tmp = (SX1*aix[3] + SX2*aix[5] + SX3*aix[7] + SX4*aix[9] + SX5*aix[11]) * (1./(SX1*SX1+SX2*SX2+SX3*SX3+SX4*SX4+SX5*SX5)); \ aix[ 3] -= SX1*tmp; \ aix[ 5] -= SX2*tmp; \ aix[ 7] -= SX3*tmp; \ aix[ 9] -= SX4*tmp; \ aix[11] -= SX5*tmp; \ for ( i=0; i<10; i++) \ printf ("%u%9.0f%7.0f%9.0f%7.0f\n",i, A[i+i], A[i+i+1], aix[i+i], aix[i+i+1] ); \ } #else # define DECONV #endif /* V A R I A B L E S */ static int ip [4096]; // bitinverse for maximum 2048 FFT static float w [4096]; // butterfly-coefficient for maximum 2048 FFT static float a [4096]; // holds real input for FFT static float Hann_256 [ 256]; static float Hann_1024 [1024]; static float Hann_1600 [1600]; ////////////////////////////// // // BesselI0 -- Regular Modified Cylindrical Bessel Function (Bessel I). // static double Bessel_I_0 ( double x ) { double denominator; double numerator; double z; if (x == 0.) return 1.; z = x * x; numerator = z* (z* (z* (z* (z* (z* (z* (z* (z* (z* (z* (z* (z* (z* 0.210580722890567e-22 + 0.380715242345326e-19 ) + 0.479440257548300e-16) + 0.435125971262668e-13 ) + 0.300931127112960e-10) + 0.160224679395361e-07 ) + 0.654858370096785e-05) + 0.202591084143397e-02 ) + 0.463076284721000e+00) + 0.754337328948189e+02 ) + 0.830792541809429e+04) + 0.571661130563785e+06 ) + 0.216415572361227e+08) + 0.356644482244025e+09 ) + 0.144048298227235e+10; denominator = z* (z* (z - 0.307646912682801e+04) + 0.347626332405882e+07) - 0.144048298227235e+10; return - numerator / denominator; } static double residual ( double x ) { return sqrt ( 1. - x*x ); } ////////////////////////////// // // KBDWindow -- Kaiser Bessel Derived Window // fills the input window array with size samples of the // KBD window with the given tuning parameter alpha. // static void KBDWindow ( float* window, unsigned int size, float alpha ) { double sumvalue = 0.; double scale; int i; scale = 0.25 / sqrt (size); for ( i = 0; i < (int)size/2; i++ ) window [i] = sumvalue += Bessel_I_0 ( M_PI * alpha * residual (4.*i/size - 1.) ); // need to add one more value to the nomalization factor at size/2: sumvalue += Bessel_I_0 ( M_PI * alpha * residual (4.*(size/2)/size-1.) ); // normalize the window and fill in the righthand side of the window: for ( i = 0; i < (int)size/2; i++ ) window [size-1-i] = window [i] = /*sqrt*/ ( window [i] / sumvalue ) * scale; } static void CosWindow ( float* window, unsigned int size ) { double x; double scale; int i; scale = 0.25 / sqrt (size); for ( i = 0; i < (int)size/2; i++ ) { x = cos ( (i+0.5) * (M_PI / size) ); window [size/2-1-i] = window [size/2+i] = scale * x * x; } } static void Window ( float* window, unsigned int size, float alpha ) { if ( alpha < 0. ) CosWindow ( window, size ) ; else KBDWindow ( window, size, alpha ); } /* F U N C T I O N S */ // generates FFT lookup-tables void Init_FFT ( void ) { int n; double x; double scale; // normalized hann functions Window ( Hann_256 , 256, KBD1 ); Window ( Hann_1024, 1024, KBD2 ); scale = 0.25 / sqrt (2048.); for ( n = 0; n < 800; n++ ) x = cos ((n+0.5) * (M_PI/1600)), Hann_1600 [799-n] = Hann_1600 [800+n] = (float)(x * x * scale); Generate_FFT_Tables ( 2048, ip, w ); } // input : Signal *x // output: energy spectrum *erg void PowSpec256 ( const float* x, float* erg ) { const float* win = Hann_256; float* aix = a; int i; ENTER(40); // windowing i = 256; while (i--) *aix++ = *x++ * *win++; // perform FFT rdft ( 256, a, ip, w ); // calculate power aix = a; // reset pointer i = 128; while (i--) { *erg++ = aix[0]*aix[0] + aix[1]*aix[1]; aix += 2; } LEAVE(40); } // input : Signal *x // output: energy spectrum *erg void PowSpec1024 ( const float* x, float* erg ) { const float* win = Hann_1024; float* aix = a; int i; ENTER(41); i = 1024; // windowing while (i--) *aix++ = *x++ * *win++; // for (i=0; i<1024; i++) // a[i] = Hann_1024[i] * ((i==0 ? 0 : i-512) + 1000); rdft ( 1024, a, ip, w ); // perform FFT aix = a; // calculate power i = 512; DECONV; // for (i = 0; i <= 512; i++ ) // printf ("%3u %12.6f %12.6f\n", i, a[i+i], a[i+i+1]); // exit(1); while (i--) { *erg++ = aix[0]*aix[0] + aix[1]*aix[1]; aix += 2; } LEAVE(41); } // input : Signal *x // output: energy spectrum *erg void PowSpec2048 ( const float* x, float* erg ) { const float* win = Hann_1600; float* aix = a; int i; ENTER(42); // windowing (only 1600 samples available -> centered in 2048!) memset ( a , 0, 224*sizeof(*a) ); aix = a + 224; i = 1600; while (i--) *aix++ = *x++ * *win++; memset ( a+1824, 0, 224*sizeof(*a) ); rdft ( 2048, a, ip, w ); // perform FFT aix = a; // calculate power i = 1024; while (i--) { *erg++ = aix[0]*aix[0] + aix[1]*aix[1]; aix += 2; } LEAVE(42); } #include "fastmath.h" // input : Signal *x // output: energy spectrum *erg and phase spectrum *phs void PolarSpec1024 ( const float* x, float* erg, float* phs ) { const float* win = Hann_1024; float* aix = a; int i; ENTER(43); i = 1024; // windowing while (i--) *aix++ = *x++ * *win++; rdft ( 1024, a, ip, w ); // perform FFT // calculate power and phase aix = a; // reset pointer i = 512; while (i--) { *erg++ = aix[0]*aix[0] + aix[1]*aix[1]; *phs++ = ATAN2F (aix[1], aix[0]); aix += 2; } LEAVE(43); } // input : logarithmized energy spectrum *cep // output: Cepstrum *cep (in-place) void Cepstrum2048 ( float* cep, const int MaxLine ) { float* aix = cep; float* bix = cep + 2048; int i; ENTER(44); // generate real, even spectrum (symmetric around 1024, cep[2048-i] = cep[i]) for ( i = 0; i < 1024; i++ ) *bix-- = *aix++; // perform IFFT rdft ( 2048, cep, ip, w ); // only real part as outcome (all even indexes of cep[]) aix = cep; bix = cep; i = MaxLine + 1; while (i--) { *aix = *bix * (float) (0.9888 / 2048.); // *aix = *bix * 0.0004828125f; aix ++; bix += 2; } LEAVE(44); } mppenc-1.16/src/winmsg.c0000644000175000017500000000437210522734510014445 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" #ifdef _WIN32 #include static HWND FrontEndHandle; int SearchForFrontend ( void ) { FrontEndHandle = FindWindow ( NULL, "mpcdispatcher" ); // check for dispatcher window and (send startup-message???) return FrontEndHandle != 0; } static void SendMsg ( const char* s ) { COPYDATASTRUCT MsgData; MsgData.dwData = 3; // build message MsgData.lpData = (char*)s; MsgData.cbData = strlen(s) + 1; SendMessage ( FrontEndHandle, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &MsgData ); // send message } void SendStartupMessage ( const char* Version, const int SV, const char* Build ) { char startup [120]; sprintf ( startup, "#START#MP+ v%s SV%i %s#", Version, SV, Build ); // fill startup-message SendMsg ( startup ); } void SendQuitMessage ( void ) { SendMsg ("#EOF#"); } void SendModeMessage ( const int Profile ) { char message [32]; sprintf ( message, "#PARAM#%d#", Profile-8 ); // fill message SendMsg ( message ); } void /* sends progress information to the frontend */ SendProgressMessage ( const int bitrate, const float speed, const float percent ) { char message [64]; sprintf ( message, "#STAT#%4ik %5.2fx %5.1f%%#", bitrate, speed, percent ); SendMsg ( message ); } #endif /* _WIN32 */ mppenc-1.16/src/huffsv7.c0000644000175000017500000005040310522734510014525 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppdec.h" Huffman_t HuffHdr [10]; // 9 bit Huffman_t HuffSCFI [ 4]; // 3 bit Huffman_t HuffDSCF [16]; // 6 bit Huffman_t HuffQ1 [2] [ 3*3*3]; // 6+ 9 bit Huffman_t HuffQ2 [2] [ 5*5]; // 7+10 bit Huffman_t HuffQ3 [2] [ 7]; // 4+ 5 bit Huffman_t HuffQ4 [2] [ 9]; // 4+ 5 bit Huffman_t HuffQ5 [2] [15]; // 6+ 8 bit Huffman_t HuffQ6 [2] [31]; // 7+13 bit Huffman_t HuffQ7 [2] [63]; // 8+14 bit // 4608 Bytes Uint8_t LUT1_0 [1<< 6]; Uint8_t LUT1_1 [1<< 9]; // 576 Bytes Uint8_t LUT2_0 [1<< 7]; Uint8_t LUT2_1 [1<<10]; // 1152 Bytes Uint8_t LUT3_0 [1<< 4]; Uint8_t LUT3_1 [1<< 5]; // 48 Bytes Uint8_t LUT4_0 [1<< 4]; Uint8_t LUT4_1 [1<< 5]; // 48 Bytes Uint8_t LUT5_0 [1<< 6]; Uint8_t LUT5_1 [1<< 8]; // 320 Bytes Uint8_t LUT6_0 [1<< 7]; Uint8_t LUT6_1 [1<< 7]; // 256 Bytes Uint8_t LUT7_0 [1<< 8]; Uint8_t LUT7_1 [1<< 8]; // 512 Bytes Uint8_t LUTDSCF [1<< 6]; // 64 Bytes = 2976 Bytes const Huffman_t* HuffQ [2] [8] = { { NULL, HuffQ1[0], HuffQ2[0], HuffQ3[0], HuffQ4[0], HuffQ5[0], HuffQ6[0], HuffQ7[0] }, { NULL, HuffQ1[1], HuffQ2[1], HuffQ3[1], HuffQ4[1], HuffQ5[1], HuffQ6[1], HuffQ7[1] } }; #ifdef USE_SV8 Huffman_t HuffN3 [2] [ 7*7]; // 8+ 9 bit Huffman_t HuffN8 [2][127]; //13+12 bit const Huffman_t* HuffN [2] [9] = { { NULL, HuffQ1[0], HuffQ2[0], HuffN3[0], HuffQ4[0], HuffQ5[0], HuffQ6[0], HuffQ7[0], HuffN8[0] }, { NULL, HuffQ1[1], HuffQ2[1], HuffN3[1], HuffQ4[1], HuffQ5[1], HuffQ6[1], HuffQ7[1], HuffN8[1] } }; #endif static const HuffSrc_t HuffSCFI_src [4] = { { 2, 3 }, { 1, 1 }, { 3, 3 }, { 0, 2 } }; static const HuffSrc_t HuffDSCF_src [16] = { { 32, 6 }, { 4, 5 }, { 17, 5 }, { 30, 5 }, { 13, 4 }, { 0, 3 }, { 3, 3 }, { 9, 4 }, { 5, 3 }, { 2, 3 }, { 14, 4 }, { 3, 4 }, { 31, 5 }, { 5, 5 }, { 33, 6 }, { 12, 4 } }; static const HuffSrc_t HuffHdr_src [10] = { { 92, 8 }, { 47, 7 }, { 10, 5 }, { 4, 4 }, { 0, 2 }, { 1, 1 }, { 3, 3 }, { 22, 6 }, { 187, 9 }, { 186, 9 } }; static const HuffSrc_t HuffQ1_src [2] [3*3*3] = { { { 54, 6 }, { 9, 5 }, { 32, 6 }, { 5, 5 }, { 10, 4 }, { 7, 5 }, { 52, 6 }, { 0, 5 }, { 35, 6 }, { 10, 5 }, { 6, 4 }, { 4, 5 }, { 11, 4 }, { 7, 3 }, { 12, 4 }, { 3, 5 }, { 7, 4 }, { 11, 5 }, { 34, 6 }, { 1, 5 }, { 53, 6 }, { 6, 5 }, { 9, 4 }, { 2, 5 }, { 33, 6 }, { 8, 5 }, { 55, 6 } }, { { 103, 8 }, { 62, 7 }, { 225, 9 }, { 55, 7 }, { 3, 4 }, { 52, 7 }, { 101, 8 }, { 60, 7 }, { 227, 9 }, { 24, 6 }, { 0, 4 }, { 61, 7 }, { 4, 4 }, { 1, 1 }, { 5, 4 }, { 63, 7 }, { 1, 4 }, { 59, 7 }, { 226, 9 }, { 57, 7 }, { 100, 8 }, { 53, 7 }, { 2, 4 }, { 54, 7 }, { 224, 9 }, { 58, 7 }, { 102, 8 } } }; static const HuffSrc_t HuffQ2_src [2] [5*5] = { { { 89, 7 }, { 47, 6 }, { 15, 5 }, { 0, 5 }, { 91, 7 }, { 4, 5 }, { 6, 4 }, { 13, 4 }, { 4, 4 }, { 5, 5 }, { 20, 5 }, { 12, 4 }, { 4, 3 }, { 15, 4 }, { 14, 5 }, { 3, 5 }, { 3, 4 }, { 14, 4 }, { 5, 4 }, { 1, 5 }, { 90, 7 }, { 2, 5 }, { 21, 5 }, { 46, 6 }, { 88, 7 } }, { { 921, 10 }, { 113, 7 }, { 51, 6 }, { 231, 8 }, { 922, 10 }, { 104, 7 }, { 30, 5 }, { 0, 3 }, { 29, 5 }, { 105, 7 }, { 50, 6 }, { 1, 3 }, { 2, 2 }, { 3, 3 }, { 49, 6 }, { 107, 7 }, { 27, 5 }, { 2, 3 }, { 31, 5 }, { 112, 7 }, { 920, 10 }, { 106, 7 }, { 48, 6 }, { 114, 7 }, { 923, 10 } } }; #ifdef USE_SV8 static const HuffSrc_t HuffN3_src [2] [7*7] = { { { 78, 7 }, { 20, 6 }, { 36, 6 }, { 51, 6 }, { 21, 6 }, { 101, 7 }, { 255, 8 }, { 37, 6 }, { 0, 5 }, { 62, 6 }, { 7, 5 }, { 60, 6 }, { 49, 6 }, { 100, 7 }, { 30, 6 }, { 53, 6 }, { 8, 5 }, { 14, 5 }, { 5, 5 }, { 54, 6 }, { 26, 6 }, { 43, 6 }, { 1, 5 }, { 20, 5 }, { 14, 4 }, { 22, 5 }, { 9, 5 }, { 46, 6 }, { 47, 6 }, { 61, 6 }, { 17, 5 }, { 16, 5 }, { 11, 5 }, { 4, 5 }, { 38, 6 }, { 6, 6 }, { 52, 6 }, { 6, 5 }, { 12, 5 }, { 2, 5 }, { 55, 6 }, { 27, 6 }, { 254, 8 }, { 126, 7 }, { 31, 6 }, { 48, 6 }, { 42, 6 }, { 7, 6 }, { 79, 7 } }, { { 65, 9 }, { 161, 8 }, { 109, 7 }, { 11, 6 }, { 116, 7 }, { 160, 8 }, { 71, 9 }, { 34, 8 }, { 97, 7 }, { 56, 6 }, { 8, 5 }, { 55, 6 }, { 85, 7 }, { 166, 8 }, { 84, 7 }, { 52, 6 }, { 3, 4 }, { 11, 4 }, { 5, 4 }, { 59, 6 }, { 86, 7 }, { 10, 6 }, { 13, 5 }, { 9, 4 }, { 0, 3 }, { 8, 4 }, { 12, 5 }, { 9, 6 }, { 98, 7 }, { 51, 6 }, { 31, 5 }, { 7, 4 }, { 30, 5 }, { 53, 6 }, { 99, 7 }, { 162, 8 }, { 108, 7 }, { 50, 6 }, { 9, 5 }, { 57, 6 }, { 82, 7 }, { 163, 8 }, { 64, 9 }, { 167, 8 }, { 87, 7 }, { 117, 7 }, { 96, 7 }, { 33, 8 }, { 70, 9 } } }; #endif static const HuffSrc_t HuffQ3_src [2] [ 7] = { { { 12, 4 }, { 4, 3 }, { 0, 2 }, { 1, 2 }, { 7, 3 }, { 5, 3 }, { 13, 4 } }, { { 4, 5 }, { 3, 4 }, { 2, 2 }, { 3, 2 }, { 1, 2 }, { 0, 3 }, { 5, 5 } } }; static const HuffSrc_t HuffQ4_src [2] [ 9] = { { { 5, 4 }, { 0, 3 }, { 4, 3 }, { 6, 3 }, { 7, 3 }, { 5, 3 }, { 3, 3 }, { 1, 3 }, { 4, 4 } }, { { 9, 5 }, { 12, 4 }, { 3, 3 }, { 0, 2 }, { 2, 2 }, { 7, 3 }, { 13, 4 }, { 5, 4 }, { 8, 5 } } }; static const HuffSrc_t HuffQ5_src [2] [15] = { { { 57, 6 }, { 23, 5 }, { 8, 4 }, { 10, 4 }, { 13, 4 }, { 0, 3 }, { 2, 3 }, { 3, 3 }, { 1, 3 }, { 15, 4 }, { 12, 4 }, { 9, 4 }, { 29, 5 }, { 22, 5 }, { 56, 6 } }, { { 229, 8 }, { 56, 6 }, { 7, 5 }, { 2, 4 }, { 0, 3 }, { 3, 3 }, { 5, 3 }, { 6, 3 }, { 4, 3 }, { 2, 3 }, { 15, 4 }, { 29, 5 }, { 6, 5 }, { 115, 7 }, { 228, 8 }, } }; static const HuffSrc_t HuffQ6_src [2] [31] = { { { 65, 7 }, { 6, 6 }, { 44, 6 }, { 45, 6 }, { 59, 6 }, { 13, 5 }, { 17, 5 }, { 19, 5 }, { 23, 5 }, { 21, 5 }, { 26, 5 }, { 30, 5 }, { 0, 4 }, { 2, 4 }, { 5, 4 }, { 7, 4 }, { 3, 4 }, { 4, 4 }, { 31, 5 }, { 28, 5 }, { 25, 5 }, { 27, 5 }, { 24, 5 }, { 20, 5 }, { 18, 5 }, { 12, 5 }, { 2, 5 }, { 58, 6 }, { 33, 6 }, { 7, 6 }, { 64, 7 }, }, { { 6472, 13 }, { 6474, 13 }, { 808, 10 }, { 405, 9 }, { 203, 8 }, { 102, 7 }, { 49, 6 }, { 9, 5 }, { 15, 5 }, { 31, 5 }, { 2, 4 }, { 6, 4 }, { 8, 4 }, { 11, 4 }, { 13, 4 }, { 0, 3 }, { 14, 4 }, { 10, 4 }, { 9, 4 }, { 5, 4 }, { 3, 4 }, { 30, 5 }, { 14, 5 }, { 8, 5 }, { 48, 6 }, { 103, 7 }, { 201, 8 }, { 200, 8 }, { 1619, 11 }, { 6473, 13 }, { 6475, 13 }, } }; static const HuffSrc_t HuffQ7_src [2] [63] = { { { 103, 8 }, // 0.3338 01100111 { 153, 8 }, // 0.3766 10011001 { 181, 8 }, // 0.4715 10110101 { 233, 8 }, // 0.5528 11101001 { 64, 7 }, // 0.6677 1000000 { 65, 7 }, // 0.7041 1000001 { 77, 7 }, // 0.7733 1001101 { 81, 7 }, // 0.8296 1010001 { 91, 7 }, // 0.9295 1011011 { 113, 7 }, // 1.0814 1110001 { 112, 7 }, // 1.0807 1110000 { 24, 6 }, // 1.2748 011000 { 29, 6 }, // 1.3390 011101 { 35, 6 }, // 1.4224 100011 { 37, 6 }, // 1.5201 100101 { 41, 6 }, // 1.6642 101001 { 44, 6 }, // 1.7292 101100 { 46, 6 }, // 1.8647 101110 { 51, 6 }, // 2.0473 110011 { 49, 6 }, // 2.0152 110001 { 54, 6 }, // 2.1315 110110 { 55, 6 }, // 2.1358 110111 { 57, 6 }, // 2.1700 111001 { 60, 6 }, // 2.2449 111100 { 0, 5 }, // 2.3063 00000 { 2, 5 }, // 2.3854 00010 { 10, 5 }, // 2.5481 01010 { 5, 5 }, // 2.4867 00101 { 9, 5 }, // 2.5352 01001 { 6, 5 }, // 2.5074 00110 { 13, 5 }, // 2.5745 01101 { 7, 5 }, // 2.5195 00111 { 11, 5 }, // 2.5502 01011 { 15, 5 }, // 2.6251 01111 { 8, 5 }, // 2.5260 01000 { 4, 5 }, // 2.4418 00100 { 3, 5 }, // 2.3983 00011 { 1, 5 }, // 2.3697 00001 { 63, 6 }, // 2.3041 111111 { 62, 6 }, // 2.2656 111110 { 61, 6 }, // 2.2549 111101 { 53, 6 }, // 2.1151 110101 { 59, 6 }, // 2.2042 111011 { 52, 6 }, // 2.0837 110100 { 48, 6 }, // 1.9446 110000 { 47, 6 }, // 1.9189 101111 { 43, 6 }, // 1.7177 101011 { 42, 6 }, // 1.7035 101010 { 39, 6 }, // 1.5287 100111 { 36, 6 }, // 1.4559 100100 { 33, 6 }, // 1.4117 100001 { 28, 6 }, // 1.2776 011100 { 117, 7 }, // 1.1107 1110101 { 101, 7 }, // 1.0636 1100101 { 100, 7 }, // 0.9751 1100100 { 80, 7 }, // 0.8132 1010000 { 69, 7 }, // 0.7091 1000101 { 68, 7 }, // 0.7084 1000100 { 50, 7 }, // 0.6277 0110010 { 232, 8 }, // 0.5386 11101000 { 180, 8 }, // 0.4408 10110100 { 152, 8 }, // 0.3759 10011000 { 102, 8 }, // 0.3160 01100110 }, { { 14244, 14 }, // 0.0059 11011110100100 { 14253, 14 }, // 0.0098 11011110101101 { 14246, 14 }, // 0.0078 11011110100110 { 14254, 14 }, // 0.0111 11011110101110 { 3562, 12 }, // 0.0320 110111101010 { 752, 10 }, // 0.0920 1011110000 { 753, 10 }, // 0.1057 1011110001 { 160, 9 }, // 0.1403 010100000 { 162, 9 }, // 0.1579 010100010 { 444, 9 }, // 0.2486 110111100 { 122, 8 }, // 0.3772 01111010 { 223, 8 }, // 0.5710 11011111 { 60, 7 }, // 0.6858 0111100 { 73, 7 }, // 0.8033 1001001 { 110, 7 }, // 0.9827 1101110 { 14, 6 }, // 1.2601 001110 { 24, 6 }, // 1.3194 011000 { 25, 6 }, // 1.3938 011001 { 34, 6 }, // 1.5693 100010 { 37, 6 }, // 1.7846 100101 { 54, 6 }, // 2.0078 110110 { 3, 5 }, // 2.2975 00011 { 9, 5 }, // 2.5631 01001 { 11, 5 }, // 2.7021 01011 { 16, 5 }, // 3.1465 10000 { 19, 5 }, // 3.4244 10011 { 21, 5 }, // 3.5921 10101 { 24, 5 }, // 3.7938 11000 { 26, 5 }, // 3.9595 11010 { 29, 5 }, // 4.1546 11101 { 31, 5 }, // 4.2623 11111 { 2, 4 }, // 4.5180 0010 { 0, 4 }, // 4.3151 0000 { 30, 5 }, // 4.2538 11110 { 28, 5 }, // 4.1422 11100 { 25, 5 }, // 3.9145 11001 { 22, 5 }, // 3.6691 10110 { 20, 5 }, // 3.4955 10100 { 14, 5 }, // 2.9155 01110 { 13, 5 }, // 2.7921 01101 { 8, 5 }, // 2.5553 01000 { 6, 5 }, // 2.3093 00110 { 2, 5 }, // 2.1200 00010 { 46, 6 }, // 1.8134 101110 { 35, 6 }, // 1.5824 100011 { 31, 6 }, // 1.4701 011111 { 21, 6 }, // 1.3187 010101 { 15, 6 }, // 1.2776 001111 { 95, 7 }, // 0.9664 1011111 { 72, 7 }, // 0.7922 1001000 { 41, 7 }, // 0.6838 0101001 { 189, 8 }, // 0.5024 10111101 { 123, 8 }, // 0.3830 01111011 { 377, 9 }, // 0.2232 101111001 { 161, 9 }, // 0.1566 010100001 { 891, 10 }, // 0.1383 1101111011 { 327, 10 }, // 0.0900 0101000111 { 326, 10 }, // 0.0790 0101000110 { 3560, 12 }, // 0.0254 110111101000 { 14255, 14 }, // 0.0117 11011110101111 { 14247, 14 }, // 0.0085 11011110100111 { 14252, 14 }, // 0.0085 11011110101100 { 14245, 14 }, // 0.0065 11011110100101 } }; #ifdef USE_SV8 static const HuffSrc_t HuffN8_src [2] [127] = { { { 2426, 13 }, { 4943, 13 }, { 787, 12 }, { 2470, 12 }, { 7270, 13 }, { 1764, 12 }, { 3632, 12 }, { 3633, 12 }, { 2486, 12 }, { 395, 11 }, { 607, 11 }, { 1242, 11 }, { 108, 10 }, { 300, 10 }, { 199, 10 }, { 440, 10 }, { 442, 10 }, { 616, 10 }, { 909, 10 }, { 897, 10 }, { 178, 9 }, { 309, 9 }, { 311, 9 }, { 451, 9 }, { 449, 9 }, { 26, 8 }, { 74, 8 }, { 94, 8 }, { 122, 8 }, { 136, 8 }, { 12, 7 }, { 29, 7 }, { 28, 7 }, { 36, 7 }, { 39, 7 }, { 46, 7 }, { 60, 7 }, { 69, 7 }, { 76, 7 }, { 92, 7 }, { 126, 7 }, { 11, 6 }, { 15, 6 }, { 10, 6 }, { 16, 6 }, { 21, 6 }, { 25, 6 }, { 28, 6 }, { 32, 6 }, { 31, 6 }, { 37, 6 }, { 47, 6 }, { 43, 6 }, { 35, 6 }, { 45, 6 }, { 48, 6 }, { 52, 6 }, { 53, 6 }, { 54, 6 }, { 62, 6 }, { 59, 6 }, { 0, 5 }, { 61, 6 }, { 51, 6 }, { 2, 5 }, { 1, 5 }, { 60, 6 }, { 57, 6 }, { 58, 6 }, { 55, 6 }, { 50, 6 }, { 49, 6 }, { 42, 6 }, { 40, 6 }, { 44, 6 }, { 41, 6 }, { 39, 6 }, { 33, 6 }, { 29, 6 }, { 26, 6 }, { 24, 6 }, { 20, 6 }, { 17, 6 }, { 13, 6 }, { 8, 6 }, { 9, 6 }, { 127, 7 }, { 93, 7 }, { 73, 7 }, { 72, 7 }, { 54, 7 }, { 38, 7 }, { 45, 7 }, { 14, 7 }, { 25, 7 }, { 15, 7 }, { 226, 8 }, { 137, 8 }, { 111, 8 }, { 95, 8 }, { 88, 8 }, { 48, 8 }, { 455, 9 }, { 450, 9 }, { 246, 9 }, { 247, 9 }, { 179, 9 }, { 55, 9 }, { 896, 10 }, { 620, 10 }, { 443, 10 }, { 302, 10 }, { 301, 10 }, { 198, 10 }, { 109, 10 }, { 1234, 11 }, { 883, 11 }, { 392, 11 }, { 394, 11 }, { 3634, 12 }, { 2487, 12 }, { 786, 12 }, { 1765, 12 }, { 1212, 12 }, { 7271, 13 }, { 2427, 13 }, { 4942, 13 } }, { { 3728, 12 }, { 4005, 12 }, { 264, 11 }, { 4004, 12 }, { 4044, 12 }, { 4045, 12 }, { 4046, 12 }, { 1424, 11 }, { 449, 11 }, { 448, 11 }, { 139, 10 }, { 231, 10 }, { 133, 10 }, { 719, 10 }, { 641, 10 }, { 676, 10 }, { 225, 10 }, { 677, 10 }, { 620, 10 }, { 72, 9 }, { 23, 9 }, { 67, 9 }, { 75, 9 }, { 113, 9 }, { 311, 9 }, { 68, 9 }, { 316, 9 }, { 467, 9 }, { 10, 8 }, { 468, 9 }, { 35, 8 }, { 27, 8 }, { 358, 9 }, { 32, 8 }, { 26, 8 }, { 501, 9 }, { 44, 8 }, { 45, 8 }, { 142, 8 }, { 173, 8 }, { 161, 8 }, { 188, 8 }, { 189, 8 }, { 190, 8 }, { 191, 8 }, { 254, 8 }, { 251, 8 }, { 255, 8 }, { 19, 7 }, { 26, 7 }, { 70, 7 }, { 76, 7 }, { 87, 7 }, { 85, 7 }, { 124, 7 }, { 7, 6 }, { 15, 6 }, { 41, 6 }, { 46, 6 }, { 2, 5 }, { 16, 5 }, { 28, 5 }, { 12, 4 }, { 1, 2 }, { 13, 4 }, { 30, 5 }, { 18, 5 }, { 0, 5 }, { 45, 6 }, { 34, 6 }, { 12, 6 }, { 3, 6 }, { 118, 7 }, { 88, 7 }, { 81, 7 }, { 29, 7 }, { 78, 7 }, { 23, 7 }, { 27, 7 }, { 253, 8 }, { 12, 7 }, { 232, 8 }, { 235, 8 }, { 159, 8 }, { 238, 8 }, { 172, 8 }, { 168, 8 }, { 143, 8 }, { 154, 8 }, { 40, 8 }, { 8, 8 }, { 478, 9 }, { 9, 8 }, { 479, 9 }, { 469, 9 }, { 42, 8 }, { 43, 8 }, { 504, 9 }, { 357, 9 }, { 321, 9 }, { 339, 9 }, { 317, 9 }, { 114, 9 }, { 82, 9 }, { 83, 9 }, { 73, 9 }, { 74, 9 }, { 1000, 10 }, { 933, 10 }, { 621, 10 }, { 718, 10 }, { 2003, 11 }, { 713, 10 }, { 2020, 11 }, { 230, 10 }, { 1865, 11 }, { 44, 10 }, { 138, 10 }, { 1280, 11 }, { 2021, 11 }, { 3729, 12 }, { 4047, 12 }, { 90, 11 }, { 265, 11 }, { 1281, 11 }, { 1425, 11 }, { 91, 11 } } }; #endif #define MAKE(d,s) Make_HuffTable ( (d), (s), sizeof(s)/sizeof(*(s)) ) #define SORT(x,o) Resort_HuffTable ( (x), sizeof(x)/sizeof(*(x)), -(Int)(o) ) #define LOOKUP(x,q) Make_LookupTable ( (q), sizeof(q), (x), sizeof(x)/sizeof(*(x)) ) void Init_Huffman_Encoder_SV7 ( void ) { // Splitting of the 36 Samples MAKE ( HuffSCFI, HuffSCFI_src ); // Differential Scalefactors MAKE ( HuffDSCF, HuffDSCF_src ); // resolution, differential quantizer indizes MAKE ( HuffHdr, HuffHdr_src ); // 3-step quantizer, 3 bundled samples MAKE ( HuffQ1[0], HuffQ1_src[0] ); // less shaped, book 0 MAKE ( HuffQ1[1], HuffQ1_src[1] ); // more shaped, book 1 // 5-step quantizer, 2 bundled samples MAKE ( HuffQ2[0], HuffQ2_src[0] ); // less shaped, book 0 MAKE ( HuffQ2[1], HuffQ2_src[1] ); // more shaped, book 1 // 7-step quantizer, single samples MAKE ( HuffQ3[0], HuffQ3_src[0] ); // less shaped, book 0 MAKE ( HuffQ3[1], HuffQ3_src[1] ); // more shaped, book 1 #ifdef USE_SV8 // 7-step quantizer, 2 bundled samples MAKE ( HuffN3[0], HuffN3_src[0] ); // less shaped, book 0 MAKE ( HuffN3[1], HuffN3_src[1] ); // more shaped, book 1 #endif // 9-step quantizer, single samples MAKE ( HuffQ4[0], HuffQ4_src[0] ); // less shaped, book 0 MAKE ( HuffQ4[1], HuffQ4_src[1] ); // more shaped, book 1 // 15-step quantizer, single samples MAKE ( HuffQ5[0], HuffQ5_src[0] ); // less shaped, book 0 MAKE ( HuffQ5[1], HuffQ5_src[1] ); // more shaped, book 1 // 31-step quantizer, single samples MAKE ( HuffQ6[0], HuffQ6_src[0] ); // less shaped, book 0 MAKE ( HuffQ6[1], HuffQ6_src[1] ); // more shaped, book 1 // 63-step quantizer, single samples MAKE ( HuffQ7[0], HuffQ7_src[0] ); // less shaped, book 0 MAKE ( HuffQ7[1], HuffQ7_src[1] ); // more shaped, book 1 #ifdef USE_SV8 // 127-step quantizer, single samples MAKE ( HuffN8[0], HuffN8_src[0] ); // book 0 MAKE ( HuffN8[1], HuffN8_src[1] ); // book 1 #endif } #ifndef MPP_ENCODER void Init_Huffman_Decoder_SV7 ( void ) { Init_Huffman_Encoder_SV7 (); SORT ( HuffHdr , 5 ); SORT ( HuffSCFI , 0 ); SORT ( HuffDSCF , 7 ); SORT ( HuffQ1[0], 0 ); SORT ( HuffQ1[1], 0 ); SORT ( HuffQ2[0], 0 ); SORT ( HuffQ2[1], 0 ); #ifdef USE_SV8 SORT ( HuffN3[0], 0 ); SORT ( HuffN3[1], 0 ); #endif SORT ( HuffQ3[0], Dc[3] ); SORT ( HuffQ3[1], Dc[3] ); SORT ( HuffQ4[0], Dc[4] ); SORT ( HuffQ4[1], Dc[4] ); SORT ( HuffQ5[0], Dc[5] ); SORT ( HuffQ5[1], Dc[5] ); SORT ( HuffQ6[0], Dc[6] ); SORT ( HuffQ6[1], Dc[6] ); SORT ( HuffQ7[0], Dc[7] ); SORT ( HuffQ7[1], Dc[7] ); #ifdef USE_SV8 SORT ( HuffN8[0], Dc[8] ); SORT ( HuffN8[1], Dc[8] ); #endif LOOKUP ( HuffQ1[0], LUT1_0 ); LOOKUP ( HuffQ1[1], LUT1_1 ); LOOKUP ( HuffQ2[0], LUT2_0 ); LOOKUP ( HuffQ2[1], LUT2_1 ); LOOKUP ( HuffQ3[0], LUT3_0 ); LOOKUP ( HuffQ3[1], LUT3_1 ); LOOKUP ( HuffQ4[0], LUT4_0 ); LOOKUP ( HuffQ4[1], LUT4_1 ); LOOKUP ( HuffQ5[0], LUT5_0 ); LOOKUP ( HuffQ5[1], LUT5_1 ); LOOKUP ( HuffQ6[0], LUT6_0 ); LOOKUP ( HuffQ6[1], LUT6_1 ); LOOKUP ( HuffQ7[0], LUT7_0 ); LOOKUP ( HuffQ7[1], LUT7_1 ); LOOKUP ( HuffDSCF , LUTDSCF ); } #endif /* end of huffsv7.c */ mppenc-1.16/src/mpp.h0000644000175000017500000001671710522734510013750 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ /****************************************************** * * * Source Compile configuration * * * ******************************************************/ #if !defined(__APPLE__) // use optimized assembler routines for Pentium III/K6-2/Athlon (only 32 bit OS, Intel x86 and no MAKE_xxBITS) // you need the NASM assembler on your system, the program becomes a little bit larger and decoding // on AMD K6-2 (x3), AMD K6-III (x3), AMD Duron (x1.7), AMD Athlon (x1.7), Pentium III (x2) and Pentium 4 (x1.8) becomes faster #define USE_ASM // Open Sound System support (only Unix with OSS support) // If your Operating System supports the Open Sound System, you can output to /dev/dsp* and // instead of writing a file the program plays the file via this sound device. // on some systems you also must link the libossaudio library, so maybe you also must edit the Makefile #define USE_OSS_AUDIO // Enlightenment Sound Daemon support (only Unix with ESD support) // If your Operating System supports the Enlightenment Sound Daemon you can output to /dev/esd and // instead of writing a file the program plays the file via this sound device. // you also must link the libesd library, so maybe you also must edit the Makefile //#define USE_ESD_AUDIO #endif // native Sun Onboard-Audio support (only SunOS) // If you have a Sun Workstation with Onboard-Audio, you can output to /dev/audio and // instead of writing a file the program plays the file via this sound device. // Some machines lacking librt.a so you are unable to link a static executable with realtime-support. // Although you can still perfectly use the dynamic executable. //#define USE_SUN_AUDIO // Sound support for SGI Irix // If you have a SGI Workstation running IRIX, you can output to /dev/audio and // instead of writing a file the program plays the file via this sound device. //#define USE_IRIX_AUDIO // Audio support for Windows (WAVE OUT) (only Windows) // If you have a Windows based system and if you also want to play files directly instead of only writing audio files, // then define the next item #define USE_WIN_AUDIO // Buffersize for Windows Audio in 4.5 KByte units // Only needed for Windows+USE_WIN_AUDIO // Good values are 8...32 for fast machines and 128...512 for slow machines // large values decrease average performance a little bit, increase memory // consumption (1 Block = 4.5 KByte), but increase buffering, so it takes a // longer time to get a dropout. Note that I don't have a 486/80...133, so // I don't know anything about their performance. // (Attention: 512 = additional 2.3 MByte of memory) #define MAX_WAVEBLOCKS 40 // increase priority if destination is an audio device // this increases the priority of the decoder when playing the file directly to a sound card to reduce/prevent // dropouts during the playback due to CPU time shortage #define USE_NICE // use realtime scheduling if destination is an audio device // This sets the program to real time priority when playing the file directly to a sound card. // Now it should be really difficult to get dropouts (file IO and other realtime programs are the remaining weak points) #define USE_REALTIME // use ANSI-Escape sequences to structure output #define USE_ANSI_ESCAPE // Use termios for reading values from keyboard without echo and ENTER #define USE_TERMIOS // if none of the next three macros MAKE_xxBIT is defined, // normal non-dithered and non-shaped 16 bit PCM output is generated // create 16 bit Output // output is 16 bit wide, you can also dither and noise shape //#define MAKE_16BIT // create 24 bit Output // output is 24 bit wide instead of 16 bit wide, you can also dither and noise shape //#define MAKE_24BIT // create 32 bit Output // output is 32 bit wide instead of 16 bit wide, you can also dither and noise shape //#define MAKE_32BIT // Select subset of function used for file I/O: // 1: ANSI via file pointer (FILE*) // 2: POSIX via file handle (int or HANDLE) // 3: POSIX like lowest level function of Turbo/Borland C // 4: WinAMP 3: running inside WinAMP // Try to use '2', if this doesn't work, try '1'. '3' is for Borland compilers. #ifndef FILEIO # if defined MPP_ENCODER # define FILEIO 1 // mppenc still uses buffered ANSI-I/O # elif defined MPP_DECODER # define FILEIO 2 # else # error Neigher MPP_DECODER nor MPP_ENCODER is defined. Abort. # endif #endif // the POSIX function read() can return less bytes than requested not only at the end of the file. // if this happens, the following macro must be defined: #define HAVE_INCOMPLETE_READ // use a shorter Huffman_t representation, may be faster // use for performance tuning #define USE_HUFF_PACK // use shorter representation for SCF_Index[][] and Res[], may be faster // use for performance tuning #define USE_ARRAY_PACK // use the System 5 timer for profiling // otherwise a special piece of code for Turbo-C is used or the Timestamp Counter on Intel IA32/gcc systems. // Both is highly non-portable. This solution is more portable (you only need a SYS 5 compatible system, // but also much much more inaccurate. //#define USE_SYSV_TIMER // do a memory shift every n subband samples, otherwise only increment pointer (6, 12, 18 and 36 are good values) // use for performance tuning #define VIRT_SHIFT 18 // selects InputBuff size, size is 4 * 2^IBUFLOG2 bytes (11...14 are good values) // use for performance tuning // can also be used to eliminate disk performance issue while tuning the program // (set to a value, so the test cases are fully read before decoding #define IBUFLOG2 14 // Dump contents of MPEGplus files (only for development), 0x00 no dump // Bit 0: maxband, Bit 1: msbits, Bit 2: allocation/resolution, Bit 3: SCF // Bit 4: Subsamples, Bit 5: Datenrate, Bit 6: Bitusage der Sektionen //#define DUMPSELECT 0xFF // 16 bit and 32 bit accesses must be aligned, otherwise a bus error occures. // try this if you get bus errors //#define MUST_ALIGNED // Experimental: use http/ftp streaming #define USE_HTTP // _use setargv module #define USE_ARGV // Use IPv4 and IPv6 //#define USE_IPv4_6 // Use only IPv6 //#define USE_IPv6 // compile StreamVersion 8 decoding (always disable, no usabiltity) // do not edit //#define USE_SV8 // disables assert() // assert() is for development only and decreases speed and increases the size of the program #ifndef NDEBUG # define NDEBUG #endif // Some other tracing (only for development) // do not edit //#define DEBUG // Some tracings of popen() // do not edit //#define DEBUG2 // activate simple profiler //#define PROFILE // make debug output in tags.c stfu #define STFU /* end of mpp.h */ mppenc-1.16/src/pipeopen.c0000644000175000017500000001161410522734510014755 0ustar bencerbencer/* * Opens a communication channel to another program using unnamed pipe mechanism and stdin/stdout. * * (C) Frank Klemm 2001,02. All rights reserved. * * Principles: * * History: * 2001 created * 2002 * * Global functions: * - pipeopen * * TODO: * - */ //#define DEBUG2 #include "mppdec.h" #include /* * */ static int EscapeProgramPathName ( const char* longprogname, char* escaped, size_t len ) { int ret = 0; #ifdef _WIN32 ret = GetShortPathName ( longprogname, escaped, len ); #else if ( strlen (longprogname) <= len-3 ) ret = sprintf ( escaped, "\"%s\"", longprogname ); // Note that this only helps against spaces and some similar things in the file name, not against all strange stuff #endif if ( ret <= 0 || ret >= (int)len ) { } return ret; } /* * */ static FILE* OpenPipeWhenBinaryExist ( const char* path, size_t pathlen, const char* executable_filename, const char* command_line ) { char filename [4096]; char cmdline [4096]; char* p = filename; FILE* fp; for ( ; *path && pathlen--; path++ ) if ( *path != '"' ) *p++ = *path; *p++ = PATH_SEP; strcpy ( p, executable_filename ); #ifdef DEBUG2 stderr_printf ("Test for file »%s« \n", filename ); #endif fp = fopen ( filename, "rb" ); if ( fp != NULL ) { fclose ( fp ); EscapeProgramPathName ( filename, cmdline, sizeof cmdline ); strcat ( cmdline, command_line ); fp = POPEN_READ_BINARY_OPEN ( cmdline ); #ifdef DEBUG2 stderr_printf ("Executed »%s«\n", cmdline ); #endif } return fp; } /* * */ static FILE* TracePathList ( const char* p, const char* executable_filename, const char* command_line ) { const char* nextsep; FILE* fp; while ( p != NULL && *p != '\0' ) { if ( (nextsep = strchr (p, ENVPATH_SEP)) == NULL ) { fp = OpenPipeWhenBinaryExist ( p, (size_t) -1, executable_filename, command_line ); p = NULL; } else { fp = OpenPipeWhenBinaryExist ( p, (size_t)(nextsep-p), executable_filename, command_line ); p = nextsep + 1; } if ( fp != NULL ) return fp; } return NULL; } /* * Executes command line given by »command«. * The command must be found in some predefined paths or in the ${PATH} aka %PATH% * The char »#« in command is replaced by the contents * of »filename«. Special characters are escaped. */ FILE* pipeopen ( const char* command, const char* filename ) { static const char pathlist [] = #ifdef _WIN32 "."; #else "/usr/bin:/usr/local/bin:/opt/mpp:."; #endif char command_line [4096]; // » -o - bar.pac« char executable_filename [4096]; // »foo.exe« char* p; const char* q; FILE* fp; // does the source file exist and is readble? if ( (fp = fopen (filename, "rb")) == NULL ) { stderr_printf ("file '%s' not found.\n", filename ); return NULL; } fclose (fp); // extract executable name from the 'command' to executable_filename, append executable extention p = executable_filename; for ( ; *command != ' ' && *command != '\0'; command++ ) *p++ = *command; strcpy ( p, EXE_EXT ); // Copy 'command' to 'command_line' replacing '#' by filename p = command_line; for ( ; *command != '\0'; command++ ) { if ( *command != '#' ) { *p++ = *command; } else { q = filename; if (*q == '-') { *p++ = '.'; *p++ = PATH_SEP; } #ifdef _WIN32 // Windows secure Way to "escape" *p++ = '"'; while (*q) *p++ = *q++; *p++ = '"'; #else // Unix secure Way to \e\s\c\a\p\e while (*q) { if ( !isalnum(*q) && *q != '.' && *q != '-' && *q != '_' && *q != '/' ) *p++ = '\\'; *p++ = *q++; } #endif } } *p = '\0'; // Try the several built-in paths to find binary fp = TracePathList ( pathlist , executable_filename, command_line ); if ( fp != NULL ) return fp; // Try the PATH settings to find binary (Why we must search for the executable in all PATH settings? --> popen itself do not return useful information) fp = TracePathList ( getenv ("PATH"), executable_filename, command_line ); if ( fp != NULL ) return fp; #ifdef DEBUG2 stderr_printf ("Nothing found to execute.\n" ); #endif return NULL; } /* end of pipeopen.c */ mppenc-1.16/src/profile.c0000644000175000017500000001165310522734510014601 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include #include #include #include #include "mppdec.h" #include "profile.h" /* * For every architecture you want to profile/checkpoint you need the following items: * * uintmax_t: * A type which is used for time calculation, mostly 32 bit or 64 bit, * should be large enough so that no overruns occures during the measurement * STD_TIMER_CLK: * Clock frequency of the used timer in MHz * RDTSC(): * A macro reading the current time into a local variable timetemp with the type uintmax_t, * Time is in 1.e-6/STD_TIMER_CLK seconds. * * Places: * typedef of uintmax_t: profile.h * RDTSC(): profile.h * STD_TIMER_CLK: profile.c * no-inline functions maybe needed by RDTSC(): * profile.c */ #ifdef PROFILE #ifdef __TURBOC__ # define STD_TIMER_CLK 1.193181667 /* MHz */ uintmax_t readtime ( void ) /* PC onboard timer */ { asm XOR AX, AX asm MOV ES, AX asm OUT 67, AL asm MOV DX, ES:[46Ch] asm IN AL, 64 asm XCHG AL, AH asm IN AL, 64 asm XCHG AL, AH asm NEG AX } #elif defined USE_SYSV_TIMER # define STD_TIMER_CLK 1.0000000 /* MHz */ # include # include uintmax_t readtime ( void ) /* System V timer */ { struct timeval tv; gettimeofday ( &tv, NULL ); return tv.tv_sec * (uintmax_t)1000000LU + tv.tv_usec; } #else # define STD_TIMER_CLK 233.3333333 /* MHz */ #endif uintmax_t timecounter [256]; const char* timename [256]; unsigned char functionstack [1024]; unsigned char* functionstack_pointer = functionstack; static void Cdecl signal_handler ( int signum ) { char name [128]; char file [128]; char no [ 32]; unsigned char* f; (void) stderr_printf ( "\n\nSignal %d detected. Call stack:\n", signum ); for ( f = functionstack+1; f <= functionstack_pointer; f++ ) { (void) sscanf ( timename[*f], "%128[^|]|%128[^|]|%32[0-9]", name, file, no ); (void) stderr_printf ( "%-24.24s%12.12s:%s\n", name, file, no ); } _exit ( 128+signum ); } void set_signal ( void ) { signal ( SIGILL , signal_handler ); signal ( SIGINT , signal_handler ); signal ( SIGSEGV, signal_handler ); signal ( SIGFPE , signal_handler ); } void report ( void ) { static char dash [] = "---------------------------------------"; uintmax_t sum; uintmax_t max; int i; int j; int k; char name [128]; char file [128]; char no [ 32]; size_t filelen; double MHz = STD_TIMER_CLK; #ifdef __linux__ FILE* fp; // read out CPU frequency if proc-FS is present if ( (fp = fopen ("/proc/cpuinfo", "r")) != NULL ) { while ( fgets(name, sizeof(name), fp) ) if ( 1 == sscanf ( name, "cpu MHz : %lf", &MHz ) ) break; (void) fclose (fp); } #endif // calculate total time for ( sum = 0, i = 1; i < sizeof(timecounter)/sizeof(*timecounter); i++ ) sum += timecounter [i]; (void) fprintf ( stderr, "\n%s%s\n", dash, dash ); (void) fprintf ( stderr, "100.0%% %13.6f ms *** TOTAL ***%25s[%.1f MHz]\n", sum/(MHz*1000.), "", MHz ); // output sorted while ( 1 ) { for ( max = 0, j = 1; j < sizeof(timecounter)/sizeof(*timecounter); j++ ) if ( timecounter [j] > max ) max = timecounter [k = j]; if (max == 0) break; sscanf ( timename [k], "%128[^|]|%128[^|]|%32[0-9]", name, file, no ); filelen = strlen (file); (void) fprintf ( stderr, "%6.2f%% %13.6f ms %-28.28s%18.18s:%s\n", 100. * timecounter[k] / sum, timecounter[k] / (MHz*1000.), name, filelen < 18 ? file : file+filelen-18, no ); timecounter [k] = 0; } (void) fprintf ( stderr, "%s%s\n", dash, dash ); (void) fflush ( stderr ); } #endif /* PROFILE */ /* end of profile.c */ mppenc-1.16/src/CMakeLists.txt0000644000175000017500000000102610524423665015536 0ustar bencerbenceradd_definitions(-DMPP_ENCODER -DFAST_MATH -DCVD_FASTLOG) add_executable(mppenc analy_filter encode_sv7 huffsv7 profile stderr winmsg ans fastmath keyboard psy tags bitstream fft4g mppenc psy_tab tools cvd fft_routines pipeopen quant wave_in) if(WIN32) target_link_libraries(mppenc winmm) endif(WIN32) if(NOT MSVC) target_link_libraries(mppenc m) endif(NOT MSVC) if(CMAKE_SYSTEM_NAME STREQUAL OpenBSD) target_link_libraries(mppenc ossaudio) endif(CMAKE_SYSTEM_NAME STREQUAL OpenBSD) install(TARGETS mppenc RUNTIME DESTINATION bin) mppenc-1.16/src/quant.c0000644000175000017500000003474410525155536014307 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" #include "fastmath.h" /* V A R I A B L E S */ float __SCF [128 + 6]; // tabulated scalefactors float __invSCF [128 + 6]; // inverted scalefactors // Quantization-coefficients: step/65536 bzw. (2*D[Res]+1)/65536 static const float __A [1 + 18] = { 0.0000762939453125f, 0.0000000000000000f, 0.0000457763671875f, 0.0000762939453125f, 0.0001068115234375f, 0.0001373291015625f, 0.0002288818359375f, 0.0004730224609375f, 0.0009613037109375f, 0.0019378662109375f, 0.0038909912109375f, 0.0077972412109375f, 0.0156097412109375f, 0.0312347412109375f, 0.0624847412109375f, 0.1249847412109375f, 0.2499847412109375f, 0.4999847412109375f }; // Requantization-coefficients: 65536/step bzw. 1/A[Res] static const float __C [1 + 18] = { 13107.200000000001f, 65535.000000000000f, 21845.333333333332f, 13107.200000000001f, 9362.285714285713f, 7281.777777777777f, 4369.066666666666f, 2114.064516129032f, 1040.253968253968f, 516.031496062992f, 257.003921568627f, 128.250489236790f, 64.062561094819f, 32.015632633121f, 16.003907203907f, 8.000976681723f, 4.000244155527f, 2.000061037018f, 1.000015259022f }; // Requantization-Offset: 2*D+1 = steps of quantizer static const int __D [1 + 18] = { 2, 0, 1, 2, 3, 4, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767 }; #define A (__A + 1) #define C (__C + 1) #define D (__D + 1) // Generation of the scalefactors and their inverses void Init_Skalenfaktoren ( void ) { int n; for ( n = -6; n < 128; n++ ) { SCF[n] = (float) ( pow(10.,-0.1*(n-1)/1.26) ); invSCF[n] = (float) ( pow(10., 0.1*(n-1)/1.26) ); } } #pragma warning ( disable : 4305 ) static float NoiseInjectionCompensation1D [18] = { #if 1 1.f, 0.884621, 0.935711, 0.970829, 0.987941, 0.994315, 0.997826, 0.999744, 1., 1., 1., 1., 1., 1., 1., 1., 1., 1. #else 1., 0.907073, // -1...+1 0.946334, // -2...+2 0.974793, // -3...+3 0.987647, // -4...+4 0.994330, // -7...+7 0.997846, // -15...+15 1., // -31...+31 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., #endif } ; #if 0 static float NoiseInjectionCompensation2D [18] [32] = { { 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, }, { 0.931595, 0.891390, 0.852494, 0.872420, 0.904053, 0.933716, 0.958976, 0.977719, 0.993979, 1.009011, 1.020961, 1.029564, 1.026582, 1.026753, 1.035573, 1.053251, 1.073429, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, 1.096344, }, { 0.878264, 0.882351, 0.904261, 0.930843, 0.949243, 0.966741, 0.980500, 0.988182, 0.993361, 0.997112, 0.998918, 0.999501, 1.003179, 1.007445, 1.008678, 0.995890, 0.991015, 0.988019, 0.985479, 0.987646, 1.003605, 1.029301, 1.040511, 1.061531, 1.083302, 1.083302, 1.083302, 1.083302, 1.083302, 1.083302, 1.083302, 1.083302, }, { 0.866977, 0.943500, 0.941561, 0.953049, 0.967274, 0.980476, 0.988678, 0.993240, 0.996376, 0.998513, 0.999545, 0.999775, 1.000898, 1.003954, 1.006308, 1.004932, 1.002867, 1.002922, 1.003624, 1.005487, 1.003919, 1.008022, 0.987693, 1.000358, 1.017461, 1.039166, 1.056053, 1.068191, 1.068191, 1.068191, 1.068191, 1.068191, }, { 0.880390, 0.976713, 0.976180, 0.976596, 0.982011, 0.988786, 0.993619, 0.996641, 0.998824, 1.000297, 1.001195, 1.001718, 1.002395, 1.003503, 1.005617, 1.005072, 1.002409, 1.003703, 1.003412, 1.003318, 1.005290, 1.007112, 1.014370, 1.010040, 1.000780, 1.005700, 1.020505, 1.030123, 1.030123, 1.030123, 1.030123, 1.030123, }, { 0.916894, 0.987164, 0.988734, 0.992318, 0.995268, 0.996932, 0.998141, 0.999072, 0.999674, 1.000104, 1.000292, 1.000386, 1.000399, 1.000222, 1.000671, 1.002127, 1.000137, 1.000046, 0.999644, 0.999156, 1.000568, 1.000098, 0.993764, 0.993954, 0.998971, 1.002835, 1.002972, 0.995376, 1.001643, 1.001643, 1.001643, 1.001643, }, { 0.982771, 0.995034, 0.997118, 0.998294, 0.998652, 0.999016, 0.999382, 0.999598, 0.999746, 0.999851, 0.999837, 0.999881, 0.999847, 1.000154, 0.999885, 1.000222, 0.999963, 1.000934, 0.999804, 0.999927, 1.000379, 0.997574, 0.997943, 0.998748, 0.998151, 0.997458, 1.000319, 1.001091, 0.998461, 0.996151, 1.005969, 1.005969, }, { 0.997150, 0.999903, 0.999424, 0.999537, 0.999661, 0.999753, 0.999851, 0.999903, 0.999928, 0.999963, 0.999969, 0.999941, 0.999974, 0.999967, 0.999996, 0.999975, 0.999966, 0.999704, 0.999946, 0.999894, 0.999905, 1.000840, 1.000716, 1.000799, 1.000406, 0.999912, 1.000153, 0.999789, 1.000495, 1.000495, 1.001167, 1.001347, }, { 0.995524, 0.999983, 1.000044, 0.999965, 0.999970, 0.999974, 0.999986, 0.999995, 0.999996, 1.000011, 0.999997, 1.000010, 1.000010, 1.000026, 1.000006, 1.000148, 1.000048, 0.999999, 1.000161, 1.000193, 0.999797, 1.000145, 0.999974, 1.000039, 0.999731, 0.999985, 1.000563, 1.000256, 1.000637, 1.000050, 1.002013, 1.001053, }, { 0.994796, 0.999833, 1.000003, 1.000012, 0.999986, 0.999991, 0.999991, 1.000000, 1.000004, 0.999999, 1.000005, 1.000004, 1.000008, 0.999996, 1.000027, 1.000097, 0.999951, 0.999938, 0.999989, 1.000001, 1.000048, 0.999935, 1.000068, 1.000134, 0.999961, 1.000198, 0.999956, 0.999957, 0.999844, 1.000087, 0.999708, 1.000198, }, { 0.996046, 0.999902, 1.000019, 1.000017, 0.999983, 0.999997, 1.000002, 0.999993, 0.999999, 1.000003, 1.000001, 1.000015, 1.000004, 1.000006, 0.999987, 0.999993, 0.999992, 1.000029, 1.000064, 0.999997, 1.000044, 1.000044, 0.999919, 0.999875, 1.000011, 0.999897, 0.999905, 0.999996, 0.999934, 0.999968, 1.000008, 0.999902, }, { 0.998703, 0.999963, 1.000021, 1.000006, 1.000008, 1.000000, 1.000003, 0.999994, 0.999990, 0.999990, 1.000003, 1.000009, 1.000001, 0.999999, 1.000001, 1.000009, 0.999999, 0.999988, 1.000003, 0.999971, 1.000005, 1.000042, 0.999924, 0.999995, 0.999998, 0.999988, 0.999961, 0.999942, 1.000046, 1.000061, 1.000112, 1.000052, }, { 0.999872, 1.000001, 1.000004, 0.999998, 0.999999, 0.999998, 0.999992, 0.999990, 0.999991, 1.000000, 1.000000, 1.000000, 1.000002, 0.999996, 1.000004, 1.000011, 0.999963, 1.000016, 1.000050, 0.999996, 0.999998, 1.000006, 0.999990, 0.999948, 0.999974, 1.000060, 1.000014, 0.999987, 0.999986, 0.999917, 0.999973, 1.000035, }, { 1.000366, 1.000006, 0.999996, 0.999995, 0.999998, 0.999996, 0.999991, 1.000001, 0.999990, 0.999996, 1.000010, 0.999999, 1.000002, 1.000000, 0.999996, 0.999990, 1.000014, 0.999978, 1.000011, 0.999983, 0.999988, 0.999971, 0.999997, 0.999989, 0.999986, 0.999958, 1.000005, 0.999992, 0.999975, 0.999975, 0.999975, 0.999975, }, { 0.999736, 0.999995, 1.000002, 1.000004, 0.999999, 1.000000, 1.000003, 1.000000, 1.000007, 0.999992, 0.999997, 0.999998, 0.999998, 0.999997, 1.000007, 1.000012, 1.000004, 0.999995, 0.999996, 1.000009, 1.000003, 1.000008, 1.000001, 1.000003, 1.000011, 1.000019, 0.999991, 0.999970, 0.999970, 0.999970, 0.999970, 0.999965, }, { 0.999970, 1.000000, 1.000000, 1.000000, 1.000001, 1.000000, 1.000000, 0.999999, 1.000001, 1.000000, 0.999999, 0.999999, 0.999999, 1.000007, 1.000005, 1.000002, 0.999999, 0.999999, 1.000000, 0.999997, 0.999999, 1.000001, 1.000001, 0.999988, 0.999988, 0.999984, 0.999995, 0.999986, 0.999986, 0.999986, 0.999986, 0.999986, }, { 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, }, { 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, }, }; #endif #pragma warning ( default : 4305 ) void NoiseInjectionComp ( void ) { int i; for ( i = 0; i < sizeof(NoiseInjectionCompensation1D)/sizeof(*NoiseInjectionCompensation1D); i++ ) NoiseInjectionCompensation1D [i] = 1.f; #if 0 for ( i = 0; i < sizeof(NoiseInjectionCompensation2D)/sizeof(**NoiseInjectionCompensation2D); i++ ) NoiseInjectionCompensation2D [0][i] = 1.f; #endif } // Quantizes a subband and calculates iSNR float ISNR_Schaetzer ( const float* input, const float SNRcomp, const int res ) { int k; float signal, error, sig, err; const float fac = A [res]; const float invfac = C [res]; const float noiseComp = NoiseInjectionCompensation1D [res]; // Summation of the absolute power and the quadratic error signal = error = 1.e-30f; for ( k = 0; k < 36; k++ ) { sig = input[k] * noiseComp; err = mpc_nearbyintf(sig * fac) * invfac - sig; signal += sig * sig; error += err * err; } // Utilization of SNRcomp only if SNR > 1 !!! return signal > error ? error / (signal * SNRcomp) : error / signal; } float ISNR_Schaetzer_Trans ( const float* input, const float SNRcomp, const int res ) { int k; float signal, error, result, sig, err; const float fac = A [res]; const float invfac = C [res]; const float noiseComp = NoiseInjectionCompensation1D [res]; // Summation of the absolute power and the quadratic error signal = error = 1.e-30f; for ( k = 0 ; k < 12; k++ ) { sig = input[k] * noiseComp; err = mpc_nearbyintf(sig * fac) * invfac - sig; signal += sig * sig; error += err * err; } result = signal > error ? error / (signal * SNRcomp) : error / signal; signal = error = 1.e-30f; for ( ; k < 24; k++ ) { sig = input[k] * noiseComp; err = mpc_nearbyintf(sig * fac) * invfac - sig; signal += sig * sig; error += err * err; } sig = signal > error ? error / (signal * SNRcomp) : error / signal; if ( sig > result ) result = sig; signal = error = 1.e-30f; for ( ; k < 36; k++ ) { sig = input[k] * noiseComp; err = mpc_nearbyintf(sig * fac) * invfac - sig; signal += sig * sig; error += err * err; } sig = signal > error ? error / (signal * SNRcomp) : error / signal; if ( sig > result ) result = sig; return result; } // Linear quantizer for a subband void QuantizeSubband ( unsigned int* qu_output, const float* input, const int res, float* errors ) { int n, quant; float signal; const int offset = D [res]; const float noiseComp = NoiseInjectionCompensation1D [res]; const float mult = A [res] * noiseComp; const float invmult = C [res]; for ( n = 0; n < 36 - MAX_NS_ORDER; n++) { quant = (unsigned int) ( mpc_lrintf( input[n] * mult ) + offset ); // limitation to 0...2D if ( quant > offset * 2 ) { quant = mini ( quant, offset * 2 ); quant = maxi ( quant, 0 ); } qu_output[n] = quant; } for ( ; n < 36; n++ ) { signal = input[n] * mult; quant = (unsigned int) ( mpc_lrintf( signal ) + offset ); // calculate the current error and save it for error refeeding errors [n + 6] = invmult * (quant - offset) - signal * noiseComp; // limitation to 0...2D if ( quant > offset * 2 ) { quant = mini ( quant, offset * 2); quant = maxi ( quant, 0 ); } qu_output[n] = quant; } } // NoiseShaper for a subband void QuantizeSubbandWithNoiseShaping ( unsigned int* qu_output, const float* input, const int res, float* errors, const float* FIR ) { int n, quant; float signal; const float mult = A [res]; const float invmult = C [res]; const int offset = D [res]; const float noiseComp = NoiseInjectionCompensation1D [res]; memset(errors, 0, 6 * sizeof *errors); // arghh, it produces pops on each frame boundary! for ( n = 0; n < 36; n++ ) { signal = input[n] * noiseComp - (FIR[5]*errors[n+0] + FIR[4]*errors[n+1] + FIR[3]*errors[n+2] + FIR[2]*errors[n+3] + FIR[1]*errors[n+4] + FIR[0]*errors[n+5]); quant = mpc_lrintf(signal * mult); // calculate the current error and save it for error refeeding errors [n + 6] = invmult * quant - signal * noiseComp; // limitation to +/-D quant = minf ( quant, +offset ); quant = maxf ( quant, -offset ); qu_output[n] = (unsigned int) ( quant + offset ); } } /* end of quant.c */ // pfk@schnecke.offl.uni-jena.de@EMAIL, Andree.Buschmann@web.de@EMAIL, BuschmannA@becker.de@EMAIL, miyaguch@eskimo.com@EMAIL, r3mix@irc.openprojects.net@EMAIL, dibrom@users.sourceforge.net@EMAIL, m.p.bakker-10@student.utwente.nl@EMAIL, djmrob@essex.ac.uk@EMAIL, dim@psytel-research.co.yu@EMAIL, lerch@zplane.de@EMAIL, takehiro@users.sourceforge.net@EMAIL, aleidinger@users.sourceforge.net@EMAIL, Robert.Hegemann@gmx.de@EMAIL, bouvigne@mp3-tech.org@EMAIL, monty@xiph.org@EMAIL, Pumpkinz99@aol.com@EMAIL, spase@outerspase.net@EMAIL, mt@wildpuppy.com@EMAIL, juha.laaksonheimo@tut.fi@EMAIL, speek@myrealbox.com@EMAIL, w.speek@12move.nl@EMAIL, martin@spueler.de@EMAIL, nicolaus.berglmeir@t-online.de@EMAIL, thomas.a.juerges@ruhr-uni-bochum.de@EMAIL, HelH@mpex.net@EMAIL, garf@roadum.demon.co.uk@EMAIL, gcp@sjeng.org@EMAIL, mike@naivesoftware.com@EMAIL, case@mobiili.net@EMAIL, steve.lhomme@free.fr@EMAIL, walter@binity.com@EMAIL mppenc-1.16/src/fft4g.c0000644000175000017500000004651710522734510014162 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" /* F U N C T I O N S */ static void makewt ( const int nw, int* ip, float* w ); static void makect ( const int nc, int* ip, float* c ); static __inline void bitrv2 ( const int n, int* ip, float* a ); // static __inline void cftfsub ( const int n, float* a, float* w ); // static __inline void rftfsub ( const int n, float* a, int nc, float* c ); // static __inline void cft1st ( const int n, float* a, float* w ); // static __inline void cftmdl_i386 ( const int n, const int l, float* a, float* w ); // 5648 static __inline void cftmdl_3DNow ( const int n, const int l, float* a, float* w ); // 4954 #if 0 # define cftmdl(n,l,a,w) cftmdl_3DNow ( n, l, a, w ) #else # define cftmdl(n,l,a,w) cftmdl_i386 ( n, l, a, w ) #endif // generates lookup-tables void Generate_FFT_Tables ( const int n, int* ip, float* w ) { int nw; int nc; nw = n >> 2; makewt ( nw, ip, w ); nc = n >> 2; makect ( nc, ip, w + nw ); } // patched to only-forward void rdft ( const int n, float* a, int* ip, float* w ) { float xi; ENTER(30); if ( n > 4) { bitrv2 ( n, ip + 2, a ); cftfsub ( n, a, w ); rftfsub ( n, a, ip[1], w + ip[0] ); } else if ( n == 4 ) { cftfsub ( n, a, w ); } xi = a[0] - a[1]; a[0] += a[1]; a[1] = xi; LEAVE(30); return; } /* -------- initializing routines -------- */ static void makewt ( const int nw, int* ip, float* w ) { int j; int nwh; float x; float y; double delta; ENTER(31); ip[0] = nw; ip[1] = 1; if ( nw > 2 ) { nwh = nw >> 1; delta = (M_PI/4) / nwh; w[0] = 1.; w[1] = 0.; w[nwh] = COS (delta * nwh); w[nwh + 1] = w[nwh]; if ( nwh > 2 ) { for ( j = 2; j < nwh; j += 2 ) { x = COS (delta * j); y = SIN (delta * j); w[j] = x; w[j + 1] = y; w[nw - j] = y; w[nw - j + 1] = x; } bitrv2 ( nw, ip + 2, w ); } } LEAVE(31); return; } static void makect ( const int nc, int* ip, float* c ) { int j; int nch; double delta; ENTER(32); ip[1] = nc; if ( nc > 1 ) { nch = nc >> 1; delta = (M_PI/4) / nch; c[0] = COS (delta * nch); c[nch] = 0.5f * c[0]; for ( j = 1; j < nch; j++ ) { c[j] = 0.5f * COS (delta * j); c[nc - j] = 0.5f * SIN (delta * j); } } LEAVE(32); return; } /* -------- child routines -------- */ static void bitrv2 ( const int n, int* ip, float* a ) { int j, j1, k, k1, l, m, m2; float xr, xi, yr, yi; ENTER(33); ip[0] = 0; l = n; m = 1; while ( (m << 3) < l ) { l >>= 1; for ( j = 0; j < m; j++ ) { ip[m + j] = ip[j] + l; } m <<= 1; } m2 = 2 * m; if ( (m << 3) == l ) { for ( k = 0; k < m; k++ ) { for ( j = 0; j < k; j++ ) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 -= m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } j1 = 2 * k + m2 + ip[k]; k1 = j1 + m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } else { for ( k = 1; k < m; k++ ) { for ( j = 0; j < k; j++ ) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } } LEAVE(33); return; } static void cftfsub ( const int n, float* a, float* w ) { int j, j1, j2, j3, l; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; ENTER(34); l = 2; if ( n > 8 ) { cft1st ( n, a, w ); l = 8; while ( (l << 2) < n ) { cftmdl ( n, l, a, w ); l <<= 2; } } if ( (l << 2) == n ) { j = 0; do { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i - x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; } while ( j += 2, j < l ); } else { j = 0; do { j1 = j + l; x0r = a[j] - a[j1]; x0i = a[j + 1] - a[j1 + 1]; a[j] += a[j1]; a[j + 1] += a[j1 + 1]; a[j1] = x0r; a[j1 + 1] = x0i; } while ( j += 2, j < l ); } LEAVE(34); return; } static void cft1st ( const int n, float* a, float* w ) { int j, k1; float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; ENTER(35); x0r = a[ 0] + a[ 2]; x0i = a[ 1] + a[ 3]; x1r = a[ 0] - a[ 2]; x1i = a[ 1] - a[ 3]; x2r = a[ 4] + a[ 6]; x2i = a[ 5] + a[ 7]; x3r = a[ 4] - a[ 6]; x3i = a[ 5] - a[ 7]; a[ 0] = x0r + x2r; a[ 1] = x0i + x2i; a[ 4] = x0r - x2r; a[ 5] = x0i - x2i; a[ 2] = x1r - x3i; a[ 3] = x1i + x3r; a[ 6] = x1r + x3i; a[ 7] = x1i - x3r; wk1r = w[ 2]; x0r = a[ 8] + a[10]; x0i = a[ 9] + a[11]; x1r = a[ 8] - a[10]; x1i = a[ 9] - a[11]; x2r = a[12] + a[14]; x2i = a[13] + a[15]; x3r = a[12] - a[14]; x3i = a[13] - a[15]; a[ 8] = x0r + x2r; a[ 9] = x0i + x2i; a[12] = x2i - x0i; a[13] = x0r - x2r; x0r = x1r - x3i; x0i = x1i + x3r; a[10] = wk1r * (x0r - x0i); a[11] = wk1r * (x0r + x0i); x0r = x3i + x1r; x0i = x3r - x1i; a[14] = wk1r * (x0i - x0r); a[15] = wk1r * (x0i + x0r); k1 = 0; j = 16; do { k1 += 2; wk2r = w[k1]; wk2i = w[k1 + 1]; wk1r = w[2*k1]; wk1i = w[2*k1 + 1]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; x0r = a[j] + a[j + 2]; x0i = a[j + 1] + a[j + 3]; x1r = a[j] - a[j + 2]; x1i = a[j + 1] - a[j + 3]; x2r = a[j + 4] + a[j + 6]; x2i = a[j + 5] + a[j + 7]; x3r = a[j + 4] - a[j + 6]; x3i = a[j + 5] - a[j + 7]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j + 4] = wk2r * x0r - wk2i * x0i; a[j + 5] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j + 2] = wk1r * x0r - wk1i * x0i; a[j + 3] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j + 6] = wk3r * x0r - wk3i * x0i; a[j + 7] = wk3r * x0i + wk3i * x0r; wk1r = w[2*k1 + 2]; wk1i = w[2*k1 + 3]; wk3r = wk1r - 2 * wk2r * wk1i; wk3i = 2 * wk2r * wk1r - wk1i; x0r = a[j + 8] + a[j + 10]; x0i = a[j + 9] + a[j + 11]; x1r = a[j + 8] - a[j + 10]; x1i = a[j + 9] - a[j + 11]; x2r = a[j + 12] + a[j + 14]; x2i = a[j + 13] + a[j + 15]; x3r = a[j + 12] - a[j + 14]; x3i = a[j + 13] - a[j + 15]; a[j + 8] = x0r + x2r; a[j + 9] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j + 12] = -wk2i * x0r - wk2r * x0i; a[j + 13] = -wk2i * x0i + wk2r * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j + 10] = wk1r * x0r - wk1i * x0i; a[j + 11] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j + 14] = wk3r * x0r - wk3i * x0i; a[j + 15] = wk3r * x0i + wk3i * x0r; } while ( j += 16, j < n ); LEAVE(35); return; } extern void Cdecl cftmdl_3DNow_1 ( const int n, const int l, float* a, float* w ); extern void Cdecl cftmdl_3DNow_2 ( const int n, const int l, float* a, float* w ); static void cftmdl_i386 ( const int n, const int l, float* a, float* w ) { int j, j1, j2, j3, k, k1, m, m2; float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; ENTER(36); m = l << 2; for ( j = 0; j < l; j += 2 ) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i - x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; } wk1r = w[2]; for ( j = m; j < l + m; j += 2 ) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x2i - x0i; a[j2 + 1] = x0r - x2r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * (x0r - x0i); a[j1 + 1] = wk1r * (x0r + x0i); x0r = x3i + x1r; x0i = x3r - x1i; a[j3] = wk1r * (x0i - x0r); a[j3 + 1] = wk1r * (x0i + x0r); } LEAVE(36); ENTER(39); k1 = 0; m2 = 2 * m; for ( k = m2; k < n; k += m2 ) { k1 += 2; wk2r = w[k1]; wk2i = w[k1 + 1]; wk1r = w[2*k1]; wk1i = w[2*k1 + 1]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; j = k; do { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = wk2r * x0r - wk2i * x0i; a[j2 + 1] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } while ( j += 2, j < l + k ); wk1r = w[2*k1 + 2]; wk1i = w[2*k1 + 3]; wk3r = wk1r - 2 * wk2r * wk1i; wk3i = 2 * wk2r * wk1r - wk1i; j = k + m; do { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = -wk2i * x0r - wk2r * x0i; a[j2 + 1] = -wk2i * x0i + wk2r * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } while ( j += 2, j < l+k+m ); } LEAVE(39); return; } static void cftmdl_3DNow ( const int n, const int l, float* a, float* w ) { int j, j1, j2, j3, k, k1, m, m2; float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; ENTER(36); cftmdl_3DNow_1 (n,l,a,w); LEAVE(36); ENTER(39); m = l << 2; k1 = 0; m2 = 2 * m; for ( k = m2; k < n; k += m2 ) { k1 += 2; wk2r = w[k1]; wk2i = w[k1 + 1]; wk1r = w[2*k1]; wk1i = w[2*k1 + 1]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; j = k; do { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = wk2r * x0r - wk2i * x0i; a[j2 + 1] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } while ( j += 2, j < l + k ); wk1r = w[2*k1 + 2]; wk1i = w[2*k1 + 3]; wk3r = wk1r - 2 * wk2r * wk1i; wk3i = 2 * wk2r * wk1r - wk1i; j = k + m; do { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = -wk2i * x0r - wk2r * x0i; a[j2 + 1] = -wk2i * x0i + wk2r * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } while ( j += 2, j < l+k+m ); } LEAVE(39); return; } static void rftfsub ( const int n, float* a, int nc, float* c ) { int j, k, kk, ks, m; float wkr, wki, xr, xi, yr, yi; ENTER(37); m = n >> 1; ks = 2 * nc / m; kk = ks; j = 2; k = n; do { k -= 2; nc -= ks; wkr = 0.5f - c[nc]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr - wki * xi; yi = wkr * xi + wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; kk += ks; } while ( j += 2, j < m ); LEAVE(37); return; } /* end of fft4g.c */ mppenc-1.16/src/mppenc.h0000644000175000017500000003534010524423665014437 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #ifndef MPPENC_MPPENC_H #define MPPENC_MPPENC_H #include "mppdec.h" #include "minimax.h" //#define IO_BUFFERING // activates IO-buffer (default: off) #define WIN32_MESSAGES 1 // support Windows-Messaging to Frontend // analyse_filter.c #define X_MEM 1152 // ans.c #define MAX_NS_ORDER 6 // maximum order of the Adaptive Noise Shaping Filter (IIR) #define MAX_ANS_BANDS 16 #define MAX_ANS_LINES (32 * MAX_ANS_BANDS) // maximum number of noiseshaped FFT-lines ///////// 16 * MAX_ANS_BANDS not sufficient? ////////////////// #define MS2SPAT1 0.5f #define MS2SPAT2 0.25f #define MS2SPAT3 0.125f #define MS2SPAT4 0.0625f // bitstream.c #define BUFFER_ALMOST_FULL 8192 #define BUFFER_FULL (BUFFER_ALMOST_FULL + 4352) // 34490 bit/frame 1320.3 kbps // cvd.c #define MAX_CVD_LINE 300 // maximum FFT-Index for CVD #define CVD_UNPRED 0.040f // unpredictability (cw) for CVD-detected bins, e33 (04) #define MIN_ANALYZED_IDX 12 // maximum base-frequency = 44100/MIN_ANALYZED_IDX ^^^^^^ #define MED_ANALYZED_IDX 50 // maximum base-frequency = 44100/MED_ANALYZED_IDX ^^^^^^ #define MAX_ANALYZED_IDX 900 // minimum base-frequency = 44100/MAX_ANALYZED_IDX (816 for Amnesia) // mppenc.h #define CENTER 448 // offset for centering current data in Main-array #define BLOCK 1152 // blocksize #define ANABUFFER (BLOCK + CENTER) // size of PCM-data array for analysis // psy.c #define SHORTFFT_OFFSET 168 // fft-offset for short FFT's #define PREFAC_LONG 10 // preecho-factor for long partitions // psy_tab.h #define PART_LONG 57 // number of partitions for long #define PART_SHORT (PART_LONG / 3) // number of partitions for short #define MAX_SPL 20 // maximum assumed Sound Pressure Level // quant.h #define SCFfac 0.832980664785f // = SCF[n-1]/SCF[n] // wave_in.h // fast but maybe more inaccurate, use if you need speed #if defined(__GNUC__) && !defined(__APPLE__) # define SIN(x) sinf ((float)(x)) # define COS(x) cosf ((float)(x)) # define ATAN2(x,y) atan2f ((float)(x), (float)(y)) # define SQRT(x) sqrtf ((float)(x)) # define LOG(x) logf ((float)(x)) # define LOG10(x) log10f ((float)(x)) # define POW(x,y) expf (logf(x) * (y)) # define POW10(x) expf (M_LN10 * (x)) # define FLOOR(x) floorf ((float)(x)) # define IFLOOR(x) (int) floorf ((float)(x)) # define FABS(x) fabsf ((float)(x)) #else # define SIN(x) (float) sin (x) # define COS(x) (float) cos (x) # define ATAN2(x,y) (float) atan2 (x, y) # define SQRT(x) (float) sqrt (x) # define LOG(x) (float) log (x) # define LOG10(x) (float) log10 (x) # define POW(x,y) (float) pow (x,y) # define POW10(x) (float) pow (10., (x)) # define FLOOR(x) (float) floor (x) # define IFLOOR(x) (int) floor (x) # define FABS(x) (float) fabs (x) #endif #define SQRTF(x) SQRT (x) #ifdef FAST_MATH # define TABSTEP 64 # define COSF(x) my_cos ((float)(x)) # define ATAN2F(x,y) my_atan2 ((float)(x), (float)(y)) # define IFLOORF(x) my_ifloor ((float)(x)) #else # undef TABSTEP # define COSF(x) COS (x) # define ATAN2F(x,y) ATAN2 (x,y) # define IFLOORF(x) IFLOOR (x) #endif typedef struct { float L [ANABUFFER]; float R [ANABUFFER]; float M [ANABUFFER]; float S [ANABUFFER]; } PCMDataTyp; typedef struct { float L [36]; float R [36]; } SubbandFloatTyp; typedef struct { unsigned int L [36]; unsigned int R [36]; } SubbandQuantTyp; typedef struct { float L [32]; float R [32]; float M [32]; float S [32]; } SMRTyp; typedef struct { FILE* fp; // File pointer to read data Ulong PCMOffset; // File offset of PCM data long double SampleFreq; // Sample frequency in Hz Uint BitsPerSample; // used bits per sample, 8*BytesPerSample-7 <= BitsPerSample <= BytesPerSample Uint BytesPerSample; // allocated bytes per sample Uint Channels; // Number of channels, 1...8 UintMax_t PCMBytes; // PCM Samples (in 8 bit units) UintMax_t PCMSamples; // PCM Samples per Channel Bool_t raw; // raw: headerless format } wave_t; // analy_filter.c void Analyse_Filter(const PCMDataTyp*, SubbandFloatTyp*, const int); void Analyse_Init ( float Left, float Right, SubbandFloatTyp* out, const int MaxBand ); void Klemm ( void ); // ans.c extern unsigned int NS_Order; // global Flag for Noise Shaping extern unsigned int NS_Order_L [32]; extern unsigned int NS_Order_R [32]; // order of the Adaptive Noiseshaping (0: off, 1...5: on) extern float FIR_L [32] [MAX_NS_ORDER]; extern float FIR_R [32] [MAX_NS_ORDER]; // contains FIR-Filter for NoiseShaping extern float ANSspec_L [MAX_ANS_LINES]; extern float ANSspec_R [MAX_ANS_LINES]; // L/R-masking threshold for ANS extern float ANSspec_M [MAX_ANS_LINES]; extern float ANSspec_S [MAX_ANS_LINES]; // M/S-masking threshold for ANS void Init_ANS ( void ); void NS_Analyse ( const int, const unsigned char* MS, const SMRTyp, const int* Transient ); // bitstream.c typedef struct { Uint32_t* ptr; unsigned int bit; } BitstreamPos; extern Uint32_t Buffer [BUFFER_FULL]; // buffer for bitstream file (128 KB) extern Uint32_t dword; // 32 bit-Word for Bitstream-I/O extern unsigned int Zaehler; // position counter for processed bitstream word (32 bit) extern UintMax_t BufferedBits; // counter for the number of written bits in the bitstream void FlushBitstream ( FILE* fp, const Uint32_t* buffer, size_t words32bit ); void UpdateHeader ( FILE* fp, Uint32_t Frames, Uint ValidSamples ); void WriteBits ( const Uint32_t input, const unsigned int bits ); void WriteBitsAt ( const Uint32_t input, const unsigned int bits, const BitstreamPos pos ); void GetBitstreamPos ( BitstreamPos* const pos ); // cvd.c int CVD2048 ( const float*, int* ); // fastmath.c void Init_FastMath ( void ); extern const float tabatan2 [] [2]; extern const float tabcos [] [2]; extern const float tabsqrt_ex []; extern const float tabsqrt_m [] [2]; // fft4g.c void rdft ( const int, float*, int*, float* ); void Generate_FFT_Tables ( const int, int*, float* ); // fft_routines.c void Init_FFT ( void ); void PowSpec256 ( const float*, float* ); void PowSpec1024 ( const float*, float* ); void PowSpec2048 ( const float*, float* ); void PolarSpec1024 ( const float*, float*, float* ); void Cepstrum2048 ( float* cep, const int ); // mppenc.c extern float SNR_comp_L [32]; extern float SNR_comp_R [32]; // SNR-compensation after SCF-combination and ANS-gain extern unsigned int MS_Channelmode; // global flag for enhanced functionality extern unsigned int Overflows; extern float SampleFreq; extern float Bandwidth; extern float KBD1; extern float KBD2; // psy.c extern unsigned int CVD_used; // global flag for ClearVoiceDetection (more switches for the psychoacoustic model) extern float varLtq; // variable threshold in quiet extern unsigned int tmpMask_used; // global flag for temporal masking extern float ShortThr; // factor for calculation masking threshold with transients extern float minSMR; // minimum SMR for all subbands void Init_Psychoakustik ( void ); SMRTyp Psychoakustisches_Modell ( const int, const PCMDataTyp*, int* TransientL, int* TransientR ); void TransientenCalc ( int* Transient, const int* TransientL, const int* TransientR ); void RaiseSMR ( const int, SMRTyp* ); void MS_LR_Entscheidung ( const int, unsigned char* MS, SMRTyp*, SubbandFloatTyp* ); // psy_tab.c extern int MinValChoice; // Flag for calculation of MinVal-values extern unsigned int EarModelFlag; // Flag for threshold in quiet extern float Ltq_offset; // Offset for threshold in quiet extern float Ltq_max; // maximum level for threshold in quiet extern float fftLtq [512]; // threshold in quiet (FFT) extern float partLtq [PART_LONG]; // threshold in quiet (Partitions) extern float invLtq [PART_LONG]; // inverse threshold in quiet (Partitions, long) extern float Loudness [PART_LONG]; // weighting factors for calculation of loudness extern float MinVal [PART_LONG]; // minimum quality that's adapted to the model, minval for long extern float SPRD [PART_LONG] [PART_LONG]; // tabulated spreading function extern float TMN; // Offset for purely sinusoid components extern float NMT; // Offset for purely noisy components extern float TransDetect; // minimum slewrate for transient detection extern float O_MAX; extern float O_MIN; extern float FAC1; extern float FAC2; // constants to calculate the used offset extern const float Butfly [7]; // Antialiasing to calculate the subband powers extern const float InvButfly [7]; // Antialiasing to calculate the masking thresholds extern const float iw [PART_LONG]; // inverse partition-width for long extern const float iw_short [PART_SHORT]; // inverse partition-width for short extern const int wl [PART_LONG]; // w_low for long extern const int wl_short [PART_SHORT]; // w_low for short extern const int wh [PART_LONG]; // w_high for long extern const int wh_short [PART_SHORT]; // w_high for short void Init_Psychoakustiktabellen ( void ); // quant.c extern float __invSCF [128 + 6]; // tabulated scalefactors (inverted) #define invSCF (__invSCF + 6) void Init_Skalenfaktoren ( void ); float ISNR_Schaetzer ( const float* samples, const float comp, const int res); float ISNR_Schaetzer_Trans ( const float* samples, const float comp, const int res); void QuantizeSubband ( unsigned int* qu_output, const float* input, const int res, float* errors ); void QuantizeSubbandWithNoiseShaping ( unsigned int* qu_output, const float* input, const int res, float* errors, const float* FIR ); void NoiseInjectionComp ( void ); // encode_sv7.c extern unsigned char MS_Flag [32]; // subband-wise mid/side flag extern int Res_L [32]; extern int Res_R [32]; // resolution steps of the subbands extern int SCF_Index_L [32] [3]; extern int SCF_Index_R [32] [3]; // Scalefactor-index for Bitstream void Init_SV7 ( void ); void WriteHeader_SV7 ( const unsigned int, const unsigned int, const unsigned int, const Uint32_t TotalFrames, const unsigned int SamplesRest, const unsigned int StreamVersion, const unsigned int SampleFreq ); void WriteBitstream_SV7 ( const int, const SubbandQuantTyp* ); void FinishBitstream ( void ); // huffsv7.c extern Huffman_t HuffHdr [10]; // contains tables for SV7-header extern Huffman_t HuffSCFI [ 4]; // contains tables for SV7-scalefactor select extern Huffman_t HuffDSCF [16]; // contains tables for SV7-scalefactor coding extern const Huffman_t* HuffQ [2] [8]; // points to tables for SV7-sample coding void Huffman_SV7_Encoder ( void ); // keyboard.c int WaitKey ( void ); int CheckKeyKeep ( void ); int CheckKey ( void ); // regress.c void Regression ( float* const _r, float* const _b, const float* p, const float* q ); // tags.c void Init_Tags ( void ); int FinalizeTags ( FILE* fp, unsigned int Version ); int addtag ( const char* key, size_t keylen, const unsigned char* value, size_t valuelen, int converttoutf8, int flags ); int gettag ( const char* key, char* dst, size_t len ); int CopyTags ( const char* filename ); // wave_in.c int Open_WAV_Header ( wave_t* type, const char* name ); size_t Read_WAV_Samples ( wave_t* t, const size_t RequestedSamples, PCMDataTyp* data, const ptrdiff_t offset, const float scalel, const float scaler, int* Silence ); int Read_WAV_Header ( wave_t* type ); // winmsg.c #ifdef _WIN32 int SearchForFrontend ( void ); void SendQuitMessage ( void ); void SendModeMessage ( const int ); void SendStartupMessage ( const char*, const int, const char* ); void SendProgressMessage ( const int, const float, const float ); #else # undef WIN32_MESSAGES # define WIN32_MESSAGES 0 # define SearchForFrontend() (0) # define SendQuitMessage() (void)0 # define SendModeMessage(x) (void)0 # define SendStartupMessage(x,y,s) (void)0 # define SendProgressMessage(x,y,z) (void)0 #endif /* _WIN32 */ #define MPPENC_DENORMAL_FIX_BASE ( 32. * 1024. /* normalized sample value range */ / ( (float) (1 << 24 /* first bit below 32-bit PCM range */ ) ) ) #define MPPENC_DENORMAL_FIX_LEFT ( MPPENC_DENORMAL_FIX_BASE ) #define MPPENC_DENORMAL_FIX_RIGHT ( MPPENC_DENORMAL_FIX_BASE * 0.5f ) #endif /* MPPENC_MPPENC_H */ #if 0 # define LAST_HUFFMAN 15 # define DUMP_HIGHRES #endif #if 0 # define DUMP_RES15 #endif #ifndef LAST_HUFFMAN # define LAST_HUFFMAN 7 #endif /* end of mppenc.h */ mppenc-1.16/src/wave_in.c0000644000175000017500000005520710522734510014574 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" static int init_in ( const int SampleCount, const int SampleFreq, const int Channels, const int BitsPerSample ); static size_t get_in ( void* DataPtr ); #if defined USE_OSS_AUDIO || defined USE_ESD_AUDIO || defined USE_SUN_AUDIO static void Set_Realtime ( void ) { # if defined USE_NICE seteuid ( 0 ); setpriority ( PRIO_PROCESS, getpid(), -20 ); seteuid ( getuid() ); # endif } #endif /* USE_OSS_AUDIO || USE_ESD_AUDIO || USE_SUN_AUDIO */ #define EXT(x) (0 == strcasecmp (ext, #x)) int Open_WAV_Header ( wave_t* type, const char* filename ) { const char* ext = strrchr ( filename, '.'); FILE* fp; type -> raw = 0; if ( 0 == strcmp ( filename, "-") || 0 == strcmp ( filename, "/dev/stdin") ) { fp = SETBINARY_IN ( stdin ); } #ifndef _WIN32 #ifndef NO_DEV_AUDIO else if ( 0 == strncmp ( filename, "/dev/", 5) ) { int fd; int arg; int org; fd = open (filename, O_RDONLY); if ( fd < 0 ) return -1; type->Channels = org = arg = 2; if ( -1 == ioctl ( fd, SOUND_PCM_WRITE_CHANNELS, &arg ) ) return -1; if (arg != org) return -1; type->BitsPerSample = org = arg = 16; type->BytesPerSample = 2; if ( -1 == ioctl ( fd, SOUND_PCM_WRITE_BITS, &arg ) ) return -1; if (arg != org) return -1; org = arg = AFMT_S16_LE; if ( -1 == ioctl ( fd, SNDCTL_DSP_SETFMT, &arg ) ) return -1; if ((arg & org) == 0) return -1; type->SampleFreq = org = arg = 44100.; if ( -1 == ioctl ( fd, SOUND_PCM_WRITE_RATE, &arg ) ) return -1; if ( 23.609375 * abs(arg-org) > abs(arg+org) ) // Sample frequency: Accept 40.5...48.0 kHz for 44.1 kHz return -1; type->raw = 1; type->PCMOffset = 0; type->PCMBytes = 0xFFFFFFFF; type->PCMSamples = 86400 * type->SampleFreq; fp = fdopen (fd, "rb"); Set_Realtime (); } #endif #else else if ( 0 == strncmp ( filename, "/dev/audio", 10 ) ) { int tmp; int fs = 44100; double dur = 86400.; sscanf ( filename, "%*[^:]:%u:%lf", &fs, &dur ); fp = (FILE*)-1; type -> Channels = 2; type -> BitsPerSample = 16; type -> BytesPerSample = 2; type -> SampleFreq = fs; type -> PCMOffset = 0; type -> PCMBytes = 0xFFFFFFFF; type -> PCMSamples = dur * type -> SampleFreq; type -> raw = 1; tmp = init_in ( 1152, (int) floor (type -> SampleFreq + 0.5), type -> Channels, type -> BitsPerSample ); if ( tmp ) return -1; # if defined USE_REALTIME SetPriorityClass ( GetCurrentProcess (), REALTIME_PRIORITY_CLASS ); # elif defined USE_NICE SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS ); # endif } #endif else if ( ext == NULL ) { fp = NULL; } else if ( EXT(.wav) ) { fp = fopen ( filename, "rb" ); } else if ( EXT(.wv) ) { // wavpack (www.wavpack.com) fp = pipeopen ( "wvunpack # -", filename ); } else if ( EXT(.la) ) { // lossless-audio (www.lossless-audio.com) fp = pipeopen ( "la -console #", filename ); } else if ( EXT(.raw) || EXT(.cdr) || EXT(.pcm) ) { fp = fopen ( filename, "rb" ); type->Channels = 2; type->BitsPerSample = 16; type->BytesPerSample = 2; type->SampleFreq = 44100.; type->raw = 1; type->PCMOffset = 0; type->PCMBytes = 0xFFFFFFFF; type->PCMSamples = 86400 * type->SampleFreq; } else if ( EXT(.pac) || EXT(.lpac) || EXT(.lpa) ) { fp = pipeopen ( "lpac -o -x #", filename ); } else if ( EXT(.fla) || EXT(.flac) ) { #ifdef _WIN32 stderr_printf ( "*** Install at least version 1.03 of FLAC.EXE. Thanks! ***\n\n" ); #endif fp = pipeopen ( "flac -d -s -c - < #", filename ); } else if ( EXT(.rka) || EXT(.rkau) ) { fp = pipeopen ( "rkau # -", filename ); } else if ( EXT(.sz) ) { fp = pipeopen ( "szip -d < #", filename ); } else if ( EXT(.sz2) ) { fp = pipeopen ( "szip2 -d < #", filename ); } else if ( EXT(.ofr) ) { fp = pipeopen ( "optimfrog d # -", filename ); } else if ( EXT(.ape) ) { fp = pipeopen ( "mac # - -d", filename ); } else if ( EXT(.shn) || EXT(.shorten) ) { #ifdef _WIN32 stderr_printf ( "*** Install at least version 3.4 of Shorten.exe. Thanks! ***\n\n" ); #endif fp = pipeopen ( "shorten -x # -", filename ); // Test if it's okay !!!! if ( fp == NULL ) fp = pipeopen ( "shortn32 -x # -", filename ); } else if ( EXT(.mod) ) { fp = pipeopen ( "xmp -b16 -c -f44100 --stereo -o- #", filename ); type->Channels = 2; type->BitsPerSample = 16; type->BytesPerSample = 2; type->SampleFreq = 44100.; type->raw = 1; type->PCMOffset = 0; type->PCMBytes = 0xFFFFFFFF; type->PCMSamples = 86400 * type->SampleFreq; } else { fp = NULL; } type -> fp = fp; return fp == NULL ? -1 : 0; } #undef EXT static float f0 ( const void* p ) { return (void)p, 0.; } static float f8 ( const void* p ) { return (((unsigned char*)p)[0] - 128) * 256.; } static float f16 ( const void* p ) { return ((unsigned char*)p)[0] + 256. * ((signed char*)p)[1]; } static float f24 ( const void* p ) { return ((unsigned char*)p)[0]*(1./256) + ((unsigned char*)p)[1] + 256 * ((signed char*)p)[2]; } static float f32 ( const void* p ) { return ((unsigned char*)p)[0]*(1./65536) + ((unsigned char*)p)[1]*(1./256) + ((unsigned char*)p)[2] + 256 * ((signed char*)p)[3]; } typedef float (*rf_t) (const void*); static int DigitalSilence ( void* buffer, size_t len ) { unsigned long* pl; unsigned char* pc; size_t loops; for ( pl = buffer, loops = len >> 3; loops--; pl += 2 ) if ( pl[0] | pl[1] ) return 0; for ( pc = (unsigned char*)pl, loops = len & 7; loops--; pc++ ) if ( pc[0] ) return 0; return 1; } size_t Read_WAV_Samples ( wave_t* t, const size_t RequestedSamples, PCMDataTyp* data, const ptrdiff_t offset, const float scalel, const float scaler, int* Silence ) { static const rf_t rf [5] = { f0, f8, f16, f24, f32 }; short Buffer [8 * 32/16 * BLOCK]; // read buffer, up to 8 channels, up to 32 bit size_t ReadSamples; // returns number of read samples size_t i; short* b = (short*) Buffer; char* c = (char*) Buffer; float* l = data -> L + offset; float* r = data -> R + offset; float* m = data -> M + offset; float* s = data -> S + offset; ENTER(120); // Read PCM data #ifdef _WIN32 if ( t->fp != (FILE*)-1 ) { ReadSamples = fread ( b, t->BytesPerSample * t->Channels, RequestedSamples, t->fp ); } else { while (1) { ReadSamples = get_in (b) / ( t->Channels * t->BytesPerSample ); if ( ReadSamples != 0 ) break; Sleep (10); } } #else ReadSamples = fread ( b, t->BytesPerSample * t->Channels, RequestedSamples, t->fp ); #endif *Silence = DigitalSilence ( b, ReadSamples * t->BytesPerSample * t->Channels ); // Add Null Samples if EOF is reached if ( ReadSamples != RequestedSamples ) //memset ( b + ReadSamples * t->Channels, 0, (RequestedSamples - ReadSamples) * (sizeof(short) * t->Channels) ); memset ( c + ReadSamples * t->Channels * t->BytesPerSample, t->BytesPerSample == 1 ? 0x80 : 0, (RequestedSamples - ReadSamples) * (t->BytesPerSample * t->Channels) ); // Convert to float and calculate M=(L+R)/2 and S=(L-R)/2 signals #if ENDIAN == HAVE_LITTLE_ENDIAN if ( t->BytesPerSample == 2 ) { switch ( t->Channels ) { case 1: for ( i = 0; i < RequestedSamples; i++, b++ ) { float temp = b[0] * scalel; l[i] = temp + MPPENC_DENORMAL_FIX_LEFT; r[i] = temp + MPPENC_DENORMAL_FIX_RIGHT; m[i] = (l[i] + r[i]) * 0.5f; s[i] = (l[i] - r[i]) * 0.5f; } break; case 2: for ( i = 0; i < RequestedSamples; i++, b += 2 ) { l[i] = b[0] * scalel + MPPENC_DENORMAL_FIX_LEFT; // left r[i] = b[1] * scaler + MPPENC_DENORMAL_FIX_RIGHT; // right m[i] = (l[i] + r[i]) * 0.5f; s[i] = (l[i] - r[i]) * 0.5f; } break; case 5: case 6: case 7: case 8: for ( i = 0; i < RequestedSamples; i++, b += t->Channels ) { l[i] = (0.4142 * b[0] + 0.2928 * b[1] + 0.2928 * b[3] - 0.1464 * b[4]) * scalel + MPPENC_DENORMAL_FIX_LEFT; // left r[i] = (0.4142 * b[2] + 0.2928 * b[1] + 0.2928 * b[4] - 0.1464 * b[3]) * scaler + MPPENC_DENORMAL_FIX_RIGHT; // right m[i] = (l[i] + r[i]) * 0.5f; s[i] = (l[i] - r[i]) * 0.5f; } break; default: for ( i = 0; i < RequestedSamples; i++, b += t->Channels ) { l[i] = b[0] * scalel + MPPENC_DENORMAL_FIX_LEFT; // left r[i] = b[1] * scaler + MPPENC_DENORMAL_FIX_RIGHT; // right m[i] = (l[i] + r[i]) * 0.5f; s[i] = (l[i] - r[i]) * 0.5f; } break; } } else #endif { unsigned int bytes = t->BytesPerSample; rf_t f = rf [bytes]; c = (char*)b; switch ( t->Channels ) { case 1: for ( i = 0; i < RequestedSamples; i++, c += bytes ) { float temp = f(c) * scalel; l[i] = temp + MPPENC_DENORMAL_FIX_LEFT; r[i] = temp + MPPENC_DENORMAL_FIX_RIGHT; m[i] = (l[i] + r[i]) * 0.5f; s[i] = (l[i] - r[i]) * 0.5f; } break; case 2: for ( i = 0; i < RequestedSamples; i++, c += 2*bytes ) { l[i] = f(c) * scalel + MPPENC_DENORMAL_FIX_LEFT; // left r[i] = f(c+bytes) * scaler + MPPENC_DENORMAL_FIX_RIGHT; // right m[i] = (l[i] + r[i]) * 0.5f; s[i] = (l[i] - r[i]) * 0.5f; } break; default: for ( i = 0; i < RequestedSamples; i++, c += bytes * t->Channels ) { l[i] = f(c) * scalel + MPPENC_DENORMAL_FIX_LEFT; // left r[i] = f(c+bytes) * scaler + MPPENC_DENORMAL_FIX_RIGHT; // right m[i] = (l[i] + r[i]) * 0.5f; s[i] = (l[i] - r[i]) * 0.5f; } break; } } LEAVE(120); return ReadSamples; } // read WAVE header static unsigned short Read16 ( FILE* fp ) { unsigned char buff [2]; if (fread ( buff, 1, 2, fp ) != 2 ) return -1; return buff[0] | (buff[1] << 8); } static unsigned long Read32 ( FILE* fp ) { unsigned char buff [4]; if ( fread ( buff, 1, 4, fp ) != 4 ) return -1; return (buff[0] | (buff[1] << 8)) | ((unsigned long)(buff[2] | (buff[3] << 8)) << 16); } int Read_WAV_Header ( wave_t* type ) { int bytealign; FILE* fp = type->fp; if ( type->raw ) return 0; fseek ( fp, 0, SEEK_SET ); if ( Read32 (fp) != 0x46464952 ) { // 4 Byte: check for "RIFF" stderr_printf ( Read32(fp) == -1 ? " ERROR: Empty file or no data from coprocess!\n\n" : " ERROR: 'RIFF' not found in WAVE header!\n\n"); return -1; } Read32 (fp); // 4 Byte: chunk size (ignored) if ( Read32 (fp) != 0x45564157 ) { // 4 Byte: check for "WAVE" stderr_printf ( " ERROR: 'WAVE' not found in WAVE header!\n\n"); return -1; } if ( Read32 (fp) != 0x20746D66 ) { // 4 Byte: check for "fmt " stderr_printf ( " ERROR: 'fmt ' not found in WAVE header!\n\n"); return -1; } Read32 (fp); // 4 Byte: read chunk-size (ignored) if ( Read16 (fp) != 0x0001 ) { // 2 Byte: check for linear PCM stderr_printf ( " ERROR: WAVE file has no linear PCM format!\n\n"); return -1; } type -> Channels = Read16 (fp); // 2 Byte: read no. of channels type -> SampleFreq = Read32 (fp); // 4 Byte: read sampling frequency Read32 (fp); // 4 Byte: read avg. blocksize (fs*channels*bytepersample) bytealign = Read16 (fp); // 2 Byte: read byte-alignment (channels*bytepersample) type->BitsPerSample = Read16 (fp); // 2 Byte: read bits per sample type->BytesPerSample= (type->BitsPerSample + 7) / 8; while ( 1 ) { // search for "data" if ( feof (fp) ) return -1; if ( Read16 (fp) != 0x6164 ) continue; if ( Read16 (fp) == 0x6174 ) break; } type->PCMBytes = Read32 (fp); // 4 Byte: no. of byte in file if ( feof (fp) ) return -1; // finally calculate number of samples if (type->PCMBytes >= 0xFFFFFF00 || type->PCMBytes == 0 || (Uint32_t)type->PCMBytes % (type -> Channels * type->BytesPerSample) != 0) { type->PCMSamples = 36000000 * type->SampleFreq; } else { type->PCMSamples = type->PCMBytes / bytealign; } type->PCMOffset = ftell (fp); return 0; } #ifdef _WIN32 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include #include #include #include #ifndef __MINGW32__ #include #endif #include #include #define NBLK 383 // 10 sec of audio typedef struct { int active; char* data; size_t datalen; WAVEHDR hdr; } oblk_t; static HWAVEIN Input_WAVHandle; static HWAVEOUT Output_WAVHandle; static size_t BufferBytes; static WAVEHDR whi [NBLK]; static char* data [NBLK]; static oblk_t array [NBLK]; static unsigned int NextInputIndex; static unsigned int NextOutputIndex; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// int init_in ( const int SampleCount, const int SampleFreq, const int Channels, const int BitsPerSample ) { WAVEFORMATEX pwf; MMRESULT r; int i; pwf.wFormatTag = WAVE_FORMAT_PCM; pwf.nChannels = Channels; pwf.nSamplesPerSec = SampleFreq; pwf.nAvgBytesPerSec = SampleFreq * Channels * ((BitsPerSample + 7) / 8); pwf.nBlockAlign = Channels * ((BitsPerSample + 7) / 8); pwf.wBitsPerSample = BitsPerSample; pwf.cbSize = 0; r = waveInOpen ( &Input_WAVHandle, WAVE_MAPPER, &pwf, 0, 0, CALLBACK_EVENT ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveInOpen failed: "); switch (r) { case MMSYSERR_ALLOCATED: fprintf ( stderr, "resource already allocated\n" ); break; case MMSYSERR_INVALPARAM: fprintf ( stderr, "invalid Params\n" ); break; case MMSYSERR_BADDEVICEID: fprintf ( stderr, "device identifier out of range\n" ); break; case MMSYSERR_NODRIVER: fprintf ( stderr, "no device driver present\n" ); break; case MMSYSERR_NOMEM: fprintf ( stderr, "unable to allocate or lock memory\n" ); break; case WAVERR_BADFORMAT: fprintf ( stderr, "attempted to open with an unsupported waveform-audio format\n" ); break; case WAVERR_SYNC: fprintf ( stderr, "device is synchronous but waveOutOpen was\n" ); break; default: fprintf ( stderr, "unknown error code: %#X\n", r ); break; } return -1; } BufferBytes = SampleCount * Channels * ((BitsPerSample + 7) / 8); for ( i = 0; i < NBLK; i++ ) { whi [i].lpData = data [i] = malloc (BufferBytes); whi [i].dwBufferLength = BufferBytes; whi [i].dwFlags = 0; whi [i].dwLoops = 0; r = waveInPrepareHeader ( Input_WAVHandle, whi + i, sizeof (*whi) ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveInPrepareHeader (%u) failed\n", i ); return -1; } r = waveInAddBuffer ( Input_WAVHandle, whi + i, sizeof (*whi) ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveInAddBuffer (%u) failed\n", i ); return -1; } } NextInputIndex = 0; waveInStart (Input_WAVHandle); return 0; } size_t get_in ( void* DataPtr ) { MMRESULT r; size_t Bytes; if ( whi [NextInputIndex].dwFlags & WHDR_DONE ) { Bytes = whi [NextInputIndex].dwBytesRecorded; memcpy ( DataPtr, data [NextInputIndex], Bytes ); r = waveInUnprepareHeader ( Input_WAVHandle, whi + NextInputIndex, sizeof (*whi) ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveInUnprepareHeader (%d) failed\n", NextInputIndex ); return -1; } whi [NextInputIndex].lpData = data [NextInputIndex]; whi [NextInputIndex].dwBufferLength = BufferBytes; whi [NextInputIndex].dwFlags = 0; whi [NextInputIndex].dwLoops = 0; r = waveInPrepareHeader ( Input_WAVHandle, whi + NextInputIndex, sizeof (*whi) ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveInPrepareHeader (%d) failed\n", NextInputIndex ); return -1; } r = waveInAddBuffer ( Input_WAVHandle, whi + NextInputIndex, sizeof (*whi) ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveInAddBuffer (%d) failed\n", NextInputIndex ); return -1; } NextInputIndex = (NextInputIndex + 1) % NBLK; return Bytes; } return 0; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// int init_out ( const int SampleCount, const int SampleFreq, const int Channels, const int BitsPerSample ) { WAVEFORMATEX pwf; MMRESULT r; int i; pwf.wFormatTag = WAVE_FORMAT_PCM; pwf.nChannels = Channels; pwf.nSamplesPerSec = SampleFreq; pwf.nAvgBytesPerSec = SampleFreq * Channels * ((BitsPerSample + 7) / 8); pwf.nBlockAlign = Channels * ((BitsPerSample + 7) / 8); pwf.wBitsPerSample = BitsPerSample; pwf.cbSize = 0; r = waveOutOpen ( &Output_WAVHandle, WAVE_MAPPER, &pwf, 0, 0, CALLBACK_EVENT ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveOutOpen failed\n" ); switch (r) { case MMSYSERR_ALLOCATED: fprintf ( stderr, "resource already allocated\n" ); break; case MMSYSERR_INVALPARAM: fprintf ( stderr, "invalid Params\n" ); break; case MMSYSERR_BADDEVICEID: fprintf ( stderr, "device identifier out of range\n" ); break; case MMSYSERR_NODRIVER: fprintf ( stderr, "no device driver present\n" ); break; case MMSYSERR_NOMEM: fprintf ( stderr, "unable to allocate or lock memory\n" ); break; case WAVERR_BADFORMAT: fprintf ( stderr, "attempted to open with an unsupported waveform-audio format\n" ); break; case WAVERR_SYNC: fprintf ( stderr, "device is synchronous but waveOutOpen was\n" ); break; default: fprintf ( stderr, "unknown error code: %#X\n", r ); break; } return -1; } BufferBytes = SampleCount * Channels * ((BitsPerSample + 7) / 8); for ( i = 0; i < NBLK; i++ ) { array [i].active = 0; array [i].data = malloc (BufferBytes); } NextOutputIndex = 0; return 0; } int put_out ( const void* DataPtr, const size_t Bytes ) { MMRESULT r; int i = NextOutputIndex; if ( array [i].active ) while ( ! (array [i].hdr.dwFlags & WHDR_DONE) ) Sleep (26); r = waveOutUnprepareHeader ( Output_WAVHandle, &(array [i].hdr), sizeof (array [i].hdr) ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveOutUnprepareHeader (%d) failed\n", i ); return -1; } array [i].active = 1; array [i].hdr.lpData = array [i].data; array [i].hdr.dwBufferLength = Bytes; array [i].hdr.dwFlags = 0; array [i].hdr.dwLoops = 0; memcpy ( array [i].data, DataPtr, Bytes ); r = waveOutPrepareHeader ( Output_WAVHandle, &(array [i].hdr), sizeof (array [i].hdr) ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveOutPrepareHeader (%d) failed\n", i ); return -1; } r = waveOutWrite ( Output_WAVHandle, &(array [i].hdr), sizeof (array [i].hdr) ); if ( r != MMSYSERR_NOERROR ) { fprintf ( stderr, "waveOutAddBuffer (%d) failed\n", i ); return -1; } NextInputIndex = (NextInputIndex + 1) % NBLK; return Bytes; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endif /* end of wave_in.c */ mppenc-1.16/src/config.h0000644000175000017500000000247410522734510014414 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ /* Determine Endianess of the machine */ #define HAVE_LITTLE_ENDIAN 1234 #define HAVE_BIG_ENDIAN 4321 #define ENDIAN HAVE_LITTLE_ENDIAN /* Test the fast float-to-int rounding trick works */ #define HAVE_IEEE754_FLOAT #define HAVE_IEEE754_DOUBLE /* Test the presence of a 80-bit floating point type for writing AIFF headers */ #define HAVE_IEEE854_LONGDOUBLE #ifndef MPPENC_VERSION # define MPPENC_VERSION "1.16" #endif #define MPPENC_BUILD "--Stable--" /* end of config.h */ mppenc-1.16/src/cvd.h0000644000175000017500000000030410522734510013711 0ustar bencerbencer{ static FILE* fp = NULL; static int x = 0; if ( fp == NULL ) fp = fopen ( "cvd.txt", "a" ); fprintf ( fp, "%7.3f %6.2f %7.2f\n", (x>>1)*1152./44100, res1, res2 ); x++; } mppenc-1.16/src/mppdec.h0000644000175000017500000012555110522734510014421 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ //// Macros typical for Compilers: // // __TURBOC__ Turbo-C, Borland-C // __BORLANDC__ Borland-C // __ZTC__ Zortech-C // _MSC_VER Microsoft-C // __EMX__ Eberhard Mattes EMX (GNU based) // __GNUC__ GNU C based compiler (also Cygwin) // __CYGWIN__ Cygnus Windows C-Compiler (GNU based) // __APPLE_CC__ Apple GCC (GNU based) //// Macros typical for Operating Systems // // __linux__ Linux // __bsdi__ BSDi // __FreeBSD__ FreeBSD // __NetBSD__ NetBSD // __OpenBSD__ OpenBSD // __unix__ Unix ???????? // _WIN16 16 bit-Windows // _WIN32 32 bit-Windows (WIN32 is wrong, not defined by not MSC) (also __GNUC__ + _WIN32 is possible) // _HPUX_SOURCE HP-UX // __BEOS__ BeOS // __APPLE__ Apple Mac OS X (only when using Apple GCC) // ??????? MS-DOS and relatives //// Macros typical for special conformances // System 5 Release 4 (SVr4) // System 5 ID (SVID) // POSIX 1.0 // POSIX 1.0b // X/OPEN // BSD 4.3 // BSD 4.4 // ANSI // Macros to manipulate Sockets + Files in one, in (+0x4000) // output times TIME/TIME_T/DTIME #ifndef MPPDEC_MPPDEC_H #define MPPDEC_MPPDEC_H //// optimization/feature defines ////////////////////////////////// #ifndef NOT_INCLUDE_CONFIG_H # include "config.h" #endif #include "./mpp.h" //// portable system includes ////////////////////////////////////// #include #include #include #include #include #include #include #include //// system dependent system includes ////////////////////////////// // low level I/O, where are prototypes and constants? #if defined _WIN32 || defined __TURBOC__ || defined __ZTC__ || defined _MSC_VER # include # include # include # include # include #elif defined __unix__ || defined __linux__ || defined __APPLE__ # include # include # include # include # include # include #else // .... add Includes for new Operating System here (with prefix: #elif defined) # include # include # include # include #endif #if defined __linux__ # include #elif defined __FreeBSD__ # include #elif defined _MSC_VER # include #endif #if defined _WIN32 # undef USE_OSS_AUDIO # undef USE_ESD_AUDIO # undef USE_SUN_AUDIO #else # undef USE_WIN_AUDIO #endif #if defined __APPLE__ # undef USE_OSS_AUDIO # undef USE_SUN_AUDIO # undef USE_WIN_AUDIO # undef USE_NICE # undef USE_REALTIME # undef USE_ASM # undef USE_ESD_AUDIO # define NO_DEV_AUDIO # undef ENDIAN # define ENDIAN HAVE_BIG_ENDIAN #endif #if defined __TURBOC__ # undef USE_OSS_AUDIO # undef USE_ESD_AUDIO # undef USE_SUN_AUDIO # undef USE_NICE # undef USE_REALTIME #endif #if defined USE_DIET || defined MAKE_24BIT || defined MAKE_32BIT # undef USE_ESD_AUDIO #endif #if defined MAKE_16BIT || defined MAKE_24BIT || defined MAKE_32BIT # undef USE_ASM #endif #if INT_MAX < 2147483647L # undef USE_ASM #endif // sound card #if defined USE_OSS_AUDIO # include # include # if defined __linux__ // the standard is that this file is stored somewhere on the hard disk # include # elif defined __bsdi_ || defined __FreeBSD__ # include # elif defined __NetBSD__ || defined __OpenBSD__ # include # elif defined __APPLE__ && defined __MACH__ # include # else # include # endif #endif /* USE_OSS_AUDIO */ #if defined USE_ESD_AUDIO # include #endif #if defined USE_SUN_AUDIO # include #endif #ifdef MPP_ENCODER # undef USE_HTTP #endif #ifdef USE_HTTP # ifdef _WIN32 # include # else # include # endif #endif #if defined USE_WIN_AUDIO # include # define WINAUDIO_FD ((FILE_T)-128) #elif defined USE_IRIX_AUDIO # define IRIXAUDIO_FD ((FILE_T)-127) #endif #define NULL_FD ((FILE_T)-126) #if defined USE_NICE && !defined _WIN32 # include #endif // scheduler stuff #if defined USE_REALTIME && !defined _WIN32 # include #endif #ifndef O_BINARY # ifdef _O_BINARY # define O_BINARY _O_BINARY # else # define O_BINARY 0 # endif #endif #if defined _WIN32 || defined __TURBOC__ # define strncasecmp(__s1,__s2,__n) strnicmp ((__s1), (__s2), (__n)) # define strcasecmp(__s1,__s2) stricmp ((__s1), (__s2)) # define MKDIR(__dir,__attr) mkdir ((__dir)) #else # define MKDIR(__dir,__attr) mkdir ((__dir), (__attr)) #endif #if defined _WIN32 # include # define snprintf _snprintf # define getcwd(__buff,__len) _getcwd ((__buff), (__len)) # define sleep(__sec) Sleep ((__sec) * 1000) #endif #if defined _WIN32 # define TIME_T long # define TIME(__x) time ( &(__x) ) # define DTIME(__x,__y) ( (double)(__y) - (__x) ) #else # define TIME_T struct timeval # define TIME(__x) gettimeofday ( &(__x), NULL ) # define DTIME(__x,__y) ( ((double)(__y).tv_sec - (__x).tv_sec) + 1.e-6 * ((double)(__y).tv_usec - (__x).tv_usec) ) #endif #if defined __GNUC__ # define inline __inline__ # define restrict #elif defined _WIN32 # define inline __inline # define restrict #else # define inline # define restrict #endif //// Binary/Low-Level-IO /////////////////////////////////////////// // // All file I/O is basicly handled via an ANSI file pointer (type: FILE*) in // FILEIO-Mode 1 and via a POSIX file descriptor (type: int) in // FILEIO-Mode 2 and 3. // // Some operations are only available via the POSIX interface (fcntl, setmode, // ...) so we need a function to get the file descriptor from a file pointer. // In FILEIO-Mode 2 and 3 this is a dummy function because we are always working // with these file descriptors. // #if FILEIO == 1 # if defined __BORLANDC__ || defined _WIN32 # define FILENO(__fp) _fileno ((__fp)) # elif defined __CYGWIN__ || defined __TURBOC__ || defined __unix__ || defined __EMX__ || defined _MSC_VER # define FILENO(__fp) fileno ((__fp)) # else # define FILENO(__fp) fileno ((__fp)) # endif #else # define FILENO(__fd) (__fd) #endif // // If we have access to a file via file name, we can open the file with an // additional "b" or a O_BINARY within the (f)open function to get a // transparent untranslated data stream which is necessary for audio bitstream // data and also for PCM data. If we are working with // stdin/stdout/FILENO_STDIN/FILENO_STDOUT we can't open the file with these // attributes, because the files are already open. So we need a non // standardized sequence to switch to this mode (not necessary for Unix). // Mostly the sequence is the same for incoming and outgoing streams, but only // mostly so we need one for IN and one for OUT. // Macros are called with the file pointer and you get back the untransalted file // pointer which can be equal or different from the original. // #if defined __EMX__ # define SETBINARY_IN(__fp) (_fsetmode ( (__fp), "b" ), (__fp)) # define SETBINARY_OUT(__fp) (_fsetmode ( (__fp), "b" ), (__fp)) #elif defined __TURBOC__ || defined __BORLANDC__ # define SETBINARY_IN(__fp) (setmode ( FILENO ((__fp)), O_BINARY ), (__fp)) # define SETBINARY_OUT(__fp) (setmode ( FILENO ((__fp)), O_BINARY ), (__fp)) #elif defined __CYGWIN__ # define SETBINARY_IN(__fp) (setmode ( FILENO ((__fp)), _O_BINARY ), (__fp)) # define SETBINARY_OUT(__fp) (setmode ( FILENO ((__fp)), _O_BINARY ), (__fp)) #elif defined _WIN32 # define SETBINARY_IN(__fp) (_setmode ( FILENO ((__fp)), _O_BINARY ), (__fp)) # define SETBINARY_OUT(__fp) (_setmode ( FILENO ((__fp)), _O_BINARY ), (__fp)) #elif defined _MSC_VER # define SETBINARY_IN(__fp) (setmode ( FILENO ((__fp)), O_BINARY ), (__fp)) # define SETBINARY_OUT(__fp) (setmode ( FILENO ((__fp)), O_BINARY ), (__fp)) #elif defined __unix__ # define SETBINARY_IN(__fp) (__fp) # define SETBINARY_OUT(__fp) (__fp) #elif 0 # define SETBINARY_IN(__fp) (freopen ( NULL, "rb", (__fp) ), (__fp)) # define SETBINARY_OUT(__fp) (freopen ( NULL, "wb", (__fp) ), (__fp)) #else # define SETBINARY_IN(__fp) (__fp) # define SETBINARY_OUT(__fp) (__fp) #endif // file I/O using ANSI buffered file I/O via file pointer FILE* (fopen, fread, fwrite, fclose) #if FILEIO == 1 # define OFF_T signed long # define FILE_T FILE* # define OPEN(name) fopen (name, "rb" ) # define OPENRW(name) fopen (name, "r+b") # define CREATE(name) fopen (name, "wb" ) # define INVALID_FILEDESC NULL # define CLOSE(fp) fclose (fp) // CLOSE returns -1 on error, otherwise 0 # define READ(fp,ptr,len) fread (ptr, 1, len, fp) // READ returns -1 or 0 on error/EOF, otherwise > 0 # define READ1(fp,ptr) fread (ptr, 1, 1, fp) // READ returns -1 or 0 on error/EOF, otherwise > 0 # define WRITE(fp,ptr,len) fwrite (ptr, 1, len, fp) // WRITE returns -1 or 0 on error/EOF, otherwise > 0 # define SEEK(fp,offs,lbl) fseek (fp, offs, lbl) // SEEK returns -1 on error, otherwise >= 0 # define FILEPOS(fp) ftell (fp) // FILEPOS returns -1 on error, otherwise >= 0 # define STDIN stdin # define STDOUT stdout # define STDERR stderr # define FDOPEN(fd,mode) fdopen (fd, mode) # define UNBUFFER(fp) setvbuf(fp, NULL, _IONBF, 0 ) # define FLUSH(fp) fflush (fp) #endif /* FILEIO==1 */ // file I/O using POSIX unbuffered file I/O via file descriptors (open, read, write, close) #if FILEIO == 2 # ifdef WIN32 # define OFF_T _off_t # else # define OFF_T off_t # endif # define FILE_T int # define OPEN(name) open (name, O_RDONLY|O_BINARY) # define OPENRW(name) open (name, O_RDWR |O_BINARY) # define CREATE(name) open (name, O_WRONLY|O_BINARY|O_TRUNC|O_CREAT, 0644) # define INVALID_FILEDESC (-1) # define CLOSE(fd) close (fd) // CLOSE returns -1 on error, otherwise 0 # if defined HAVE_INCOMPLETE_READ # define READ(fd,ptr,len) complete_read (fd, ptr, len) // READ returns -1 or 0 on error/EOF, otherwise > 0 # else # define READ(fd,ptr,len) (size_t)read (fd, ptr, len)// READ returns -1 or 0 on error/EOF, otherwise > 0 # endif # define READ1(fd,ptr) (size_t)read (fd, ptr, 1) // READ returns -1 or 0 on error/EOF, otherwise > 0 # define WRITE(fd,ptr,len) (size_t)write (fd, ptr, len)// WRITE returns -1 or 0 on error/EOF, otherwise > 0 # define SEEK(fd,offs,lbl) lseek (fd, offs, lbl) // SEEK returns -1 on error, otherwise >= 0 # define FILEPOS(fd) lseek (fd, 0L, SEEK_CUR) // FILEPOS returns -1 on error, otherwise >= 0 # define STDIN 0 # define STDOUT 1 # define STDERR 2 # define FDOPEN(fd,mode) (fd) # define UNBUFFER(fd) (void)(fd) # define FLUSH(fd) (void)(fd) #endif /* FILEIO==2 */ // file I/O using Turbo-C lowest level unbuffered file I/O via file descriptors (_open, _read, _write, _close) #if FILEIO == 3 # define OFF_T signed long # define FILE_T int # define OPEN(name) _open (name, O_RDONLY) # define OPENRW(name) _open (name, O_RDWR ) # define CREATE(name) _creat(name, 0) # define INVALID_FILEDESC (-1) # define CLOSE(fd) _close (fd) // CLOSE returns -1 on error, otherwise 0 # define READ(fd,ptr,len) (size_t)_read (fd, ptr, len)// READ returns -1 or 0 on error/EOF, otherwise > 0 # define READ1(fd,ptr) (size_t)_read (fd, ptr, 1) // READ returns -1 or 0 on error/EOF, otherwise > 0 # define WRITE(fd,ptr,len) (size_t)_write (fd, ptr, len)// WRITE returns -1 or 0 on error/EOF, otherwise > 0 # define SEEK(fd,offs,lbl) lseek (fd, offs, lbl) // SEEK returns -1 on error, otherwise >= 0 # define FILEPOS(fd) lseek (fd, 0L, SEEK_CUR) // FILEPOS returns -1 on error, otherwise >= 0 # define STDIN 0 # define STDOUT 1 # define STDERR 2 # undef SETBINARY_IN # undef SETBINARY_OUT # define SETBINARY_IN(fd) (fd) # define SETBINARY_OUT(fd) (fd) # define FDOPEN(fd,mode) (fd) # define UNBUFFER(fd) (void)(fd) # define FLUSH(fd) (void)(fd) #endif /* FILEIO==3 */ #if FILEIO != 2 && defined USE_HTTP # error HTTP can only be used by FILEIO==2 #endif #if defined _WIN32 || defined __BEOS__ # define WRITE_SOCKET(sock,ptr,len) send (sock, ptr, len, 0) # define READ_SOCKET(sock,ptr,len) recv (sock, ptr, len, 0) #else # define WRITE_SOCKET(sock,ptr,len) write (sock, ptr, len) # define READ_SOCKET(sock,ptr,len) read (sock, ptr, len) #endif #ifdef _WIN32 # define POPEN_READ_BINARY_OPEN(cmd) _popen ((cmd), "rb") # define POPEN_WRITE_BINARY_OPEN(cmd) _popen ((cmd), "wb") # define PCLOSE(fp) _pclose(fp) #else # define POPEN_READ_BINARY_OPEN(cmd) popen ((cmd), "r") # define POPEN_WRITE_BINARY_OPEN(cmd) popen ((cmd), "w") # define PCLOSE(fp) pclose(fp) #endif #if defined _WIN32 # define STRUCT_STAT struct _stat # define STAT_CMD(f,s) _stat (f, s) #else # define STRUCT_STAT struct stat # define STAT_CMD(f,s) stat (f, s) #endif /* WIN32 */ #ifndef S_ISDIR # if defined S_IFDIR # define S_ISDIR(x) ((x) & S_IFDIR) # elif defined _S_IFDIR # define S_ISDIR(x) ((x) & _S_IFDIR) # elif defined __S_IFDIR # define S_ISDIR(x) ((x) & __S_IFDIR) # else # error Cannot find a way to test for a directory # endif #endif /* !S_ISDIR */ #if defined __unix__ || defined __bsdi__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __TURBOC__ || defined _WIN32 || defined __APPLE__ # define ISATTY(fd) isatty (fd) #else # define ISATTY(fd) 0 #endif // Path separator #if defined __unix__ || defined __bsdi__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __APPLE__ # define PATH_SEP '/' # define DRIVE_SEP '\0' # define EXE_EXT "" # define DEV_NULL "/dev/null" # define ENVPATH_SEP ':' #elif defined _WIN32 || defined __TURBOC__ || defined __ZTC__ || defined _MSC_VER # define PATH_SEP '\\' # define DRIVE_SEP ':' # define EXE_EXT ".exe" # define DEV_NULL "\\nul" # define ENVPATH_SEP ';' #else # define PATH_SEP '/' // Amiga: C:/ # define DRIVE_SEP ':' # define EXE_EXT "" # define DEV_NULL "nul" # define ENVPATH_SEP ';' #endif // maximum length of file names #ifndef PATHLEN_MAX # if defined FILENAME_MAX # define PATHLEN_MAX FILENAME_MAX # elif INT_MAX < 2147483647L # define PATHLEN_MAX 128 # else # define PATHLEN_MAX 1024 # endif #endif /* !PATHLEN_MAX */ #ifdef _WIN32 # define TitleBar(text) SetConsoleTitle (text) #else # define TitleBar(text) (void) (text) #endif //// constants ///////////////////////////////////////////////////// #ifdef USE_SV8 # define MAX_SV "SV8" #else # define MAX_SV "SV7" #endif #ifdef USE_ASM # define BUILD "3DNOW!/SSE" #else # define BUILD "" #endif #define COPYRIGHT "(C) 1999-2003 Buschmann/Klemm/Piecha/Wolf" #define DECODER_DELAY (512 - 32 + 1) #define BLK_SIZE (36 * 32) //// logging defines, for development only ///////////////////////// #if defined _WIN32 || defined __TURBOC__ # define LOGPATH ".\\" # define MUSICPATH "D:\\AUDIO\\" #else # define LOGPATH "./" # define MUSICPATH "/Archive/Audio/" #endif #define _(x) (void)(fprintf(stderr,"<%d>\n",(x)),fflush(stderr)) #ifdef DEBUG # define REP(x) (void)(x) #else # define REP(x) #endif //// numerical constants /////////////////////////////////////////// #define C00 (Float) 0.500000000000000000000000L // Cxx = 0.5 / cos (xx*M_PI/64) #define C01 (Float) 0.500602998235196301334178L #define C02 (Float) 0.502419286188155705518560L #define C03 (Float) 0.505470959897543659956626L #define C04 (Float) 0.509795579104159168925062L #define C05 (Float) 0.515447309922624546962323L #define C06 (Float) 0.522498614939688880640101L #define C07 (Float) 0.531042591089784174473998L #define C08 (Float) 0.541196100146196984405269L #define C09 (Float) 0.553103896034444527838540L #define C10 (Float) 0.566944034816357703685831L #define C11 (Float) 0.582934968206133873665654L #define C12 (Float) 0.601344886935045280535340L #define C13 (Float) 0.622504123035664816182728L #define C14 (Float) 0.646821783359990129535794L #define C15 (Float) 0.674808341455005746033820L #define C16 (Float) 0.707106781186547524436104L #define C17 (Float) 0.744536271002298449773679L #define C18 (Float) 0.788154623451250224773056L #define C19 (Float) 0.839349645415527038721463L #define C20 (Float) 0.899976223136415704611808L #define C21 (Float) 0.972568237861960693780520L #define C22 (Float) 1.060677685990347471323668L #define C23 (Float) 1.169439933432884955134476L #define C24 (Float) 1.306562964876376527851784L #define C25 (Float) 1.484164616314166277319733L #define C26 (Float) 1.722447098238333927796261L #define C27 (Float) 2.057781009953411550808880L #define C28 (Float) 2.562915447741506178719328L #define C29 (Float) 3.407608418468718785698107L #define C30 (Float) 5.101148618689163857960189L #define C31 (Float)10.190008123548056810994678L #define SS05 (Float) 0.840896415253714543018917L // 0.5^0.25 #ifndef M_PI # define M_PI 3.1415926535897932384626433832795029 // 4*atan(1) # define M_PIl 3.1415926535897932384626433832795029L # define M_LN2 0.6931471805599453094172321214581766 // ln(2) # define M_LN2l 0.6931471805599453094172321214581766L # define M_LN10 2.3025850929940456840179914546843642 // ln 10 */ # define M_LN10l 2.3025850929940456840179914546843642L #endif //// 'Cdecl' forces the use of standard C/C++ calling convention /////// #if defined _WIN32 # define Cdecl __cdecl #elif defined __ZTC__ # define Cdecl _cdecl #elif defined __TURBOC__ # define Cdecl cdecl #else # define Cdecl #endif //// expect handling of GCC //////////////////////////////////////// #ifdef __GNUC__ # if __GNUC__ < 3 # define __builtin_expect(cond,exp) (cond) # ifndef expect # define expect(cond,exp) __builtin_expect(cond,exp) # endif # else # ifndef expect # define expect(cond,exp) __builtin_expect(cond,exp) # endif # endif #else # define __builtin_expect(cond,exp) (cond) # ifndef expect # define expect(cond,exp) __builtin_expect(cond,exp) # endif #endif #define if0(x) if (expect(x,0)) #define if1(x) if (expect(x,1)) #define while0(x) while (expect(x,0)) #define while1(x) while (expect(x,1)) #ifndef __GNUC__ # define __attribute__(x) #else # define __attribute__(x) #endif //// Remaining macros ////////////////////////////////////////////// // selects input buffer size and some constants needed for input buffer handling #ifndef IBUFLOG2 // must be at least 10 (bitrate always <626 kbps) or better 11 ( <1253 kbps) # if INT_MAX < 2147483647L # define IBUFLOG2 11 // 8 KByte buffer, possible 11...13 (32 KByte limit) # else # define IBUFLOG2 21 // 8 MByte buffer, possible 11...29 ( 2 GByte limit) # endif #endif #define IBUFSIZE ((size_t)(1LU<<(IBUFLOG2))) #define IBUFSIZE2 ((size_t)((IBUFSIZE)/2)) #define IBUFMASK ((size_t)((IBUFSIZE)-1)) // save memory space for 16 bit compiler (data + stack < 64 KByte) #if INT_MAX < 2147483647L # if VIRT_SHIFT > 6 # undef VIRT_SHIFT # define VIRT_SHIFT 6 # endif # if IBUFLOG2 > 11 # undef IBUFLOG2 # define IBUFLOG2 11 # endif # define USE_HUFF_PACK # define USE_ARRAY_PACK #endif // generate a macro which contains information about compile time settings #define STR(x) _STR(x) #define _STR(x) #x #ifdef NDEBUG # define T1 "" #else # define T1 "DEBUG " #endif #if defined USE_OSS_AUDIO || defined USE_ESD_AUDIO || defined USE_SUN_AUDIO || defined USE_WIN_AUDIO # define T2 "SND " #else # define T2 "" #endif #ifdef USE_NICE # define T3 "NICE " #else # define T3 "" #endif #if defined USE_REALTIME # define T4 "RT " #else # define T4 "" #endif #ifdef HAVE_IEEE754_FLOAT # define T5 "IEEE " #else # define T5 "" #endif #define T6 "IO=" STR(FILEIO) " " #ifdef USE_HUFF_PACK # define T7 "H-PCK " #else # define T7 "" #endif #ifdef USE_ARRAY_PACK # define T8 "A-PCK " #else # define T8 "" #endif #define T9 "SHFT=" STR(VIRT_SHIFT) " " #define T10 "IBUF=" STR(IBUFLOG2) " " #define COMPILER_FLAGS T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 // align a pointer by maybe incrementing it #define ALIGN(ptr,alignment) \ (void*)((((ptrdiff_t)(ptr)) & (-(ptrdiff_t)(alignment))) + (alignment)) // aligns a pointer with alignment, the source array should be at least alignment-1 Bytes longer than the needed length //// Simple types ////////////////////////////////////////////////// #if CHAR_BIT == 8 && SCHAR_MAX == 127L typedef unsigned char Uint8_t; // guaranteed 8 bit unsigned integer type with range 0...255 typedef signed char Int8_t; // guaranteed 8 bit signed integer type with range -128...127 #else # error No 8 bit int type found. Tested: char #endif #if SHRT_MAX == 32767L typedef unsigned short int Uint16_t; // guaranteed 16 bit unsigned integer type with range 0...65535 typedef signed short int Int16_t; // guaranteed 16 bit signed integer type with range -32768...32767 #else # error No 16 bit int type found. Tested: short #endif #if INT_MAX == 2147483647L typedef unsigned int Uint32_t; // guaranteed 32 bit unsigned integer type with range 0...4294967295 typedef signed int Int32_t; // guaranteed 32 bit signed integer type with range -2147483648...2147483647 #elif LONG_MAX == 2147483647L typedef unsigned long int Uint32_t; // guaranteed 32 bit unsigned integer type with range 0...4294967295 typedef signed long int Int32_t; // guaranteed 32 bit signed integer type with range -2147483648...2147483647 #else # error No 32 bit int type found. Tested: int, long #endif #if defined __C99__ // C9x has a type which is exact 64 bit typedef int64_t Int64_t; typedef uint64_t Uint64_t; typedef intmax_t IntMax_t; typedef uintmax_t UintMax_t; # define IntMax_MIN -9223372036854775808 # define IntMax_MAX 9223372036854775807 # define UintMax_MAX 18446744073709551615 # define UintMAX_FP(x) (long double)(x) #elif defined __GNUC__ // GCC uses long long as 64 bit typedef signed long long Int64_t; typedef unsigned long long Uint64_t; typedef signed long long IntMax_t; typedef unsigned long long UintMax_t; # define IntMax_MIN -9223372036854775808LL # define IntMax_MAX 9223372036854775807LL # define UintMax_MAX 18446744073709551615LLU # define UintMAX_FP(x) (long double)(x) #elif defined _MSC_VER typedef signed __int64 Int64_t; typedef unsigned __int64 Uint64_t; typedef signed __int64 IntMax_t; typedef unsigned __int64 UintMax_t; # define IntMax_MIN -9223372036854775808I64 # define IntMax_MAX 9223372036854775807I64 # define UintMax_MAX 18446744073709551615UI64 # define UintMAX_FP(x) (long double)(IntMax_t)(x) #elif defined LLONG_MAX // long long (when existing) is normally 64 bit typedef signed long long Int64_t; typedef unsigned long long Uint64_t; typedef signed long long IntMax_t; typedef unsigned long long UintMax_t; # define IntMax_MIN -9223372036854775808LL # define IntMax_MAX 9223372036854775807LL # define UintMax_MAX 18446744073709551615LLU # define UintMAX_FP(x) (long double)(x) #elif LONG_MAX > 0xFFFFFFFFLU // long is longer than 33 bit, assume 64 bit typedef signed long Int64_t; typedef unsigned long Uint64_t; typedef signed long IntMax_t; typedef unsigned long UintMax_t; # define IntMax_MIN -9223372036854775808L # define IntMax_MAX 9223372036854775807L # define UintMax_MAX 18446744073709551615LU # define UintMAX_FP(x) (long double)(x) #elif defined _WIN32 // Microsoft and Intel call it __int64 typedef signed __int64 Int64_t; typedef unsigned __int64 Uint64_t; typedef signed __int64 IntMax_t; typedef unsigned __int64 UintMax_t; # define IntMax_MIN -9223372036854775808I64 # define IntMax_MAX 9223372036854775807I64 # define UintMax_MAX 18446744073709551615UI64 # define UintMAX_FP(x) (long double)(IntMax_t)(x) #else # define NO_INT64_T // no type mapped to 64 bit integer typedef signed long IntMax_t; typedef unsigned long UintMax_t; # define IntMax_MIN -2147483648L # define IntMax_MAX 2147483647L # define UintMax_MAX 4294967295LU # define UintMAX_FP(x) (long double)(x) #endif #if defined _WIN32 && !defined __GNUC__ && !defined __C99__ typedef signed long ssize_t; #endif #ifdef USE_ARRAY_PACK typedef signed char Bool_t; // ==0: false, !=0: true #else typedef signed int Bool_t; // ==0: false, !=0: true #endif typedef Uint32_t Ibuf_t; // type for input buffer, currently this type must be 32 bit typedef signed char Schar; // at least -127...+127 typedef unsigned char Uchar; // at least 0...255 typedef signed short int Short; // at least -32767...+32767, memory economic type typedef unsigned short int Ushort; // at least 0...65535, memory economic type typedef signed int Int; // at least -32767...+32767, fast type typedef unsigned int Uint; // at least 0...65535, fast type typedef signed long int Long; // at least -2147483647...+2147483647, but more is better typedef unsigned long int Ulong; // at least 0...4294967295, but more is better // size_t; // size of memory objects // ptrdiff_t; // pointer differences, may be larger than size_t typedef float Float32_t; // guaranteed 32 bit floating point type typedef double Float64_t; // guaranteed 64 bit floating point type typedef float Float; // fastest floating point type, memory economic (used for all PCM calculations) #define SIZEOF_Float 4 // size of the type 'Float' in sizeof units typedef double Double; // floating point with extended precision (more than 32 bit mantissa) typedef long double Ldouble; // most exact floating point format typedef Int16_t Int2x16_t [2]; typedef Int32_t Int2x32_t [2]; #if defined MAKE_16BIT || defined MAKE_24BIT || defined MAKE_32BIT # ifdef NO_INT64_T # error No 64 bit int type found, needed for HQ 16...32 bit output # endif typedef Int2x32_t Int2xSample_t; # if defined MAKE_32BIT # define SAMPLE_SIZE 32 # define PROG_NAME "mppdec32" # define SAMPLE_SIZE_STRING " (32 bit HQ)" # define Write_PCM(fd,p,b) Write_PCM_HQ_2x32bit ( fd, p, b ) # define Synthese_Filter(Stream,offset,Vi,Yi,ch) \ Synthese_Filter_32_C ( Stream, offset, Vi, Yi, ch ) # undef USE_ESD_AUDIO # elif defined MAKE_24BIT # define SAMPLE_SIZE 24 # define PROG_NAME "mppdec24" # define SAMPLE_SIZE_STRING " (24 bit HQ)" # define Write_PCM(fd,p,b) Write_PCM_HQ_2x24bit ( fd, p, b ) # define Synthese_Filter(Stream,offset,Vi,Yi,ch) \ Synthese_Filter_32_C ( Stream, offset, Vi, Yi, ch ) # undef USE_ESD_AUDIO # elif defined MAKE_16BIT # define SAMPLE_SIZE 16 # define PROG_NAME "mppdec16" # define SAMPLE_SIZE_STRING " (16 bit HQ)" # define Write_PCM(fd,p,b) Write_PCM_HQ_2x16bit ( fd, p, b ) # define Synthese_Filter(Stream,offset,Vi,Yi,ch) \ Synthese_Filter_32_C ( Stream, offset, Vi, Yi, ch ) # endif #else typedef Int2x16_t Int2xSample_t; # define SAMPLE_SIZE 16 # define PROG_NAME "mppdec" # define SAMPLE_SIZE_STRING "" # define Write_PCM(fd,p,b) Write_PCM_2x16bit ( fd, p, b ) # ifdef USE_ASM # define Synthese_Filter(Stream,offset,Vi,Yi,ch) \ Synthese_Filter_16 ( Stream, offset, Vi, Yi ) # else # define Synthese_Filter(Stream,offset,Vi,Yi,ch) \ Synthese_Filter_16_C ( Stream, offset, Vi, Yi ) # endif /* USE_ASM */ #endif //// More complex types //////////////////////////////////////////// typedef struct { Int L [36]; Int R [36]; } Quant_t ; typedef struct { Uint L; Uint R; } UPair_t ; typedef struct { Int L; Int R; } Pair_t ; typedef struct { #ifdef USE_ARRAY_PACK Schar L; Schar R; #else Int L; Int R; #endif } CPair_t ; typedef Float FloatArray [32]; typedef UPair_t UPairArray [32]; typedef Pair_t PairArray [32]; typedef CPair_t CPairArray [32]; typedef Float SCFTriple [3]; typedef struct { #ifndef MPP_ENCODER Uint32_t Code; // >=32 bit # ifdef USE_HUFF_PACK Schar Value; // >= 7 bit Uchar Length; // >= 4 bit # else Int Value; Uint Length; # endif #else # ifdef USE_HUFF_PACK Uint8_t Length; // >= 4 bit Uint8_t ___; Uint16_t Code; // >= 14 bit # else Uint Code; Uint Length; # endif #endif } Huffman_t ; typedef struct { Uint Code : 16; // >= 14 bit Uint Length : 8; // >= 4 bit } HuffSrc_t ; typedef struct { OFF_T FileSize; Int GenreNo; Int TrackNo; char Genre [128]; char Year [ 20]; char Track [ 8]; char Title [256]; char Artist [256]; char Album [256]; char Comment [512]; } TagInfo_t ; typedef void (*SyntheseFilter16_t) ( Int2x16_t* Stream, Int* const offset, Float* Vi, const FloatArray* Yi ); typedef void (*SyntheseFilter32_t) ( Int2x32_t* Stream, Int* const offset, Float* Vi, const FloatArray* Yi, int ch ); typedef Int (*HeaderWriter_t) ( FILE_T outputFile, Ldouble SampleFreq, Uint BitsPerSample, Uint Channels, Ulong SamplesPerChannel ); #if defined MAKE_16BIT || defined MAKE_24BIT || defined MAKE_32BIT typedef struct { const Float* FilterCoeff; Uint64_t Mask; Float64_t Add; Float Dither; Uint32_t Overdrives; Int64_t MaxLevel; Bool_t NoShaping; Float ErrorHistory [2] [16]; // max. 2 channels, 16th order Noise shaping Float DitherHistory [2] [16]; Int32_t LastRandomNumber [2]; } dither_t; #else typedef struct { Uint32_t Overdrives; Int32_t MaxLevel; } dither_t; #endif //// Variables ///////////////////////////////////////////////////// // decode.c extern Ibuf_t InputBuff [IBUFSIZE]; // read buffer for the MP+ data stream extern size_t InputCnt; // current offset in this buffer // huffsv7.c extern Huffman_t HuffHdr [10]; extern Huffman_t HuffSCFI [ 4]; extern Huffman_t HuffDSCF [16]; extern Huffman_t HuffQ1 [2] [ 3*3*3]; extern Huffman_t HuffQ2 [2] [ 5*5]; extern Huffman_t HuffQ3 [2] [ 7]; extern Huffman_t HuffN3 [2] [ 7*7]; extern Huffman_t HuffQ4 [2] [ 9]; extern Huffman_t HuffQ5 [2] [15]; extern Huffman_t HuffQ6 [2] [31]; extern Huffman_t HuffQ7 [2] [63]; extern Huffman_t HuffN8 [2][127]; extern const Huffman_t* HuffQ [2] [ 8]; extern const Huffman_t* HuffN [2] [ 9]; extern Uint8_t LUT1_0 [1<< 6]; extern Uint8_t LUT1_1 [1<< 9]; extern Uint8_t LUT2_0 [1<< 7]; extern Uint8_t LUT2_1 [1<<10]; extern Uint8_t LUT3_0 [1<< 4]; extern Uint8_t LUT3_1 [1<< 5]; extern Uint8_t LUT4_0 [1<< 4]; extern Uint8_t LUT4_1 [1<< 5]; extern Uint8_t LUT5_0 [1<< 6]; extern Uint8_t LUT5_1 [1<< 8]; extern Uint8_t LUT6_0 [1<< 7]; extern Uint8_t LUT6_1 [1<< 7]; extern Uint8_t LUT7_0 [1<< 8]; extern Uint8_t LUT7_1 [1<< 8]; extern Uint8_t LUTDSCF [1<< 6]; // huffsv46.c extern const Huffman_t* Entropie [18]; extern const Huffman_t* Region [32]; extern Huffman_t SCFI_Bundle [ 8]; extern Huffman_t DSCF_Entropie [13]; // mppdec.c extern Float Y_L [36] [32]; extern Float Y_R [36] [32]; extern CPair_t SCF_Index [3] [32]; // Scalefactor extern CPair_t Res [32]; // resolution steps of the subbands extern Quant_t Q [32]; // quantized samples extern CPair_t SCFI [32]; // transfer order of the SCF extern Bool_t MS_Band [32]; // subband-wise flag for M/S-signal guidance extern Bool_t MS_used; // global flag for M/S-signal guidance extern Bool_t IS_used; #define LITTLE 0 #define BIG 1 extern Bool_t output_endianess; #if ENDIAN == HAVE_LITTLE_ENDIAN # define machine_endianess LITTLE #elif ENDIAN == HAVE_BIG_ENDIAN # define machine_endianess BIG #endif // requant.c extern Float __SCF [6 + 128]; // tabulated Scalefactors from -6 to +127 #define SCF ( __SCF + 6 ) extern Int8_t Q_bit [32]; // number of bits to save the resolution (SV6) extern Int8_t Q_res [32] [16]; // Index -> resolution (SV6) extern Uint Bitrate; extern Int Min_Band; extern Int Max_Band; extern Float __Cc [1 + 18]; extern const Uint __Dc [1 + 18]; #define Cc ( __Cc + 1 ) #define Dc ( __Dc + 1 ) // synthtab.c extern const Float Cos64 [32]; extern const Float Di_opt [32] [16]; // stderr.c //// procedures/functions ////////////////////////////////////////// // cpu_feat.c Bool_t Cdecl Has_MMX ( void ); Bool_t Cdecl Has_SIMD ( void ); Bool_t Cdecl Has_SIMD2 ( void ); Bool_t Cdecl Has_3DNow ( void ); // decode.c void Bitstream_init ( void ); Ulong BitsRead ( void ); Uint32_t Bitstream_read ( Int bits ); Uint32_t Bitstream_peek ( Uint pos, Int bits ); void Bitstream_skip ( Uint bits ); Uint32_t Bitstream_preview ( Int bits ); // same as above, but data doesn't get receipted yet void Read_Bitstream_SV6 ( void ); void Read_Bitstream_SV7 ( void ); void Read_Bitstream_SV8 ( void ); // http.c int http_open ( const char* URL ); // huffsv7.c void Init_Huffman_Decoder_SV7 ( void ); void Init_Huffman_Encoder_SV7 ( void ); // huffsv46.c void Init_Huffman_Decoder_SV4_6 ( void ); // id3tag.c Int Read_ID3V1_Tags ( FILE_T fp, TagInfo_t* tip ); Int Read_APE_Tags ( FILE_T fp, TagInfo_t* tip ); // requant.c void Init_QuantTab ( Int maximum_Band, Bool_t used_IS, Double amplification, Uint StreamVersion ); // synth.c Uint32_t random_int ( void ); void Cdecl Calculate_New_V_i387 ( const Float* Sample, Float* V ); void Cdecl Calculate_New_V_3DNow ( const Float* Sample, Float* V ); void Cdecl New_V_Helper2 ( Float* A, const Float* Sample ); void Cdecl New_V_Helper3 ( Float* A, const Float* Sample ); void Cdecl New_V_Helper4 ( Float* V ); void Cdecl VectorMult_i387 ( void* buff, const Float* V ); void Cdecl VectorMult_3DNow ( void* buff, const Float* V ); void Cdecl VectorMult_SIMD ( void* buff, const Float* V ); void Synthese_Filter_16_C ( Int2x16_t* Stream, Int* const offset, Float* Vi, const FloatArray* Yi ); void Synthese_Filter_32_C ( Int2x32_t* Stream, Int* const offset, Float* Vi, const FloatArray* Yi, Uint channel ); void Cdecl Reset_FPU ( void ); void Cdecl Reset_FPU_3DNow ( void ); void Cdecl memcpy_dn_MMX ( void* dst, const void* src, size_t words64byte ); void Cdecl memcpy_dn_SIMD ( void* dst, const void* src, size_t words128byte ); void Init_Dither ( Int bits, int shapingtype, Double dither ); void OverdriveReport ( void ); SyntheseFilter16_t Get_Synthese_Filter ( void ); // tools.c size_t Read_LittleEndians ( FILE_T fp, Uint32_t* dst, size_t words32bit ); void Requantize_MidSideStereo ( Int Stop_Band, const Bool_t* used_MS ); void Requantize_IntensityStereo ( Int Start_Band, Int Stop_Band ); void Resort_HuffTable ( Huffman_t* const Table, const size_t elements, Int offset ); void Make_HuffTable ( Huffman_t* dst, const HuffSrc_t* src, size_t len ); void Make_LookupTable ( Uint8_t* LUT, size_t LUT_len, const Huffman_t* const Table, const size_t elements ); size_t complete_read ( int fd, void* dest, size_t bytes ); int isdir ( const char* Name ); void Init_FPU ( void ); // wave_out.c Int Write_WAVE_Header ( FILE_T outputFile, Ldouble SampleFreq, Uint BitsPerSample, Uint Channels, Ulong SamplesPerChannel ); Int Write_AIFF_Header ( FILE_T outputFile, Ldouble SampleFreq, Uint BitsPerSample, Uint Channels, Ulong SamplesPerChannel ); Int Write_Raw_Header ( FILE_T outputFile, Ldouble SampleFreq, Uint BitsPerSample, Uint Channels, Ulong SamplesPerChannel ); Int Set_DSP_OSS_Params ( FILE_T outputFile, Ldouble SampleFreq, Uint BitsPerSample, Uint Channels ); Int Set_DSP_Sun_Params ( FILE_T outputFile, Ldouble SampleFreq, Uint BitsPerSample, Uint Channels ); Int Set_ESD_Params ( FILE_T dummyFile , Ldouble SampleFreq, Uint BitsPerSample, Uint Channels ); Int Set_WIN_Params ( FILE_T dummyFile , Ldouble SampleFreq, Uint BitsPerSample, Uint Channels ); Int Set_IRIX_Params ( FILE_T dummyFile , Ldouble SampleFreq, Uint BitsPerSample, Uint Channels ); size_t Write_PCM_2x16bit ( FILE_T outputFile, Int2x16_t* data, size_t len ); size_t Write_PCM_HQ_2x16bit ( FILE_T outputFile, Int2x32_t* data, size_t len ); size_t Write_PCM_HQ_2x24bit ( FILE_T outputFile, Int2x32_t* data, size_t len ); size_t Write_PCM_HQ_2x32bit ( FILE_T outputFile, Int2x32_t* data, size_t len ); int WIN_Play_Samples ( const void* buff, size_t len ); int IRIX_Play_Samples ( const void* buff, size_t len ); int WIN_Audio_close ( void ); int IRIX_Audio_close ( void ); void DisableSUID ( void ); void EnableSUID ( void ); // pipeopen.c FILE* pipeopen ( const char* command, const char* filename ); // stderr.c void SetStderrSilent ( Bool_t state ); Bool_t GetStderrSilent ( void ); int Cdecl stderr_printf ( const char* format, ... ); // _setargv.c long treewalk ( const char* start, const char** mask, int (*fn)(const char* filename, void* aux), void* aux ); void mysetargv ( int* argc, char*** argv, const char** extentions ); #if ENDIAN == HAVE_BIG_ENDIAN # define ReadLE32(dst,psrc) dst = *(Uint32_t*)(psrc) # define ReadBE32(dst,psrc) \ ((Uint8_t*)&(dst))[0] = ((Uint8_t*)(psrc))[3], \ ((Uint8_t*)&(dst))[1] = ((Uint8_t*)(psrc))[2], \ ((Uint8_t*)&(dst))[2] = ((Uint8_t*)(psrc))[1], \ ((Uint8_t*)&(dst))[3] = ((Uint8_t*)(psrc))[0] #elif defined __i386__ /* 486+ */ # define ReadBE32(dst,psrc) __asm__ ( "bswap %0" : "=r" (dst) : "0" (*(Uint32_t*)(psrc)) ) # define ReadLE32(dst,psrc) dst = *(Uint32_t*)(psrc) # else # define ReadBE32(dst,psrc) \ ((Uint8_t*)&(dst))[0] = ((Uint8_t*)(psrc))[3], \ ((Uint8_t*)&(dst))[1] = ((Uint8_t*)(psrc))[2], \ ((Uint8_t*)&(dst))[2] = ((Uint8_t*)(psrc))[1], \ ((Uint8_t*)&(dst))[3] = ((Uint8_t*)(psrc))[0] # define ReadLE32(dst,psrc) dst = *(Uint32_t*)(psrc) # endif //// Profiler include ////////////////////////////////////////////// #include "profile.h" #ifdef _MSC_VER #pragma warning ( disable : 4244 ) #endif #endif /* MPPDEC_MPPDEC_H */ /* end of mppdec.h */ mppenc-1.16/src/fastmath.c0000644000175000017500000000426210525155536014756 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" #include "fastmath.h" #ifdef FAST_MATH const float tabatan2 [ 2*TABSTEP+1] [2]; const float tabcos [26*TABSTEP+1] [2]; const float tabsqrt_ex [256]; const float tabsqrt_m [ TABSTEP+1] [2]; void Init_FastMath ( void ) { int i; mpc_floatint X, Y; double xm, x0, xp, x, y; float* p; p = (float*) tabatan2; for ( i = -TABSTEP; i <= TABSTEP; i++ ) { xm = atan ((i-0.5)/TABSTEP); x0 = atan ((i+0.0)/TABSTEP); xp = atan ((i+0.5)/TABSTEP); x = x0/2 + (xm + xp)/4; y = xp - xm; *p++ = x; *p++ = y; } p = (float*) tabcos; for ( i = -13*TABSTEP; i <= 13*TABSTEP; i++ ) { xm = cos ((i-0.5)/TABSTEP); x0 = cos ((i+0.0)/TABSTEP); xp = cos ((i+0.5)/TABSTEP); x = x0/2 + (xm + xp)/4; y = xp - xm; *p++ = x; *p++ = y; } p = (float*) tabsqrt_ex; for ( i = 0; i < 255; i++ ) { X.n = (i << 23); Y.n = (i << 23) + (1<<23) - 1; *p++ = sqrt(X.f); } X.n = (255 << 23) - 1; *p++ = sqrt(X.f); p = (float*) tabsqrt_m; for ( i = 1*TABSTEP; i <= 2*TABSTEP; i++ ) { xm = sqrt ((i-0.5)/TABSTEP); x0 = sqrt ((i+0.0)/TABSTEP); xp = sqrt ((i+0.5)/TABSTEP); x = x0/2 + (xm + xp)/4; y = xp - xm; *p++ = x; *p++ = y; } } #endif mppenc-1.16/src/minimax.h0000644000175000017500000000416510522734510014610 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #ifndef MPP_MINIMAX_H #define MPP_MINIMAX_H #if defined __GNUC__ && defined __cplusplus # define maxi(A,B) ( (A) >? (B) ) # define mini(A,B) ( (A) ? (B) ) # define mind(A,B) ( (A) ? (B) ) # define minf(A,B) ( (A) (B) ? (A) : (B) ) # define mini(A,B) ( (A) < (B) ? (A) : (B) ) # define maxd(A,B) ( (A) > (B) ? (A) : (B) ) # define mind(A,B) ( (A) < (B) ? (A) : (B) ) # define maxf(A,B) ( (A) > (B) ? (A) : (B) ) # define minf(A,B) ( (A) < (B) ? (A) : (B) ) # define absi(A) abs (A) # define absf(A) fabsf (A) # define absd(A) fabs (A) #else # define maxi(A,B) ( (A) > (B) ? (A) : (B) ) # define mini(A,B) ( (A) < (B) ? (A) : (B) ) # define maxd(A,B) ( (A) > (B) ? (A) : (B) ) # define mind(A,B) ( (A) < (B) ? (A) : (B) ) # define maxf(A,B) ( (A) > (B) ? (A) : (B) ) # define minf(A,B) ( (A) < (B) ? (A) : (B) ) # define absi(A) ( (A) >= 0 ? (A) : -(A) ) # define absf(A) ( (A) >= 0.f ? (A) : -(A) ) # define absd(A) ( (A) >= 0. ? (A) : -(A) ) #endif /* GNUC && C++ */ #endif /* MPP_MINIMAX_H */ mppenc-1.16/src/mppenc.c0000644000175000017500000025005510525727755014444 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ /* overflow of subband-samples */ #include #include #include #include "mppenc.h" /* G L O B A L V A R I A B L E S */ float SNR_comp_L [32]; float SNR_comp_R [32]; // SNR-compensation after SCF-combination and ANS-gain float Power_L [32] [3]; float Power_R [32] [3]; float PNS = 0.; int Max_Band; // maximum bandwidth /* MS-Coding */ unsigned int MS_Channelmode; // global flag for enhanced functionality float SampleFreq = 0.; float Bandwidth = 0.; int PredictionBands = 0; int CombPenalities = -1; float KBD1 = 2; float KBD2 = -1.; int DisplayUpdateTime = 1; int APE_Version = 2000; int LowDelay = 0; Bool_t IsEndBeep = 0; #define MODE_OVERWRITE 0 #define MODE_NEVER_OVERWRITE 1 #define MODE_ASK_FOR_OVERWRITE 2 /* other general global variables */ unsigned int DelInput = 0; // deleting the input file after encoding unsigned int WriteMode = MODE_ASK_FOR_OVERWRITE; // overwriting a possibly existing MPC file int MainQual; // Profiles unsigned int verbose = 0; // more information during output unsigned int NoUnicode = 1; // console is unicode or not (tag translation) UintMax_t SamplesInWAVE = 0; // number of samples per channel in the WAV file unsigned int Overflows = 0; // number of internal (filterbank) clippings float MaxOverFlow = 0.f; // maximum overflow float ScalingFactorl = 1.f; // Scaling the input signal float ScalingFactorr = 1.f; // Scaling the input signal float FadeShape = 1.f; // Shape of the fade float FadeInTime = 0.f; // Duration of FadeIn in secs float FadeOutTime = 0.f; // Duration of FadeOut in secs float SkipTime = 0.f; // Skip the beginning of the file (sec) double Duration = 1.e+99; // Maximum encoded audio length Bool_t FrontendPresent = 0; // Flag for frontend-detection Bool_t XLevel = 1; // Encode extreme levels with relative SCFs const char About [] = "MPC Encoder " MPPENC_VERSION " " MPPENC_BUILD " (C) 1999-2006 Buschmann/Klemm/Piecha/MDT"; #if defined _WIN32 || defined __TURBOC__ # include #else # ifdef USE_TERMIOS # include static struct termios stored_settings; static void echo_on ( void ) { tcsetattr ( 0, TCSANOW, &stored_settings ); } static void echo_off ( void ) { struct termios new_settings; tcgetattr ( 0, &stored_settings ); new_settings = stored_settings; new_settings.c_lflag &= ~ECHO; new_settings.c_lflag &= ~ICANON; /* Disable canonical mode, and set buffer size to 1 byte */ new_settings.c_cc[VTIME] = 0; new_settings.c_cc[VMIN] = 1; tcsetattr ( 0, TCSANOW, &new_settings ); } # else # define echo_off() (void)0 # define echo_on() (void)0 # endif static int getch ( void ) { unsigned char buff [1]; int ret; echo_off (); ret = READ1 ( STDIN, buff ); echo_on (); return ret == 1 ? buff[0] : -1; } #endif static int waitkey ( void ) { int c; fflush (stdout); while ( (c = getch() ) <= ' ' ) ; return c; } static void longhelp ( void ) { stderr_printf ( "\n" "\033[1m\rUsage:\033[0m\n" " mppenc [--options] \n" " mppenc [--options] \n" "\n" ); stderr_printf ( "\033[1m\rInput_File must be of the following:\033[0m\n" " - stdin (only RIFF WAVE files)\n" " /dev/audio soundcard (using OSS, 44.1 kHz)\n" " *.wav RIFF WAVE file\n" " *.raw/cdr Raw PCM (2ch, 16bit, 44.1kHz)\n" " *.pac/lpac LPAC file (Windows Only)\n" " *.fla/flac FLAC file\n" " *.ape Monkey's Audio file (APE extension only)\n" " *.rka/rkau RK Audio file (Windows Only)\n" " *.sz SZIP file\n" " *.shn Shorten file\n" " *.wv Wavpack File\n" " *.ofr OptimFROG file (Windows Only)\n" "\n" " Currently only 32, 37.8, 44.1 and 48 kHz, 1-8 channels, 8-32 bit linear PCM\n" " is supported. When using one of the lossless compressed formats, a proper\n" " binary must be installed within the system's $PATH.\n" "\n" "\033[1m\rOutput_File must be of the following: (or generated from Input_File)\033[0m\n" " *.mpc Musepack file\n" " *.mp+/mpp MPEGplus file (Deprecated)\n" " - stdout\n" " /dev/null trash can\n" "\n" ); stderr_printf ( "\033[1m\rProfiles and Quality Scale:\033[0m\n" "\n" " Option of using a profile (--radio) or mapped quality scale (--quality 4.0).\n" " In addition, quality scale is effective centesimally. (i.e. --quality 4.25)\n" " Available options are as follows:\n" "\n" " below telephone (--quality 0.00) poor quality (~ 20 kbps)\n" " below telephone (--quality 1.00) poor quality (~ 30 kbps)\n" " --telephone (--quality 2.00) low quality (~ 60 kbps)\n" " --thumb (--quality 3.00) low/medium quality (~ 90 kbps)\n" " --radio (--quality 4.00) medium quality (~ 130 kbps)\n" " --standard (--quality 5.00) high quality (dflt) (~ 180 kbps)\n" " (or --normal)\n" " --extreme (--quality 6.00) excellent quality (~ 210 kbps)\n" " (or --xtreme)\n" " --insane (--quality 7.00) excellent quality (~ 240 kbps)\n" " --braindead (--quality 8.00) excellent quality (~ 270 kbps)\n" " above braindead (--quality 9.00) excellent quality (~ 300 kbps)\n" " above braindead (--quality 10.00) excellent quality (~ 350 kbps)\n" "\n" ); stderr_printf ( "\033[1m\rFile/Message handling:\033[0m\n" " --silent repress console messages (dflt: off)\n" " --verbose increase verbosity (dflt: off)\n" " --longhelp print this help text\n" " --stderr foo append messages to file 'foo'\n" " --neveroverwrite never overwrite existing Output_File (dflt: off)\n" " --interactive ask to overwrite an existing Output_File (dflt: on)\n" " --overwrite overwrite existing Output_File (dflt: off)\n" " --deleteinput delete Input_File after encoding (dflt: off)\n" " --beep beep when encoding is finished (dflt: off)\n" "\n" ); stderr_printf ( "\033[1m\rTagging (uses APE 2.0 tags):\033[0m\n" " --tag key=value Add tag \"key\" with \"value\" as contents\n" " --tagfile key=f dto., take value from a file 'f'\n" " --tagfile key dto., take value from console\n" " --artist 'value' shortcut for --tag 'Artist=value'\n" " --album 'value' shortcut for --tag 'Album=value'\n" " other possible keys are: debutalbum, publisher, conductor,\n" " title, subtitle, track, comment, composer, copyright,\n" " publicationright, filename, recordlocation, recorddate,\n" " ean/upc, year, releasedate, genre, media, index, isrc,\n" " abstract, bibliography, introplay, media, language, ...\n" " --unicode unicode input from console (unix only)\n" "\n" ); stderr_printf ( "\033[1m\rAudio processing:\033[0m\n" ); stderr_printf ( " --skip x skip the first x seconds (dflt: %3.1f)\n", SkipTime ); stderr_printf ( " --dur x stop encoding after at most x seconds of encoded audio\n" ); stderr_printf ( " --fade x fadein+out in seconds\n" ); stderr_printf ( " --fadein x fadein in seconds (dflt: %3.1f)\n", FadeInTime ); stderr_printf ( " --fadeout x fadeout in seconds (dflt: %3.1f)\n", FadeOutTime ); stderr_printf ( " --fadeshape x fade shape (dflt: %3.1f),\n" " see http://www.uni-jena.de/~pfk/mpc/img/fade.png\n", FadeShape ); stderr_printf ( " --scale x scale input signal by x (dflt: %7.5f)\n", ScalingFactorl ); stderr_printf ( " --scale x,y scale input signal, separate for each channel\n" ); stderr_printf ( "\n" ); stderr_printf ( "\033[1m\rExpert settings:\033[0m\n" ); stderr_printf ( "==Masking thresholds======\n" ); stderr_printf ( " --quality x set Quality to x (dflt: 5)\n" ); stderr_printf ( " --nmt x set NMT value to x dB (dflt: %4.1f)\n", NMT ); stderr_printf ( " --tmn x set TMN value to x dB (dflt: %4.1f)\n", TMN ); stderr_printf ( " --pns x set PNS value to x dB (dflt: %4.1f)\n", PNS ); stderr_printf ( "==ATH/Bandwidth settings==\n" ); stderr_printf ( " --bw x maximum bandwidth in Hz (dflt: %4.1f kHz)\n", (Max_Band+1)*(SampleFreq/32000.) ); stderr_printf ( " --minSMR x minimum SMR of x dB over encoded bandwidth (dflt: %2.1f)\n", minSMR ); stderr_printf ( " --ltq xyy x=0: ISO threshold in quiet (not recommended)\n" " x=1: more sensitive threshold in quiet (Buschmann)\n" " x=2: even more sensitive threshold in quiet (Filburt)\n" " x=3: Klemm\n" " x=4: Buschmann-Klemm Mix\n" " x=5: minimum of Klemm and Buschmann (dflt)\n" " y=00...99: HF roll-off (00:+30 dB, 99:-30 dB @20 kHz\n" ); stderr_printf ( " --ltq_gain x add offset of x dB to chosen ltq (dflt: %+4.1f)\n", Ltq_offset ); stderr_printf ( " --ltq_max x maximum level for ltq (dflt: %4.1f dB)\n", Ltq_max ); stderr_printf ( " --ltq_var x adaptive threshold in quiet: 0: off, >0: on (dflt: %g)\n",varLtq ); stderr_printf ( " --tmpMask x exploit postmasking: 0: off, 1: on (dflt: %i)\n", tmpMask_used ); stderr_printf ( "==Other settings==========\n" ); stderr_printf ( " --ms x Mid/Side Stereo, 0: off, 1: reduced, 2: on, 3: decoupled,\n" " 10: enhanced 1.5/3 dB, 11: 2/6 dB, 12: 2.5/9 dB,\n" " 13: 3/12 dB, 15: 3/oo dB (dflt: %i)\n", MS_Channelmode ); stderr_printf ( " --ans x Adaptive Noise Shaping Order: 0: off, 1...6: on (dflt: %i)\n", NS_Order ); stderr_printf ( " --cvd x ClearVoiceDetection, 0: off, 1: on, 2: dual (dflt: %i)\n", CVD_used ); stderr_printf ( " --shortthr x short FFT threshold (dflt: %4.1f)\n", ShortThr ); stderr_printf ( " --transdet x slewrate for transient detection (dflt: %3.1f)\n", TransDetect ); stderr_printf ( " --minval x calculation of MinVal (1:Buschmann, 2,3:Klemm)\n" ); stderr_printf ( " --noxlevel use old filterbank clipping solving strategy\n" ); stderr_printf ( "\n" ); stderr_printf ( "\033[1m\rExamples:\033[0m\n" " mppenc inputfile.wav\n" " mppenc inputfile.wav outputfile.mpc\n" " mppenc --radio inputfile.wav outputfile.mpc\n" " mppenc --silent --radio --pns 0.25 inputfile.wav outputfile.mpc\n" " mppenc --nmt 12 --tmn 28 inputfile.wav outputfile.mpc\n" "\n"); } static void shorthelp ( void ) { stderr_printf ( "\n" "\033[1m\rUsage:\033[0m\n" " mppenc [--options] \n" " mppenc [--options] \n" "\n" "\033[1m\rStandard options:\033[0m\n" " --silent repress console messages (dflt: off)\n" " --verbose increase verbosity (dflt: off)\n" " --deleteinput delete Input_File after encoding (dflt: off)\n" " --overwrite overwrite existing Output_File (dflt: off)\n" " --fade sec fade in and out with 'sec' duration (dflt: 0.0)\n" "\n" "\033[1m\rProfiles and Quality Scale:\033[0m\n" " --thumb (--quality 3.00) low/medium quality (~ 90 kbps)\n" " --radio (--quality 4.00) medium quality (~ 130 kbps)\n" " --standard (--quality 5.00) high quality (dflt) (~ 180 kbps)\n" " --extreme (--quality 6.00) excellent quality (~ 210 kbps)\n" " --insane (--quality 7.00) excellent quality (~ 240 kbps)\n" "\n" "\033[1m\rExamples:\033[0m\n" " mppenc inputfile.wav\n" " mppenc inputfile.wav outputfile.mpc\n" " mppenc --insane inputfile.wav outputfile.mpc\n" " mppenc --silent --radio inputfile.wav outputfile.mpc\n" "\n" "For further information use the --longhelp option.\n" ); } /* * Wishes for fading: * * _____________________ * /| |\ * / | | \ * / | | \ * ____/ | | \______________ * | | | | | | * |t1| t2 | | t4 |t5| * | t3 | * |<-------------- M P C ------------->| * |<-------------------- W A V E ------------------>| * * t1: StartTime (Standard: 0, positive: from beginning of file, negative: from end of file) * t2: FadeInTime (Standard: 0, positive: Fadetime) * t3: EndTime (Standard: 0, non-positive: from end of file, positive: from beginning of file) * t4: FadeOutTime (Standard: 0, positive: Fadetime) * t5: PostGapTime (Standard: 0, positive: additional silence) * * The beginning of phase t4 can also be triggered by the signal SIGINT. * With SIGTERM, the current frame is fully decoded and then terminated. * * Another question is if you can't put t1 before the zero, same with t3 and t5 * (track-spanning cutting). */ #include "fastmath.h" float bump_exp = 1.f; float bump_start = 0.040790618517f; static void setbump ( double e ) { bump_exp = e; bump_start = 1 - sqrt (1 - 1 / (1 - log(1.e-5) / e)); } static double bump ( double x ) { x = bump_start + x * (1. - bump_start); if ( x <= 0.) return 0.; if ( x >= 1.) return 1.; x *= (2. - x); x = (x - 1.) / x; return exp (x * bump_exp); } static void Fading_In ( PCMDataTyp* data, unsigned int N, const float fs ) { float inv_fs = 1.f / fs; float fadein_pos; float scale; int n; int idx; ENTER(2); for ( n = 0; n < BLOCK; n++, N++ ) { idx = n + CENTER; fadein_pos = N * inv_fs; scale = fadein_pos / FadeInTime; scale = bump (scale); data->L[idx] *= scale; data->R[idx] *= scale; data->M[idx] *= scale; data->S[idx] *= scale; } LEAVE(2); } static void Fading_Out ( PCMDataTyp* data, unsigned int N, const float fs ) { float inv_fs = 1.f / fs; float fadeout_pos; float scale; int n; int idx; ENTER(3); for ( n = 0; n < BLOCK; n++, N++ ) { idx = n + CENTER; fadeout_pos = UintMAX_FP(SamplesInWAVE - N) * inv_fs; scale = fadeout_pos / FadeOutTime; scale = bump (scale); data->L[idx] *= scale; data->R[idx] *= scale; data->M[idx] *= scale; data->S[idx] *= scale; } LEAVE(3); } static const unsigned char Penalty [256] = { 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 2, 5, 9, 15, 23, 36, 54, 79,116,169,246,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, }; #define P(new,old) Penalty [128 + (old) - (new)] static void SCF_Extraktion ( const int MaxBand, SubbandFloatTyp* x ) { int Band; int n; int d01; int d12; int d02; int warnL; int warnR; int* scfL; int* scfR; int comp_L [3]; int comp_R [3]; float tmp_L [3]; float tmp_R [3]; float facL; float facR; float L; float R; float SL; float SR; ENTER(4); for ( Band = 0; Band <= MaxBand; Band++ ) { // Suche nach Maxima L = FABS (x[Band].L[ 0]); R = FABS (x[Band].R[ 0]); SL = x[Band].L[ 0] * x[Band].L[ 0]; SR = x[Band].R[ 0] * x[Band].R[ 0]; for ( n = 1; n < 12; n++ ) { if (L < FABS (x[Band].L[n])) L = FABS (x[Band].L[n]); if (R < FABS (x[Band].R[n])) R = FABS (x[Band].R[n]); SL += x[Band].L[n] * x[Band].L[n]; SR += x[Band].R[n] * x[Band].R[n]; } Power_L [Band][0] = SL; Power_R [Band][0] = SR; tmp_L [0] = L; tmp_R [0] = R; L = FABS (x[Band].L[12]); R = FABS (x[Band].R[12]); SL = x[Band].L[12] * x[Band].L[12]; SR = x[Band].R[12] * x[Band].R[12]; for ( n = 13; n < 24; n++ ) { if (L < FABS (x[Band].L[n])) L = FABS (x[Band].L[n]); if (R < FABS (x[Band].R[n])) R = FABS (x[Band].R[n]); SL += x[Band].L[n] * x[Band].L[n]; SR += x[Band].R[n] * x[Band].R[n]; } Power_L [Band][1] = SL; Power_R [Band][1] = SR; tmp_L [1] = L; tmp_R [1] = R; L = FABS (x[Band].L[24]); R = FABS (x[Band].R[24]); SL = x[Band].L[24] * x[Band].L[24]; SR = x[Band].R[24] * x[Band].R[24]; for ( n = 25; n < 36; n++ ) { if (L < FABS (x[Band].L[n])) L = FABS (x[Band].L[n]); if (R < FABS (x[Band].R[n])) R = FABS (x[Band].R[n]); SL += x[Band].L[n] * x[Band].L[n]; SR += x[Band].R[n] * x[Band].R[n]; } Power_L [Band][2] = SL; Power_R [Band][2] = SR; tmp_L [2] = L; tmp_R [2] = R; // calculation of the scalefactor-indexes // -12.6f*log10(x)+57.8945021823f = -10*log10(x/32767)*1.26+1 // normalize maximum of +/- 32767 to prevent quantizer overflow // It can stand a maximum of +/- 32768 ... // Where is scf{R,L} [0...2] initialized ??? scfL = SCF_Index_L [Band]; scfR = SCF_Index_R [Band]; if (tmp_L [0] > 0.) scfL [0] = IFLOORF (-12.6f * LOG10 (tmp_L [0]) + 57.8945021823f ); if (tmp_L [1] > 0.) scfL [1] = IFLOORF (-12.6f * LOG10 (tmp_L [1]) + 57.8945021823f ); if (tmp_L [2] > 0.) scfL [2] = IFLOORF (-12.6f * LOG10 (tmp_L [2]) + 57.8945021823f ); if (tmp_R [0] > 0.) scfR [0] = IFLOORF (-12.6f * LOG10 (tmp_R [0]) + 57.8945021823f ); if (tmp_R [1] > 0.) scfR [1] = IFLOORF (-12.6f * LOG10 (tmp_R [1]) + 57.8945021823f ); if (tmp_R [2] > 0.) scfR [2] = IFLOORF (-12.6f * LOG10 (tmp_R [2]) + 57.8945021823f ); // restriction to SCF_Index = 0...63, make note of the internal overflow warnL = warnR = 0; if (scfL[0] & ~63) { if (scfL[0] < 0) { if (XLevel==0) scfL[0] = 0, warnL = 1; } else scfL[0] = 63; } if (scfL[1] & ~63) { if (scfL[1] < 0) { if (XLevel==0) scfL[1] = 0, warnL = 1; } else scfL[1] = 63; } if (scfL[2] & ~63) { if (scfL[2] < 0) { if (XLevel==0) scfL[2] = 0, warnL = 1; } else scfL[2] = 63; } if (scfR[0] & ~63) { if (scfR[0] < 0) { if (XLevel==0) scfR[0] = 0, warnR = 1; } else scfR[0] = 63; } if (scfR[1] & ~63) { if (scfR[1] < 0) { if (XLevel==0) scfR[1] = 0, warnR = 1; } else scfR[1] = 63; } if (scfR[2] & ~63) { if (scfR[2] < 0) { if (XLevel==0) scfR[2] = 0, warnR = 1; } else scfR[2] = 63; } // save old values for compensation calculation comp_L[0] = scfL[0]; comp_L[1] = scfL[1]; comp_L[2] = scfL[2]; comp_R[0] = scfR[0]; comp_R[1] = scfR[1]; comp_R[2] = scfR[2]; // determination and replacement of scalefactors of minor differences with the smaller one??? // a smaller one is quantized more roughly, i.e. the noise gets amplified??? if ( CombPenalities >= 0 ) { if ( P(scfL[0],scfL[1]) + P(scfL[0],scfL[2]) <= CombPenalities ) scfL[2] = scfL[1] = scfL[0]; else if ( P(scfL[1],scfL[0]) + P(scfL[1],scfL[2]) <= CombPenalities ) scfL[0] = scfL[2] = scfL[1]; else if ( P(scfL[2],scfL[0]) + P(scfL[2],scfL[1]) <= CombPenalities ) scfL[0] = scfL[1] = scfL[2]; else if ( P(scfL[0],scfL[1]) <= CombPenalities ) scfL[1] = scfL[0]; else if ( P(scfL[1],scfL[0]) <= CombPenalities ) scfL[0] = scfL[1]; else if ( P(scfL[1],scfL[2]) <= CombPenalities ) scfL[2] = scfL[1]; else if ( P(scfL[2],scfL[1]) <= CombPenalities ) scfL[1] = scfL[2]; if ( P(scfR[0],scfR[1]) + P(scfR[0],scfR[2]) <= CombPenalities ) scfR[2] = scfR[1] = scfR[0]; else if ( P(scfR[1],scfR[0]) + P(scfR[1],scfR[2]) <= CombPenalities ) scfR[0] = scfR[2] = scfR[1]; else if ( P(scfR[2],scfR[0]) + P(scfR[2],scfR[1]) <= CombPenalities ) scfR[0] = scfR[1] = scfR[2]; else if ( P(scfR[0],scfR[1]) <= CombPenalities ) scfR[1] = scfR[0]; else if ( P(scfR[1],scfR[0]) <= CombPenalities ) scfR[0] = scfR[1]; else if ( P(scfR[1],scfR[2]) <= CombPenalities ) scfR[2] = scfR[1]; else if ( P(scfR[2],scfR[1]) <= CombPenalities ) scfR[1] = scfR[2]; } else { d12 = scfL [2] - scfL [1]; d01 = scfL [1] - scfL [0]; d02 = scfL [2] - scfL [0]; if ( 0 < d12 && d12 < 5 ) scfL [2] = scfL [1]; else if (-3 < d12 && d12 < 0 ) scfL [1] = scfL [2]; else if ( 0 < d01 && d01 < 5 ) scfL [1] = scfL [0]; else if (-3 < d01 && d01 < 0 ) scfL [0] = scfL [1]; else if ( 0 < d02 && d02 < 4 ) scfL [2] = scfL [0]; else if (-2 < d02 && d02 < 0 ) scfL [0] = scfL [2]; d12 = scfR [2] - scfR [1]; d01 = scfR [1] - scfR [0]; d02 = scfR [2] - scfR [0]; if ( 0 < d12 && d12 < 5 ) scfR [2] = scfR [1]; else if (-3 < d12 && d12 < 0 ) scfR [1] = scfR [2]; else if ( 0 < d01 && d01 < 5 ) scfR [1] = scfR [0]; else if (-3 < d01 && d01 < 0 ) scfR [0] = scfR [1]; else if ( 0 < d02 && d02 < 4 ) scfR [2] = scfR [0]; else if (-2 < d02 && d02 < 0 ) scfR [0] = scfR [2]; } // calculate SNR-compensation tmp_L [0] = invSCF [comp_L[0] - scfL[0]]; tmp_L [1] = invSCF [comp_L[1] - scfL[1]]; tmp_L [2] = invSCF [comp_L[2] - scfL[2]]; tmp_R [0] = invSCF [comp_R[0] - scfR[0]]; tmp_R [1] = invSCF [comp_R[1] - scfR[1]]; tmp_R [2] = invSCF [comp_R[2] - scfR[2]]; SNR_comp_L [Band] = (tmp_L[0]*tmp_L[0] + tmp_L[1]*tmp_L[1] + tmp_L[2]*tmp_L[2]) * 0.3333333333f; SNR_comp_R [Band] = (tmp_R[0]*tmp_R[0] + tmp_R[1]*tmp_R[1] + tmp_R[2]*tmp_R[2]) * 0.3333333333f; // normalize the subband samples facL = invSCF[scfL[0]]; facR = invSCF[scfR[0]]; for ( n = 0; n < 12; n++ ) { x[Band].L[n] *= facL; x[Band].R[n] *= facR; } facL = invSCF[scfL[1]]; facR = invSCF[scfR[1]]; for ( n = 12; n < 24; n++ ) { x[Band].L[n] *= facL; x[Band].R[n] *= facR; } facL = invSCF[scfL[2]]; facR = invSCF[scfR[2]]; for ( n = 24; n < 36; n++ ) { x[Band].L[n] *= facL; x[Band].R[n] *= facR; } // limit to +/-32767 if internal clipping if ( warnL ) for ( n = 0; n < 36; n++ ) { if (x[Band].L[n] > +32767.f) { Overflows++; MaxOverFlow = maxf (MaxOverFlow, x[Band].L[n]); x[Band].L[n] = 32767.f; } else if (x[Band].L[n] < -32767.f) { Overflows++; MaxOverFlow = maxf (MaxOverFlow, -x[Band].L[n]); x[Band].L[n] = -32767.f; } } if ( warnR ) for ( n = 0; n < 36; n++ ) { if (x[Band].R[n] > +32767.f) { Overflows++; MaxOverFlow = maxf (MaxOverFlow, x[Band].R[n]); x[Band].R[n] = 32767.f; } else if (x[Band].R[n] < -32767.f) { Overflows++; MaxOverFlow = maxf (MaxOverFlow, -x[Band].R[n]); x[Band].R[n] = -32767.f; } } } LEAVE(4); return; } static void Quantisierung ( const int MaxBand, const int* resL, const int* resR, const SubbandFloatTyp* subx, SubbandQuantTyp* subq ) { static float errorL [32] [36 + MAX_NS_ORDER]; static float errorR [32] [36 + MAX_NS_ORDER]; int Band; ENTER(5); // quantize Subband- and Subframe-samples for ( Band = 0; Band <= MaxBand; Band++, resL++, resR++ ) { if ( *resL > 0 ) { if ( NS_Order_L [Band] > 0 ) { QuantizeSubbandWithNoiseShaping ( subq[Band].L, subx[Band].L, *resL, errorL [Band], FIR_L [Band] ); memcpy ( errorL [Band], errorL[Band] + 36, MAX_NS_ORDER * sizeof (**errorL) ); } else { QuantizeSubband ( subq[Band].L, subx[Band].L, *resL, errorL [Band] ); memcpy ( errorL [Band], errorL[Band] + 36, MAX_NS_ORDER * sizeof (**errorL) ); } } else { } if ( *resR > 0 ) { if ( NS_Order_R [Band] > 0 ) { QuantizeSubbandWithNoiseShaping ( subq[Band].R, subx[Band].R, *resR, errorR [Band], FIR_R [Band] ); memcpy ( errorR [Band], errorR [Band] + 36, MAX_NS_ORDER * sizeof (**errorL) ); } else { QuantizeSubband ( subq[Band].R, subx[Band].R, *resR, errorL [Band] ); memcpy ( errorR [Band], errorR [Band] + 36, MAX_NS_ORDER * sizeof (**errorL) ); } } else { } } LEAVE(5); return; } static int PNS_SCF ( int* scf, float S0, float S1, float S2 ) { // printf ("%7.1f %7.1f %7.1f ", sqrt(S0/12), sqrt(S1/12), sqrt(S2/12) ); #if 1 if ( S0 < 0.5 * S1 || S1 < 0.5 * S2 || S0 < 0.5 * S2 ) return 0; if ( S1 < 0.25 * S0 || S2 < 0.25 * S1 || S2 < 0.25 * S0 ) return 0; #endif if ( S0 >= 0.8 * S1 ) { if ( S0 >= 0.8 * S2 && S1 > 0.8 * S2 ) S0 = S1 = S2 = 0.33333333333f * (S0 + S1 + S2); else S0 = S1 = 0.5f * (S0 + S1); } else { if ( S1 >= 0.8 * S2 ) S1 = S2 = 0.5f * (S1 + S2); } scf [0] = scf [1] = scf [2] = 63; S0 = sqrt (S0/12 * 4/1.2005080577484075047860806747022); S1 = sqrt (S1/12 * 4/1.2005080577484075047860806747022); S2 = sqrt (S2/12 * 4/1.2005080577484075047860806747022); if (S0 > 0.) scf [0] = IFLOORF (-12.6f * LOG10 (S0) + 57.8945021823f ); if (S1 > 0.) scf [1] = IFLOORF (-12.6f * LOG10 (S1) + 57.8945021823f ); if (S2 > 0.) scf [2] = IFLOORF (-12.6f * LOG10 (S2) + 57.8945021823f ); if ( scf[0] & ~63 ) scf[0] = scf[0] > 63 ? 63 : 0; if ( scf[1] & ~63 ) scf[1] = scf[1] > 63 ? 63 : 0; if ( scf[2] & ~63 ) scf[2] = scf[2] > 63 ? 63 : 0; return 1; } static void Allocate ( const int MaxBand, int* res, float* x, int* scf, const float* comp, const float* smr, const SCFTriple* Pow, const int* Transient ) { int Band; int k; float tmpMNR; // to adjust the scalefactors float save [36]; // to adjust the scalefactors float MNR; // Mask-to-Noise ratio ENTER(6); for ( Band = 0; Band <= MaxBand; Band++, res++, comp++, smr++, scf += 3, x += 72 ) { // printf ( "%2u: %u\n", Band, Transient[Band] ); // Find out needed quantization resolution Res to fulfill the calculated MNR // This is done by exactly measuring the quantization residuals against the signal itself // Starting with Res=1 Res in increased until MNR becomes less than 1. if ( Band > 0 && res[-1] < 3 && *smr >= 1. && *smr < Band * PNS && PNS_SCF ( scf, Pow [Band][0], Pow [Band][1], Pow [Band][2] ) ) { *res = -1; } else { for ( MNR = *smr * 1.; MNR > 1. && *res != 15; ) MNR = *smr * (Transient[Band] ? ISNR_Schaetzer_Trans : ISNR_Schaetzer) ( x, *comp, ++*res ); } // Fine adapt SCF's (MNR > 0 prevents adaption of zero samples, which is nonsense) // only apply to Huffman-coded samples (otherwise no savings in bitrate) if ( *res > 0 && *res <= LAST_HUFFMAN && MNR < 1. && MNR > 0. && !Transient[Band] ) { while ( scf[0] > 0 && scf[1] > 0 && scf[2] > 0 ) { --scf[2]; --scf[1]; --scf[0]; // adapt scalefactors and samples memcpy ( save, x, sizeof save ); for (k = 0; k < 36; k++ ) x[k] *= SCFfac; tmpMNR = *smr * (Transient[Band] ? ISNR_Schaetzer_Trans : ISNR_Schaetzer) ( x, *comp, *res );// recalculate MNR // FK: if ( tmpMNR > MNR && tmpMNR <= 1 ) { // check for MNR if ( tmpMNR <= 1 ) { // check for MNR MNR = tmpMNR; } else { ++scf[0]; ++scf[1]; ++scf[2]; // restore scalefactors and samples memcpy ( x, save, sizeof save ); break; } } } } LEAVE(6); return; } typedef struct { float ShortThr; unsigned char MinValChoice; unsigned int EarModelFlag; signed char Ltq_offset; float TMN; float NMT; signed char minSMR; signed char Ltq_max; unsigned short BandWidth; unsigned char tmpMask_used; unsigned char CVD_used; float varLtq; unsigned char MS_Channelmode; unsigned char CombPenalities; unsigned char NS_Order; float PNS; float TransDetect; } Profile_Setting_t; #define PROFILE_PRE2_TELEPHONE 5 // --quality 0 #define PROFILE_PRE_TELEPHONE 6 // --quality 1 #define PROFILE_TELEPHONE 7 // --quality 2 #define PROFILE_THUMB 8 // --quality 3 #define PROFILE_RADIO 9 // --quality 4 #define PROFILE_STANDARD 10 // --quality 5 #define PROFILE_XTREME 11 // --quality 6 #define PROFILE_INSANE 12 // --quality 7 #define PROFILE_BRAINDEAD 13 // --quality 8 #define PROFILE_POST_BRAINDEAD 14 // --quality 9 #define PROFILE_POST2_BRAINDEAD 15 // --quality 10 static const Profile_Setting_t Profiles [16] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, /* Short MinVal EarModel Ltq_ min Ltq_ Band- tmpMask CVD_ varLtq MS Comb NS_ Trans */ /* Thr Choice Flag offset TMN NMT SMR max Width _used used channel Penal used PNS Det */ { 1.e9f, 1, 300, 30, 3.0, -1.0, 0, 106, 4820, 1, 1, 1., 3, 24, 6, 1.09f, 200 }, // 0: pre-Telephone { 1.e9f, 1, 300, 24, 6.0, 0.5, 0, 100, 7570, 1, 1, 1., 3, 20, 6, 0.77f, 180 }, // 1: pre-Telephone { 1.e9f, 1, 400, 18, 9.0, 2.0, 0, 94, 10300, 1, 1, 1., 4, 18, 6, 0.55f, 160 }, // 2: Telephone { 50.0f, 2, 430, 12, 12.0, 3.5, 0, 88, 13090, 1, 1, 1., 5, 15, 6, 0.39f, 140 }, // 3: Thumb { 15.0f, 2, 440, 6, 15.0, 5.0, 0, 82, 15800, 1, 1, 1., 6, 10, 6, 0.27f, 120 }, // 4: Radio { 5.0f, 2, 550, 0, 18.0, 6.5, 1, 76, 19980, 1, 2, 1., 11, 9, 6, 0.00f, 100 }, // 5: Standard { 4.0f, 2, 560, -6, 21.0, 8.0, 2, 70, 22000, 1, 2, 1., 12, 7, 6, 0.00f, 80 }, // 6: Xtreme { 3.0f, 2, 570, -12, 24.0, 9.5, 3, 64, 24000, 1, 2, 2., 13, 5, 6, 0.00f, 60 }, // 7: Insane { 2.8f, 2, 580, -18, 27.0, 11.0, 4, 58, 26000, 1, 2, 4., 13, 4, 6, 0.00f, 40 }, // 8: BrainDead { 2.6f, 2, 590, -24, 30.0, 12.5, 5, 52, 28000, 1, 2, 8., 13, 4, 6, 0.00f, 20 }, // 9: post-BrainDead { 2.4f, 2, 599, -30, 33.0, 14.0, 6, 46, 30000, 1, 2, 16., 15, 2, 6, 0.00f, 10 }, //10: post-BrainDead }; static int TestProfileParams ( void ) { // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 static signed char TMNStereoAdj [] = { -6, -18, -15, -18, -12, -9, -6, 0,0,0, +1, +1, +1, +1, 0, +1 }; // Penalties for TMN static signed char NMTStereoAdj [] = { -3, -18, -15, -15, -9, -6, -3, 0,0,0, 0, +1, +1, +1, 0, +1 }; // Penalties for NMT int i; MainQual = PROFILE_PRE2_TELEPHONE; for ( i = PROFILE_PRE2_TELEPHONE; i <= PROFILE_POST2_BRAINDEAD; i++ ) { if ( ShortThr > Profiles [i].ShortThr ) continue; if ( MinValChoice < Profiles [i].MinValChoice ) continue; if ( EarModelFlag < Profiles [i].EarModelFlag ) continue; if ( Ltq_offset > Profiles [i].Ltq_offset ) continue; if ( Ltq_max > Profiles [i].Ltq_max ) continue; // offset should normally be considered here if ( TMN + TMNStereoAdj [MS_Channelmode] < Profiles [i].TMN + TMNStereoAdj [Profiles [i].MS_Channelmode] ) continue; if ( NMT + NMTStereoAdj [MS_Channelmode] < Profiles [i].NMT + NMTStereoAdj [Profiles [i].MS_Channelmode] ) continue; if ( minSMR < Profiles [i].minSMR ) continue; if ( Bandwidth < Profiles [i].BandWidth ) continue; if ( tmpMask_used < Profiles [i].tmpMask_used ) continue; if ( CVD_used < Profiles [i].CVD_used ) continue; // if ( varLtq > Profiles [i].varLtq ) continue; // if ( NS_Order < Profiles [i].NS_Order ) continue; if ( PNS > Profiles [i].PNS ) continue; MainQual = i; } return MainQual; } static void SetQualityParams ( float qual ) { int i; float mix; if ( qual < 0. ) { qual = 0.; } if ( qual > 10. ) { qual = 10.; #ifdef _WIN32 stderr_printf ( "\nmppenc: Can't open MACDll.dll, quality set to 10.0\n" ); #else stderr_printf ( "\nmppenc: Can't open libMAC.so, quality set to 10.0\n" ); #endif } i = (int) qual + PROFILE_PRE2_TELEPHONE; mix = qual - (int) qual; MainQual = i; ShortThr = Profiles [i].ShortThr * (1-mix) + Profiles [i+1].ShortThr * mix; MinValChoice = Profiles [i].MinValChoice ; EarModelFlag = Profiles [i].EarModelFlag ; Ltq_offset = Profiles [i].Ltq_offset * (1-mix) + Profiles [i+1].Ltq_offset * mix; varLtq = Profiles [i].varLtq * (1-mix) + Profiles [i+1].varLtq * mix; Ltq_max = Profiles [i].Ltq_max * (1-mix) + Profiles [i+1].Ltq_max * mix; TMN = Profiles [i].TMN * (1-mix) + Profiles [i+1].TMN * mix; NMT = Profiles [i].NMT * (1-mix) + Profiles [i+1].NMT * mix; minSMR = Profiles [i].minSMR ; Bandwidth = Profiles [i].BandWidth * (1-mix) + Profiles [i+1].BandWidth * mix; tmpMask_used = Profiles [i].tmpMask_used ; CVD_used = Profiles [i].CVD_used ; MS_Channelmode = Profiles [i].MS_Channelmode; CombPenalities = Profiles [i].CombPenalities; NS_Order = Profiles [i].NS_Order ; PNS = Profiles [i].PNS * (1-mix) + Profiles [i+1].PNS * mix; TransDetect = Profiles [i].TransDetect* (1-mix) + Profiles [i+1].TransDetect* mix; } /* Planned: return the evaluated options, without InputFile and OutputFile, argc implicit instead of explicit */ static int EvalParameters ( int argc, char** argv, char** InputFile, char** OutputFile, int onlyfilenames ) { int k; size_t len; static char output [2048]; static char errmsg [] = "\n\033[33;41;1mERROR\033[0m: Missing argument for option '--%s'\n\n"; FILE* fp; char* p; char buff [32768]; /********************************* In / Out Files *********************************/ *InputFile = argv [argc-1]; *OutputFile = NULL; // search for output file if ( argc >= 3 ) { len = strlen (argv[argc-1]); if ( strcmp (argv[argc-1], "/dev/null") == 0 || strcmp (argv[argc-1], "-") == 0 || (len >= 4 && (0 == strcasecmp (argv [argc-1] + len - 4, ".MPC") || 0 == strcasecmp (argv [argc-1] + len - 4, ".MPP") || 0 == strcasecmp (argv [argc-1] + len - 4, ".MP+"))) ) { *OutputFile = argv[argc-1]; *InputFile = argv[argc-2]; argc -= 2; } } // if no Output-File is stated, set OutFile to InFile.mpc if ( *OutputFile == NULL ) { strcpy ( *OutputFile = output, *InputFile ); len = strlen ( output ); if ( len > 4 && output[len-4] == '.' ) len -= 4; strcpy (output+len, ".mpc"); argc -= 1; } if ( onlyfilenames ) return 0; /********************************* In / Out Files *********************************/ // search for options for ( k = 1; k < argc; k++ ) { const char* arg = argv [k]; if ( arg[0] != '-' || arg[1] != '-' ) continue; arg += 2; if ( 0 == strcmp ( arg, "verbose" ) ) { // verbose verbose++; } else if ( 0 == strcmp ( arg, "telephone" ) ) { // MainQual SetQualityParams (2.0); } else if ( 0 == strcmp ( arg, "thumb" ) ) { // MainQual SetQualityParams (3.0); } else if ( 0 == strcmp ( arg, "radio" ) ) { SetQualityParams (4.0); } else if ( 0 == strcmp ( arg, "standard") || 0 == strcmp ( arg, "normal") ) { SetQualityParams (5.0); } else if ( 0 == strcmp ( arg, "xtreme") || 0 == strcmp ( arg, "extreme") ) { SetQualityParams (6.0); } else if ( 0 == strcmp ( arg, "insane") ) { SetQualityParams (7.0); } else if ( 0 == strcmp ( arg, "braindead") ) { SetQualityParams (8.0); } else if ( 0 == strcmp ( arg, "quality") ) { // Quality if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } SetQualityParams (atof (argv[k]) ); } else if ( 0 == strcmp ( arg, "neveroverwrite") ) { // NeverOverWrite WriteMode = MODE_NEVER_OVERWRITE; } else if ( 0 == strcmp ( arg, "forcewrite") || 0 == strcmp ( arg, "overwrite") ) { // ForceWrite WriteMode = MODE_OVERWRITE; } else if ( 0 == strcmp ( arg, "interactive") ) { // Interactive WriteMode = MODE_ASK_FOR_OVERWRITE; } else if ( 0 == strcmp ( arg, "delinput") || 0 == strcmp ( arg, "delete") || 0 == strcmp ( arg, "deleteinput" ) ) { // DelInput DelInput = 0xAFFEDEAD; } else if ( 0 == strcmp ( arg, "beep") ) { IsEndBeep = 1; } else if ( 0 == strcmp ( arg, "scale") ) { // ScalingFactor if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } ScalingFactorl = ScalingFactorr = (float) atof (argv[k]); if (strchr (argv[k], ',')) ScalingFactorr = (float) atof (strchr (argv[k], ',') + 1); if ( ScalingFactorl == 0.97f || ScalingFactorl == 0.98f ) stderr_printf ("--scale 0.97 or --scale 0.98 is nearly useless to prevent clipping. Use replaygain tool\nto determine EXACT attenuation to avoid clipping. Factor can be between 0.696 and 1.000.\nSee \"http://www.uni-jena.de/~pfk/mpp/clipexample.html\".\n\n" ); } else if ( 0 == strcmp ( arg, "kbd") ) { // ScalingFactor if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } if ( 2 != sscanf ( argv[k], "%f,%f", &KBD1, &KBD2 )) { stderr_printf ( "%s: missing two arguments", arg ); return -1; } Init_FFT (); } else if ( 0 == strcmp ( arg, "fadein") ) { // FadeInTime if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } FadeInTime = (float) atof (argv[k]); if ( FadeInTime < 0.f ) FadeInTime = 0.f; } else if ( 0 == strcmp ( arg, "fadeout") ) { // FadeOutTime if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } FadeOutTime = (float) atof (argv[k]); if ( FadeOutTime < 0.f ) FadeOutTime = 0.f; } else if ( 0 == strcmp ( arg, "fade") ) { // FadeInTime + FadeOutTime if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } FadeOutTime = (float) atof (argv[k]); if ( FadeOutTime < 0.f ) FadeOutTime = 0.f; FadeInTime = FadeOutTime; } else if ( 0 == strcmp ( arg, "fadeshape") ) { // FadeOutTime if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } FadeShape = (float) atof (argv[k]); if ( FadeShape < 0.001f || FadeShape > 1000.f ) FadeShape = 1.f; setbump ( FadeShape ); } else if ( 0 == strcmp ( arg, "skip") || 0 == strcmp ( arg, "start") ) { // SkipTime if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } SkipTime = (float) atof (argv[k]); } else if ( 0 == strcmp ( arg, "dur") || 0 == strcmp ( arg, "duration") ) { // maximum Duration if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } Duration = atof (argv[k]); } else if ( 0 == strcmp ( arg, "ans") ) { // AdaptiveNoiseShaping if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } NS_Order = atoi (argv[k]); NS_Order = mini ( NS_Order, MAX_NS_ORDER ); } else if ( 0 == strcmp ( arg, "predict") ) { // AdaptiveNoiseShaping if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } PredictionBands = atoi (argv[k]); PredictionBands = mini ( PredictionBands, 32 ); } else if ( 0 == strcmp ( arg, "ltq_var") || 0 == strcmp ( arg, "ath_var") ) { // ltq_var if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } varLtq = atof (argv[k]); } else if ( 0 == strcmp ( arg, "pns") ) { // pns if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } PNS = atof (argv[k]); } else if ( 0 == strcmp ( arg, "minval") ) { // MinValChoice if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } MinValChoice = atoi (argv[k]); } else if ( 0 == strcmp ( arg, "transdet") ) { // TransDetect if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } TransDetect = (float) atof (argv[k]); } else if ( 0 == strcmp ( arg, "shortthr") ) { // ShortThr if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } ShortThr = (float) atof (argv[k]); } else if ( 0 == strcmp ( arg, "noxlevel") ) { // Xlevel XLevel = 0; } else if ( 0 == strcmp ( arg, "xlevel") ) { // Xlevel stderr_printf ( "\nXlevel coding now enabled by default, --xlevel ignored.\n" ); } else if ( 0 == strcmp ( arg, "nmt") ) { // NMT if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } NMT = (float) atof (argv[k]); } else if ( 0 == strcmp ( arg, "tmn") ) { // TMN if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } TMN = (float) atof (argv[k]); } else if ( 0 == strcmp ( arg, "cvd") ) { // ClearVoiceDetection if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } CVD_used = atoi (argv[k]); if ( CVD_used == 0 ) stderr_printf ( "\nDisabling CVD always reduces quality!\a\n" ); } else if ( 0 == strcmp ( arg, "ms") ) { // Mid/Side Stereo if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } MS_Channelmode = atoi (argv[k]); } else if ( 0 == strcmp ( arg, "minSMR") ) { // minimum SMR if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } if ( minSMR > (float) atof (argv[k]) ) stderr_printf ( "This option usage may reduces quality!\a\n" ); minSMR = (float) atof (argv[k]); } else if ( 0 == strcmp ( arg, "tmpMask") ) { // temporal post-masking if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } tmpMask_used = atoi (argv[k]); } else if ( 0 == strcmp ( arg, "ltq_max") || 0 == strcmp ( arg, "ath_max") ) { // Maximum for threshold in quiet if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } Ltq_max = (float) atof (argv[k]); } else if ( 0 == strcmp ( arg, "ltq_gain") || 0 == strcmp ( arg, "ath_gain") ) {// Offset for threshold in quiet if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } Ltq_offset = (float) atof (argv[k]); } else if ( 0 == strcmp ( arg, "silent") || 0 == strcmp ( arg, "quiet") ) { SetStderrSilent (1); } else if ( 0 == strcmp ( arg, "stderr") ) { // Offset for threshold in quiet if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } freopen ( argv[k], "a", stderr ); } else if ( 0 == strcmp ( arg, "ltq") || 0 == strcmp ( arg, "ath") ) { // threshold in quiet if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } EarModelFlag = atoi (argv[k]); } else if ( 0 == strcmp ( arg, "noco") ) { NoiseInjectionComp (); } else if ( 0 == strcmp ( arg, "newcomb") ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } CombPenalities = atoi (argv[k]); } else if ( 0 == strcmp ( arg, "ape1") ) { // Mark APE as APE 1.000 APE_Version = 1000; } else if ( 0 == strcmp ( arg, "ape2") ) { // Mark APE as APE 2.000 APE_Version = 2000; } else if ( 0 == strcmp ( arg, "unicode") ) { // no tag conversion NoUnicode = 0; } else if ( 0 == strcmp ( arg, "lowdelay") ) { LowDelay = 1; } else if ( 0 == strcmp ( arg, "bw") || 0 == strcmp ( arg, "lowpass") ) { // bandwidth if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } Bandwidth = atof (argv[k]); } else if ( 0 == strcmp ( arg, "displayupdatetime") ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } DisplayUpdateTime = atoi (argv[k]); } else if ( 0 == strcmp ( arg, "artist" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Artist", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "album" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Album", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "debutalbum" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Debut Album", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "publisher" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Publisher", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "conductor" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Conductor", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "title" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Title", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "subtitle" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Subtitle", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "track" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Track", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "comment" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Comment", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "composer" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Composer", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "copyright" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Copyright", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "publicationright" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Publicationright", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "filename" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "File", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "recordlocation" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Record Location", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "recorddate" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Record Date", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "ean/upc" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "EAN/UPC", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "year" ) || 0 == strcmp ( arg, "releasedate") ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Year", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "genre" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Genre", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "media" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Media", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "index" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Index", 0, p, strlen(p), NoUnicode*3, 0 ); } else if ( 0 == strcmp ( arg, "isrc" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "ISRC", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "abstract" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Abstract", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "bibliography" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Bibliography", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "introplay" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Introplay", 0, p, strlen(p), NoUnicode*3, 0 ); } else if ( 0 == strcmp ( arg, "media" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = argv[k]; addtag ( "Media", 0, p, strlen(p), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "tag" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = strchr ( argv[k], '=' ); if ( p == NULL ) addtag ( argv[k], strlen(argv[k]), "", 0, NoUnicode, 0 ); else addtag ( argv[k], p-argv[k], p+1, strlen(p+1), NoUnicode, 0 ); } else if ( 0 == strcmp ( arg, "tagfile" ) ) { if ( ++k >= argc ) { stderr_printf ( errmsg, arg ); return -1; } p = strchr ( argv[k], '=' ); if ( p == NULL ) { stderr_printf (" Enter value for tag key '%s': ", argv[k] ); fgets ( buff, sizeof buff, stdin ); len = strlen (buff); while ( len > 0 && (buff [len-1] == '\r' || buff [len-1] == '\n') ) len--; addtag ( arg, strlen(arg), buff, len, NoUnicode*6, 0 ); } else { fp = fopen ( p+1, "rb" ); if ( fp == NULL ) { fprintf ( stderr, "Can't open file '%s'.\n", p+1 ); } else { addtag ( argv[k], p-argv[k], buff, fread (buff,1,sizeof buff,fp), NoUnicode*2, 3 ); fclose (fp); } } } else { char c; stderr_printf ( "\n\033[33;41;1mERROR\033[0m: unknown option '--%s' !\n", arg ); stderr_printf ( "\nNevertheless continue with encoding (Y/n)? \a" ); c = waitkey (); if ( c != 'Y' && c != 'y' ) { stderr_printf ( "\n\n*** Abort ***\n" ); return -1; } stderr_printf ( "\n" ); } } TestProfileParams (); return 0; } static void ShowParameters ( char* inDatei, char* outDatei ) { static const char unk [] = "???"; static const char* EarModel [] = { "ISO (bad!!!)", "Busch", "Filburt", "Klemm", "Klemm/Busch mix", "min(Klemm,Busch)" }; static const char th [ 7] [4] = { "no", "1st", "2nd", "3rd", "4th", "5th", "6th" }; static const char able [ 3] [9] = { "Disabled", "Enabled", "Dual" }; static const char* stereo [16] = { "Simple uncoupled Stereo", "Mid/Side Stereo + Intensity Stereo 2 bit", "Mid/Side Stereo + Intensity Stereo 4 bit", "Mid/Side Stereo, destroyed imaging (unusable)", "Mid/Side Stereo, much reduced imaging", "Mid/Side Stereo, reduced imaging (-3 dB)", "Mid/Side Stereo when superior", unk, unk, unk, "Mid/Side Stereo when superior + enhanced (1.5/3 dB)", "Mid/Side Stereo when superior + enhanced (2/6 dB)", "Mid/Side Stereo when superior + enhanced (2.5/9 dB)", "Mid/Side Stereo when superior + enhanced (3/12 dB)", unk, "Mid/Side Stereo when superior + enhanced (3/oo dB)" }; static const char* const Profiles [16] = { "n.a", "Unstable/Experimental", unk, unk, unk, "below Telephone", "below Telephone", "Telephone", "Thumb", "Radio", "Standard", "Xtreme", "Insane", "BrainDead", "above BrainDead", "above BrainDead" }; stderr_printf ( "\n" " encoding file '%s'\n" " to file '%s'\n" "\n" " SV %u.%u%s, Profile '%s'\n", inDatei, outDatei, 7, PNS > 0 ? 1 : 0, XLevel ? " + XLevel coding" : "", Profiles [MainQual] ); if ( verbose > 0 ) { stderr_printf ( "\n" ); if ( FadeInTime != 0. || FadeOutTime != 0. || verbose > 1 ) stderr_printf ( " PCM fader : fade-in: %.2f s, fade-out: %.2f s, shape: %g\n", FadeInTime, FadeOutTime, FadeShape ); if ( ScalingFactorr != 1. || ScalingFactorl != 1. || verbose > 1 ) stderr_printf ( " Scaling input by : left %.5f, right: %.5f\n", ScalingFactorl, ScalingFactorr ); stderr_printf ( " Maximum encoded bandwidth: %4.1f kHz\n", (Max_Band+1) * (SampleFreq/32./2000.) ); stderr_printf ( " Adaptive Noise Shaping : max. %s order\n", th [NS_Order] ); stderr_printf ( " Clear Voice Detection : %s\n", able [CVD_used] ); stderr_printf ( " Mid/Side Stereo : %s\n", stereo [MS_Channelmode] ); stderr_printf ( " Threshold of Hearing : Model %3u: %s, Max ATH: %2.0f dB, Offset: %+1.0f dB, +Offset@20 kHz:%3.0f dB\n", EarModelFlag, EarModelFlag/100 < sizeof(EarModel)/sizeof(*EarModel) ? EarModel [EarModelFlag/100] : unk, Ltq_max, Ltq_offset, -0.6 * (int) (EarModelFlag % 100 - 50) ); if ( NMT != 6.5 || verbose > 1 ) stderr_printf ( " Noise masks Tone Ratio : %4.1f dB\n", NMT ); if ( TMN != 18.0 || verbose > 1 ) stderr_printf ( " Tone masks Noise Ratio : %4.1f dB\n", TMN ); if ( PNS > 0 ) stderr_printf ( " PNS Threshold : %4.2f\n", PNS ); if ( !tmpMask_used ) stderr_printf ( " No exploitation of temporal post masking\n" ); else if ( verbose > 1 ) stderr_printf ( " Exploitation of temporal post masking\n" ); if ( minSMR > 0. ) stderr_printf ( " Minimum Signal-to-Mask : %4.1f dB\n", minSMR ); else if ( verbose > 1 ) stderr_printf ( " No minimum SMR (psycho model controlled filtering)\n" ); if ( DelInput == 0xAFFEDEAD ) stderr_printf ( " Deleting input file after (successful) encoding\n" ); else if ( verbose > 1 ) stderr_printf ( " No deleting of input file after encoding\n" ); } stderr_printf ( "\n" ); } /* * Print out the time to stderr with a precision of 10 ms always using * 12 characters. Time is represented by the sample count. An additional * prefix character (normally ' ' or '-') is prepended before the first * digit. */ static const char* PrintTime ( UintMax_t samples, int sign ) { static char ret [32]; Ulong tmp = (Ulong) ( UintMAX_FP(samples) * 100. / SampleFreq ); Uint hour = (Uint) ( tmp / 360000 ); Uint min = (Uint) ( tmp / 6000 % 60 ); Uint sec = (Uint) ( tmp / 100 % 60 ); Uint csec = (Uint) ( tmp % 100 ); if ( UintMAX_FP(samples) >= SampleFreq * 360000. ) return " "; else if ( hour > 9 ) sprintf ( ret, "%c%2u:%02u", sign, hour, min ); else if ( hour > 0 ) sprintf ( ret, " %c%1u:%02u", sign, hour, min ); else if ( min > 9 ) sprintf ( ret, " %c%2u", sign, min ); else sprintf ( ret, " %c%1u", sign, min ); sprintf ( ret + 6, ":%02u.%02u", sec, csec ); return ret; } static void ShowProgress ( UintMax_t samples, UintMax_t total_samples, UintMax_t databits ) { static clock_t start; clock_t curr; float percent; float kbps; float speed; float total_estim; if ( samples == 0 ) { if ( DisplayUpdateTime >= 0 ) { stderr_printf (" %%|avg.bitrate| speed|play time (proc/tot)| CPU time (proc/tot)| ETA\n" " -.- -.- kbps -.--x -:--.- -:--.- -:--.- -:--.- -:--.-\r" ); } start = clock (); return; } curr = clock (); if ( curr == start ) return; percent = 100.f * UintMAX_FP(samples) / UintMAX_FP(total_samples); kbps = 1.e-3f * UintMAX_FP(databits) * SampleFreq / UintMAX_FP(samples); speed = 1.f * UintMAX_FP(samples) * (CLOCKS_PER_SEC / SampleFreq) / (unsigned long)(curr - start) ; total_estim = 1.f * UintMAX_FP(total_samples) / UintMAX_FP(samples) * (unsigned long)(curr - start); // progress percent if ( total_samples < IntMax_MAX ) stderr_printf ("\r%5.1f ", percent ); else stderr_printf ("\r " ); // average data rate stderr_printf ( "%6.1f kbps ", kbps ); // encoder speed stderr_printf ( "%5.2fx ", speed ); // 2x duration in WAVE file time (encoded/total) stderr_printf ("%10.10s" , PrintTime ( samples , (char)' ')+1 ); stderr_printf ("%10.10s ", PrintTime ( total_samples, (char)' ')+1 ); // 2x coding time (encoded/total) stderr_printf ("%10.10s" , PrintTime ( (curr - start) * (SampleFreq/CLOCKS_PER_SEC), (char)' ')+1 ); stderr_printf ("%10.10s ", PrintTime ( total_estim * (SampleFreq/CLOCKS_PER_SEC), (char)' ')+1 ); // ETA stderr_printf ( "%10.10s\r", samples < total_samples ? PrintTime ((total_estim - curr + start) * (SampleFreq/CLOCKS_PER_SEC), (char)' ')+1 : "" ); fflush ( stderr ); if ( WIN32_MESSAGES && FrontendPresent ) SendProgressMessage ( kbps, speed, percent ); } static int myfeof ( FILE* fp ) { int ch; if ( fp != (FILE*)-1 ) return feof (fp); ch = CheckKeyKeep (); if ( ch == 'q' || ch == 'Q' ) return 1; return 0; } static void fill_float(float * buffer,float val,unsigned count) { unsigned n; for(n=0;n 32 ) { stderr_printf ( "\033[33;41;1mERROR\033[0m: %i bits per sample are not supported!\n\n", Wave.BitsPerSample ); return 1; } switch ( Wave.Channels ) { case 0: stderr_printf ( "\033[33;41;1mERROR\033[0m: 0 channels file, this is nonsense\n\n" ); return 1; case 1: case 2: break; case 3: case 4: case 5: case 6: case 7: case 8: stderr_printf ( "WARNING: %i channel(s) file, only first 2 channels are encoded.\n\n", Wave.Channels ); break; default: stderr_printf ( "\033[33;41;1mERROR\033[0m: %i channel(s) file, not supported\n\n", Wave.Channels ); return 1; } SetQualityParams (5.0); if ( EvalParameters ( argc, argv, &InputName, &OutputName, 0 ) < 0 ) return 1; if ( UintMAX_FP(SamplesInWAVE) >= Wave.SampleFreq * (SkipTime + Duration) ) { SamplesInWAVE = Wave.SampleFreq * (SkipTime + Duration); } Init_Psychoakustiktabellen (); // must be done AFTER decoding command line parameters // check fade-length if ( FadeInTime + FadeOutTime > UintMAX_FP(SamplesInWAVE) / Wave.SampleFreq ) { stderr_printf ( "WARNING: Duration of fade in + out exceeds file length!\n"); FadeInTime = FadeOutTime = 0.5 * UintMAX_FP(SamplesInWAVE) / Wave.SampleFreq; } /* open bitstream file */ if ( 0 == strcmp ( OutputName, "/dev/null") ) { OutputFile = fopen (DEV_NULL, "wb"); } else if ( 0 == strcmp ( OutputName, "-") || 0 == strcmp ( OutputName, "/dev/stdout") ) { OutputFile = SETBINARY_OUT (stdout); } else switch ( WriteMode ) { default: stderr_printf ( "\033[33;41;1mERROR\033[0m: Invalid Write mode, internal error\n" ); return 1; case MODE_NEVER_OVERWRITE: OutputFile = fopen ( OutputName, "rb" ); if ( OutputFile != NULL ) { fclose ( OutputFile ); stderr_printf ( "\033[33;41;1mERROR\033[0m: Output file '%s' already exists\n", OutputName ); return 1; } OutputFile = fopen ( OutputName, "w+b" ); break; case MODE_OVERWRITE: OutputFile = fopen ( OutputName, "w+b" ); break; case MODE_ASK_FOR_OVERWRITE: OutputFile = fopen ( OutputName, "rb" ); if ( OutputFile != NULL ) { char c; fclose ( OutputFile ); stderr_printf ( "\nmppenc: Output file '%s' already exists, overwrite (Y/n)? ", OutputName ); c = waitkey (); if ( c != 'Y' && c != 'y' ) { stderr_printf ( "No!!!\n\n*** Canceled overwrite ***\n" ); return 1; } stderr_printf ( " YES\n" ); } OutputFile = fopen ( OutputName, "w+b" ); break; } if ( OutputFile == NULL ) { stderr_printf ( "\033[33;41;1mERROR\033[0m: Could not create output file '%s'\n", OutputName ); return 1; } #ifndef IO_BUFFERING setvbuf ( OutputFile, NULL, _IONBF, 0 ); #endif ShowParameters ( InputName, OutputName ); if ( WIN32_MESSAGES && FrontendPresent ) SendModeMessage (MainQual); if ( SkipTime > 0. ) { unsigned long SkipSamples = SampleFreq * SkipTime; ssize_t read; while ( SkipSamples > 0 ) { read = Read_WAV_Samples ( &Wave, mini(BLOCK, SkipSamples), &Main, CENTER, ScalingFactorl, ScalingFactorr, &Silence ); if ( read <= 0 ) break; SkipSamples -= read; SamplesInWAVE -= read; } } BufferedBits = 0; LastValidFrame = (SamplesInWAVE + BLOCK - 1) / BLOCK; LastValidSamples = (SamplesInWAVE + BLOCK - 1) - BLOCK * LastValidFrame + 1; WriteHeader_SV7 ( Max_Band, MainQual, MS_Channelmode > 0, LastValidFrame, LastValidSamples, PNS > 0 ? 0x17 : 0x07, SampleFreq ); // initialize timer ShowProgress ( 0, SamplesInWAVE, BufferedBits ); T = time ( NULL ); // read samples CurrentRead = Read_WAV_Samples ( &Wave, (int)minf(BLOCK, SamplesInWAVE - AllSamplesRead), &Main, CENTER, ScalingFactorl, ScalingFactorr, &Silence ); AllSamplesRead += CurrentRead; if (CurrentRead > 0) { fill_float( Main.L, Main.L[CENTER], CENTER ); fill_float( Main.R, Main.R[CENTER], CENTER ); fill_float( Main.M, Main.M[CENTER], CENTER ); fill_float( Main.S, Main.S[CENTER], CENTER ); } Analyse_Init ( Main.L[CENTER], Main.R[CENTER], X, Max_Band ); // adapt SamplesInWAVE to the real number of contained samples if ( myfeof (Wave.fp) ) { stderr_printf ( "WAVE file has incorrect header: header: %.3f s, contents: %.3f s \n", UintMAX_FP(AllSamplesRead) / SampleFreq, UintMAX_FP(SamplesInWAVE) / SampleFreq ); SamplesInWAVE = AllSamplesRead; // in the case of a broken wav-header, recalculate the overall frames // and the valid samples for the last frame LastValidFrame = (SamplesInWAVE + BLOCK - 1) / BLOCK; LastValidSamples = (SamplesInWAVE + BLOCK - 1) - BLOCK * LastValidFrame + 1; // fprintf ( stderr, "\nKorrupt WAV file in Frame %d: NEU!: Frames: %u, last valid: %u\n", -1, LastValidFrame, LastValidSamples ); } for ( N = 0; (UintMax_t)N * BLOCK < SamplesInWAVE + DECODER_DELAY; N++ ) { // setting residual data-fields to zero if ( CurrentRead < BLOCK && N > 0 ) { fill_float( Main.L + (CENTER + CurrentRead), Main.L[CENTER + CurrentRead - 1], BLOCK - CurrentRead ); fill_float( Main.R + (CENTER + CurrentRead), Main.R[CENTER + CurrentRead - 1], BLOCK - CurrentRead ); fill_float( Main.M + (CENTER + CurrentRead), Main.M[CENTER + CurrentRead - 1], BLOCK - CurrentRead ); fill_float( Main.S + (CENTER + CurrentRead), Main.S[CENTER + CurrentRead - 1], BLOCK - CurrentRead ); } /*********************************************************************************/ /* Fade In and Fade Out */ /*********************************************************************************/ if ( FadeInTime > 0. ) if ( FadeInTime > UintMAX_FP(BLOCK + (UintMax_t)N*BLOCK) / Wave.SampleFreq ) Fading_In ( &Main, N*BLOCK, Wave.SampleFreq ); if ( FadeOutTime > 0. ) if ( FadeOutTime > UintMAX_FP(SamplesInWAVE - (UintMax_t)N*BLOCK) / Wave.SampleFreq ) Fading_Out ( &Main, N*BLOCK, Wave.SampleFreq ); /********************************************************************/ /* Encoder-Core */ /********************************************************************/ // you only get null samples at the output of the filterbank when the last frame contains zeroes memset ( Res_L, 0, sizeof Res_L ); memset ( Res_R, 0, sizeof Res_R ); if ( !Silence || !OldSilence ) { Analyse_Filter ( &Main, X, Max_Band ); // Analysis-Filterbank (Main -> X) SMR = Psychoakustisches_Modell ( Max_Band*0+31, &Main, TransientL, TransientR ); // Psychoacoustics return SMRs for input data 'Main' if ( minSMR > 0 ) RaiseSMR ( Max_Band, &SMR ); // Minimum-operation on SBRs (full bandwidth) if ( MS_Channelmode > 0 ) MS_LR_Entscheidung ( Max_Band, MS_Flag, &SMR, X ); // Selection of M/S- or L/R-Coding SCF_Extraktion ( Max_Band, X ); // Extraction of the scalefactors and normalization of the subband samples TransientenCalc ( Transient, TransientL, TransientR ); if ( NS_Order > 0 ) { NS_Analyse ( Max_Band, MS_Flag, SMR, Transient ); // calculate possible ANS-Filter and the expected gain } Allocate ( Max_Band, Res_L, X[0].L, SCF_Index_L[0], SNR_comp_L, SMR.L, Power_L, Transient ); // allocate bits for left + right channel Allocate ( Max_Band, Res_R, X[0].R, SCF_Index_R[0], SNR_comp_R, SMR.R, Power_R, Transient ); Quantisierung ( Max_Band, Res_L, Res_R, X, Q ); // quantize samples } if ( Zaehler >= BUFFER_ALMOST_FULL || LowDelay ) { FlushBitstream ( OutputFile, Buffer, Zaehler ); Zaehler = 0; } OldSilence = Silence; OldBufferedBits = BufferedBits; GetBitstreamPos ( &bitstreampos ); WriteBits ( 0, 20 ); // Reserve 20 bits for jump-information WriteBitstream_SV7 ( Max_Band, Q ); // write SV7-Bitstream WriteBitsAt ( (Uint32_t)(BufferedBits - OldBufferedBits - 20), 20, bitstreampos ); // Patch 20 bits for jump-information to the right value if ( (Int)(time (NULL) - T) >= 0 ) { // output T += labs (DisplayUpdateTime); ShowProgress ( (UintMax_t)(N+1) * BLOCK, SamplesInWAVE, BufferedBits ); } // for backwards-compatibility with older decoders write the 11 bit for // reconstruction of exact filelength before the very last frame memmove ( Main.L, Main.L + BLOCK, CENTER * sizeof(float) ); memmove ( Main.R, Main.R + BLOCK, CENTER * sizeof(float) ); memmove ( Main.M, Main.M + BLOCK, CENTER * sizeof(float) ); memmove ( Main.S, Main.S + BLOCK, CENTER * sizeof(float) ); //if ( AllSamplesRead + BLOCK > SamplesInWAVE ) //{ // int n = 0; //} // read samples CurrentRead = Read_WAV_Samples ( &Wave, (int)minf(BLOCK, SamplesInWAVE - AllSamplesRead), &Main, CENTER, ScalingFactorl, ScalingFactorr, &Silence ); AllSamplesRead += CurrentRead; // adapt SamplesInWAV to the real number of contained samples if ( myfeof (Wave.fp) ) { stderr_printf ( "WAVE file has incorrect header: header: %.3f s, contents: %.3f s \n", UintMAX_FP(AllSamplesRead) / SampleFreq, UintMAX_FP(SamplesInWAVE) / SampleFreq ); SamplesInWAVE = AllSamplesRead; // in the case of broken wav-header, recalculate the overall frames // and the valid samples for the last frame LastValidFrame = (SamplesInWAVE + BLOCK - 1) / BLOCK; LastValidSamples = (SamplesInWAVE + BLOCK - 1) - BLOCK * LastValidFrame + 1; // fprintf ( stderr, "\nKorrupt WAV file in Frame %d: NEU!: Frames: %u, last valid: %u\n", N, LastValidFrame, LastValidSamples ); } if ( N == LastValidFrame - 1 ) { WriteBits ( LastValidSamples, 11 ); // fprintf ( stderr, "\nGültige Samples im letzten Frame: %4u \n", LastValidSamples ); } if ( N >= LastValidFrame ) { // fprintf ( stderr, "Zusätzlicher Frame %u (von %u) angehängt. \n", N, LastValidFrame ); } } LEAVE(2); // write the last incomplete word to buffer, so it's written during the next flush FinishBitstream(); ShowProgress ( SamplesInWAVE, SamplesInWAVE, BufferedBits ); FlushBitstream ( OutputFile, Buffer, Zaehler ); Zaehler = 0; UpdateHeader ( OutputFile, LastValidFrame, LastValidSamples ); FinalizeTags ( OutputFile, APE_Version ); fclose ( OutputFile ); fclose ( Wave.fp ); if ( DelInput == 0xAFFEDEAD && remove (InputName) == -1 ) // delete input file if DelInput is active stderr_printf ( "\n\n\033[33;41;1mERROR\033[0m: Could not delete input file '%s'\n", InputName ); if ( WIN32_MESSAGES && FrontendPresent ) SendQuitMessage (); stderr_printf ( "\n" ); return 0; } void OverdriveReport ( void ) { if ( Overflows > 0 ) { // report internal clippings if ( XLevel == 0 ) { stderr_printf ( "\n" "\033[1m\rWARNING:\n" "\033[0m\r %u internal clippings occured due to a restriction of StreamVersion 7.\n" " Re-encode with '--scale %.3f', or remove option '--noxlevel'.\a\n\n", Overflows, ScalingFactorl * 32767. / MaxOverFlow - 0.0005f ); } else { stderr_printf ( "\n" "\033[1m\rWARNING:\n" "\033[0m\r %u internal clippings occured due to a restriction of StreamVersion 7.\n" " Use the '--scale' method to avoid additional distortions. Note that this\n" " file already has annoying distortions due to slovenly CD mastering.\a\n\n", Overflows ); } } } /************ The main() function *****************************/ int Cdecl main ( int argc, char** argv ) { int ret; #if (defined USE_OSS_AUDIO || defined USE_ESD_AUDIO || defined USE_SUN_AUDIO) && (defined USE_REALTIME || defined USE_NICE) // DisableSUID (); #endif #ifdef _OS2 _wildcard ( &argc, &argv ); #endif if ( WIN32_MESSAGES ) { FrontendPresent = SearchForFrontend (); // search for presence of Windows Frontend if ( FrontendPresent ) SendStartupMessage ( MPPENC_VERSION, 7, MPPENC_BUILD ); } START(); ENTER(1); // Welcome message if ( argc < 2 || ( 0 != strcmp (argv[1], "--silent") && 0 != strcmp (argv[1], "--quiet")) ) (void) stderr_printf ("\r\x1B[1m\r%s\n\x1B[0m\r \r", About ); // no arguments or call for help if ( argc < 2 || 0==strcmp (argv[1],"-h") || 0==strcmp (argv[1],"-?") || 0==strcmp (argv[1],"--help") ) { SetQualityParams (5.0); dup2 ( 1, 2 ); shorthelp (); return 1; } if ( 0==strcmp (argv[1],"--longhelp") || 0==strcmp (argv[1],"-??") ) { SetQualityParams (5.0); dup2 ( 1, 2 ); longhelp (); return 1; } // initialize tables which must be initialized once and only once #ifdef FAST_MATH Init_FastMath (); // check if something has to be done for each file !! #endif Init_SV7 (); Init_Psychoakustiktabellen (); Init_Skalenfaktoren (); Init_Psychoakustik (); Init_FPU (); Init_ANS (); Klemm (); ret = mainloop ( argc, argv ); // analyze command line and do the requested work OverdriveReport (); // output a report if clipping was necessary if(IsEndBeep) stderr_printf("\a\a\a"); LEAVE(1); REPORT(); #ifdef BUGBUG reppr (); #endif return ret; } /* end of mppenc.c */ mppenc-1.16/src/tools.c0000644000175000017500000005020510522734510014275 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ /* * A list of different mixed tools * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Read_LittleEndians() * Portable file handling * Requantize_MidSideStereo(), Requantize_IntensityStereo() * Requantisation of quantized samples for synthesis filter * Resort_HuffTable(), Make_HuffTable(), Make_LookupTable() * Generating and sorting Huffman tables, making fast lookup tables */ #include #include #include "mppdec.h" #if defined HAVE_INCOMPLETE_READ && FILEIO != 1 size_t complete_read ( int fd, void* dest, size_t bytes ) { size_t bytesread = 0; size_t ret; while ( bytes > 0 ) { #if defined _WIN32 && defined USE_HTTP && !defined MPP_ENCODER ret = fd & 0x4000 ? recv ( fd & 0x3FFF, dest, bytes, 0) : read ( fd, dest, bytes ); #else ret = read ( fd, dest, bytes ); #endif if ( ret == 0 || ret == (size_t)-1 ) break; dest = (void*)(((char*)dest) + ret); bytes -= ret; bytesread += ret; } return bytesread; } #endif int isdir ( const char* Name ) { #if FILEIO == 1 return 1; #else STRUCT_STAT st; if ( STAT_CMD ( Name, &st ) != 0 ) return 0; return S_ISDIR ( st.st_mode ); #endif } /* * Change_Endian32() changes the endianess of a 32-bit memory block in-place * by swapping the byte order. This is a little bit tricky, but a well * known method which is much much faster than byte picking, especially on modern CPUs, * because it avoids memory aliasing. Note that this method * is poison for old 16-bit compilers! */ #if ENDIAN == HAVE_BIG_ENDIAN static void Change_Endian32 ( Uint32_t* dst, size_t words32bit ) { ENTER(160); for ( ; words32bit--; dst++ ) { # if INT_MAX >= 2147483647L Uint32_t tmp = *dst; tmp = ((tmp << 0x10) & 0xFFFF0000) | ((tmp >> 0x10) & 0x0000FFFF); tmp = ((tmp << 0x08) & 0xFF00FF00) | ((tmp >> 0x08) & 0x00FF00FF); *dst = tmp; # else Uint8_t tmp; tmp = ((Uint8_t*)dst)[0]; ((Uint8_t*)dst)[0] = ((Uint8_t*)dst)[3]; ((Uint8_t*)dst)[3] = tmp; tmp = ((Uint8_t*)dst)[1]; ((Uint8_t*)dst)[1] = ((Uint8_t*)dst)[2]; ((Uint8_t*)dst)[2] = tmp; # endif } LEAVE(160); return; } #endif /* ENDIAN == HAVE_BIG_ENDIAN */ /* * Read_LittleEndians() reads little endian 32-bit ints from the stream * 'fp'. Quantities are selected in 32-bit items. On big endian machines * the byte order is changed in-place after reading the data, so all is * okay. */ size_t Read_LittleEndians ( FILE_T fp, Uint32_t* dst, size_t words32bit ) { size_t wordsread; ENTER(161); wordsread = READ ( fp, dst, words32bit * sizeof(*dst) ) / sizeof(*dst); #if ENDIAN == HAVE_BIG_ENDIAN Change_Endian32 ( dst, wordsread ); #endif LEAVE(161); return wordsread; } #ifndef MPP_ENCODER /* * This is the main requantisation routine which does the following things: * * - rescaling the quantized values (int) to their original value (float) * - recalculating both stereo channels for MS stereo * * See also: Requantize_IntensityStereo() * * For performance reasons all cases are programmed separately and the code * is unrolled. * * Input is: * - Stop_Band: * the last band using MS or LR stereo * - used_MS[Band]: * MS or LR stereo flag for every band (0...Stop_Band), Value is 1 * for MS and 0 for LR stereo. * - Res[Band].{L,R}: * Quantisation resolution for every band (0...Stop_Band) and * channels (L, R). Value is 0...17. * - SCF_Index[3][Band].{L,R}: * Scale factor for every band (0...Stop_Band), subframe (0...2) * and channel (L, R). * - Q[Band].{L,R}[36] * 36 subband samples for every band (0...Stop_Band) and channel (L, R). * - SCF[64], Cc[18], Dc[18]: * Lookup tables for Scale factor and Quantisation resolution. * * Output is: * - Y_L: Left channel subband signals * - Y_R: Right channel subband signals * * These signals are used for the synthesis filter in the synth*.[ch] * files to generate the PCM output signal. */ static const float ISMatrix [32] [2] = { { 1.00000000f, 0.00000000f }, { 0.98078528f, 0.19509032f }, { 0.92387953f, 0.38268343f }, { 0.83146961f, 0.55557023f }, { 0.70710678f, 0.70710678f }, { 0.55557023f, 0.83146961f }, { 0.38268343f, 0.92387953f }, { 0.19509032f, 0.98078528f }, { 0.00000000f, 1.00000000f }, { -0.19509032f, 0.98078528f }, { -0.38268343f, 0.92387953f }, { -0.55557023f, 0.83146961f }, { -0.70710678f, 0.70710678f }, { -0.83146961f, 0.55557023f }, { -0.92387953f, 0.38268343f }, { -0.98078528f, 0.19509032f }, { -1.00000000f, 0.00000000f }, { -0.98078528f, -0.19509032f }, { -0.92387953f, -0.38268343f }, { -0.83146961f, -0.55557023f }, { -0.70710678f, -0.70710678f }, { -0.55557023f, -0.83146961f }, { -0.38268343f, -0.92387953f }, { -0.19509032f, -0.98078528f }, { -0.00000000f, -1.00000000f }, { 0.19509032f, -0.98078528f }, { 0.38268343f, -0.92387953f }, { 0.55557023f, -0.83146961f }, { 0.70710678f, -0.70710678f }, { 0.83146961f, -0.55557023f }, { 0.92387953f, -0.38268343f }, { 0.98078528f, -0.19509032f }, }; void Requantize_MidSideStereo ( Int Stop_Band, const Bool_t* used_MS ) { Int Band; // 0...Stop_Band Uint k; // 0...35 Float ML; Float MR; Float mid; Float side; ENTER(162); for ( Band = 0; Band <= Stop_Band; Band++ ) { if ( used_MS[Band] ) // MidSide coded: left channel contains Mid signal, right channel Side signal if ( Res[Band].R < -1 ) { k = 0; ML = SCF[SCF_Index[0][Band].L] * Cc[Res[Band].L]; do { mid = Q[Band].L[k] * ML; Y_L[k][Band] = mid * ISMatrix [used_MS[Band]][0]; Y_R[k][Band] = mid * ISMatrix [used_MS[Band]][1]; } while (++k < 12); ML = SCF[SCF_Index[1][Band].L] * Cc[Res[Band].L]; do { mid = Q[Band].L[k] * ML; Y_L[k][Band] = mid * ISMatrix [used_MS[Band]][0]; Y_R[k][Band] = mid * ISMatrix [used_MS[Band]][1]; } while (++k < 24); ML = SCF[SCF_Index[2][Band].L] * Cc[Res[Band].L]; do { mid = Q[Band].L[k] * ML; Y_L[k][Band] = mid * ISMatrix [used_MS[Band]][0]; Y_R[k][Band] = mid * ISMatrix [used_MS[Band]][1]; } while (++k < 36); } else if ( Res[Band].L < -1 ) { k = 0; ML = SCF[SCF_Index[0][Band].R] * Cc[Res[Band].R]; do { mid = Q[Band].R[k] * ML; Y_R[k][Band] = mid * ISMatrix [used_MS[Band]][0]; Y_L[k][Band] = mid * ISMatrix [used_MS[Band]][1]; } while (++k < 12); ML = SCF[SCF_Index[1][Band].R] * Cc[Res[Band].R]; do { mid = Q[Band].R[k] * ML; Y_R[k][Band] = mid * ISMatrix [used_MS[Band]][0]; Y_L[k][Band] = mid * ISMatrix [used_MS[Band]][1]; } while (++k < 24); ML = SCF[SCF_Index[2][Band].R] * Cc[Res[Band].R]; do { mid = Q[Band].R[k] * ML; Y_R[k][Band] = mid * ISMatrix [used_MS[Band]][0]; Y_L[k][Band] = mid * ISMatrix [used_MS[Band]][1]; } while (++k < 36); } else if ( Res[Band].L ) if ( Res[Band].R ) { // M!=0, S!=0 k = 0; ML = SCF[SCF_Index[0][Band].L] * Cc[Res[Band].L]; MR = SCF[SCF_Index[0][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = (mid = Q[Band].L[k] * ML) - (side = Q[Band].R[k] * MR); Y_L[k][Band] = mid + side; } while (++k < 12); ML = SCF[SCF_Index[1][Band].L] * Cc[Res[Band].L]; MR = SCF[SCF_Index[1][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = (mid = Q[Band].L[k] * ML) - (side = Q[Band].R[k] * MR); Y_L[k][Band] = mid + side; } while (++k < 24); ML = SCF[SCF_Index[2][Band].L] * Cc[Res[Band].L]; MR = SCF[SCF_Index[2][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = (mid = Q[Band].L[k] * ML) - (side = Q[Band].R[k] * MR); Y_L[k][Band] = mid + side; } while (++k < 36); } else { // M!=0, S=0 k = 0; ML = SCF[SCF_Index[0][Band].L] * Cc[Res[Band].L]; do { Y_R[k][Band] = Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 12); ML = SCF[SCF_Index[1][Band].L] * Cc[Res[Band].L]; do { Y_R[k][Band] = Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 24); ML = SCF[SCF_Index[2][Band].L] * Cc[Res[Band].L]; do { Y_R[k][Band] = Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 36); } else if ( Res[Band].R ) { // M==0, S!=0 k = 0; ML = SCF[SCF_Index[0][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = - ( Y_L[k][Band] = Q[Band].R[k] * ML ); } while (++k < 12); ML = SCF[SCF_Index[1][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = - ( Y_L[k][Band] = Q[Band].R[k] * ML ); } while (++k < 24); ML = SCF[SCF_Index[2][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = - ( Y_L[k][Band] = Q[Band].R[k] * ML ); } while (++k < 36); } else { // M==0, S==0 for (k=0; k<36; k++) { Y_R[k][Band] = Y_L[k][Band] = 0.f; } } else // Left/Right coded: left channel contains left, right the right signal if ( Res[Band].L ) if ( Res[Band].R ) { // L!=0, R!=0 k = 0; ML = SCF[SCF_Index[0][Band].L] * Cc[Res[Band].L]; MR = SCF[SCF_Index[0][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = Q[Band].R[k] * MR; Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 12); ML = SCF[SCF_Index[1][Band].L] * Cc[Res[Band].L]; MR = SCF[SCF_Index[1][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = Q[Band].R[k] * MR; Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 24); ML = SCF[SCF_Index[2][Band].L] * Cc[Res[Band].L]; MR = SCF[SCF_Index[2][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = Q[Band].R[k] * MR; Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 36); } else { // L!=0, R==0 k = 0; ML = SCF[SCF_Index[0][Band].L] * Cc[Res[Band].L]; do { Y_R[k][Band] = 0.f; Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 12); ML = SCF[SCF_Index[1][Band].L] * Cc[Res[Band].L]; do { Y_R[k][Band] = 0.f; Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 24); ML = SCF[SCF_Index[2][Band].L] * Cc[Res[Band].L]; do { Y_R[k][Band] = 0.f; Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 36); } else if ( Res[Band].R ) { // L==0, R!=0 k = 0; MR = SCF[SCF_Index[0][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = Q[Band].R[k] * MR; Y_L[k][Band] = 0.f; } while (++k < 12); MR = SCF[SCF_Index[1][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = Q[Band].R[k] * MR; Y_L[k][Band] = 0.f; } while (++k < 24); MR = SCF[SCF_Index[2][Band].R] * Cc[Res[Band].R]; do { Y_R[k][Band] = Q[Band].R[k] * MR; Y_L[k][Band] = 0.f; } while (++k < 36); } else { // L==0, R==0 for (k=0; k<36; k++) { Y_R[k][Band] = Y_L[k][Band] = 0.f; } } } LEAVE(162); return; } /* * This is the main requantisation routine for Intensity Stereo. * It does the same as Requantize_MidSideStereo() but for IS. * * Input is: * - Stop_Band: * the last band using MS or LR stereo * - Res[Band].L: * Quantisation resolution for every band (0...Stop_Band) and * the left channel which is used for both channels. Value is 0...17. * - SCF_Index[3][Band].{L,R}: * Scale factor for every band (0...Stop_Band), subframe (0...2) * and channel (L, R). * - Q[Band].L[36] * 36 subband samples for every band (0...Stop_Band), both channels use * the of the left channel * - SCF[64], Cc[18], Dc[18]: * Lookup tables for Scale factor and Quantisation resolution. * * Output is: * - Y_L: Left channel subband signals * - Y_R: Right channel subband signals * * These signals are used for the synthesis filter in the synth*.[ch] * files to generate the PCM output signal. */ void Requantize_IntensityStereo ( Int Start_Band, Int Stop_Band ) { Int Band; // Start_Band...Stop_Band Uint k; // 0...35 Float ML; Float MR; ENTER(163); for ( Band = Start_Band; Band <= Stop_Band; Band++ ) { if ( Res[Band].L ) { k = 0; ML = SCF[SCF_Index[0][Band].L] * Cc[Res[Band].L] * SS05; MR = SCF[SCF_Index[0][Band].R] * Cc[Res[Band].L] * SS05; do { Y_R[k][Band] = Q[Band].L[k] * MR; Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 12); ML = SCF[SCF_Index[1][Band].L] * Cc[Res[Band].L] * SS05; MR = SCF[SCF_Index[1][Band].R] * Cc[Res[Band].L] * SS05; do { Y_R[k][Band] = Q[Band].L[k] * MR; Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 24); ML = SCF[SCF_Index[2][Band].L] * Cc[Res[Band].L] * SS05; MR = SCF[SCF_Index[2][Band].R] * Cc[Res[Band].L] * SS05; do { Y_R[k][Band] = Q[Band].L[k] * MR; Y_L[k][Band] = Q[Band].L[k] * ML; } while (++k < 36); } else { for (k=0; k<36; k++) { Y_R[k][Band] = Y_L[k][Band] = 0.f; } } } LEAVE(163); return; } /* * Helper function for the qsort() in Resort_HuffTable() to sort a Huffman table * by its codes. */ static int Cdecl cmp_fn ( const void* p1, const void* p2 ) { if ( ((const Huffman_t*)p1) -> Code < ((const Huffman_t*)p2) -> Code ) return +1; if ( ((const Huffman_t*)p1) -> Code > ((const Huffman_t*)p2) -> Code ) return -1; return 0; } /* * This functions sorts a Huffman table by its codes. It has also two other functions: * * - The table contains LSB aligned codes, these are first MSB aligned. * - The value entry is filled by its position plus 'offset' (Note that * Make_HuffTable() don't fill this item. Offset can be used to offset * range for instance from 0...6 to -3...+3. * * Note that this function generates trash if you call it twice! */ void Resort_HuffTable ( Huffman_t* const Table, const size_t elements, Int offset ) { size_t i; for ( i = 0; i < elements; i++ ) { Table[i].Value = i + offset; Table[i].Code <<= (32 - Table[i].Length); } qsort ( Table, elements, sizeof(*Table), cmp_fn ); return; } #endif /* MPP_ENCODER */ /* * Fills out the items Code and Length (but not Value) of a Huffman table * from a bit packed Huffman table 'src'. Table is not sorted, so this is * the table which is suitable for an encoder. Be careful: To get a table * usable for a decoder you must use Resort_HuffTable() after this * function. It's a little bit dangerous to divide the functionality, maybe * there is a more secure and handy solution to this problem. */ void Make_HuffTable ( Huffman_t* dst, const HuffSrc_t* src, size_t len ) { size_t i; for ( i = 0; i < len; i++,src++,dst++ ) { dst->Code = src->Code ; dst->Length = src->Length; } } /* * Generates a Lookup table for quick Huffman decoding. This table must * have a size of a power of 2. Input is the pre-sorted Huffman table, * sorted by Resort_HuffTable() and its length, and the length of the * lookup table. Output is the Lookup table. It can be used for table based * decoding (Huffman_decode_fastest) which fully decodes by means of the * LUT. This is only handy for small huffman codes up to 9...10 bit * maximum length. For longer codes partial lookup is possible with * Huffman_decode_faster() which first estimates possible codes by means * of LUT and then searches the exact code like the tableless version * Huffman_decode(). */ void Make_LookupTable ( Uint8_t* LUT, size_t LUT_len, const Huffman_t* const Table, const size_t elements ) { size_t i; size_t idx = elements; Uint32_t dval = (Uint32_t)0x80000000L / LUT_len * 2; Uint32_t val = dval - 1; for ( i = 0; i < LUT_len; i++, val += dval ) { while ( idx > 0 && val >= Table[idx-1].Code ) idx--; *LUT++ = (Uint8_t)idx; } return; } void Init_FPU ( void ) { Uint16_t cw; #if defined __i386__ && defined _FPU_GETCW && defined _FPU_SETCW _FPU_GETCW ( cw ); cw &= ~0x300; _FPU_SETCW ( cw ); #elif defined __i386__ && defined FPU_GETCW && defined FPU_SETCW FPU_GETCW ( cw ); cw &= ~0x300; FPU_SETCW ( cw ); #elif defined __MINGW32__ __asm__ ("fnstcw %0" : "=m" (*&cw)); cw &= ~0x300; __asm__ ("fldcw %0" : : "m" (*&cw)); #elif defined(_WIN32) && !defined(_WIN64) _asm { fstcw cw }; cw &= ~0x300; _asm { fldcw cw }; #else ; #endif } /* end of tools.c */ mppenc-1.16/src/analy_filter.c0000644000175000017500000003420210522734510015605 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include #include "mppenc.h" #define FASTER /* C O N S T A N T S */ #undef _ #define _(value) (float)(value##.##L / 0x200000) static float Ci_opt [512] = { _( 0), _( 213), _( 2037), _( 6574), _(75038), _( 6574), _(2037), _(213), _( -1), _( 218), _( 2000), _( 5959), _(74992), _( 7134), _(2063), _(208), _( -1), _( 222), _( 1952), _( 5288), _(74856), _( 7640), _(2080), _(202), _( -1), _( 225), _( 1893), _( 4561), _(74630), _( 8092), _(2087), _(196), _( -1), _( 227), _( 1822), _( 3776), _(74313), _( 8492), _(2085), _(190), _( -1), _( 228), _( 1739), _( 2935), _(73908), _( 8840), _(2075), _(183), _( -1), _( 228), _( 1644), _( 2037), _(73415), _( 9139), _(2057), _(176), _( -2), _( 227), _( 1535), _( 1082), _(72835), _( 9389), _(2032), _(169), _( -2), _( 224), _( 1414), _( 70), _(72169), _( 9592), _(2001), _(161), _( -2), _( 221), _( 1280), _( -998), _(71420), _( 9750), _(1962), _(154), _( -2), _( 215), _( 1131), _( -2122), _(70590), _( 9863), _(1919), _(147), _( -3), _( 208), _( 970), _( -3300), _(69679), _( 9935), _(1870), _(139), _( -3), _( 200), _( 794), _( -4533), _(68692), _( 9966), _(1817), _(132), _( -4), _( 189), _( 605), _( -5818), _(67629), _( 9959), _(1759), _(125), _( -4), _( 177), _( 402), _( -7154), _(66494), _( 9916), _(1698), _(117), _( -5), _( 163), _( 185), _( -8540), _(65290), _( 9838), _(1634), _(111), _( -5), _( 146), _( -45), _( -9975), _(64019), _( 9727), _(1567), _(104), _( -6), _( 127), _( -288), _(-11455), _(62684), _( 9585), _(1498), _( 97), _( -7), _( 106), _( -545), _(-12980), _(61289), _( 9416), _(1428), _( 91), _( -7), _( 83), _( -814), _(-14548), _(59838), _( 9219), _(1356), _( 85), _( -8), _( 57), _(-1095), _(-16155), _(58333), _( 8998), _(1283), _( 79), _( -9), _( 29), _(-1388), _(-17799), _(56778), _( 8755), _(1210), _( 73), _( -10), _( -2), _(-1692), _(-19478), _(55178), _( 8491), _(1137), _( 68), _( -11), _( -36), _(-2006), _(-21189), _(53534), _( 8209), _(1064), _( 63), _( -13), _( -72), _(-2330), _(-22929), _(51853), _( 7910), _( 991), _( 58), _( -14), _( -111), _(-2663), _(-24694), _(50137), _( 7597), _( 919), _( 53), _( -16), _( -153), _(-3004), _(-26482), _(48390), _( 7271), _( 848), _( 49), _( -17), _( -197), _(-3351), _(-28289), _(46617), _( 6935), _( 779), _( 45), _( -19), _( -244), _(-3705), _(-30112), _(44821), _( 6589), _( 711), _( 41), _( -21), _( -294), _(-4063), _(-31947), _(43006), _( 6237), _( 645), _( 38), _( -24), _( -347), _(-4425), _(-33791), _(41176), _( 5879), _( 581), _( 35), _( -26), _( -401), _(-4788), _(-35640), _(39336), _( 5517), _( 519), _( 31), _( -29), _( -459), _(-5153), _(-37489), _(37489), _( 5153), _( 459), _( 29), _( -31), _( -519), _(-5517), _(-39336), _(35640), _( 4788), _( 401), _( 26), _( -35), _( -581), _(-5879), _(-41176), _(33791), _( 4425), _( 347), _( 24), _( -38), _( -645), _(-6237), _(-43006), _(31947), _( 4063), _( 294), _( 21), _( -41), _( -711), _(-6589), _(-44821), _(30112), _( 3705), _( 244), _( 19), _( -45), _( -779), _(-6935), _(-46617), _(28289), _( 3351), _( 197), _( 17), _( -49), _( -848), _(-7271), _(-48390), _(26482), _( 3004), _( 153), _( 16), _( -53), _( -919), _(-7597), _(-50137), _(24694), _( 2663), _( 111), _( 14), _( -58), _( -991), _(-7910), _(-51853), _(22929), _( 2330), _( 72), _( 13), _( -63), _(-1064), _(-8209), _(-53534), _(21189), _( 2006), _( 36), _( 11), _( -68), _(-1137), _(-8491), _(-55178), _(19478), _( 1692), _( 2), _( 10), _( -73), _(-1210), _(-8755), _(-56778), _(17799), _( 1388), _( -29), _( 9), _( -79), _(-1283), _(-8998), _(-58333), _(16155), _( 1095), _( -57), _( 8), _( -85), _(-1356), _(-9219), _(-59838), _(14548), _( 814), _( -83), _( 7), _( -91), _(-1428), _(-9416), _(-61289), _(12980), _( 545), _(-106), _( 7), _( -97), _(-1498), _(-9585), _(-62684), _(11455), _( 288), _(-127), _( 6), _(-104), _(-1567), _(-9727), _(-64019), _( 9975), _( 45), _(-146), _( 5), _(-111), _(-1634), _(-9838), _(-65290), _( 8540), _( -185), _(-163), _( 5), _(-117), _(-1698), _(-9916), _(-66494), _( 7154), _( -402), _(-177), _( 4), _(-125), _(-1759), _(-9959), _(-67629), _( 5818), _( -605), _(-189), _( 4), _(-132), _(-1817), _(-9966), _(-68692), _( 4533), _( -794), _(-200), _( 3), _(-139), _(-1870), _(-9935), _(-69679), _( 3300), _( -970), _(-208), _( 3), _(-147), _(-1919), _(-9863), _(-70590), _( 2122), _(-1131), _(-215), _( 2), _(-154), _(-1962), _(-9750), _(-71420), _( 998), _(-1280), _(-221), _( 2), _(-161), _(-2001), _(-9592), _(-72169), _( -70), _(-1414), _(-224), _( 2), _(-169), _(-2032), _(-9389), _(-72835), _(-1082), _(-1535), _(-227), _( 2), _(-176), _(-2057), _(-9139), _(-73415), _(-2037), _(-1644), _(-228), _( 1), _(-183), _(-2075), _(-8840), _(-73908), _(-2935), _(-1739), _(-228), _( 1), _(-190), _(-2085), _(-8492), _(-74313), _(-3776), _(-1822), _(-227), _( 1), _(-196), _(-2087), _(-8092), _(-74630), _(-4561), _(-1893), _(-225), _( 1), _(-202), _(-2080), _(-7640), _(-74856), _(-5288), _(-1952), _(-222), _( 1), _(-208), _(-2063), _(-7134), _(-74992), _(-5959), _(-2000), _(-218), _( 1), }; #undef _ static float M [1024]; void Klemm ( void ) { int i; int k; float S [512]; for ( i=0; i<32; i++ ) { for ( k=0; k<32; k++ ) { M [i*32 + k] = (float) cos ( ((2*i+1)*k & 127) * M_PI/64 ); } } #ifdef FASTER for ( i = 0; i < 384; i++ ) S[i] = Ci_opt[i]; for ( i = 384; i < 392; i++ ) S[i] = 0; for ( i = 392; i < 512; i++ ) S[i] = -Ci_opt[i]; for ( i = 0; i < 512; i++ ) Ci_opt[i] = S[i]; for ( i = 0; i < 128; i++ ) Ci_opt[i] = S[(i&7) + 120 - (i&120)]; for ( i = 128; i < 384; i++ ) Ci_opt[i] = S[i]; for ( i = 384; i < 512; i++ ) Ci_opt[i] = S[ 384 + (i&7) + 120 - (i&120)]; #endif } /* D E F I N E S */ #define X_MEM 1152 /* V A R I A B L E S */ float X_L [ X_MEM + 480 ]; float X_R [ X_MEM + 480 ]; /* F U N C T I O N S */ // vectoring & partial calculation static void Vectoring ( const float* x, float* y ) { #ifdef FASTER int i = 0; const float* c1; const float* c2; const float* x1; const float* x2; # define EXPR(c,x) (c[0]*x[0] + c[1]*x[64] + c[2]*x[128] + c[3]*x[192] + c[4]*x[256] + c[5]*x[320] + c[6]*x[384] + c[7]*x[448]) i++; *y++ = EXPR ((Ci_opt+128),(x+31)); c1 = Ci_opt - 8; c2 = Ci_opt + 128; x1 = x + 16; x2 = x + 31; do { x1--, x2--, i++; c1 += 8, c2 += 8; *y++ = EXPR (c1,x1) + EXPR (c2,x2); } while ( i < 16 ); i++; *y++ = EXPR ((Ci_opt+120),(x+0)) + EXPR ((Ci_opt+256),(x+32)); c1 = Ci_opt + 384 - 8; c2 = Ci_opt + 256; x1 = x + 47; x2 = x + 32; do { x1++, x2++, i++; c1 += 8, c2 += 8; *y++ = EXPR (c1,x1) + EXPR (c2,x2); } while ( i < 32 ); #else int i; const float* c = Ci_opt; for ( i = 0; i < 16; i++, c += 32, x += 4, y += 4 ) { y[0] = c[ 0] * x[ 0] + c[ 1] * x[ 64] + c[ 2] * x[128] + c[ 3] * x[192] + c[ 4] * x[256] + c[ 5] * x[320] + c[ 6] * x[384] + c[ 7] * x[448]; y[1] = c[ 8] * x[ 1] + c[ 9] * x[ 65] + c[10] * x[129] + c[11] * x[193] + c[12] * x[257] + c[13] * x[321] + c[14] * x[385] + c[15] * x[449]; y[2] = c[16] * x[ 2] + c[17] * x[ 66] + c[18] * x[130] + c[19] * x[194] + c[20] * x[258] + c[21] * x[322] + c[22] * x[386] + c[23] * x[450]; y[3] = c[24] * x[ 3] + c[25] * x[ 67] + c[26] * x[131] + c[27] * x[195] + c[28] * x[259] + c[29] * x[323] + c[30] * x[387] + c[31] * x[451]; } #endif } // matrixing with Mi[32][32] = Mi[1024] static void Matrixing ( const int MaxBand, const float* mi, const float* y, float* samples ) { int i; #ifdef FASTER for ( i = 0; i <= MaxBand; i++, mi += 32, samples += 72 ) { // 144 = sizeof(SubbandFloatTyp)/sizeof(float) samples[0] = y[ 0] + mi[ 1] * y[ 1] + mi[ 2] * y[ 2] + mi[ 3] * y[ 3] + mi[ 4] * y[ 4] + mi[ 5] * y[ 5] + mi[ 6] * y[ 6] + mi[ 7] * y[ 7] + mi[ 8] * y[ 8] + mi[ 9] * y[ 9] + mi[10] * y[10] + mi[11] * y[11] + mi[12] * y[12] + mi[13] * y[13] + mi[14] * y[14] + mi[15] * y[15] + mi[16] * y[16] + mi[17] * y[17] + mi[18] * y[18] + mi[19] * y[19] + mi[20] * y[20] + mi[21] * y[21] + mi[22] * y[22] + mi[23] * y[23] + mi[24] * y[24] + mi[25] * y[25] + mi[26] * y[26] + mi[27] * y[27] + mi[28] * y[28] + mi[29] * y[29] + mi[30] * y[30] + mi[31] * y[31]; } #else for ( i = 0; i <= MaxBand; i++, mi += 32, samples += 72 ) { // 144 = sizeof(SubbandFloatTyp)/sizeof(float) samples[0] = y[16] + mi[ 1] * (y[15]+y[17]) + mi[ 2] * (y[14]+y[18]) + mi[ 3] * (y[13]+y[19]) + mi[ 4] * (y[12]+y[20]) + mi[ 5] * (y[11]+y[21]) + mi[ 6] * (y[10]+y[22]) + mi[ 7] * (y[ 9]+y[23]) + mi[ 8] * (y[ 8]+y[24]) + mi[ 9] * (y[ 7]+y[25]) + mi[10] * (y[ 6]+y[26]) + mi[11] * (y[ 5]+y[27]) + mi[12] * (y[ 4]+y[28]) + mi[13] * (y[ 3]+y[29]) + mi[14] * (y[ 2]+y[30]) + mi[15] * (y[ 1]+y[31]) + mi[16] * (y[ 0]+y[32]) + mi[31] * (y[47]-y[49]) + mi[30] * (y[46]-y[50]) + mi[29] * (y[45]-y[51]) + mi[28] * (y[44]-y[52]) + mi[27] * (y[43]-y[53]) + mi[26] * (y[42]-y[54]) + mi[25] * (y[41]-y[55]) + mi[24] * (y[40]-y[56]) + mi[23] * (y[39]-y[57]) + mi[22] * (y[38]-y[58]) + mi[21] * (y[37]-y[59]) + mi[20] * (y[36]-y[60]) + mi[19] * (y[35]-y[61]) + mi[18] * (y[34]-y[62]) + mi[17] * (y[33]-y[63]); } #endif } // Analysis-Filterbank void Analyse_Filter ( const PCMDataTyp* in, SubbandFloatTyp* out, const int MaxBand ) { #ifdef FASTER float Y_L [32]; float Y_R [32]; #else float Y_L [64]; float Y_R [64]; #endif float* x; const float* pcm; int n; int i; /************************* calculate L-signal ***************************/ ENTER(180); memcpy ( X_L + X_MEM, X_L, 480*sizeof(*X_L) ); x = X_L + X_MEM; pcm = in->L + 479; // 479 = CENTER + 31 for ( n = 0; n < 36; n++, pcm += 64 ) { x -= 32; // updating vector x #ifdef FASTER for ( i = 0; i < 16; i++ ) x[i] = *pcm--; for ( i = 31; i >= 16; i-- ) x[i] = *pcm--; #else for ( i = 0; i < 32; i++ ) x[i] = *pcm--; #endif Vectoring ( x, Y_L ); // vectoring & partial calculation Matrixing ( MaxBand, M, Y_L, &out[0].L[n] ); // matrixing } /************************* calculate R-signal ***************************/ memcpy ( X_R + X_MEM, X_R, 480*sizeof(*X_R) ); x = X_R + X_MEM; pcm = in->R + 479; // 479 = CENTER + 31 for ( n = 0; n < 36; n++, pcm += 64 ) { x -= 32; // updating vector x #ifdef FASTER for ( i = 0; i < 16; i++ ) x[i] = *pcm--; for ( i = 31; i >= 16; i-- ) x[i] = *pcm--; #else for ( i = 0; i < 32; i++ ) x[i] = *pcm--; #endif Vectoring ( x, Y_R ); // vectoring & partial calculation Matrixing ( MaxBand, M, Y_R, &out[0].R[n] ); // matrixing } LEAVE(180); } void Analyse_Init ( float Left, float Right, SubbandFloatTyp* out, const int MaxBand ) { #ifdef FASTER float Y_L [32]; float Y_R [32]; #else float Y_L [64]; float Y_R [64]; #endif float* x; int n; int i; /************************* calculate L-signal ***************************/ ENTER(180); memcpy ( X_L + X_MEM, X_L, 480*sizeof(*X_L) ); x = X_L + X_MEM; for ( n = 0; n < 36; n++ ) { x -= 32; // updating vector x #ifdef FASTER for ( i = 0; i < 16; i++ ) x[i] = Left; for ( i = 31; i >= 16; i-- ) x[i] = Left; #else for ( i = 0; i < 32; i++ ) x[i] = Left; #endif Vectoring ( x, Y_L ); // vectoring & partial calculation Matrixing ( MaxBand, M, Y_L, &out[0].L[n] ); // matrixing } /************************* calculate R-signal ***************************/ memcpy ( X_R + X_MEM, X_R, 480*sizeof(*X_R) ); x = X_R + X_MEM; for ( n = 0; n < 36; n++ ) { x -= 32; // updating vector x #ifdef FASTER for ( i = 0; i < 16; i++ ) x[i] = Right; for ( i = 31; i >= 16; i-- ) x[i] = Right; #else for ( i = 0; i < 32; i++ ) x[i] = Right; #endif Vectoring ( x, Y_R ); // vectoring & partial calculation Matrixing ( MaxBand, M, Y_R, &out[0].R[n] ); // matrixing } LEAVE(180); } /* end of analy_filter.c */ mppenc-1.16/src/keyboard.c0000644000175000017500000000450310522734510014735 0ustar bencerbencer/* * Keyboard input functions * * (C) Frank Klemm 2002. All rights reserved. * * Principles: * * History: * ca. 1998 created * 2002 * * Global functions: * - * * TODO: * - */ #include "mppenc.h" #if defined _WIN32 || defined __TURBOC__ # include int WaitKey ( void ) { return getch (); } int CheckKeyKeep ( void ) { int ch; if ( !kbhit () ) return -1; ch = getch (); ungetch (ch); return ch; } int CheckKey ( void ) { if ( !kbhit () ) return -1; return getch (); } #else # ifdef USE_TERMIOS # include static struct termios stored_settings; static void echo_on ( void ) { tcsetattr ( 0, TCSANOW, &stored_settings ); } static void echo_off ( void ) { struct termios new_settings; tcgetattr ( 0, &stored_settings ); new_settings = stored_settings; new_settings.c_lflag &= ~ECHO; new_settings.c_lflag &= ~ICANON; // Disable canonical mode, and set buffer size to 1 byte new_settings.c_cc[VTIME] = 0; new_settings.c_cc[VMIN] = 1; tcsetattr ( 0, TCSANOW, &new_settings ); } # else # define echo_off() (void)0 # define echo_on() (void)0 # endif int WaitKey ( void ) { unsigned char buff [1]; int ret; echo_off (); ret = read ( 0, buff, 1 ); echo_on (); return ret == 1 ? buff[0] : -1; } int CheckKeyKeep ( void ) { struct timeval tv = { 0, 0 }; // Do not wait at all, not even a microsecond fd_set read_fd; FD_ZERO ( &read_fd ); // Must be done first to initialize read_fd FD_SET ( 0, &read_fd ); // Makes select() ask if input is ready; 0 is file descriptor for stdin if ( -1 == select ( 1, // number of the largest fd to check + 1 &read_fd, NULL, // No writes NULL, // No exceptions &tv ) ) return -1; // an error occured return FD_ISSET (0, &read_fd) ? 0xFF : -1; // read_fd now holds a bit map of files that are readable. We test the entry for the standard input (file 0). } int CheckKey ( void ) { if ( CheckKeyKeep () < 0 ) return -1; return WaitKey (); } #endif /* end of keyboard.c */ mppenc-1.16/src/encode_sv7.c0000644000175000017500000003675510522734510015207 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" /* * SV1: DATE 13.12.1998 * SV2: DATE 12.06.1999 * SV3: DATE 19.10.1999 * SV4: DATE 20.10.1999 * SV5: DATE 18.06.2000 * SV6: DATE 10.08.2000 * SV7: DATE 23.08.2000 * SV7.f: DATE 20.07.2002 */ unsigned char MS_Flag [32]; // Flag to save if Subband was MS- or LR-coded int SCF_Last_L [32]; int SCF_Last_R [32]; // Last coded SCF value static unsigned char DSCF_RLL_L [32]; static unsigned char DSCF_RLL_R [32]; // Duration of the differential SCF-coding for RLL (run length limitation) int Res_L [32]; int Res_R [32]; // Quantization precision of the subbands int SCF_Index_L [32] [3]; int SCF_Index_R [32] [3]; // Scalefactor index for quantized subband values // initialize SV7 void Init_SV7 ( void ) { Init_Huffman_Encoder_SV7 (); } // writes SV7-header void WriteHeader_SV7 ( const unsigned int MaxBand, const unsigned int Profile, const unsigned int MS_on, const Uint32_t TotalFrames, const unsigned int SamplesRest, const unsigned int StreamVersion, const unsigned int SampleFreq ) { WriteBits ( StreamVersion, 8 ); // StreamVersion WriteBits ( 0x2B504D , 24 ); // Magic Number "MP+" WriteBits ( TotalFrames , 32 ); // # of frames WriteBits ( 0 , 1 ); // former IS-Flag (not supported anymore) WriteBits ( MS_on , 1 ); // MS-Coding Flag WriteBits ( MaxBand , 6 ); // Bandwidth #if 0 if ( MPPENC_VERSION [3] & 1 ) WriteBits ( 1 , 4 ); // 1: Experimental profile else #endif WriteBits ( Profile , 4 ); // 5...15: below Telephone...above BrainDead WriteBits ( 0 , 2 ); // for future use switch ( SampleFreq ) { case 44100: WriteBits ( 0, 2 ); break; case 48000: WriteBits ( 1, 2 ); break; case 37800: WriteBits ( 2, 2 ); break; case 32000: WriteBits ( 3, 2 ); break; default : stderr_printf ( "Internal error\n"); exit (1); } WriteBits ( 0 , 16 ); // maximum input sample value, currently filled by replaygain WriteBits ( 0 , 32 ); // title based gain controls, currently filled by replaygain WriteBits ( 0 , 32 ); // album based gain controls, currently filled by replaygain WriteBits ( 1 , 1 ); // true gapless: used? WriteBits ( SamplesRest , 11 ); // true gapless: valid samples in last frame WriteBits ( 1 , 1 ); // we now support fast seeking WriteBits ( 0 , 19 ); WriteBits ( (MPPENC_VERSION[0]&15)*100 + (MPPENC_VERSION[2]&15)*10 + (MPPENC_VERSION[3]&15), 8 ); // for future use } void FinishBitstream ( void ) { Buffer [Zaehler++] = dword; // Assigning the "last" word } #define ENCODE_SCF1( new, old, rll ) \ d = new - old + 7; \ if ( d <= 14u && rll < 32) { \ WriteBits ( Table[d].Code, Table[d].Length ); \ } \ else { \ if ( new < 0 ) new = 0, Overflows++; \ WriteBits ( Table[15].Code, Table[15].Length ); \ WriteBits ( (unsigned int)new, 6 ); \ rll = 0; \ } #define ENCODE_SCFn( new, old, rll ) \ d = new - old + 7; \ if ( d <= 14u ) { \ WriteBits ( Table[d].Code, Table[d].Length ); \ } \ else { \ if ( new < 0 ) new = 0, Overflows++; \ WriteBits ( Table[15].Code, Table[15].Length ); \ WriteBits ( (unsigned int)new, 6 ); \ rll = 0; \ } static void test ( const int* const Res, const unsigned int* q ) { #if 0 int i; switch ( *Res ) { case 1: for ( i = 0; i < 36; i ++ ) if ( q[i] != 1 ) return; fprintf ( stderr, "Alles Nullsamples, aber Auflösung = %u\n", *Res ); *Res = 0; break; case 2: for ( i = 0; i < 36; i ++ ) if ( q[i] != 2 ) return; fprintf ( stderr, "Alles Nullsamples, aber Auflösung = %u\n", *Res ); *Res = 0; break; } #endif } // formatting and writing SV7-bitstream for one frame void WriteBitstream_SV7 ( const int MaxBand, const SubbandQuantTyp* Q ) { int n; int k; unsigned int d; unsigned int idx; unsigned int book; const Huffman_t* Table; const Huffman_t* Table0; const Huffman_t* Table1; int sum; const unsigned int* q; unsigned char SCFI_L [32]; unsigned char SCFI_R [32]; ENTER(110); /************************************ Resolution *********************************/ WriteBits ( (unsigned int)Res_L[0], 4 ); // subband 0 WriteBits ( (unsigned int)Res_R[0], 4 ); if ( MS_Channelmode > 0 && !(Res_L[0]==0 && Res_R[0]==0) ) WriteBits ( MS_Flag[0] , 1 ); Table = HuffHdr; // subband 1...MaxBand for ( n = 1; n <= MaxBand; n++ ) { test ( Res_L+n, Q[n].L ); d = Res_L[n] - Res_L[n-1] + 5; if ( d <= 8u ) { WriteBits ( Table[d].Code, Table[d].Length ); } else { WriteBits ( Table[9].Code, Table[9].Length ); WriteBits ( Res_L[n] , 4 ); } test ( Res_R+n, Q[n].R ); d = Res_R[n] - Res_R[n-1] + 5; if ( d <= 8u ) { WriteBits ( Table[d].Code, Table[d].Length ); } else { WriteBits ( Table[9].Code, Table[9].Length ); WriteBits ( Res_R[n] , 4 ); } if ( MS_Channelmode > 0 && !(Res_L[n]==0 && Res_R[n]==0) ) WriteBits ( MS_Flag[n], 1 ); } /************************************ SCF encoding type ***********************************/ Table = HuffSCFI; for ( n = 0; n <= MaxBand; n++ ) { if ( Res_L[n] ) { SCFI_L[n] = 2 * (SCF_Index_L[n][0] == SCF_Index_L[n][1]) + (SCF_Index_L[n][1] == SCF_Index_L[n][2]); WriteBits ( Table[SCFI_L[n]].Code, Table[SCFI_L[n]].Length ); } if ( Res_R[n] ) { SCFI_R[n] = 2 * (SCF_Index_R[n][0] == SCF_Index_R[n][1]) + (SCF_Index_R[n][1] == SCF_Index_R[n][2]); WriteBits ( Table[SCFI_R[n]].Code, Table[SCFI_R[n]].Length ); } } /************************************* SCF **********************************/ Table = HuffDSCF; for ( n = 0; n <= MaxBand; n++ ) { if ( Res_L[n] ) { switch ( SCFI_L[n] ) { default: ENCODE_SCF1 ( SCF_Index_L[n][0], SCF_Last_L [n] , DSCF_RLL_L[n] ); ENCODE_SCFn ( SCF_Index_L[n][1], SCF_Index_L[n][0], DSCF_RLL_L[n] ); ENCODE_SCFn ( SCF_Index_L[n][2], SCF_Index_L[n][1], DSCF_RLL_L[n] ); SCF_Last_L[n] = SCF_Index_L[n][2]; break; case 1: ENCODE_SCF1 ( SCF_Index_L[n][0], SCF_Last_L [n] , DSCF_RLL_L[n] ); ENCODE_SCFn ( SCF_Index_L[n][1], SCF_Index_L[n][0], DSCF_RLL_L[n] ); SCF_Last_L[n] = SCF_Index_L[n][1]; break; case 2: ENCODE_SCF1 ( SCF_Index_L[n][0], SCF_Last_L[n] , DSCF_RLL_L[n] ); ENCODE_SCFn ( SCF_Index_L[n][2], SCF_Index_L[n][0], DSCF_RLL_L[n] ); SCF_Last_L[n] = SCF_Index_L[n][2]; break; case 3: ENCODE_SCF1 ( SCF_Index_L[n][0], SCF_Last_L[n] , DSCF_RLL_L[n] ); SCF_Last_L[n] = SCF_Index_L[n][0]; break; } } if (DSCF_RLL_L[n] <= 32) DSCF_RLL_L[n]++; // Increased counters for SCF that haven't been initialized again if ( Res_R[n] ) { switch ( SCFI_R[n] ) { default: ENCODE_SCF1 ( SCF_Index_R[n][0], SCF_Last_R[n] , DSCF_RLL_R[n] ); ENCODE_SCFn ( SCF_Index_R[n][1], SCF_Index_R[n][0], DSCF_RLL_R[n] ); ENCODE_SCFn ( SCF_Index_R[n][2], SCF_Index_R[n][1], DSCF_RLL_R[n] ); SCF_Last_R[n] = SCF_Index_R[n][2]; break; case 1: ENCODE_SCF1 ( SCF_Index_R[n][0], SCF_Last_R[n] , DSCF_RLL_R[n] ); ENCODE_SCFn ( SCF_Index_R[n][1], SCF_Index_R[n][0], DSCF_RLL_R[n] ); SCF_Last_R[n] = SCF_Index_R[n][1]; break; case 2: ENCODE_SCF1 ( SCF_Index_R[n][0], SCF_Last_R[n] , DSCF_RLL_R[n] ); ENCODE_SCFn ( SCF_Index_R[n][2], SCF_Index_R[n][0], DSCF_RLL_R[n] ); SCF_Last_R[n] = SCF_Index_R[n][2]; break; case 3: ENCODE_SCF1 ( SCF_Index_R[n][0], SCF_Last_R[n] , DSCF_RLL_R[n] ); SCF_Last_R[n] = SCF_Index_R[n][0]; break; } } if (DSCF_RLL_R[n] <= 32) DSCF_RLL_R[n]++; // Increased counters for SCF that haven't been freshly initialized } /*********************************** Samples *********************************/ for ( n = 0; n <= MaxBand; n++ ) { sum = 0; q = Q[n].L; switch ( Res_L[n] ) { case -1: case 0: break; case 1: Table0 = HuffQ [0][1]; Table1 = HuffQ [1][1]; for ( k = 0; k < 36; k += 3 ) { idx = q[k+0] + 3*q[k+1] + 9*q[k+2]; sum += Table0 [idx].Length; sum -= Table1 [idx].Length; } book = sum >= 0; WriteBits ( book, 1 ); Table = HuffQ [book][1]; for ( k = 0; k < 36; k += 3 ) { idx = q[k+0] + 3*q[k+1] + 9*q[k+2]; WriteBits ( Table[idx].Code, Table[idx].Length ); } break; case 2: Table0 = HuffQ [0][2]; Table1 = HuffQ [1][2]; for ( k = 0; k < 36; k += 2 ) { idx = q[k+0] + 5*q[k+1]; sum += Table0 [idx].Length; sum -= Table1 [idx].Length; } book = sum >= 0; WriteBits ( book, 1 ); Table = HuffQ [book][2]; for ( k = 0; k < 36; k += 2 ) { idx = q[k+0] + 5*q[k+1]; WriteBits ( Table[idx].Code, Table[idx].Length ); } break; case 3: case 4: case 5: case 6: case 7: Table0 = HuffQ [0][Res_L[n]]; Table1 = HuffQ [1][Res_L[n]]; for ( k = 0; k < 36; k++ ) { sum += Table0 [q[k]].Length; sum -= Table1 [q[k]].Length; } book = sum >= 0; WriteBits ( book, 1 ); Table = HuffQ [book][Res_L[n]]; for ( k = 0; k < 36; k++ ) { idx = q[k]; WriteBits ( Table[idx].Code, Table[idx].Length ); } break; default: for ( k = 0; k < 36; k++ ) WriteBits ( q[k], Res_L[n]-1 ); break; } sum = 0; q = Q[n].R; switch ( Res_R[n] ) { case -1: case 0: break; case 1: Table0 = HuffQ [0][1]; Table1 = HuffQ [1][1]; for ( k = 0; k < 36; k += 3 ) { idx = q[k+0] + 3*q[k+1] + 9*q[k+2]; sum += Table0 [idx].Length; sum -= Table1 [idx].Length; } book = sum >= 0; WriteBits ( book, 1 ); Table = HuffQ [book][1]; for ( k = 0; k < 36; k += 3 ) { idx = q[k+0] + 3*q[k+1] + 9*q[k+2]; WriteBits ( Table[idx].Code, Table[idx].Length ); } break; case 2: Table0 = HuffQ [0][2]; Table1 = HuffQ [1][2]; for ( k = 0; k < 36; k += 2 ) { idx = q[k+0] + 5*q[k+1]; sum += Table0 [idx].Length; sum -= Table1 [idx].Length; } book = sum >= 0; WriteBits ( book, 1 ); Table = HuffQ [book][2]; for ( k = 0; k < 36; k += 2 ) { idx = q[k+0] + 5*q[k+1]; WriteBits ( Table[idx].Code, Table[idx].Length ); } break; case 3: case 4: case 5: case 6: case 7: Table0 = HuffQ [0][Res_R[n]]; Table1 = HuffQ [1][Res_R[n]]; for ( k = 0; k < 36; k++ ) { sum += Table0 [q[k]].Length; sum -= Table1 [q[k]].Length; } book = sum >= 0; WriteBits ( book, 1 ); Table = HuffQ [book][Res_R[n]]; for ( k = 0; k < 36; k++ ) { idx = q[k]; WriteBits ( Table[idx].Code, Table[idx].Length ); } break; default: for ( k = 0; k < 36; k++ ) WriteBits ( q[k], Res_R[n] - 1 ); break; } } LEAVE(110); return; } #undef ENCODE_SCF1 #undef ENCODE_SCFn #if 0 void Dump ( const unsigned int* q, const int Res ) { switch ( Res ) { case 1: for ( k = 0; k < 36; k++, q++ ) printf ("%2d%c", *q-1, k==35?'\n':' '); break; case 2: for ( k = 0; k < 36; k++, q++ ) printf ("%2d%c", *q-2, k==35?'\n':' '); break; case 3: case 4: case 5: case 6: case 7: if ( Res == 5 ) for ( k = 0; k < 36; k++, q++ ) printf ("%2d%c", *q-7, k==35?'\n':' '); break; case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: printf ("%2u: ", Res-1 ); for ( k = 0; k < 36; k++, q++ ) { printf ("%6d", *q - (1 << (Res-2)) ); } printf ("\n"); break; } } #endif /* end of encode_sv7.c */ mppenc-1.16/src/tags.c0000644000175000017500000022537110523123625014103 0ustar bencerbencer/* * Encoder tag handling * * (C) Frank Klemm 2002. Janne Hyvärinen 2002. All rights reserved. * * Principles: * * * History: * 2002-06 created * 2002-08-12 added translation method 5 to addtag() * Tags taken from source file can't overwrite already existing items * added Init_Tags() * 2002-08-13 Added all windows code pages * 2002-10-09 Added code to parse tags from filename * * Global functions: * - addtag() * * TODO: * - '/' and '\' should be possible as PATH_SEP */ #include "mppenc.h" #ifdef USE_WIDECHAR # include #endif static const char* GenreList [] = { "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror", "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat", "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C", "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "SynthPop" }; struct APETagFooterStruct { Uint8_t ID [8]; // should equal 'APETAGEX' Uint8_t Version [4]; // currently 1000 (version 1.000) Uint8_t Length [4]; // the complete size of the tag, including this footer Uint8_t TagCount [4]; // the number of fields in the tag Uint8_t Flags [4]; // the tag flags (none currently defined) Uint8_t Reserved [8]; // reserved for later use }; typedef struct { char* key; size_t keylen; unsigned char* value; size_t valuelen; unsigned int flags; } TagItem_t; static TagItem_t T [256]; // up to 256 items, otherwise program crashs static unsigned int TagCount = 0; #if defined __TURBOC__ static unsigned short CP_850 [256] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0, }; #elif defined _WIN32 static unsigned short CP_37 [256] = { // ??? 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F, 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087, 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x000A, 0x0017, 0x001B, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007, 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004, 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A, 0x0020, 0x00A0, 0x00E2, 0x00E4, 0x00E0, 0x00E1, 0x00E3, 0x00E5, 0x00E7, 0x00F1, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C, 0x0026, 0x00E9, 0x00EA, 0x00EB, 0x00E8, 0x00ED, 0x00EE, 0x00EF, 0x00EC, 0x00DF, 0x0021, 0x0024, 0x002A, 0x0029, 0x003B, 0x00AC, 0x002D, 0x002F, 0x00C2, 0x00C4, 0x00C0, 0x00C1, 0x00C3, 0x00C5, 0x00C7, 0x00D1, 0x00A6, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F, 0x00F8, 0x00C9, 0x00CA, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022, 0x00D8, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x00AB, 0x00BB, 0x00F0, 0x00FD, 0x00FE, 0x00B1, 0x00B0, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x00AA, 0x00BA, 0x00E6, 0x00B8, 0x00C6, 0x00A4, 0x00B5, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x00A1, 0x00BF, 0x00D0, 0x00DD, 0x00DE, 0x00AE, 0x005E, 0x00A3, 0x00A5, 0x00B7, 0x00A9, 0x00A7, 0x00B6, 0x00BC, 0x00BD, 0x00BE, 0x005B, 0x005D, 0x00AF, 0x00A8, 0x00B4, 0x00D7, 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x00AD, 0x00F4, 0x00F6, 0x00F2, 0x00F3, 0x00F5, 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x00B9, 0x00FB, 0x00FC, 0x00F9, 0x00FA, 0x00FF, 0x005C, 0x00F7, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00B2, 0x00D4, 0x00D6, 0x00D2, 0x00D3, 0x00D5, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x00B3, 0x00DB, 0x00DC, 0x00D9, 0x00DA, 0x009F, }; static unsigned short CP_42 [256] = { // CP_SYMBOLS 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0xF020, 0xF021, 0xF022, 0xF023, 0xF024, 0xF025, 0xF026, 0xF027, 0xF028, 0xF029, 0xF02A, 0xF02B, 0xF02C, 0xF02D, 0xF02E, 0xF02F, 0xF030, 0xF031, 0xF032, 0xF033, 0xF034, 0xF035, 0xF036, 0xF037, 0xF038, 0xF039, 0xF03A, 0xF03B, 0xF03C, 0xF03D, 0xF03E, 0xF03F, 0xF040, 0xF041, 0xF042, 0xF043, 0xF044, 0xF045, 0xF046, 0xF047, 0xF048, 0xF049, 0xF04A, 0xF04B, 0xF04C, 0xF04D, 0xF04E, 0xF04F, 0xF050, 0xF051, 0xF052, 0xF053, 0xF054, 0xF055, 0xF056, 0xF057, 0xF058, 0xF059, 0xF05A, 0xF05B, 0xF05C, 0xF05D, 0xF05E, 0xF05F, 0xF060, 0xF061, 0xF062, 0xF063, 0xF064, 0xF065, 0xF066, 0xF067, 0xF068, 0xF069, 0xF06A, 0xF06B, 0xF06C, 0xF06D, 0xF06E, 0xF06F, 0xF070, 0xF071, 0xF072, 0xF073, 0xF074, 0xF075, 0xF076, 0xF077, 0xF078, 0xF079, 0xF07A, 0xF07B, 0xF07C, 0xF07D, 0xF07E, 0xF07F, 0xF080, 0xF081, 0xF082, 0xF083, 0xF084, 0xF085, 0xF086, 0xF087, 0xF088, 0xF089, 0xF08A, 0xF08B, 0xF08C, 0xF08D, 0xF08E, 0xF08F, 0xF090, 0xF091, 0xF092, 0xF093, 0xF094, 0xF095, 0xF096, 0xF097, 0xF098, 0xF099, 0xF09A, 0xF09B, 0xF09C, 0xF09D, 0xF09E, 0xF09F, 0xF0A0, 0xF0A1, 0xF0A2, 0xF0A3, 0xF0A4, 0xF0A5, 0xF0A6, 0xF0A7, 0xF0A8, 0xF0A9, 0xF0AA, 0xF0AB, 0xF0AC, 0xF0AD, 0xF0AE, 0xF0AF, 0xF0B0, 0xF0B1, 0xF0B2, 0xF0B3, 0xF0B4, 0xF0B5, 0xF0B6, 0xF0B7, 0xF0B8, 0xF0B9, 0xF0BA, 0xF0BB, 0xF0BC, 0xF0BD, 0xF0BE, 0xF0BF, 0xF0C0, 0xF0C1, 0xF0C2, 0xF0C3, 0xF0C4, 0xF0C5, 0xF0C6, 0xF0C7, 0xF0C8, 0xF0C9, 0xF0CA, 0xF0CB, 0xF0CC, 0xF0CD, 0xF0CE, 0xF0CF, 0xF0D0, 0xF0D1, 0xF0D2, 0xF0D3, 0xF0D4, 0xF0D5, 0xF0D6, 0xF0D7, 0xF0D8, 0xF0D9, 0xF0DA, 0xF0DB, 0xF0DC, 0xF0DD, 0xF0DE, 0xF0DF, 0xF0E0, 0xF0E1, 0xF0E2, 0xF0E3, 0xF0E4, 0xF0E5, 0xF0E6, 0xF0E7, 0xF0E8, 0xF0E9, 0xF0EA, 0xF0EB, 0xF0EC, 0xF0ED, 0xF0EE, 0xF0EF, 0xF0F0, 0xF0F1, 0xF0F2, 0xF0F3, 0xF0F4, 0xF0F5, 0xF0F6, 0xF0F7, 0xF0F8, 0xF0F9, 0xF0FA, 0xF0FB, 0xF0FC, 0xF0FD, 0xF0FE, 0xF0FF, }; static unsigned short CP_437 [256] = { // MS-DOS: US 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0, }; static unsigned short CP_500 [256] = { // ??? 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F, 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087, 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x000A, 0x0017, 0x001B, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007, 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004, 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A, 0x0020, 0x00A0, 0x00E2, 0x00E4, 0x00E0, 0x00E1, 0x00E3, 0x00E5, 0x00E7, 0x00F1, 0x005B, 0x002E, 0x003C, 0x0028, 0x002B, 0x0021, 0x0026, 0x00E9, 0x00EA, 0x00EB, 0x00E8, 0x00ED, 0x00EE, 0x00EF, 0x00EC, 0x00DF, 0x005D, 0x0024, 0x002A, 0x0029, 0x003B, 0x005E, 0x002D, 0x002F, 0x00C2, 0x00C4, 0x00C0, 0x00C1, 0x00C3, 0x00C5, 0x00C7, 0x00D1, 0x00A6, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F, 0x00F8, 0x00C9, 0x00CA, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022, 0x00D8, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x00AB, 0x00BB, 0x00F0, 0x00FD, 0x00FE, 0x00B1, 0x00B0, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x00AA, 0x00BA, 0x00E6, 0x00B8, 0x00C6, 0x00A4, 0x00B5, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x00A1, 0x00BF, 0x00D0, 0x00DD, 0x00DE, 0x00AE, 0x00A2, 0x00A3, 0x00A5, 0x00B7, 0x00A9, 0x00A7, 0x00B6, 0x00BC, 0x00BD, 0x00BE, 0x00AC, 0x007C, 0x00AF, 0x00A8, 0x00B4, 0x00D7, 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x00AD, 0x00F4, 0x00F6, 0x00F2, 0x00F3, 0x00F5, 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x00B9, 0x00FB, 0x00FC, 0x00F9, 0x00FA, 0x00FF, 0x005C, 0x00F7, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x00B2, 0x00D4, 0x00D6, 0x00D2, 0x00D3, 0x00D5, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x00B3, 0x00DB, 0x00DC, 0x00D9, 0x00DA, 0x009F, }; static unsigned short CP_850 [256] = { // MS-DOS Latin 1 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0, }; static unsigned short CP_860 [256] = { // MS-DOS: Portuguese 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0, }; static unsigned short CP_861 [256] = { // MS-DOS: Iceland 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0, }; static unsigned short CP_863 [256] = { // MS-DOS: Canadian French 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x2017, 0x00C0, 0x00A7, 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00B8, 0x00B3, 0x00AF, 0x00CE, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0, }; static unsigned short CP_865 [256] = { // MS-DOS: Nordic 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0, }; static unsigned short CP_874 [256] = { // MS-DOS: Thai 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC, 0x0081, 0x0082, 0x0083, 0x0084, 0x2026, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0xF8C1, 0xF8C2, 0xF8C3, 0xF8C4, 0x0E3F, 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xF8C5, 0xF8C6, 0xF8C7, 0xF8C8, }; static unsigned short CP_1250 [256] = { // Windows: Latin 2 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0083, 0x201E, 0x2026, 0x2020, 0x2021, 0x0088, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0098, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9, }; static unsigned short CP_1251 [256] = { // Windows: Cyrillic 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0098, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, }; static unsigned short CP_1252 [256] = { // Windows: Latin 1 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, }; static unsigned short CP_1253 [256] = { // Windows: Greek 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x0088, 0x2030, 0x008A, 0x2039, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0098, 0x2122, 0x009A, 0x203A, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0xF8F9, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0xF8FA, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xF8FB, }; static unsigned short CP_1254 [256] = { // Windows: Latin 5 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x008E, 0x008F, 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x009E, 0x0178, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF, }; static unsigned short CP_1255 [256] = { // Windows: Hebrew 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x008A, 0x2039, 0x008C, 0x008D, 0x008E, 0x008F, 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x009A, 0x203A, 0x009C, 0x009D, 0x009E, 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0xF88D, 0xF88E, 0xF88F, 0xF890, 0xF891, 0xF892, 0xF893, 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0xF894, 0xF895, 0x200E, 0x200F, 0xF896, }; static unsigned short CP_1256 [256] = { // Windows: Arabic 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643, 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2, }; static unsigned short CP_1257 [256] = { // Windows: Baltic 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0083, 0x201E, 0x2026, 0x2020, 0x2021, 0x0088, 0x2030, 0x008A, 0x2039, 0x008C, 0x00A8, 0x02C7, 0x00B8, 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0098, 0x2122, 0x009A, 0x203A, 0x009C, 0x00AF, 0x02DB, 0x009F, 0x00A0, 0xF8FC, 0x00A2, 0x00A3, 0x00A4, 0xF8FD, 0x00A6, 0x00A7, 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9, }; static unsigned short CP_1258 [256] = { // Windows: Vietnam 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x008A, 0x2039, 0x0152, 0x008D, 0x008E, 0x008F, 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x009A, 0x203A, 0x0153, 0x009D, 0x009E, 0x0178, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF, }; static unsigned short CP_10000 [256] = { // Apple Macintosh 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x2126, 0x00E6, 0x00F8, 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7, }; static unsigned short CP_10079 [256] = { // ??? 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, 0x00DD, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x2126, 0x00E6, 0x00F8, 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, 0x00FF, 0x0178, 0x2044, 0x00A4, 0x00D0, 0x00F0, 0x00DE, 0x00FE, 0x00FD, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7, }; #endif /* * Resets Item Counter * Do frees any memory. */ void Init_Tags ( void ) { int i; for ( i = 0; i < (int)TagCount; i++ ) { if ( T[i].key != NULL ) free ( T[i].key ); T[i].key = NULL; if ( T[i].value != NULL ) free ( T[i].value ); T[i].value = NULL; } TagCount = 0; } int gettag ( const char* key, char* dst, size_t len ) { size_t valuelen; size_t keylen = strlen (key); int i; for ( i = 0; i < (int)TagCount; i++ ) if ( keylen == T[i].keylen && 0 == memcmp (T[i].key, key, keylen) ) { valuelen = len-1 > T[i].valuelen ? T[i].valuelen : len-1 ; memcpy ( dst, T[i].value, valuelen ); dst [valuelen] = '\0'; return 0; } memset ( dst, 0, len ); return -1; } static unsigned char* utf8char ( unsigned char* dst, unsigned long value ) { if ( value == '\r' || value == 0xFFFE || value == 0xFFFF ) { ; } else if ( value < 0x80 ) { *dst++ = value; } else if ( value < 0x800 ) { *dst++ = 0xC0 + ((value >> 6) & 0x1F); *dst++ = 0x80 + ((value >> 0) & 0x3F); } else if ( value < 0x10000 ) { *dst++ = 0xE0 + ((value >> 12) & 0x0F); *dst++ = 0x80 + ((value >> 6) & 0x3F); *dst++ = 0x80 + ((value >> 0) & 0x3F); } else if ( value < 0x200000 ) { *dst++ = 0xF0 + ((value >> 18) & 0x07); *dst++ = 0x80 + ((value >> 12) & 0x3F); *dst++ = 0x80 + ((value >> 6) & 0x3F); *dst++ = 0x80 + ((value >> 0) & 0x3F); } else if ( value < 0x4000000 ) { *dst++ = 0xF8 + ((value >> 24) & 0x03); *dst++ = 0x80 + ((value >> 18) & 0x3F); *dst++ = 0x80 + ((value >> 12) & 0x3F); *dst++ = 0x80 + ((value >> 6) & 0x3F); *dst++ = 0x80 + ((value >> 0) & 0x3F); } else if ( value < 0x80000000 ) { *dst++ = 0xFC + ((value >> 30) & 0x01); *dst++ = 0x80 + ((value >> 24) & 0x3F); *dst++ = 0x80 + ((value >> 18) & 0x3F); *dst++ = 0x80 + ((value >> 12) & 0x3F); *dst++ = 0x80 + ((value >> 6) & 0x3F); *dst++ = 0x80 + ((value >> 0) & 0x3F); } return dst; } /* * IsUnicode() * * Gets a memory block and tries to find out whether this is binary data or a valid Windows Unicode file. * When return 1, it is very likely (but not 100% secure) that the content is Unicode encoded. */ static int IsUnicode ( const unsigned char* src, size_t len ) { if ( len <= 2 ) return 0; if ( len & 1 ) // odd number of bytes? return 0; if ( src [0] != 0xFF || src [1] != 0xFE ) // Microsoft Unicode preample (also useful to detect endianess, but currently only little endian is supported) return 0; for ( len >>= 1; len > 0; len--, src += 2 ) { // Check for invalid codes (FFFE, FFFF, DC00...DFFF without a prepend D800...DBFF, D800...DBFF without a n appended DC00...DFFF) if ( ( src [1] & 0xFC ) == 0xDC ) return 0; if ( src [1] == 0xFF && ( src [0] & 0xFE ) == 0xFE ) return 0; if ( ( src [1] & 0xFC ) == 0xD8 ) { if ( len < 2 || ( src [3] & 0xFC ) != 0xDC ) return 0; } else { len--; src += 2; } } return 1; // good chance to be a UTF-8 } /* * addtag() * * Add a item to the item list of a tag. Item key is given by (key,keylen), item value by (value,valuelen). * * The following value translation modes are possible: * 0: no translation at all * 1: translate from console charset to UTF-8 (currently ISO-8859-1 for non-Windows and non-DOS OS) * 2: auto detect: contents is a valid Window Unicode File => translate to UTF-8, else no translation at all * 3: like 1), but convert ';' to null character * 4: UTF-16 LE => translate to UTF-8 * 5: translate from ISO-8859-1 to UTF-8 * 6: like 1), but convert from OEM codepage (Win32) * (should become an enum) * * Note: * Windows 95/98/ME has no usable NLS support * */ int addtag ( const char* key, // the item key size_t keylen, // length of item key, or 0 for auto-determine const unsigned char* value, // the item value size_t valuelen, // the length of the item value (before any possible translation) int converttoutf8, // convert flags of item value int flags ) // item flags proposal { unsigned char* p; unsigned char* q; unsigned char ch; size_t i; #ifdef _WIN32 const unsigned short* CP_ptr; unsigned int Codepage; if ( converttoutf8 == 6 ) { Codepage = GetOEMCP (); converttoutf8 = 1; } else { Codepage = GetACP (); } switch ( Codepage ) { case CP_ACP: CP_ptr = CP_1252; break; case CP_OEMCP: CP_ptr = CP_850; break; case CP_MACCP: CP_ptr = CP_10000; break; case CP_THREAD_ACP: CP_ptr = CP_1252; break; default: CP_ptr = CP_850; break; case 37: CP_ptr = CP_37; break; case 42: CP_ptr = CP_42; break; case 437: CP_ptr = CP_437; break; case 500: CP_ptr = CP_500; break; case 850: CP_ptr = CP_850; break; case 860: CP_ptr = CP_860; break; case 861: CP_ptr = CP_861; break; case 863: CP_ptr = CP_863; break; case 865: CP_ptr = CP_865; break; case 874: CP_ptr = CP_874; break; case 1250: CP_ptr = CP_1250; break; case 1251: CP_ptr = CP_1251; break; case 1252: CP_ptr = CP_1252; break; case 1253: CP_ptr = CP_1253; break; case 1254: CP_ptr = CP_1254; break; case 1255: CP_ptr = CP_1255; break; case 1256: CP_ptr = CP_1256; break; case 1257: CP_ptr = CP_1257; break; case 1258: CP_ptr = CP_1258; break; case 10000: CP_ptr = CP_10000; break; case 10079: CP_ptr = CP_10079; break; } #endif if ( converttoutf8 == 2 && IsUnicode ( value, valuelen ) ) { converttoutf8 = 4; value += 2; // remove first two bytes (zero width space 0xFEFF) valuelen = ( valuelen - 2) >> 1; flags &= ~2; // reset binary flag (it's now text) } if ( keylen == 0 ) keylen = strlen ( key ); p = malloc ( keylen ); memcpy ( p, key, keylen ); T [TagCount] . key = p; T [TagCount] . keylen = keylen; switch ( converttoutf8 ) { default: p = malloc ( 1 * valuelen ); // copy break; case 1: // at most 1 native character => 3 UTF bytes case 4: // at 1 wide => 3, 2 wide => 4 p = malloc ( 3 * valuelen ); break; } q = p; for ( i = 0; i < valuelen; i++ ) { ch = value [i]; switch ( converttoutf8 ) { default: // 0: no translation at all --or-- 2: auto detect: contents is a valid Window Unicode File => translate to UTF-8, else no translation at all *q++ = ch; break; case 5: // 5: translate from ISO-8859-1 to UTF-8 q = utf8char ( q, ch ); break; case 3: // 3: like 1), but convert ';' to null character if ( ch == ';' ) ch = '\0'; /* fall through */ case 1: // 1: translate from console charset to UTF-8 (currently ISO-8859-1 for non-Windows and non-DOS OS) #if defined __TURBOC__ q = utf8char ( q, CP_850 [ch] ); #elif defined _WIN32 // fprintf ( stderr, "%c %02X U+%04X\n", ch, ch, CP_ptr [ch] ); q = utf8char ( q, CP_ptr [ch] ); #elif defined USE_WIDECHAR { int ret; wchar_t wch = 0; ret = mbtowc ( &wch, value + i, valuelen - i ); if ( ret > 0 ) q = utf8char ( q, wch ), i += ret - 1; } #else q = utf8char ( q, ch ); #endif break; case 4: // 4: UTF-16 LE => translate to UTF-8 if ( (value [i+i+1] & 0xFC ) == 0xD8 && (value [i+i+3] & 0xFC ) == 0xDC ) { // UTF-16 code (2x16 bit for Unicodes 0x010000...0x10FFFF) q = utf8char ( q, ((value [i+i] + (value [i+i+1] << 8) - 0xD800) << 10) + (value [i+i+2] + (value [i+i+3] << 8) - 0xDC00) + 0x10000 ); i++; } else { q = utf8char ( q, value [i+i] + (value [i+i+1] << 8) ); } break; } } p = realloc ( p, valuelen = q-p ); for ( i = 0; i < TagCount; i++ ) if ( T [i].keylen == T [TagCount].keylen && 0 == strncasecmp (T [i].key, T [TagCount].key, T [i].keylen ) ) { // found old tag with the same name => replace free ( T [TagCount].key ); free ( T [i].value ); goto set; } i = TagCount++; set: T [i] . value = p; T [i] . valuelen = valuelen; T [i] . flags = flags; return 0; } static int Cdecl cmpfn2 ( const void* p1, const void* p2 ) { const TagItem_t* q1 = (TagItem_t*) p1; const TagItem_t* q2 = (TagItem_t*) p2; return q1 -> valuelen - q2 -> valuelen; } /* * Writes collect tag items and write it to a file. * Items are destroyed, so tags can only be written once. */ int FinalizeTags ( FILE* fp, unsigned int Version ) { static unsigned char H [32] = "APETAGEX"; unsigned char dw [8]; unsigned long estimatedbytes = 32; // 32 byte footer + all items, these are the 32 bytes footer, the items are added later unsigned long writtenbytes = -32; // actually writtenbytes-32, which should be equal to estimatedbytes (= footer + all items) unsigned int i; if ( TagCount == 0 ) return 0; qsort ( T, TagCount, sizeof (*T), cmpfn2 ); for ( i = 0; i < TagCount; i++ ) estimatedbytes += 9 + T[i] . keylen + T[i] . valuelen; if ( estimatedbytes >= 8192 + 103 ) stderr_printf ( "\nTag is %.1f Kbyte long. This is longer than the maximum recommended 8 KByte.\n\a", estimatedbytes/1024. ); H [ 8] = Version >> 0; H [ 9] = Version >> 8; H [10] = Version >> 16; H [11] = Version >> 24; H [12] = estimatedbytes >> 0; H [13] = estimatedbytes >> 8; H [14] = estimatedbytes >> 16; H [15] = estimatedbytes >> 24; H [16] = TagCount >> 0; H [17] = TagCount >> 8; H [18] = TagCount >> 16; H [19] = TagCount >> 24; H [23] = 0x80 | 0x20; writtenbytes += fwrite ( H, 1, 32, fp ); for ( i = 0; i < TagCount; i++ ) { dw [0] = T [i] . valuelen >> 0; dw [1] = T [i] . valuelen >> 8; dw [2] = T [i] . valuelen >> 16; dw [3] = T [i] . valuelen >> 24; dw [4] = T [i] . flags >> 0; dw [5] = T [i] . flags >> 8; dw [6] = T [i] . flags >> 16; dw [7] = T [i] . flags >> 24; writtenbytes += fwrite ( dw , 1, 8 , fp ); writtenbytes += fwrite ( T[i].key , 1, T[i].keylen , fp ); writtenbytes += fwrite ( "" , 1, 1 , fp ); if ( T[i].valuelen > 0 ) writtenbytes += fwrite ( T[i].value, 1, T[i].valuelen, fp ); } H [23] = 0x80; writtenbytes += fwrite ( H, 1, 32, fp ); if ( estimatedbytes != writtenbytes ) stderr_printf ( "\nError writing APE tag.\n" ); TagCount = 0; return 0; } static int TagKeyExists ( const char* key, size_t keylen ) { unsigned int i; if ( keylen == 0 ) keylen = strlen ( key ); for ( i = 0; i < TagCount; i++ ) if ( T [i].keylen == keylen && 0 == strncasecmp (T [i].key, key, keylen ) ) return 1; return 0; } /* * Copies src to dst. Copying is stopped at `\0' char is detected or if * len chars are copied. * Trailing blanks are removed and the string is `\0` terminated. */ static void memcpy_crop ( const char* key, char* src, size_t len, int flags ) { while ( len > 0 && ( src [len-1] == ' ' || src [len-1] == '\0' ) ) len--; if ( len > 0 ) if ( ! TagKeyExists ( key, 0 ) ) addtag ( key, 0, src, len, 1, flags ); } static int CopyTags_ID3 ( FILE* fp ) { Uint8_t tmp [128]; if ( -1 == SEEK ( fp, -128L, SEEK_END ) ) return -1; if ( 128 != READ ( fp, tmp, 128 ) ) return -1; if ( 0 != memcmp ( tmp, "TAG", 3 ) ) { return -1; } if ( !tmp[3] && !tmp[33] && !tmp[63] && !tmp[93] && !tmp[97] ) return -1; memcpy_crop ( "Title" , tmp + 3, 30, 0 ); memcpy_crop ( "Artist" , tmp + 33, 30, 0 ); memcpy_crop ( "Album" , tmp + 63, 30, 0 ); memcpy_crop ( "Year" , tmp + 93, 4, 0 ); memcpy_crop ( "Comment", tmp + 97, 30, 0 ); if ( tmp[127] < sizeof(GenreList)/sizeof(*GenreList) ) if ( ! TagKeyExists ( "Genre", 0 ) ) addtag ("Genre", 0, GenreList [tmp[127]], strlen (GenreList [tmp[127]]), 0, 0 ); if ( tmp[125] == 0 && tmp[126] != 0 ) if ( ! TagKeyExists ( "Track", 0 ) ) { sprintf ( tmp, "%u", tmp[126] ); addtag ("Track", 0, tmp, strlen (tmp), 0, 0 ); } return 0; } static unsigned int Read_LE_Uint32 ( const unsigned char* p ) { return ((Uint32_t)p[0] << 0) | ((Uint32_t)p[1] << 8) | ((Uint32_t)p[2] << 16) | ((Uint32_t)p[3] << 24); } static int CopyTags_APE ( FILE* fp ) { Uint32_t len; Uint32_t flags; Uint32_t version; unsigned char buff [32768]; unsigned char key [257]; unsigned char* p; struct APETagFooterStruct T; Uint32_t TagLen; Uint32_t TagCount; // Uint32_t tmp; if ( -1 == SEEK ( fp, -(long)sizeof T, SEEK_END ) ) return -1; if ( sizeof(T) != READ ( fp, &T, sizeof T ) ) return -1; if ( memcmp ( T.ID, "APETAGEX", sizeof(T.ID) ) != 0 ) return -1; version = Read_LE_Uint32 (T.Version); if ( version != 1000 && version != 2000 ) return -1; TagLen = Read_LE_Uint32 (T.Length); if ( TagLen <= sizeof T ) return -1; if ( -1 == SEEK ( fp, -(long)TagLen, SEEK_END ) ) return -1; memset ( buff, 0, sizeof(buff) ); if ( TagLen - sizeof T != READ ( fp, buff, TagLen - sizeof T ) ) return -1; TagCount = Read_LE_Uint32 (T.TagCount); for ( p = buff; TagCount--; ) { len = Read_LE_Uint32 ( p ); p += 4; flags = Read_LE_Uint32 ( p ); p += 4; strcpy ( key, p ); p += strlen (key) + 1; if ( ! TagKeyExists ( key, 0 ) ) addtag ( key, 0, p, len > 0 && p [len-1] == '\0' ? len-1 : len, version >= 2000 ? 0 : 5, flags ); p += len; } return 0; } static void FullPathName ( char* dst, size_t dstlen, const char* filename ) // Can contain stuff like ".." and "." { // const char* p; char* q = dst; #if DRIVE_SEP != '\0' int drive = 0; if ( isalpha (filename[0]) && filename[1] == DRIVE_SEP && filename[2] != PATH_SEP ) { drive = filename[0] & 0x1F; filename += 2; } #endif if ( filename[0] != PATH_SEP ) { #ifdef _WIN32 _getdcwd( drive, dst, dstlen ); #else getcwd ( dst, dstlen ); #endif q += strlen (q); #ifdef _WIN32 if ( dst[0] != PATH_SEP || dst[1] != '\0' ) #else if ( dst[2] != PATH_SEP || dst[3] != '\0' ) #endif *q++ = PATH_SEP; } strcpy ( q, filename ); return; } /********************************************************************************************/ /* " " ' ' " - " '-' "." '.' "/" '/' " -- " '_' "[#0]" '0' "[#n]" [number] 'n' "#n" number 'M' "(#N)" (CD x) 'N' it should also be possible: (CD x/x), (DVD x), (DVD x/x) "#A" Artist 'A' "#C" CD/Album 'C' "#T" Title 'T' "#x" extention 'x' /#C -- [#n] #A -- #T#x | Acid Jazz/100% Acid Jazz -- [04] Leena Conquest (and Hip Hop Fingers) -- Boundaries (Radio Edit).pac /#C -- [#n] #A -- #C -- #T#x| Meditation/Jade Collection (1998) -- [10] Rhian -- Red Sun, Blue River -- The Miracle Song.mpc /#A/#C -- [#n] #T#x | Andreas Vollenweider/Eolian Minstrel -- [02] Across the Iron River.pac /#A/#C#N -- [#n] #T#x | Barbra Streisand/The Concert (CD 1) -- [01] Overture /#A -- #C -- [#n] #T#x | Friedemann/Friedemann -- Aquamarin -- [09] In the Court of the Mermaid.pac /#C/[#n] #A -- #T#x | Jazz Lyrik Prosa/[11] Eberhard Esche -- Anektode.pac /#A -- #T#x | Lais/Lais -- 06.pac /#C/(#N) -- [#n] #A -- #T#x | Tanz- und Folkfest 2001 -- Klingende Post/(CD 2) -- [09] Andy Irvine -- Gladiators.pac /#A -- #C -- [#0]#x | Friedemann/Friedemann -- Aquamarin -- [00].pac /#A/#C (#N) -- [#0]#x | Tangerine Dream/The Warsaw Concert (CD 2) -- [00].pac /#A/#T#x | Heinz-Rudolf Kunze/Dein ist mein ganzes Herz.pac /#A/#C -- [#0]#x | Sting/Nada como el Sol -- [00].mpc */ static const char* const parser_strings [] = { "/A_Tx", "/A/Tx", "/A_C_0x", "/C_n A_Tx", "/C_n A_C_Tx", // new "/A/C_n Tx", "/A/C N_n Tx", "/A_C_n Tx", "/C/n A_Tx", "/C/N_n A_Tx", "/A/C N_0x", "/A/C_0x", }; static void copy ( char* dst, const char* src, size_t len ) { memcpy ( dst, src, len ); dst [len] = '\0'; } /* * dst[0] = Artist * dst[1] = CD * dst[2] = Title * dst[3] = +CD * dst[4] = number * dst[5] = ext */ #ifndef isdigit # define isdigit(x) ((unsigned int)((x) - '0') < 10) #endif static int parse ( char** dst, const char* src, const char* format ) { int i; const char* srcend = src + strlen(src); const char* p; char* q; for ( i = 0; i < 6; i++) dst[i][0] = '\0'; for ( i = strlen(format); i-- > 0; ) { p = srcend; #ifndef STFU stderr_printf ( "%c: ", format[i] ); #endif switch ( format[i] ) { case '.': case ' ': case '/': // !!!!!!! if (p[-1] != format[i]) return 1; p--; break; case '_': if (0 != memcmp (p-4, " -- ", 4)) return 1; p -= 4; break; case '-': if (0 != memcmp (p-3, " - ", 3)) return 1; p -= 3; break; case '0': if (p[-1] != ']' || p[-2] != '0' || p[-3] != '0' || p[-4] != '[') return 1; copy (dst[4], p-3, 2); p -= 4; break; case 'n': if (p[-1] != ']' || !isdigit(p[-2]) || !isdigit(p[-3]) || p[-4] != '[') return 1; copy (dst[4], p-3, 2); p -= 4; break; case 'M': if ( !isdigit(p[-1]) || !isdigit(p[-2]) ) return 1; copy (dst[4], p-2, 2); p -= 2; break; case 'N': if (p[-1] != ')' || !isdigit(p[-2]) || p[-3] != ' ' || p[-4] != 'D' || p[-5] != 'C' || p[-6] != '(') return 1; dst[3][0] = ' '; copy (dst[3]+1, p-6, 6); p -= 6; break; case 'A': q = dst[0]; goto big; case 'C': q = dst[1]; goto big; case 'T': q = dst[2]; goto big; big: while ( 0 == memcmp (p-4, "/mpc", 4) || 0 == memcmp (p-4, "/mp3", 4) || 0 == memcmp (p-4, "/pac", 4) || 0 == memcmp (p-4, "/ape", 4) || 0 == memcmp (p-4, "/pac", 4) || 0 == memcmp (p-3, "/.." , 3) || 0 == memcmp (p-2, "/." , 2) ) { do { p--; srcend--; } while ( *p != PATH_SEP ); } while ( p[-1] != PATH_SEP && p[-1] != DRIVE_SEP && 0 != memcmp (p-4, " -- ", 4 ) && (p[-1] != ')' || !isdigit(p[-2]) || p[-3] != ' ' || p[-4] != 'D' || p[-5] != 'C' || p[-6] != '(') && (p[-1] != ' ' || p[-2] != ']' || !isdigit(p[-3]) || !isdigit(p[-4]) || p[-5] != '[') && (p[-1] != ']' || p[-2] != '0' || p[-3] != '0' || p[-4] != '[') ) p--; copy ( q, p, srcend - p ); break; case 'x': do { p--; if (p[0] == PATH_SEP || p[0] == DRIVE_SEP) return -1; } while (*p != '.'); copy (dst[5], p, srcend-p ); break; } #ifndef STFU stderr_printf ( "%*.*s\033[7m%*.*s\033[0m\n", p-src, p-src, src, srcend-p, srcend-p, p ); #endif srcend = p; } return 0; } static int hexdigit ( const char s ) { if ( (unsigned char)(s-'0') < 10u ) return s-'0'; if ( (unsigned char)(s-'A') < 6u ) return s-'A'+10; return -1; } static void spaceconverting ( char* dst, const char* src ) // can work inplace { for ( ; src[0] != '\0' ; src++) { if ( src[0] == '_' ) *dst++ = ' '; else if ( src[0] == '%' && hexdigit(src[1]) >= 0 && hexdigit(src[2]) >= 0 ) *dst++ = hexdigit(src[1]) * 16 + hexdigit(src[2]), src += 2; else *dst++ = *src; } *dst = '\0'; } static int Parser ( const char* src ) { size_t i; char tmp [6] [1024]; char* buff [6] = { tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5] }; char merge [1024]; char* q; #ifndef STFU stderr_printf ( "\n »%s«\n", src ); #endif memset ( tmp , 0, sizeof tmp ); memset ( merge, 0, sizeof merge ); for ( i = 0; i < sizeof(parser_strings)/sizeof(*parser_strings); i++ ) { if ( 0 == parse ( buff, src, parser_strings[i] ) ) { sprintf ( merge, "%s%s", tmp[1], tmp[3] ); q = merge + strlen (merge); if ( q-7 >= merge && q[-7]==' ' && q[-6]=='(' && atoi(q-5) >= 1900 && atoi(q-5) < 2050 && q[-1] == ')' ) { q[-1] = '\0'; q[-7] = '\0'; q -= 5; } else { q = NULL; } spaceconverting ( tmp[0], tmp[0] ); spaceconverting ( merge , merge ); spaceconverting ( tmp[2], tmp[2] ); spaceconverting ( tmp[4], tmp[4] ); spaceconverting ( tmp[5], tmp[5] ); stderr_printf ("\n"); stderr_printf ("Artist = »%s«\n", tmp[0] ); stderr_printf ("CD = »%s«\n", merge ); stderr_printf ("Title = »%s«\n", tmp[2] ); stderr_printf ("No# = »%s«\n", tmp[4] ); stderr_printf ("Extent = »%s«\n", tmp[5] ); stderr_printf ("Year = »%s«\n", q ? q : "????" ); #if 1 if ( tmp[0][0] && ! TagKeyExists ( "Artist", 0 ) ) addtag ( "Artist", 0, tmp[0], strlen (tmp[0]), 5, 0 ); if ( merge[0] && ! TagKeyExists ( "Album" , 0 ) ) addtag ( "Album" , 0, merge , strlen (merge) , 5, 0 ); if ( tmp[2][0] && ! TagKeyExists ( "Title" , 0 ) ) addtag ( "Title" , 0, tmp[2], strlen (tmp[2]), 5, 0 ); if ( tmp[4][0] && ! TagKeyExists ( "Track" , 0 ) ) addtag ( "Track" , 0, tmp[4], strlen (tmp[4]), 5, 0 ); if ( q != NULL && ! TagKeyExists ( "Year" , 0 ) ) addtag ( "Year" , 0, q , 4 , 5, 0 ); #endif return 1; } #ifndef STFU stderr_printf ("???\n--\n"); #endif } return 0; } /*******************************************************************************/ static int CopyTags_Name ( const char* filename ) { char buff [4096]; FullPathName ( buff, sizeof buff, filename ); Parser ( buff ); return 0; } int CopyTags ( const char* filename ) { FILE* fp; if ( 0 == strncmp (filename, "/dev/", 5 ) ) return 0; fp = fopen ( filename, "rb" ); if ( fp == NULL ) return -1; CopyTags_APE (fp); // APE tags have higher priority than ID3V1 tags CopyTags_ID3 (fp); //CopyTags_Name (filename); fclose (fp); return 0; } /* end of tags.c */ mppenc-1.16/src/profile.h0000644000175000017500000000677610522734510014620 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #ifndef MPPDEC_PROFILE_H #define MPPDEC_PROFILE_H #ifdef PROFILE /* T I M E C O U N T - F U N C T I O N */ # if defined _WIN32 typedef /*unsigned*/ __int64 uintmax_t; #pragma warning ( disable: 4035 ) static __inline uintmax_t rdtscll ( void ) { __asm { rdtsc }; } #pragma warning ( default: 4035 ) # define RDTSC() timetemp = rdtscll () # define __FUNCTION__ "?" # elif defined __TURBOC__ typedef signed long uintmax_t; uintmax_t readtime ( void ); # define RDTSC() timetemp = readtime () # define __FUNCTION__ "?" # else typedef unsigned long long uintmax_t; # include # define RDTSC() rdtscll (timetemp) # endif /* _WIN32 */ /* M A C R O S */ # define _STR(x) #x # define __STR(x) _STR(x) # define ENTER(x) do { \ uintmax_t timetemp; \ RDTSC(); \ timecounter[*functionstack_pointer] += timetemp; \ timecounter[*++functionstack_pointer = x] -= timetemp; \ timename[x] = __FUNCTION__ "()|" __FILE__ "|" __STR(__LINE__); \ } while (0) # define NEXT(x,n) do { \ uintmax_t timetemp; \ RDTSC(); \ timecounter[*functionstack_pointer] += timetemp; \ timecounter[*functionstack_pointer = x] -= timetemp; \ timename[x] = __FUNCTION__ "-" __STR(n) "|" __FILE__ "|" __STR(__LINE__); \ } while (0) # define LEAVE(x) do { \ uintmax_t timetemp; \ RDTSC(); \ timecounter[x] += timetemp; \ timecounter[*--functionstack_pointer] -= timetemp; \ } while (0) # define START() set_signal () # define REPORT() report () /* V A R I A B L E S */ extern uintmax_t timecounter [256]; extern const char* timename [256]; extern unsigned char functionstack [1024]; extern unsigned char* functionstack_pointer; /* F U N C T I O N S */ void set_signal ( void ); void report ( void ); #else /* M A C R O S */ # define START() # define ENTER(x) # define NEXT(x,n) # define LEAVE(x) # define REPORT() #endif /* PROFILE */ #endif /* MPPDEC_PROFILE_H */ /* end of profile.h */ mppenc-1.16/src/predict.h0000644000175000017500000001436410522734510014602 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" #define MAX_LPC_ORDER 35 #define log2(x) ( log (x) * (1./M_LN2) ) #define ORDER_PENALTY 0 static int // best prediction order model CalculateLPCCoeffs ( Int32_t* buf, // Samples size_t nbuf, // Number of samples Int32_t offset, // double* lpcout, // quantized prediction coefficients int nlpc, // max. prediction order float* psigbit, // expected number of bits per original signal sample float* presbit ) // expected number of bits per residual signal sample { static double* fbuf = NULL; static int nflpc = 0; static int nfbuf = 0; int nbit; int i; int j; int bestnbit; int bestnlpc; double e; double bestesize; double ci; double esize; double acf [MAX_LPC_ORDER + 1]; double ref [MAX_LPC_ORDER + 1]; double lpc [MAX_LPC_ORDER + 1]; double tmp [MAX_LPC_ORDER + 1]; double escale = 0.5 * M_LN2 * M_LN2 / nbuf; double sum; if ( nlpc >= nbuf ) // if necessary, limit the LPC order to the number of samples available nlpc = nbuf - 1; if ( nlpc > nflpc || nbuf > nfbuf ) { // grab some space for a 'zero mean' buffer of floats if needed if ( fbuf != NULL ) free ( fbuf - nflpc ); fbuf = nlpc + ((double*) calloc ( nlpc+nbuf, sizeof (*fbuf) )); nfbuf = nbuf; nflpc = nlpc; } e = 0.; for ( j = 0; j < nbuf; j++ ) { // zero mean signal and compute energy sum = fbuf [j] = buf[j] - (double)offset; e += sum * sum; } esize = e > 0. ? 0.5 * log2 (escale * e) : 0.; *psigbit = esize; // return the expected number of bits per original signal sample acf [0] = e; // store the best values so far (the zeroth order predictor) bestnlpc = 0; bestnbit = nbuf * esize; bestesize = esize; for ( i = 1; i <= nlpc && e > 0. && i < bestnlpc + 4; i++ ) { // just check two more than bestnlpc sum = 0.; for ( j = i; j < nbuf; j++ ) // compute the jth autocorrelation coefficient sum += fbuf [j] * fbuf [j-i]; acf [i] = sum; ci = 0.; // compute the reflection and LP coeffients for order j predictor for ( j = 1; j < i; j++ ) ci += lpc [j] * acf [i-j]; lpc [i] = ref [i] = ci = (acf [i] - ci) / e; for ( j = 1; j < i; j++ ) tmp [j] = lpc [j] - ci * lpc [i-j]; for ( j = 1; j < i; j++ ) lpc [j] = tmp [j]; e *= 1 - ci*ci; // compute the new energy in the prediction residual esize = e > 0. ? 0.5 * log2 (escale * e) : 0.; nbit = nbuf * esize + i * ORDER_PENALTY; if ( nbit < bestnbit ) { // store this model if it is the best so far bestnlpc = i; // store best model order bestnbit = nbit; bestesize = esize; for ( j = 0; j < bestnlpc; j++ ) // store the quantized LP coefficients lpcout [j] = lpc [j+1]; } } *presbit = bestesize; // return the expected number of bits per residual signal sample return bestnlpc; // return the best model order } static void Pred ( const unsigned int* new, unsigned int* old ) { static Double DOUBLE [36]; Float org; Float pred; int i; int j; int sum = 18; int order; double oldeff = 0.; double neweff = 0.; for ( i = 0; i < 36; i++ ) sum += old [i]; sum = (int) floor (sum / 36.); order = CalculateLPCCoeffs ( old, 36, sum*0, DOUBLE, 35, &org, &pred ); printf ("avg: %4u [%2u] %.2f %.2f\n\n", sum, order, org, pred ); if ( order < 1 ) return; for ( i = 0; i < order; i++ ) printf ("%f ", DOUBLE[i] ); printf ("\n"); for ( i = 0; i < 36; i++ ) { double sum = 0.; for ( j = 1; j <= order; j++ ) { sum += (i-j < 0 ? old[i-j+36] : new [i-j]) * DOUBLE [j-1]; } printf ("%2u: %6.2f %3d\n", i, sum, new [i] ); oldeff += new[i] * new[i]; neweff += (sum-new[i]) * (sum-new[i]); } printf ("%6.2f %6.2f\n", sqrt(oldeff), sqrt(neweff) ); } void Predicate ( int Channel, int Band, unsigned int* x, int* scf ) { static Int32_t OLD [2] [32] [36]; int i; printf ("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"); for ( i = 0; i < 36; i++ ) printf ("%2d ", OLD [Channel][Band][i] ); printf ("\n"); for ( i = 0; i < 36; i++ ) printf ("%2d ", x[i] ); printf ("\n"); printf ("%2u-%2u-%2u ", scf[0], scf[1], scf[2] ); Pred ( x, OLD [Channel][Band] ); for ( i = 0; i < 36; i++ ) OLD [Channel][Band][i] = x[i]; } /* end of predict.c */ mppenc-1.16/src/fastmath.h0000644000175000017500000000552510525155536014766 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ typedef union mpc_floatint { float f; Int32_t n; } mpc_floatint; static __inline Int32_t mpc_nearbyintf(float fVal) { mpc_floatint tmp; tmp.f = fVal + 0x00FF8000; tmp.n = tmp.n - 0x4B7F8000; return tmp.n; } #define mpc_lrintf mpc_nearbyintf static __inline Int32_t mpc_round32(float fVal) { mpc_floatint tmp; tmp.f = fVal + 0x00FD8000; tmp.n = tmp.n - 0x4B7D8000; return tmp.n; } #ifdef FAST_MATH static __inline float my_atan2 ( float x, float y ) { float t, ret; int i; mpc_floatint mx, my; mx.f = x; my.f = y; if ( (mx.n & 0x7FFFFFFF) < (my.n & 0x7FFFFFFF) ) { i = mpc_round32 (t = TABSTEP * (mx.f / my.f)); ret = tabatan2 [1*TABSTEP+i][0] + tabatan2 [1*TABSTEP+i][1] * (t-i); if ( my.n < 0 ) ret = (float)(ret - M_PI); } else if ( mx.n < 0 ) { i = mpc_round32 (t = TABSTEP * (my.f / mx.f)); ret = - M_PI/2 - tabatan2 [1*TABSTEP+i][0] + tabatan2 [1*TABSTEP+i][1] * (i-t); } else if ( mx.n > 0 ) { i = mpc_round32 (t = TABSTEP * (my.f / mx.f)); ret = + M_PI/2 - tabatan2 [1*TABSTEP+i][0] + tabatan2 [1*TABSTEP+i][1] * (i-t); } else { ret = 0.; } return ret; } static __inline float my_cos ( float x ) { float t, ret; int i; i = mpc_round32 (t = TABSTEP * x); ret = tabcos [13*TABSTEP+i][0] + tabcos [13*TABSTEP+i][1] * (t-i); return ret; } static __inline int my_ifloor ( float x ) { mpc_floatint mx; mx.f = (float) (x + (0x0C00000L + 0.500000001)); return mx.n - 1262485505; } static __inline float my_sqrt ( float x ) { float ret; int i, ex; mpc_floatint mx; mx.f = x; ex = mx.n >> 23; // get the exponent mx.n = (mx.n & 0x7FFFFF) | 0x42800000; // delete the exponent i = mpc_round32 (mx.f); // Integer-part of the mantissa (round ????????????) ret = tabsqrt_m [i-TABSTEP][0] + tabsqrt_m [i-TABSTEP][1] * (mx.f-i); // calculate value ret *= tabsqrt_ex [ex]; return ret; } #endif mppenc-1.16/src/cvd.c0000644000175000017500000003357710525155536013736 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" /* C O N S T A N T S */ // from MatLab-Simulation (Fourier-transforms of the Cos-Rolloff) #if 0 static const float Puls [11] = { -0.02724753942504f, -0.10670808991329f, -0.06198987803623f, 0.18006206051664f, 0.49549552704050f, 0.64201253447071f, 0.49549552704050f, 0.18006206051664f, -0.06198987803623f, -0.10670808991329f, -0.02724753942504f }; #endif static const float Puls [ 9] = { -0.10670808991329f, -0.06198987803623f, 0.18006206051664f, 0.49549552704050f, 0.64201253447071f, 0.49549552704050f, 0.18006206051664f, -0.06198987803623f, -0.10670808991329f }; /* // Generating the Cos-Rolloff of the Cepstral-analysis, Cos-Rolloff from 5512,5 Hz to 11025 Hz // for ( k = 0; k <= 1024; k++ ) { // if (k < 256) CosWin [k-256] = 1; // else if (k < 512) CosWin [k-256] = 0.5 + 0.5*cos (M_PI*(k-256)/256); // else CosWin [k-256] = 0; // } */ static const float CosWin [256] = { 1.0000000000000000f, 0.9999623298645020f, 0.9998494386672974f, 0.9996612071990967f, 0.9993977546691895f, 0.9990590810775757f, 0.9986452460289002f, 0.9981563091278076f, 0.9975923895835877f, 0.9969534873962402f, 0.9962397813796997f, 0.9954513311386108f, 0.9945882558822632f, 0.9936507344245911f, 0.9926388263702393f, 0.9915527701377869f, 0.9903926253318787f, 0.9891586899757385f, 0.9878510832786560f, 0.9864699840545654f, 0.9850156307220459f, 0.9834882616996765f, 0.9818880558013916f, 0.9802152514457703f, 0.9784701466560364f, 0.9766530394554138f, 0.9747641086578369f, 0.9728036522865295f, 0.9707720279693604f, 0.9686695337295532f, 0.9664964079856873f, 0.9642530679702759f, 0.9619397521018982f, 0.9595569372177124f, 0.9571048617362976f, 0.9545840024948120f, 0.9519946575164795f, 0.9493372440338135f, 0.9466121792793274f, 0.9438198208808899f, 0.9409606456756592f, 0.9380350708961487f, 0.9350435137748718f, 0.9319864511489868f, 0.9288643002510071f, 0.9256775975227356f, 0.9224267601966858f, 0.9191123247146606f, 0.9157348275184631f, 0.9122946262359619f, 0.9087924361228943f, 0.9052286148071289f, 0.9016037583351135f, 0.8979184627532959f, 0.8941732048988342f, 0.8903686404228210f, 0.8865052461624146f, 0.8825836181640625f, 0.8786044120788574f, 0.8745682239532471f, 0.8704755902290344f, 0.8663271069526672f, 0.8621235489845276f, 0.8578653931617737f, 0.8535534143447876f, 0.8491881489753723f, 0.8447702527046204f, 0.8403005003929138f, 0.8357794880867004f, 0.8312078714370728f, 0.8265864253044128f, 0.8219157457351685f, 0.8171966671943665f, 0.8124297261238098f, 0.8076158165931702f, 0.8027555346488953f, 0.7978496551513672f, 0.7928989529609680f, 0.7879040837287903f, 0.7828658819198608f, 0.7777851223945618f, 0.7726625204086304f, 0.7674987912178040f, 0.7622948288917542f, 0.7570513486862183f, 0.7517691850662231f, 0.7464491128921509f, 0.7410919070243835f, 0.7356983423233032f, 0.7302693724632263f, 0.7248056530952454f, 0.7193081378936768f, 0.7137775421142578f, 0.7082147598266602f, 0.7026206851005554f, 0.6969960331916809f, 0.6913416981697083f, 0.6856585741043091f, 0.6799474954605103f, 0.6742093563079834f, 0.6684449315071106f, 0.6626551747322083f, 0.6568408608436585f, 0.6510030031204224f, 0.6451423168182373f, 0.6392598152160645f, 0.6333563923835754f, 0.6274328231811523f, 0.6214900612831116f, 0.6155290603637695f, 0.6095505952835083f, 0.6035556793212891f, 0.5975451469421387f, 0.5915199518203735f, 0.5854809284210205f, 0.5794290900230408f, 0.5733652114868164f, 0.5672903656959534f, 0.5612053275108337f, 0.5551111102104187f, 0.5490085482597351f, 0.5428986549377441f, 0.5367822647094727f, 0.5306603908538818f, 0.5245338082313538f, 0.5184035897254944f, 0.5122706294059753f, 0.5061357617378235f, 0.5000000000000000f, 0.4938642382621765f, 0.4877294003963471f, 0.4815963804721832f, 0.4754661619663239f, 0.4693396389484406f, 0.4632177054882050f, 0.4571013450622559f, 0.4509914219379425f, 0.4448888897895813f, 0.4387946724891663f, 0.4327096343040466f, 0.4266347587108612f, 0.4205709397792816f, 0.4145190417766571f, 0.4084800481796265f, 0.4024548530578613f, 0.3964443206787109f, 0.3904493749141693f, 0.3844709396362305f, 0.3785099089145660f, 0.3725671768188477f, 0.3666436076164246f, 0.3607401549816132f, 0.3548576533794403f, 0.3489970266819000f, 0.3431591391563416f, 0.3373448550701141f, 0.3315550684928894f, 0.3257906734943390f, 0.3200524747371674f, 0.3143413960933685f, 0.3086582720279694f, 0.3030039668083191f, 0.2973793447017670f, 0.2917852103710175f, 0.2862224578857422f, 0.2806918919086456f, 0.2751943469047546f, 0.2697306573390961f, 0.2643016278743744f, 0.2589081227779388f, 0.2535509169101715f, 0.2482308149337769f, 0.2429486215114594f, 0.2377051562070847f, 0.2325011938810349f, 0.2273375093936920f, 0.2222148776054382f, 0.2171340882778168f, 0.2120959013700485f, 0.2071010768413544f, 0.2021503448486328f, 0.1972444802522659f, 0.1923841983079910f, 0.1875702589750290f, 0.1828033626079559f, 0.1780842244625092f, 0.1734135746955872f, 0.1687921136617661f, 0.1642205268144608f, 0.1596994996070862f, 0.1552297323942184f, 0.1508118808269501f, 0.1464466154575348f, 0.1421345919370651f, 0.1378764659166336f, 0.1336728632450104f, 0.1295244395732880f, 0.1254318058490753f, 0.1213955804705620f, 0.1174163669347763f, 0.1134947761893272f, 0.1096313893795013f, 0.1058267876505852f, 0.1020815446972847f, 0.0983962342143059f, 0.0947714000940323f, 0.0912075936794281f, 0.0877053514122963f, 0.0842651948332787f, 0.0808876454830170f, 0.0775732174515724f, 0.0743224024772644f, 0.0711356922984123f, 0.0680135712027550f, 0.0649565011262894f, 0.0619649514555931f, 0.0590393692255020f, 0.0561801902949810f, 0.0533878505229950f, 0.0506627671420574f, 0.0480053536593914f, 0.0454160086810589f, 0.0428951233625412f, 0.0404430739581585f, 0.0380602329969406f, 0.0357469581067562f, 0.0335035994648933f, 0.0313304923474789f, 0.0292279683053494f, 0.0271963365375996f, 0.0252359099686146f, 0.0233469791710377f, 0.0215298328548670f, 0.0197847411036491f, 0.0181119665503502f, 0.0165117643773556f, 0.0149843730032444f, 0.0135300243273377f, 0.0121489353477955f, 0.0108413146808743f, 0.0096073597669601f, 0.0084472559392452f, 0.0073611787520349f, 0.0063492907211185f, 0.0054117450490594f, 0.0045486823655665f, 0.0037602325901389f, 0.0030465149320662f, 0.0024076367262751f, 0.0018436938989908f, 0.0013547716662288f, 0.0009409435442649f, 0.0006022718735039f, 0.0003388077020645f, 0.0001505906548118f, 0.0000376490788767f, }; /* F U N C T I O N S */ // sets all the harmonics static void SetVoiceLines ( int* VoiceLine, const float base, int val ) { int n; int max = (int) (MAX_CVD_LINE * base / 1024.f); // harmonics up to Index MAX_CVD_LINE (spectral lines outside of that don't make sense) int line; float frq = 1024.f / base; // frq = 1024./i is the Index of the basic harmonic // go through all harmonics for ( n = 1; n <= max; n++ ) { line = (int) (n * frq); VoiceLine [line] = VoiceLine [line+1] = val; } } // Analyze the Cepstrum, search for the basic harmonic static void CEP_Analyse2048 ( float* res1, float* res2, float* qual1, float* qual2, float* cep ) { int n; int line; float cc [MAX_ANALYZED_IDX + 3]; // cross correlation float ref; float line_sum; float sum; float kkf; float norm; const float* x; // cross-correlation with pulse shape // Calculate idx = MIN_ANALYZED_IDX-2 to MAX_ANALYZED_IDX+2, // because they are read during search for maximum // 50 -> 882 Hz, 700 -> 63 Hz base frequency *res1 = *res2 = 0. ; memset ( cc, 0, sizeof cc ); for ( n = MIN_ANALYZED_IDX - 2; n <= MAX_ANALYZED_IDX + 2; n++ ) { x = cep + n; if ( x[0] > 0 ) { norm = x[-4] * x[-4] + x[-3] * x[-3] + x[-2] * x[-2] + x[-1] * x[-1] + x[ 0] * x[ 0] + x[ 1] * x[ 1] + x[ 2] * x[ 2] + x[ 3] * x[ 3] + x[ 4] * x[ 4]; kkf = x[-4] * Puls [0] + x[-3] * Puls [1] + x[-2] * Puls [2] + x[-1] * Puls [3] + x[ 0] * Puls [4] + x[ 1] * Puls [5] + x[ 2] * Puls [6] + x[ 3] * Puls [7] + x[ 4] * Puls [8]; cc [n] = kkf * kkf / norm; // calculate the square of ncc to avoid sqrt() } } // search for the (relative) maximum ref = 0.f; line = MED_ANALYZED_IDX; for ( n = MAX_ANALYZED_IDX; n >= MED_ANALYZED_IDX; n-- ) { if ( cc[n] * cep[n] * cep[n] > ref && cc[n] > 0.40f && // e33 (02) 0.85 cep[n] > 0.00f && // e33 (02) cc[n ] >= cc[n+1] && cc[n ] >= cc[n-1] && cc[n+1] >= cc[n+2] && cc[n-1] >= cc[n-2] ) { ref = cc[n] * cep[n] * cep[n]; line = n; } } // Calculating the center of the maximum (Interpolation) x = cep + line; sum = x[-3] + x[-2] + x[-1] + x[0] + x[1] + x[2] + x[3] + 1.e-30f; line_sum = (x[1]-x[-1]) + 2 * (x[2]-x[-2]) + 3 * (x[3]-x[-3]) + sum * line + 1.e-30f; /* e33 (04) */ ref = cc[line ] * cep[line ] * cep[line ] + cc[line-1] * cep[line-1] * cep[line-1] + cc[line+1] * cep[line+1] * cep[line+1]; //{ // static unsigned int x = 0; // // printf ("%7.3f s ", (x/2)*1152./44100 ); // x++; //} //printf ("ref=%5.3f *res1=%7.3f f=%8.3f ", ref, line_sum / sum, 44100. / (line_sum / sum) ); *qual1 = ref; if ( ref > 0.015f ) *res1 = line_sum / sum; if ( CVD_used < 2 ) return; // search for the (relative) maximum ref = 0.f; line = MIN_ANALYZED_IDX; for ( n = MED_ANALYZED_IDX + 1; n >= MIN_ANALYZED_IDX - 1; n-- ) { cc [2*n ] += 0.5 * cc [n]; cc [2*n+1] += 0.5 * (cc [n] + cc[n+1]); cep [2*n ] += 0.5 * cep [n]; cep [2*n+1] += 0.5 * (cep [n] + cep[n+1]); } for ( n = 2*MED_ANALYZED_IDX; n >= 2*MIN_ANALYZED_IDX; n-- ) { if ( cc[n] * cep[n] * cep[n] > ref && cc[n] > 0.85f && /* e33 (02) */ cep[n] > 0.00f && /* e33 (02) */ cc[n ] >= cc[n+1] && cc[n ] >= cc[n-1] && cc[n+1] >= cc[n+2] && cc[n-1] >= cc[n-2] ) { ref = cc[n] * cep[n] * cep[n]; line = n; } } // Calculating the center of the maximum (Interpolation) x = cep + line; sum = x[-3] + x[-2] + x[-1] + x[0] + x[1] + x[2] + x[3] + 1.e-30f; line_sum = (x[1]-x[-1]) + 2 * (x[2]-x[-2]) + 3 * (x[3]-x[-3]) + sum * line + 1.e-30f; /* e33 (04) */ ref = cc[line ] * cep[line ] * cep[line ] + cc[line-1] * cep[line-1] * cep[line-1] + cc[line+1] * cep[line+1] * cep[line+1]; //printf ("ref=%5.3f *res2=%8.3f f=%8.3f\n", ref, 0.5 * line_sum / sum, 44100. / (0.5 * line_sum / sum) ); *qual2 = ref; if ( ref >= 0.1f ) *res2 = 0.5 * line_sum / sum; return; } #ifndef CVD_FASTLOG # define logfast(x) ((float) log (x)) #else static __inline float /* This is a rough estimation with an accuracy of |x|<0.0037 */ logfast ( float x ) { union { double d; Int32_t n[2]; } tmp; tmp.d = x * x; tmp.d *= tmp.d; tmp.d *= tmp.d; #if ENDIAN == HAVE_LITTLE_ENDIAN return (tmp.n[1] + (45127.5 - 1072693248.)) * ( M_LN2 / (1L<<23) ); #else return (tmp.n[0] + (45127.5 - 1072693248.)) * ( M_LN2 / (1L<<23) ); #endif } #endif // ClearVoiceDetection for spectrum *spec // input : Spectrum *spec // output: Array *vocal contains information if the FFT-Line is a harmonic component int CVD2048 ( const float* spec, int* vocal ) { static float cep [4096]; // cep[4096] -- array, which is also used for the 2048 FFT const float* win = CosWin; // pointer to cos-roll-off float res1; float res2; float qual1; float qual2; int n; ENTER(20); // Calculating logarithmated, windowed spectrum cep[] // cep[512...1024] = 0 -- cep[1025...2047] doesn't matter, because the first have to be filled by fft for ( n = 0; n < 256; n++ ) cep[n] = logfast (*spec++); for ( n = 256; n < 512; n++ ) cep[n] = logfast (*spec++) * *win++; memset ( cep+512, 0, 513*sizeof(*cep) ); // Calculating cepstrum of cep[] (the function Cepstrum() outputs the cepstrum in-place) Cepstrum2048 ( cep, MAX_ANALYZED_IDX ); // search the harmonic CEP_Analyse2048 ( &res1, &res2, &qual1, &qual2, cep ); //#include "cvd.h" if ( res1 > 0.f || res2 > 0.f ) { if ( res1 > 0. ) SetVoiceLines ( vocal, res1, 100 ); if ( res2 > 0. ) SetVoiceLines ( vocal, res2, 20 ); LEAVE(20); return 1; } LEAVE(20); return 0; } mppenc-1.16/src/bitstream.c0000644000175000017500000001245210522734510015131 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" Uint32_t Buffer [BUFFER_FULL]; // Buffer for bitstream-file Uint32_t dword = 0; // 32-bit-Word for Bitstream-I/O int filled = 32; // Position in the the 32-bit-word that's currently about to be filled unsigned int Zaehler = 0; // Position pointer for the processed bitstream-word (32 bit) UintMax_t BufferedBits = 0; // Counter for the number of written bits in the bitstream /* * Change_Endian32() changes the endianess of a 32-bit memory block in-place * by swapping the byte order. This is a little bit tricky, but a well * known method which is much much faster, especially on modern CPUs, than * byte picking, because it avoids memory aliasing. Note that this method * is poison for old 16-bit compilers! */ #if ENDIAN == HAVE_BIG_ENDIAN static void Change_Endian32 ( unsigned int* dst, size_t words32bit ) { ENTER(160); for ( ; words32bit--; dst++ ) { # if INT_MAX >= 2147483647L unsigned int tmp = *dst; tmp = ((tmp << 0x10) & 0xFFFF0000) | ((tmp >> 0x10) & 0x0000FFFF); tmp = ((tmp << 0x08) & 0xFF00FF00) | ((tmp >> 0x08) & 0x00FF00FF); *dst = tmp; # else char tmp; tmp = ((char*)dst)[0]; ((char*)dst)[0] = ((char*)dst)[3]; ((char*)dst)[3] = tmp; tmp = ((char*)dst)[1]; ((char*)dst)[1] = ((char*)dst)[2]; ((char*)dst)[2] = tmp; # endif } LEAVE(160); return; } #endif /* ENDIAN == HAVE_BIG_ENDIAN */ void FlushBitstream ( FILE* fp, const Uint32_t* buffer, size_t words32bit ) { size_t WrittenDwords = 0; const Uint32_t* p = buffer; #if ENDIAN == HAVE_BIG_ENDIAN size_t CC = words32bit; Change_Endian32 ( (Uint32_t*)buffer, CC ); #endif // Write Buffer do { WrittenDwords = fwrite ( p, sizeof(*buffer), words32bit, fp ); if ( WrittenDwords == 0 ) { stderr_printf ( "\b\n WARNING: Disk full?, retry after 10 sec ...\a" ); sleep (10); } if ( WrittenDwords > 0 ) { p += WrittenDwords; words32bit -= WrittenDwords; } } while ( words32bit != 0 ); #if ENDIAN == HAVE_BIG_ENDIAN Change_Endian32 ( (Uint32_t*)buffer, CC ); #endif } void UpdateHeader ( FILE* fp, Uint32_t Frames, Uint ValidSamples ) { Uint8_t buff [4]; // Write framecount to header if ( fseek ( fp, 4L, SEEK_SET ) < 0 ) return; buff [0] = (Uint8_t)(Frames >> 0); buff [1] = (Uint8_t)(Frames >> 8); buff [2] = (Uint8_t)(Frames >> 16); buff [3] = (Uint8_t)(Frames >> 24); fwrite ( buff, 1, 4, fp ); // Write ValidSamples to header if ( fseek ( fp, 22L, SEEK_SET ) < 0 ) return; fread ( buff, 1, 2, fp ); if ( ferror(fp) ) return; if ( fseek ( fp, 22L, SEEK_SET ) < 0 ) return; ValidSamples <<= 4; ValidSamples |= 0x800F & (((Uint) buff[1] << 8) | buff[0]); buff [0] = (Uint8_t)(ValidSamples >> 0); buff [1] = (Uint8_t)(ValidSamples >> 8); fwrite ( buff, 1, 2, fp ); // Set filepointer to end of file (dirty method, should be old position!!) fseek ( fp, 0L, SEEK_END ); } void WriteBits ( const Uint32_t input, const unsigned int bits ) { BufferedBits += bits; filled -= bits; if ( filled > 0 ) { dword |= input << filled; } else if ( filled < 0 ) { Buffer [Zaehler++] = dword | ( input >> -filled ); filled += 32; dword = input << filled; } else { Buffer [Zaehler++] = dword | input; filled = 32; dword = 0; } } // Bits in the original stream have to be 0, maximum X bits allowed to be set in input // Actual bitstream must have already written ptr[0] and ptr[1] void WriteBitsAt ( const Uint32_t input, const unsigned int bits, BitstreamPos const pos ) { Uint32_t* ptr = pos.ptr; int filled = pos.bit - bits; // fprintf ( stderr, "%5u %2u %08lX %2u\n", input, bits, pos.ptr, pos.bit ); Buffer [Zaehler] = dword; if ( filled > 0 ) { ptr [0] |= input << ( +filled); } else if ( filled < 0 ) { ptr [0] |= input >> ( -filled); ptr [1] |= input << (32+filled); } else { ptr [0] |= input; } dword = Buffer [Zaehler]; } void GetBitstreamPos ( BitstreamPos* const pos ) { pos -> ptr = Buffer + Zaehler; pos -> bit = filled; } /* end of bitstream.c */ mppenc-1.16/src/psy_tab.c0000644000175000017500000004604110525165005014601 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ #include "mppenc.h" // Antialiasing for calculation of the subband power const float Butfly [7] = { 0.5f, 0.2776f, 0.1176f, 0.0361f, 0.0075f, 0.000948f, 0.0000598f }; // Antialiasing for calculation of the masking thresholds const float InvButfly [7] = { 2.f, 3.6023f, 8.5034f, 27.701f, 133.33f, 1054.852f, 16722.408f }; // w_low for long 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 const int wl [PART_LONG] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 38, 41, 44, 47, 50, 54, 58, 62, 67, 72, 78, 84, 91, 98, 106, 115, 124, 134, 145, 157, 170, 184, 199, 216, 234, 254, 276, 301, 329, 360, 396, 437, 485 }; const int wh [PART_LONG] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 37, 40, 43, 46, 49, 53, 57, 61, 66, 71, 77, 83, 90, 97, 105, 114, 123, 133, 144, 156, 169, 183, 198, 215, 233, 253, 275, 300, 328, 359, 395, 436, 484, 511 }; // Width: 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 4 4 4 5 5 6 6 7 7 8 9 9 10 11 12 13 14 15 17 18 20 22 25 28 31 36 41 48 27 // inverse partition-width for long const float iw [PART_LONG] = { 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/3, 1.f/3, 1.f/3, 1.f/3, 1.f/3, 1.f/4, 1.f/4, 1.f/4, 1.f/5, 1.f/5, 1.f/6, 1.f/6, 1.f/7, 1.f/7, 1.f/8, 1.f/9, 1.f/9, 1.f/10, 1.f/11, 1.f/12, 1.f/13, 1.f/14, 1.f/15, 1.f/17, 1.f/18, 1.f/20, 1.f/22, 1.f/25, 1.f/28, 1.f/31, 1.f/36, 1.f/41, 1.f/48, 1.f/27 }; // w_low for short 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const int wl_short [PART_SHORT] = { 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 18, 23, 29, 36, 46, 59, 75, 99 }; const int wh_short [PART_SHORT] = { 0, 1, 2, 3, 5, 6, 7, 9, 12, 14, 18, 23, 29, 36, 46, 58, 75, 99, 127 }; // inverse partition-width for short const float iw_short [PART_SHORT] = { 1.f, 1.f, 1.f, 1.f, 1.f/2, 1.f/2, 1.f/2, 1.f/2, 1.f/3, 1.f/3, 1.f/4, 1.f/6, 1.f/7, 1.f/8, 1.f/11, 1.f/13, 1.f/17, 1.f/25, 1.f/29 }; /* Nr. wl wh fl fh bl bh bm Nr. wl wh fl fh bl bh bm 0: 0 0 0 0 0.000000 0.000000 0.000000 1: 1 1 43 43 0.425460 0.425460 0.425460 0: 0 0 0 0 0.000000 0.000000 0.000000 2: 2 2 86 86 0.850241 0.850241 0.850241 3: 3 3 129 129 1.273448 1.273448 1.273448 4: 4 4 172 172 1.694205 1.694205 1.694205 1: 1 1 172 172 1.694205 1.694205 1.694205 5: 5 5 215 215 2.111672 2.111672 2.111672 6: 6 6 258 258 2.525051 2.525051 2.525051 7: 7 7 301 301 2.933594 2.933594 2.933594 2: 2 2 345 345 3.336612 3.336612 3.336612 8: 8 8 345 345 3.336612 3.336612 3.336612 9: 9 9 388 388 3.733479 3.733479 3.733479 10: 10 10 431 431 4.123635 4.123635 4.123635 3: 3 3 517 517 4.881924 4.881924 4.881924 11- 11 12 474 517 4.506591 4.881924 4.695234 12: 13 14 560 603 5.249283 5.608381 5.429880 13: 15 16 646 689 5.958998 6.300971 6.131073 4: 4 5 689 861 6.300971 7.581073 6.958618 14: 17 18 732 775 6.634195 6.958618 6.797509 15: 19 20 818 861 7.274232 7.581073 7.428745 16: 21 22 904 947 7.879211 8.168753 8.025049 5: 5 6 861 1034 7.581073 8.722594 8.168753 17: 23 24 991 1034 8.449828 8.722594 8.587239 18: 25 26 1077 1120 8.987223 9.243908 9.116546 19: 27 28 1163 1206 9.492850 9.734263 9.614484 6: 6 7 1034 1206 8.722594 9.734263 9.243908 20: 29 30 1249 1292 9.968365 10.195382 10.082745 21: 31 32 1335 1378 10.415539 10.629064 10.523116 22: 33 34 1421 1464 10.836184 11.037125 10.937413 7: 8 9 1378 1550 10.629064 11.421352 11.037125 23: 35 37 1507 1593 11.232108 11.605071 11.421352 24: 38 40 1637 1723 11.783474 12.125139 11.956764 25: 41 43 1766 1852 12.288791 12.602659 12.447904 8: 10 12 1723 2067 12.125139 13.316883 12.753228 26: 44 46 1895 1981 12.753228 13.042468 12.899777 27: 47 49 2024 2110 13.181453 13.448898 13.316883 28: 50 53 2153 2283 13.577635 13.945465 13.764881 9: 12 14 2067 2412 13.316883 14.288198 13.825796 29: 54 57 2326 2455 14.062349 14.397371 14.232693 30: 58 61 2498 2627 14.504172 14.811258 14.660130 31: 62 66 2670 2842 14.909464 15.283564 15.100115 10: 15 18 2584 3101 14.711029 15.795819 15.283564 32: 67 71 2885 3058 15.372757 15.714074 15.546390 33: 72 77 3101 3316 15.795819 16.185532 15.994471 34: 78 83 3359 3575 16.259980 16.616871 16.441494 11: 18 23 3101 3962 15.795819 17.204658 16.547424 35: 84 90 3618 3876 16.685418 17.079349 16.885941 36: 91 97 3919 4177 17.142352 17.506445 17.327264 37: 98 105 4221 4522 17.564981 17.959646 17.765487 12: 23 29 3962 4996 17.204658 18.533945 17.904788 38: 106 114 4565 4910 18.014031 18.433233 18.227034 39: 115 123 4953 5297 18.483782 18.874805 18.682185 40: 124 133 5340 5728 18.922095 19.332992 19.130789 13: 29 36 4996 6202 18.533945 19.801451 19.198897 41: 134 144 5771 6202 19.377073 19.801451 19.592946 42: 145 156 6245 6718 19.842285 20.272889 20.061808 43: 157 169 6761 7278 20.310373 20.739167 20.529583 14: 36 46 6202 7924 19.801451 21.222342 20.565177 44: 170 183 7321 7881 20.773175 21.191895 20.987911 45: 184 198 7924 8527 21.222342 21.623344 21.428652 46: 199 215 8570 9259 21.650236 22.050787 21.857360 15: 46 58 7924 9991 21.222342 22.420001 21.882271 47: 216 233 9302 10034 22.074042 22.440072 22.263795 48- 234 253 10078 10896 22.459969 22.807140 22.640652 49: 254 275 10939 11843 22.823891 23.144847 22.991444 16: 59 75 10164 12920 22.499251 23.461146 23.044078 50: 276 300 11886 12920 23.158772 23.461146 23.317264 51: 301 328 12963 14126 23.472530 23.748999 23.617861 52: 329 359 14169 15461 23.758199 24.005540 23.888450 17: 75 99 12920 17054 23.461146 24.248491 23.920884 53: 360 395 15504 17011 24.012922 24.242660 24.134368 54: 396 436 17054 18777 24.248491 24.454928 24.357873 55: 437 484 18820 20844 24.459492 24.647977 24.559711 18: 99 127 17054 21878 24.248491 24.727775 24.524955 56: 485 511 20887 22007 24.651498 24.737100 24.695685 */ /* V A R I A B L E S */ float MinVal [PART_LONG]; // contains minimum tonality soffsets float Loudness [PART_LONG]; // weighting factors for loudness calculation float SPRD [PART_LONG] [PART_LONG]; // tabulated spreading function float O_MAX; float O_MIN; float FAC1; float FAC2; // constants for offset calculation float partLtq [PART_LONG]; // threshold in quiet (partitions) float invLtq [PART_LONG]; // inverse threshold in quiet (partitions, long) float fftLtq [512]; // threshold in quiet (FFT) float Ltq_offset; // Offset for threshold in quiet float Ltq_max; // maximum level for threshold in quiet float TMN; float NMT; float TransDetect; unsigned int EarModelFlag; int MinValChoice; /* * Klemm 1994 and 1997. Experimental data. Sorry, data looks a little bit * dodderly. Data below 30 Hz is extrapolated from other material, above 18 * kHz the ATH is limited due to the original purpose (too much noise at * ATH is not good even if it's theoretically inaudible). */ static float ATHformula_Frank ( float freq ) { /* * one value per 100 cent = 1 * semitone = 1/4 * third = 1/12 * octave = 1/40 decade * rest is linear interpolated, values are currently in millibel rel. 20 µPa */ static short tab [] = { /* 10.0 */ 9669, 9669, 9626, 9512, /* 12.6 */ 9353, 9113, 8882, 8676, /* 15.8 */ 8469, 8243, 7997, 7748, /* 20.0 */ 7492, 7239, 7000, 6762, /* 25.1 */ 6529, 6302, 6084, 5900, /* 31.6 */ 5717, 5534, 5351, 5167, /* 39.8 */ 5004, 4812, 4638, 4466, /* 50.1 */ 4310, 4173, 4050, 3922, /* 63.1 */ 3723, 3577, 3451, 3281, /* 79.4 */ 3132, 3036, 2902, 2760, /* 100.0 */ 2658, 2591, 2441, 2301, /* 125.9 */ 2212, 2125, 2018, 1900, /* 158.5 */ 1770, 1682, 1594, 1512, /* 199.5 */ 1430, 1341, 1260, 1198, /* 251.2 */ 1136, 1057, 998, 943, /* 316.2 */ 887, 846, 744, 712, /* 398.1 */ 693, 668, 637, 606, /* 501.2 */ 580, 555, 529, 502, /* 631.0 */ 475, 448, 422, 398, /* 794.3 */ 375, 351, 327, 322, /* 1000.0 */ 312, 301, 291, 268, /* 1258.9 */ 246, 215, 182, 146, /* 1584.9 */ 107, 61, 13, -35, /* 1995.3 */ -96, -156, -179, -235, /* 2511.9 */ -295, -350, -401, -421, /* 3162.3 */ -446, -499, -532, -535, /* 3981.1 */ -513, -476, -431, -313, /* 5011.9 */ -179, 8, 203, 403, /* 6309.6 */ 580, 736, 881, 1022, /* 7943.3 */ 1154, 1251, 1348, 1421, /* 10000.0 */ 1479, 1399, 1285, 1193, /* 12589.3 */ 1287, 1519, 1914, 2369, #if 0 /* 15848.9 */ 3352, 4865, 5942, 6177, /* 19952.6 */ 6385, 6604, 6833, 7009, /* 25118.9 */ 7066, 7127, 7191, 7260, #else /* 15848.9 */ 3352, 4352, 5352, 6352, /* 19952.6 */ 7352, 8352, 9352, 9999, /* 25118.9 */ 9999, 9999, 9999, 9999, #endif }; double freq_log; unsigned index; if ( freq < 10. ) freq = 10.; if ( freq > 29853. ) freq = 29853.; freq_log = 40. * log10 (0.1 * freq); /* 4 steps per third, starting at 10 Hz */ index = (unsigned) freq_log; return 0.01 * (tab [index] * (1 + index - freq_log) + tab [index+1] * (freq_log - index)); } /* F U N C T I O N S */ // calculation of the threshold in quiet in FFT-resolution static void Ruhehoerschwelle ( unsigned int EarModelFlag, int Ltq_offset, int Ltq_max ) { int n; int k; float f; float erg; double tmp; float absLtq [512]; for ( n = 0; n < 512; n++ ) { f = (float) ( (n+1) * (float)(SampleFreq / 2000.) / 512 ); // Frequency in kHz switch ( EarModelFlag / 100 ) { case 0: // ISO-threshold in quiet tmp = 3.64*pow (f,-0.8) - 6.5*exp (-0.6*(f-3.3)*(f-3.3)) + 0.001*pow (f, 4.0); break; default: case 1: // measured threshold in quiet (Nick Berglmeir, Andree Buschmann, Kopfhörer) tmp = 3.00*pow (f,-0.8) - 5.0*exp (-0.1*(f-3.0)*(f-3.0)) + 0.0000015022693846297*pow (f, 6.0) + 10.*exp (-(f-0.1)*(f-0.1)); break; case 2: // measured threshold in quiet (Filburt, Kopfhörer) tmp = 9.00*pow (f,-0.5) - 15.0*exp (-0.1*(f-4.0)*(f-4.0)) + 0.0341796875*pow (f, 2.5) + 15.*exp (-(f-0.1)*(f-0.1)) - 18; tmp = mind ( tmp, Ltq_max - 18 ); break; case 3: tmp = ATHformula_Frank ( 1.e3 * f ); break; case 4: tmp = ATHformula_Frank ( 1.e3 * f ); if ( f > 4.8 ) { tmp += 3.00*pow (f,-0.8) - 5.0*exp (-0.1*(f-3.0)*(f-3.0)) + 0.0000015022693846297*pow (f, 6.0) + 10.*exp (-(f-0.1)*(f-0.1)); tmp *= 0.5 ; } break; case 5: tmp = ATHformula_Frank ( 1.e3 * f ); if ( f > 4.8 ) { tmp = 3.00*pow (f,-0.8) - 5.0*exp (-0.1*(f-3.0)*(f-3.0)) + 0.0000015022693846297*pow (f, 6.0) + 10.*exp (-(f-0.1)*(f-0.1)); } break; } tmp -= f * f * (int)(EarModelFlag % 100 - 50) * 0.0015; // 00: +30 dB, 100: -30 dB @20 kHz tmp = mind ( tmp, Ltq_max ); // Limit ATH tmp += Ltq_offset - 23; // Add chosen Offset fftLtq[n] = absLtq[n] = POW10 ( 0.1 * tmp); // conversion into power } // threshold in quiet in partitions (long) for ( n = 0; n < PART_LONG; n++ ) { erg = 1.e20f; for ( k = wl[n]; k <= wh[n]; k++ ) erg = minf (erg, absLtq[k]); partLtq[n] = erg; // threshold in quiet invLtq [n] = 1.f / partLtq[n]; // Inverse } } #ifdef _MSC_VER static double asinh ( double x ) { return x >= 0 ? log (sqrt (x*x+1) + x) : -log (sqrt (x*x+1) - x); } #endif static double Freq2Bark ( double Hz ) // Klemm 2002 { return 9.97074*asinh (1.1268e-3 * Hz) - 6.25817*asinh (0.197193e-3 * Hz) ; } static double Bark2Freq ( double Bark ) // Klemm 2002 { return 956.86 * sinh (0.101561*Bark) + 11.7296 * sinh (0.304992*Bark) + 6.33622e-3*sinh (0.538621*Bark); } static double LongPart2Bark ( int Part ) { return Freq2Bark ((wl [Part] + wh [Part]) * SampleFreq / 2048.); } // calculating the table for loudness calculation based on absLtq = ank static void Loudness_Tabelle (void) { int n; float midfreq; float tmp; // ca. dB(A) for ( n = 0; n < PART_LONG; n++ ){ midfreq = (wh[n] + wl[n] + 3) * (0.25 * SampleFreq / 512); // center frequency in kHz, why +3 ??? tmp = LOG10 (midfreq) - 3.5f; // dB(A) tmp = -10 * tmp * tmp + 3 - midfreq/3000; Loudness [n] = POW10 ( 0.1 * tmp ); // conversion into power } } static double Bass ( float f, float TMN, float NMT, float bass ) { static unsigned char lfe [11] = { 120, 100, 80, 60, 50, 40, 30, 20, 15, 10, 5 }; int tmp = (int) ( 1024/44100. * f + 0.5 ); switch ( tmp ) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: return TMN + bass * lfe [tmp]; case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: return TMN; case 19: case 20: case 21: case 22: return TMN*0.75 + NMT*0.25; case 23: case 24: return TMN*0.50 + NMT*0.50; case 25: case 26: return TMN*0.25 + NMT*0.75; default: return NMT; } } // calculating the coefficient for utilization of the tonality offset, depending on TMN und NMT static void Tonalitaetskoeffizienten ( void ) { double tmp; int n; float bass; bass = 0.1/8 * NMT; if ( MinValChoice <= 2 && bass > 0.1 ) bass = 0.1f; if ( MinValChoice <= 1 ) bass = 0.0f; // alternative: calculation of the minval-values dependent on TMN and TMN for ( n = 0; n < PART_LONG; n++ ) { tmp = Bass ( (wl [n] + wh [n]) / 2048. * SampleFreq, TMN, NMT, bass ); MinVal [n] = POW10 ( -0.1 * tmp ); // conversion into power } // calculation of the constants for "tonality offset" O_MAX = POW10 ( -0.1 * TMN ); O_MIN = POW10 ( -0.1 * NMT ); FAC1 = POW10 ( -0.1 * (NMT - (TMN - NMT) * 0.229) ) ; FAC2 = (TMN - NMT) * (0.99011159 * 0.1); } // calculation of the spreading function static void Spread ( void ) { int i; int j; float tmpx; float tmpy; float tmpz; float x; // calculation of the spreading-function for all occuring values for ( i = 0; i < PART_LONG; i++ ) { // i is masking Partition, Source for ( j = 0; j < PART_LONG; j++ ) { // j is masking Partition, Target tmpx = LongPart2Bark (j) - LongPart2Bark (i);// Difference of the partitions in Bark tmpy = tmpz = 0.; // tmpz = 0: no dip if ( tmpx < 0 ) { // downwards (S1) tmpy = -32.f * tmpx; // 32 dB per Bark, e33 (10) } else if ( tmpx > 0 ) { // upwards (S2) #if 0 x = (wl[i]+wh[i])/2 * (float)(SampleFreq / 2000)/512; // center frequency in kHz ??????? if (i==0) x = 0.5f * (float)(SampleFreq / 2000)/512; // if first spectral line #else x = i ? wl[i]+wh[i] : 1; x *= SampleFreq / 1000. / 2048; // center frequency in kHz #endif // dB/Bark tmpy = (22.f + 0.23f / x) * tmpx; // e33 (10) // dip (up to 6 dB) tmpz = 8 * minf ( (tmpx-0.5f) * (tmpx-0.5f) - 2 * (tmpx-0.5f), 0.f ); } // calculate coefficient SPRD[i][j] = POW10 ( -0.1 * (tmpy+tmpz) ); // [Source] [Target] } } // Normierung e33 (10) for ( i = 0; i < PART_LONG; i++ ) { // i is masked Partition float norm = 0.f; for ( j = 0; j < PART_LONG; j++ ) // j is masking Partition norm += SPRD [j] [i]; for ( j = 0; j < PART_LONG; j++ ) // j is masking Partition SPRD [j] [i] /= norm; } } // call all initialisation procedures void Init_Psychoakustiktabellen ( void ) { Max_Band = (int) ( Bandwidth * 64. / SampleFreq ); if ( Max_Band < 1 ) Max_Band = 1; if ( Max_Band > 31 ) Max_Band = 31; Tonalitaetskoeffizienten (); Ruhehoerschwelle ( EarModelFlag, Ltq_offset, Ltq_max ); Loudness_Tabelle (); Spread (); } /* end of psy_tab.c */ mppenc-1.16/src/stderr.c0000644000175000017500000001617610522734510014451 0ustar bencerbencer/* * stderr - Message output system * * (C) Frank Klemm, Janne Hyvärinen 2002. All rights reserved. * * Principles: * * History: * 2001 created * 2002 Spring added functionality to switch on and off printing to easily allow silent modes * 2002-10-10 Escape sequence handling for Windows added. * * Global functions: * - SetStderrSilent() * - GetStderrSilent() * - stderr_printf() * * TODO: * - */ #include "mppdec.h" #ifdef _WIN32 # include #endif static Bool_t stderr_silent = 0; void SetStderrSilent ( Bool_t state ) { stderr_silent = state; } Bool_t GetStderrSilent ( void ) { return stderr_silent; } int Cdecl stderr_printf ( const char* format, ... ) { char buff [2 * PATHLEN_MAX + 3072]; char* p = buff; char* q; int ret; va_list v; /* print to a buffer */ va_start ( v, format ); ret = vsprintf ( p, format, v ); va_end ( v ); if ( !stderr_silent ) { #if defined __unix__ || defined __UNIX__ WRITE ( STDERR, buff, ret ); #elif defined _WIN32 # define FOREGROUND_ALL ( FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED ) # define BACKGROUND_ALL ( BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED ) // for Windows systems we must merge carriage returns into the stream to avoid staircases // Also escape sequences must be detected and replaced (incomplete now) char buff [128]; static int init = 0; CONSOLE_SCREEN_BUFFER_INFO con_info; static HANDLE hSTDERR; static WORD attr; static WORD attr_initial; DWORD written; if ( init == 0 ) { hSTDERR = GetStdHandle ( STD_ERROR_HANDLE ); attr = hSTDERR == INVALID_HANDLE_VALUE || GetConsoleScreenBufferInfo ( hSTDERR, &con_info ) == 0 ? FOREGROUND_ALL : con_info.wAttributes; attr_initial = attr; init = 1; } if ( hSTDERR == INVALID_HANDLE_VALUE ) { while ( ( q = strchr (p, '\n')) != NULL ) { WRITE ( STDERR, p, q-p ); WRITE ( STDERR, "\r\n", 2 ); p = q+1; } WRITE ( STDERR, p, strlen (p) ); } else { for ( ; *p; p++ ) { switch ( *p ) { case '\n': SetConsoleTextAttribute ( hSTDERR, attr_initial ); fprintf ( stderr, "\r\n" ); SetConsoleTextAttribute ( hSTDERR, attr ); break; case '\x1B': if ( p[1] == '[' ) { unsigned int tmp; p++; cont: p++; for ( tmp = 0; (unsigned int)( *p - '0' ) < 10u; p++ ) tmp = 10 * tmp + ( *p - '0' ); switch ( *p ) { case ';': case 'm': switch ( tmp ) { case 0: attr = FOREGROUND_ALL; break; // reset defaults case 1: attr |= FOREGROUND_INTENSITY; break; // high intensity on case 2: attr &= ~FOREGROUND_ALL; attr |= FOREGROUND_INTENSITY; break; // (very) low intensity case 3: break; // italic on case 4: break; // underline on case 5: break; // blinking on case 7: break; // reverse case 8: attr = 0; break; // invisible case 30: attr &= ~FOREGROUND_ALL; break; case 31: attr &= ~FOREGROUND_ALL; attr |= FOREGROUND_RED; break; case 32: attr &= ~FOREGROUND_ALL; attr |= FOREGROUND_GREEN; break; case 33: attr &= ~FOREGROUND_ALL; attr |= FOREGROUND_RED | FOREGROUND_GREEN; break; case 34: attr &= ~FOREGROUND_ALL; attr |= FOREGROUND_BLUE; break; case 35: attr &= ~FOREGROUND_ALL; attr |= FOREGROUND_RED | FOREGROUND_BLUE; break; case 36: attr &= ~FOREGROUND_ALL; attr |= FOREGROUND_GREEN | FOREGROUND_BLUE; break; case 37: case 39: attr |= FOREGROUND_ALL; break; case 40: case 49: attr &= ~BACKGROUND_ALL; break; case 41: attr &= ~BACKGROUND_ALL; attr |= BACKGROUND_RED; break; case 42: attr &= ~BACKGROUND_ALL; attr |= BACKGROUND_GREEN; break; case 43: attr &= ~BACKGROUND_ALL; attr |= BACKGROUND_RED | BACKGROUND_GREEN; break; case 44: attr &= ~BACKGROUND_ALL; attr |= BACKGROUND_BLUE; break; case 45: attr &= ~BACKGROUND_ALL; attr |= BACKGROUND_RED | BACKGROUND_BLUE; break; case 46: attr &= ~BACKGROUND_ALL; attr |= BACKGROUND_GREEN | BACKGROUND_BLUE; break; case 47: attr |= BACKGROUND_ALL; break; } SetConsoleTextAttribute ( hSTDERR, attr ); if ( *p == ';' ) goto cont; break; default: WriteFile ( hSTDERR, buff, sprintf ( buff, "Unknown escape sequence ending with '%c'\n", *p ), &written, NULL ); break; } break; } default: fputc ( *p, stderr ); break; } } /* end for */ } #else // for non-Unix systems we must merge carriage returns into the stream to avoid staircases while ( ( q = strchr (p, '\n')) != NULL ) { WRITE ( STDERR, p, q-p ); WRITE ( STDERR, "\r\n", 2 ); p = q+1; } WRITE ( STDERR, p, strlen (p) ); #endif } return ret; } /* end of stderr.c */ mppenc-1.16/src/ans.c0000644000175000017500000002616410522734510013725 0ustar bencerbencer/* * Musepack audio compression * Copyright (C) 1999-2004 Buschmann/Klemm/Piecha/Wolf * * 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 */ /* * Depending on how transient it is, it can be further reduced (up to 0=No ANS). * Estimate coefficient for feedback at Order=1 over Mask_fu - Mask_fo. * 3 quantization routines: Order=0, Order=1, Order=2...6 * Order doesn't specify the power of the noise shaping, but only the flexibility of the form. * Don't reset utilization of the "remains" at the frame borders; * "remains"-utilization as scalefactor-independent values, * so that a utilization beyond Subframe/Frame Borders is even possible. */ #include "mppenc.h" static float InvFourier [MAX_NS_ORDER + 1] [16]; static float Cos_Tab [16] [MAX_NS_ORDER + 1]; static float Sin_Tab [16] [MAX_NS_ORDER + 1]; unsigned int NS_Order; // Maximum order for ANS unsigned int NS_Order_L [32]; unsigned int NS_Order_R [32]; // frame-wise order of the Noiseshaping (0: off, 1...5: on) float FIR_L [32] [MAX_NS_ORDER]; float FIR_R [32] [MAX_NS_ORDER]; // contains FIR-Filter for NoiseShaping float ANSspec_L [MAX_ANS_LINES]; float ANSspec_R [MAX_ANS_LINES]; // L/R-masking thresholds for ANS float ANSspec_M [MAX_ANS_LINES]; float ANSspec_S [MAX_ANS_LINES]; // M/S-masking thresholds for ANS void Init_ANS ( void ) { int n; int k; // calculate Fourier tables for ( k = 0; k <= MAX_NS_ORDER; k++ ) { for ( n = 0; n < 16; n++ ) { InvFourier [k] [n] = (float) cos ( +2*M_PI/64 * (2*n) * k ) / 16.; Cos_Tab [n] [k] = (float) cos ( -2*M_PI/64 * (2*n+1) * (k+1) ); Sin_Tab [n] [k] = (float) sin ( -2*M_PI/64 * (2*n+1) * (k+1) ); } } } // calculates optimal reflection coefficients and time response of a prediction filter in LPC analysis static __inline void durbin_akf_to_kh1( float* k, // out: reflection coefficients float* h, // out: time response const float* akf ) // in : autocorrelation function (0..1 used) { h[0] = k[0] = akf [1] / akf [0]; } static __inline void durbin_akf_to_kh2( float* k, // out: reflection coefficients float* h, // out: time response const float* akf ) // in : autocorrelation function (0..2 used) { float tk,e; tk = akf [1] / akf[0]; e = akf[0] * (1. - tk*tk); h[0] = k[0] = tk; h[0] *= 1. - (h[1] = k[1] = tk = (akf[2] - h[0] * akf[1]) / e); } static __inline void durbin_akf_to_kh3( float* k, // out: reflection coefficients float* h, // out: time response const float* akf ) // in : autocorrelation function (0..3 used) { float a,b,tk,e; tk = akf[1] / akf[0]; e = akf[0] * (1. - tk*tk); h[0] = k[0] = tk; tk = (akf[2] - h[0] * akf[1]) / e; e *= 1. - tk*tk; h[0] *= 1. - (h[1] = k[1] = tk); h[2] = k[2] = tk = (akf[3] - h[0] * akf[2] - h[1] * akf[1]) / e; h[0] = (a=h[0]) - (b=h[1])*tk; h[1] = b - a*tk; } static __inline void durbin_akf_to_kh ( float* k, // out: reflection coefficients float* h, // out: time response float* akf, // in : autocorrelation function (0..n used) const int n ) // in : number of parameters to calculate { int i,j; float s,a,b,tk,e; float* p; float* q; e = akf [0]; for ( i = 0; i < n; i++ ) { s = 0.f; p = h; q = akf+i; j = i; while ( j-- ) s += *p++ * *q--; tk = (akf[i+1] - s) / e; e *= 1. - tk*tk; h[i] = k[i] = tk; p = h; q = h + i - 1; for ( ; p < q; p++, q-- ) { a = *p; b = *q; *p = a - b*tk; *q = b - a*tk; } if ( p == q ) *p *= 1. - tk; } } static const unsigned char maxANSOrder [32] = { 6, 5, 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static void FindOptimalANS ( const int MaxBand, const unsigned char* ms, const float* spec0, const float* spec1, unsigned int* NS, float* snr_comp, float fir [] [MAX_NS_ORDER], const float* smr0, const float* smr1, int scf [32] [3], const int Transient [32] ) { int Band; int n; int k; int order; float akf [MAX_NS_ORDER + 1]; float h [MAX_NS_ORDER]; float reflex [MAX_NS_ORDER]; float spec [16]; float invspec [16]; float norm; float ns_loss; float min_spec; float min_diff; float re; float im; float ns_energy; float gain; float NS_Gain; float actSMR; int max; const float* tmp; ENTER(235); for ( Band = 0; Band <= MaxBand && maxANSOrder[Band]; Band++ ) { if ( scf[Band][0] != scf[Band][1] || scf[Band][1] != scf[Band][2] ) continue; if ( Transient[Band] ) continue; max = maxANSOrder [Band]; if ( ms[Band] ) { // setting pointer and SMR in relation to the M/S-flag tmp = &spec1 [Band<<4]; // pointer to MS-data actSMR = smr1 [Band]; // selecting SMR } else { tmp = &spec0 [Band<<4]; // pointer to LR-data actSMR = smr0 [Band]; // selecting SMR } if ( actSMR >= 1. ) { NS_Gain = 1.f; // reset gain norm = 1.e-30f; // Selection of the masking threshold of the current subband, also considering frequency inversion in every 2nd subband if ( Band & 1 ) for ( n = 0, tmp += 15; n < 16; n++ ) norm += spec[n] = *tmp--; else for ( n = 0; n < 16; n++ ) norm += spec[n] = *tmp++; // Preprocessing: normalization of the the power of spec[] to 1, and search for minimum of masking threshold norm = 16.f / norm; min_spec = 1.e+12f; for ( n = 0; n < 16; n++ ) { invspec[n] = 1.f / (spec[n] *= norm); if ( spec[n] < min_spec ) // normalize spec[] min_spec = spec[n]; } // Calculation of the auto-correlation function tmp = InvFourier [0]; for ( k = 0; k <= max; k++, tmp += 16 ) { akf[k] = tmp[ 0]*invspec[ 0] + tmp[ 1]*invspec[ 1] + tmp[ 2]*invspec[ 2] + tmp[ 3]*invspec[ 3] + tmp[ 4]*invspec[ 4] + tmp[ 5]*invspec[ 5] + tmp[ 6]*invspec[ 6] + tmp[ 7]*invspec[ 7] + tmp[ 8]*invspec[ 8] + tmp[ 9]*invspec[ 9] + tmp[10]*invspec[10] + tmp[11]*invspec[11] + tmp[12]*invspec[12] + tmp[13]*invspec[13] + tmp[14]*invspec[14] + tmp[15]*invspec[15]; } // Searching for the noise-shaper with maximum gain for ( order = 1; order <= max; order++ ) { switch ( order ) { // calculating best FIR-Filter for the return case 1: durbin_akf_to_kh1 (reflex, h, akf); break; case 2: durbin_akf_to_kh2 (reflex, h, akf); break; case 3: durbin_akf_to_kh3 (reflex, h, akf); break; default: durbin_akf_to_kh (reflex, h, akf, order); break; } ns_loss = 1.e-30f; // estimating the gain min_diff = 1.e+12f; for ( n = 0; n < 16; n++ ) { re = 1.f; // calculating the obtained noise shaping im = 0.f; for ( k = 0; k < order; k++ ) { re -= h[k] * Cos_Tab[n][k]; im += h[k] * Sin_Tab[n][k]; } ns_energy = re*re + im*im; // calculated spectral shaped noise ns_loss += ns_energy; // noise energy increases with shaping if ( spec[n] < min_diff * ns_energy ) // Searching for minimum distance between the shaped noise and the masking threshold min_diff = spec[n] / ns_energy; } // Updating the Filter if new gain is bigger than old gain and if the extra noise power through shaping is smaller than the SMR of this band gain = 16. * min_diff / (min_spec * ns_loss); if ( gain > NS_Gain && ns_loss < actSMR ) { NS [Band] = order; NS_Gain = gain; memcpy ( fir [Band], h, order * sizeof(*h) ); } } if ( NS_Gain > 1.f ) { // Activation of ANS if there is gain snr_comp[Band] *= NS_Gain; } } } LEAVE(235); return; } // perform ANS-analysis (calculation of FIR-filter and gain) void NS_Analyse ( const int MaxBand, const unsigned char* MSflag, const SMRTyp smr, const int* Transient ) { ENTER(10); // for L or M, respectively memset ( FIR_L, 0, sizeof FIR_L ); // reset FIR memset ( NS_Order_L, 0, sizeof NS_Order_L ); // reset Flags FindOptimalANS ( MaxBand, MSflag, ANSspec_L, ANSspec_M, NS_Order_L, SNR_comp_L, FIR_L, smr.L, smr.M, SCF_Index_L, Transient ); // for R or S, respectively memset ( FIR_R, 0, sizeof FIR_R ); // reset FIR memset ( NS_Order_R, 0, sizeof NS_Order_R ); // reset Flags FindOptimalANS ( MaxBand, MSflag, ANSspec_R, ANSspec_S, NS_Order_R, SNR_comp_R, FIR_R, smr.R, smr.S, SCF_Index_R, Transient ); LEAVE(10); return; } /* end of ans.c */ mppenc-1.16/INSTALL0000644000175000017500000000057010525200527013232 0ustar bencerbencerKnown prerequisites: - cmake >= 2.2 - ossaudio libraries (OpenBSD only) Steps: 'cmake .' - Generate the build system 'make' - Compile mppenc binary 'make install' - Install freshly compiled binary on your system Notes: - If you need to install mppenc in another directory than the default one, call cmake with this command instead 'cmake -DCMAKE_INSTALL_PREFIX:=/myPath' mppenc-1.16/Changelog0000644000175000017500000000244010525671406014021 0ustar bencerbencer1.16: * Add fast seeking flag in reserved header data. Enable bit-perfect fast seeking. Patch by Andrew Cupper & Nicolas Botti * Add optional beeping at the end of encoding (--beep) * Remove tag guessing from filename on unix * Add unicode input support for tags (--unicode). Patch by Valery Bruniaux * Frontend patches from Xmixahlx & Shy * Code clean-up * Port build system to cmake for unix & msvc2005 for win32 1.15v * Workaround for denormal number issues. Synthetic samples with passages of digital silence are handled correctly regardless of the compiler used * Translation of German source code comments to English. Patch by Citay 1.15u * Changes in the way the encoded signal is padded to MPC frame boundaries. Beginning and end of track encoding is handled differently, resulting in significantly improved gapless coding. Thanks to Xiph's Monty for the initial advice 1.15t * Aggressive compiler settings could cause a glitch in rare synthetic samples 1.15s * In some rare cases, the output file would have an incorrect duration (4 missing samples) when encoding some very long tracks * There was a glitch at the end of the track when encoding from a 24-bit source through pipe * --xlevel is used by default. Use --noxlevel to override * Removed "Unstable/Experimental" flag writing mppenc-1.16/bin/0000755000175000017500000000000010525730167012757 5ustar bencerbencer