int ModifyFile ( const gain_info_t* G, unsigned int mask ) { unsigned char buff [20]; Int32_t val; FILE_T fd = OPENRW ( G -> FileName ); if ( fd == INVALID_FILEDESC ) { stderr_printf ("Can't patch '%s'\n", G -> FileName ); return 1; } if ( READ ( fd, buff, sizeof(buff) ) != sizeof(buff) ) { stderr_printf ("Can't read header of '%s'\n", G -> FileName ); return 2; } if ( 0 != memcmp ( buff, "MP+", 3) || (buff[3] & 15) != 7 ) { stderr_printf ("Not a MPC file SV7: '%s'\n", G -> FileName ); return 3; } if ( mask & 1 ) { // Title Peak level val = G -> TitlePeak; buff [12] = (Uint8_t)(val >> 0); buff [13] = (Uint8_t)(val >> 8); val = (Int32_t)(G -> TitlePeak / 1.18); buff [ 8] = (Uint8_t)(val >> 0); buff [ 9] = (Uint8_t)(val >> 8); }
// 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 }
static void CalcReplayGain ( const char* filename, gain_info_t* G ) { FILE* fp; float buffl [NO]; float buffr [NO]; Int16_t buff [NO] [2]; size_t i; size_t len; size_t lastlen = 0; unsigned int max = 0; float level; float mult; if ((fp = pipeopen ( "mppdec --silent --scale 0.5 --gain 0 --raw - - < #", filename)) == NULL) { stderr_printf ( "Can't decode '%s'\n", filename ); exit (9); } memset ( buff, 0, sizeof(buff) ); G->Silence = 0; lastlen = len = fread (buff, 4, NO, fp); for ( i = 0; i < len; i++ ) { buffl [i] = 2. * buff [i] [0]; buffr [i] = 2. * buff [i] [1]; if ( abs(buff[i][0]) > max ) max = abs(buff[i][0]); if ( abs(buff[i][1]) > max ) max = abs(buff[i][1]); } AnalyzeSamples ( buffl, buffr, len, 2 ); level = 0.; mult = 1.; for ( i = 0; i < len; i++ ) { level += mult * (buff [i] [0] * buff [i] [0] + buff [i] [1] * buff [i] [1]); mult *= 0.95; } level = 2*sqrt(level * 0.05); if ( level > LEVEL_THR ) G->Silence |= 2; sh ( NULL, level ); while (( len = fread (buff, 4, NO, fp) ) > 0 ) { lastlen = len; for ( i = 0; i < len; i++ ) { buffl [i] = 2. * buff [i] [0]; buffr [i] = 2. * buff [i] [1]; if ( abs(buff[i][0]) > max ) max = abs(buff[i][0]); if ( abs(buff[i][1]) > max ) max = abs(buff[i][1]); } AnalyzeSamples ( buffl, buffr, len, 2 ); } level = 0.; mult = 1.; for ( i = 1; i <= NO; i++ ) { int idx = (lastlen + NO - i) % NO; level += mult * (buff [idx] [0] * buff [idx] [0] + buff [idx] [1] * buff [idx] [1]); mult *= 0.95; } level = 2*sqrt(level * 0.05); if ( level > LEVEL_THR ) G->Silence |= 1; sh(filename,level); PCLOSE (fp); #if 0 GetTitleDynamics (); #endif G -> FileName = filename; G -> TitleGain = GetTitleGain (); G -> TitlePeak = 2 * max + 1; G -> AlbumGain = GetAlbumGain (); G -> AlbumPeak = G->AlbumPeak < G->TitlePeak ? G->TitlePeak : G->AlbumPeak; return; }
static Int32_t ReadReplayGain ( const char* p ) { Int32_t ret = 0; int sgn = +1; if ( 0 == strcmp ( p, "--auto") ) return AUTO; if ( 0 == strcmp ( p, "--list") ) return LIST; if ( 0 == strcmp ( p, "--listall") ) return LISTALL; if ( 0 == strcmp ( p, "--listreport") ) return Kreport = 1, LIST; if ( 0 == strcmp ( p, "--listallreport") ) return Kreport = 1, LISTALL; if ( 0 == strcmp ( p, "--autodB") ) return dBp = 1, AUTO; if ( 0 == strcmp ( p, "--listdB") ) return dBp = 1, LIST; if ( 0 == strcmp ( p, "--listalldB") ) return dBp = 1, LISTALL; if ( 0 == strcmp ( p, "--listreportdB") ) return dBp = 1, Kreport = 1, LIST; if ( 0 == strcmp ( p, "--listallreportdB") ) return dBp = 1, Kreport = 1, LISTALL; if (*p == '+') p++; else if (*p == '-') sgn = -sgn, p++; while ( (unsigned int)(*p - '0') < 10u ) ret = 10 * ret + (unsigned int)(*p++ - '0'); ret *= 100; switch (*p) { case '.': if ( p[1] == '\0' ) break; else if ( (unsigned int)(p[1] - '0') < 10u ) ret += (p[1] - '0') * 10; else goto error; if ( p[2] == '\0' ) break; else if ( (unsigned int)(p[2] - '0') < 10u ) ret += (p[2] - '0'); else goto error; if ( p[3] == '\0' ) break; else if ( (unsigned int)(p[3] - '0') < 10u ) ret += (p[2] >= '5'); else goto error; break; default: error: stderr_printf ("Illegal string in number: %s\n", p ); exit (1); case '\0': break; } return ret * sgn; }