/* returns GAIN_ANALYSIS_OK if successful, GAIN_ANALYSIS_ERROR if not */ gain_calc_status ReplayGain_analyze_samples(replaygain_ReplayGain* self, const double* left_samples, const double* right_samples, size_t num_samples, int num_channels) { const double* curleft; const double* curright; long batchsamples; long cursamples; long cursamplepos; long i; if ( num_samples == 0 ) return GAIN_ANALYSIS_OK; cursamplepos = 0; batchsamples = num_samples; switch ( num_channels) { case 1: right_samples = left_samples; case 2: break; default: return GAIN_ANALYSIS_ERROR; } if ( num_samples < MAX_ORDER ) { memcpy (self->linprebuf + MAX_ORDER, left_samples , num_samples * sizeof(double) ); memcpy ( self->rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(double) ); } else { memcpy ( self->linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(double) ); memcpy ( self->rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(double) ); } while ( batchsamples > 0 ) { cursamples = batchsamples > self->sampleWindow - self->totsamp ? self->sampleWindow - self->totsamp : batchsamples; if ( cursamplepos < MAX_ORDER ) { curleft = self->linpre + cursamplepos; curright = self->rinpre + cursamplepos; if (cursamples > MAX_ORDER - cursamplepos ) cursamples = MAX_ORDER - cursamplepos; } else { curleft = left_samples + cursamplepos; curright = right_samples + cursamplepos; } YULE_FILTER ( curleft , self->lstep + self->totsamp, cursamples, ABYule[self->freqindex]); YULE_FILTER ( curright, self->rstep + self->totsamp, cursamples, ABYule[self->freqindex]); BUTTER_FILTER ( self->lstep + self->totsamp, self->lout + self->totsamp, cursamples, ABButter[self->freqindex]); BUTTER_FILTER ( self->rstep + self->totsamp, self->rout + self->totsamp, cursamples, ABButter[self->freqindex]); curleft = self->lout + self->totsamp; /* Get the squared values */ curright = self->rout + self->totsamp; i = cursamples % 16; while (i--) { self->lsum += fsqr(*curleft++); self->rsum += fsqr(*curright++); } i = cursamples / 16; while (i--) { self->lsum += fsqr(curleft[0]) + fsqr(curleft[1]) + fsqr(curleft[2]) + fsqr(curleft[3]) + fsqr(curleft[4]) + fsqr(curleft[5]) + fsqr(curleft[6]) + fsqr(curleft[7]) + fsqr(curleft[8]) + fsqr(curleft[9]) + fsqr(curleft[10]) + fsqr(curleft[11]) + fsqr(curleft[12]) + fsqr(curleft[13]) + fsqr(curleft[14]) + fsqr(curleft[15]); curleft += 16; self->rsum += fsqr(curright[0]) + fsqr(curright[1]) + fsqr(curright[2]) + fsqr(curright[3]) + fsqr(curright[4]) + fsqr(curright[5]) + fsqr(curright[6]) + fsqr(curright[7]) + fsqr(curright[8]) + fsqr(curright[9]) + fsqr(curright[10]) + fsqr(curright[11]) + fsqr(curright[12]) + fsqr(curright[13]) + fsqr(curright[14]) + fsqr(curright[15]); curright += 16; } batchsamples -= cursamples; cursamplepos += cursamples; self->totsamp += cursamples; if ( self->totsamp == self->sampleWindow ) { /* Get the Root Mean Square (RMS) for this set of samples */ double val = STEPS_per_dB * 10. * log10 ( (self->lsum + self->rsum) / self->totsamp * 0.5 + 1.e-37 ); int ival = (int) val; if ( ival < 0 ) ival = 0; if ( ival >= (int)(sizeof(self->A)/sizeof(*(self->A))) ) ival = sizeof(self->A)/sizeof(*(self->A)) - 1; self->A [ival]++; self->lsum = self->rsum = 0.; memmove ( self->loutbuf , self->loutbuf + self->totsamp, MAX_ORDER * sizeof(double) ); memmove ( self->routbuf , self->routbuf + self->totsamp, MAX_ORDER * sizeof(double) ); memmove ( self->lstepbuf, self->lstepbuf + self->totsamp, MAX_ORDER * sizeof(double) ); memmove ( self->rstepbuf, self->rstepbuf + self->totsamp, MAX_ORDER * sizeof(double) ); self->totsamp = 0; } if ( self->totsamp > self->sampleWindow ) /* somehow I really screwed up: Error in programming! Contact author about self->totsamp > self->sampleWindow */ return GAIN_ANALYSIS_ERROR; } if ( num_samples < MAX_ORDER ) { memmove ( self->linprebuf, self->linprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(double) ); memmove ( self->rinprebuf, self->rinprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(double) ); memcpy ( self->linprebuf + MAX_ORDER - num_samples, left_samples, num_samples * sizeof(double) ); memcpy ( self->rinprebuf + MAX_ORDER - num_samples, right_samples, num_samples * sizeof(double) ); } else { memcpy ( self->linprebuf, left_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(double) ); memcpy ( self->rinprebuf, right_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(double) ); } return GAIN_ANALYSIS_OK; }
int AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples, const Float_t * right_samples, size_t num_samples, int num_channels) { const Float_t *curleft; const Float_t *curright; long batchsamples; long cursamples; long cursamplepos; int i; if (num_samples == 0) return GAIN_ANALYSIS_OK; cursamplepos = 0; batchsamples = (long) num_samples; switch (num_channels) { case 1: right_samples = left_samples; break; case 2: break; default: return GAIN_ANALYSIS_ERROR; } if (num_samples < MAX_ORDER) { memcpy(rgData->linprebuf + MAX_ORDER, left_samples, num_samples * sizeof(Float_t)); memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t)); } else { memcpy(rgData->linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t)); memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t)); } while (batchsamples > 0) { cursamples = batchsamples > rgData->sampleWindow - rgData->totsamp ? rgData->sampleWindow - rgData->totsamp : batchsamples; if (cursamplepos < MAX_ORDER) { curleft = rgData->linpre + cursamplepos; curright = rgData->rinpre + cursamplepos; if (cursamples > MAX_ORDER - cursamplepos) cursamples = MAX_ORDER - cursamplepos; } else { curleft = left_samples + cursamplepos; curright = right_samples + cursamplepos; } YULE_FILTER(curleft, rgData->lstep + rgData->totsamp, cursamples, ABYule[rgData->freqindex]); YULE_FILTER(curright, rgData->rstep + rgData->totsamp, cursamples, ABYule[rgData->freqindex]); BUTTER_FILTER(rgData->lstep + rgData->totsamp, rgData->lout + rgData->totsamp, cursamples, ABButter[rgData->freqindex]); BUTTER_FILTER(rgData->rstep + rgData->totsamp, rgData->rout + rgData->totsamp, cursamples, ABButter[rgData->freqindex]); curleft = rgData->lout + rgData->totsamp; /* Get the squared values */ curright = rgData->rout + rgData->totsamp; i = cursamples % 8; while (i--) { rgData->lsum += fsqr(*curleft++); rgData->rsum += fsqr(*curright++); } i = cursamples / 8; while (i--) { rgData->lsum += fsqr(curleft[0]) + fsqr(curleft[1]) + fsqr(curleft[2]) + fsqr(curleft[3]) + fsqr(curleft[4]) + fsqr(curleft[5]) + fsqr(curleft[6]) + fsqr(curleft[7]); curleft += 8; rgData->rsum += fsqr(curright[0]) + fsqr(curright[1]) + fsqr(curright[2]) + fsqr(curright[3]) + fsqr(curright[4]) + fsqr(curright[5]) + fsqr(curright[6]) + fsqr(curright[7]); curright += 8; } batchsamples -= cursamples; cursamplepos += cursamples; rgData->totsamp += cursamples; if (rgData->totsamp == rgData->sampleWindow) { /* Get the Root Mean Square (RMS) for this set of samples */ double const val = STEPS_per_dB * 10. * log10((rgData->lsum + rgData->rsum) / rgData->totsamp * 0.5 + 1.e-37); size_t ival = (val <= 0) ? 0 : (size_t) val; if (ival >= sizeof(rgData->A) / sizeof(*(rgData->A))) ival = sizeof(rgData->A) / sizeof(*(rgData->A)) - 1; rgData->A[ival]++; rgData->lsum = rgData->rsum = 0.; memmove(rgData->loutbuf, rgData->loutbuf + rgData->totsamp, MAX_ORDER * sizeof(Float_t)); memmove(rgData->routbuf, rgData->routbuf + rgData->totsamp, MAX_ORDER * sizeof(Float_t)); memmove(rgData->lstepbuf, rgData->lstepbuf + rgData->totsamp, MAX_ORDER * sizeof(Float_t)); memmove(rgData->rstepbuf, rgData->rstepbuf + rgData->totsamp, MAX_ORDER * sizeof(Float_t)); rgData->totsamp = 0; } if (rgData->totsamp > rgData->sampleWindow) /* somehow I really screwed up: Error in programming! Contact author about totsamp > sampleWindow */ return GAIN_ANALYSIS_ERROR; } if (num_samples < MAX_ORDER) { memmove(rgData->linprebuf, rgData->linprebuf + num_samples, (MAX_ORDER - num_samples) * sizeof(Float_t)); memmove(rgData->rinprebuf, rgData->rinprebuf + num_samples, (MAX_ORDER - num_samples) * sizeof(Float_t)); memcpy(rgData->linprebuf + MAX_ORDER - num_samples, left_samples, num_samples * sizeof(Float_t)); memcpy(rgData->rinprebuf + MAX_ORDER - num_samples, right_samples, num_samples * sizeof(Float_t)); } else { memcpy(rgData->linprebuf, left_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t)); memcpy(rgData->rinprebuf, right_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t)); } return GAIN_ANALYSIS_OK; }
int AnalyzeSamples ( const Float_t* left_samples, const Float_t* right_samples, size_t num_samples, int num_channels ) { const Float_t* curleft; const Float_t* curright; long batchsamples; long cursamples; long cursamplepos; int i; if ( num_samples == 0 ) return GAIN_ANALYSIS_OK; cursamplepos = 0; batchsamples = num_samples; switch ( num_channels) { case 1: right_samples = left_samples; case 2: break; default: return GAIN_ANALYSIS_ERROR; } if ( num_samples < MAX_ORDER ) { memcpy ( linprebuf + MAX_ORDER, left_samples , num_samples * sizeof(Float_t) ); memcpy ( rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t) ); } else { memcpy ( linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t) ); memcpy ( rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t) ); } while ( batchsamples > 0 ) { cursamples = batchsamples > sampleWindow-totsamp ? sampleWindow - totsamp : batchsamples; if ( cursamplepos < MAX_ORDER ) { curleft = linpre+cursamplepos; curright = rinpre+cursamplepos; if (cursamples > MAX_ORDER - cursamplepos ) cursamples = MAX_ORDER - cursamplepos; } else { curleft = left_samples + cursamplepos; curright = right_samples + cursamplepos; } YULE_FILTER ( curleft , lstep + totsamp, cursamples, ABYule[freqindex]); YULE_FILTER ( curright, rstep + totsamp, cursamples, ABYule[freqindex]); BUTTER_FILTER ( lstep + totsamp, lout + totsamp, cursamples, ABButter[freqindex]); BUTTER_FILTER ( rstep + totsamp, rout + totsamp, cursamples, ABButter[freqindex]); curleft = lout + totsamp; // Get the squared values curright = rout + totsamp; i = cursamples % 16; while (i--) { lsum += fsqr(*curleft++); rsum += fsqr(*curright++); } i = cursamples / 16; while (i--) { lsum += fsqr(curleft[0]) + fsqr(curleft[1]) + fsqr(curleft[2]) + fsqr(curleft[3]) + fsqr(curleft[4]) + fsqr(curleft[5]) + fsqr(curleft[6]) + fsqr(curleft[7]) + fsqr(curleft[8]) + fsqr(curleft[9]) + fsqr(curleft[10]) + fsqr(curleft[11]) + fsqr(curleft[12]) + fsqr(curleft[13]) + fsqr(curleft[14]) + fsqr(curleft[15]); curleft += 16; rsum += fsqr(curright[0]) + fsqr(curright[1]) + fsqr(curright[2]) + fsqr(curright[3]) + fsqr(curright[4]) + fsqr(curright[5]) + fsqr(curright[6]) + fsqr(curright[7]) + fsqr(curright[8]) + fsqr(curright[9]) + fsqr(curright[10]) + fsqr(curright[11]) + fsqr(curright[12]) + fsqr(curright[13]) + fsqr(curright[14]) + fsqr(curright[15]); curright += 16; } batchsamples -= cursamples; cursamplepos += cursamples; totsamp += cursamples; if ( totsamp == sampleWindow ) { // Get the Root Mean Square (RMS) for this set of samples double val = STEPS_per_dB * 10. * log10 ( (lsum+rsum) / totsamp * 0.5 + 1.e-37 ); int ival = (int) val; if ( ival < 0 ) ival = 0; if ( ival >= (int)(sizeof(A)/sizeof(*A)) ) ival = sizeof(A)/sizeof(*A) - 1; A [ival]++; lsum = rsum = 0.; memmove ( loutbuf , loutbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); memmove ( routbuf , routbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); memmove ( lstepbuf, lstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); memmove ( rstepbuf, rstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); totsamp = 0; } if ( totsamp > sampleWindow ) // somehow I really screwed up: Error in programming! Contact author about totsamp > sampleWindow return GAIN_ANALYSIS_ERROR; } if ( num_samples < MAX_ORDER ) { memmove ( linprebuf, linprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) ); memmove ( rinprebuf, rinprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) ); memcpy ( linprebuf + MAX_ORDER - num_samples, left_samples, num_samples * sizeof(Float_t) ); memcpy ( rinprebuf + MAX_ORDER - num_samples, right_samples, num_samples * sizeof(Float_t) ); } else { memcpy ( linprebuf, left_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) ); memcpy ( rinprebuf, right_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) ); } return GAIN_ANALYSIS_OK; }