sample LPSpectralDifferenceODF::process_frame(int signal_size, sample* signal) { sample sum = 0.0; sample amp = 0.0; sample prediction = 0.0; // do a FFT of the current frame memcpy(in, &signal[0], sizeof(sample)*frame_size); window_frame(in); fftw_execute(p); // calculate the amplitude differences between bins from consecutive frames for(int bin = 0; bin < num_bins; bin++) { amp = sqrt((out[bin][0]*out[bin][0]) + (out[bin][1]*out[bin][1])); /* get LP coefficients */ burg(order, prev_amps[bin], order, order, coefs); /* get the difference between current and predicted values */ linear_prediction(order, prev_amps[bin], order, coefs, 1, &prediction); sum += fabs(amp - prediction); /* move frames back by 1 */ for(int j = 0; j < order-1; j++) { prev_amps[bin][j] = prev_amps[bin][j+1]; } prev_amps[bin][order-1] = amp; } return sum; }
sample LPEnergyODF::process_frame(int signal_size, sample* signal) { sample odf = 0.0; sample prediction = 0.0; /* calculate signal energy */ sample energy = 0.0; for(int i = 0; i < frame_size; i++) { energy += signal[i] * signal[i]; } /* get LP coefficients */ burg(order, prev_values, order, order, coefs); /* get the difference between current and predicted energy values */ linear_prediction(order, prev_values, order, coefs, 1, &prediction); odf = fabs(energy - prediction); /* move energies 1 frame back then update last energy */ for(int i = 0; i < order-1; i++) { prev_values[i] = prev_values[i+1]; } prev_values[order-1] = energy; return odf; }
SEXP Burg(SEXP x, SEXP order) { x = PROTECT(coerceVector(x, REALSXP)); int n = LENGTH(x), pmax = asInteger(order); SEXP coefs = PROTECT(allocVector(REALSXP, pmax * pmax)), var1 = PROTECT(allocVector(REALSXP, pmax + 1)), var2 = PROTECT(allocVector(REALSXP, pmax + 1)); burg(n, REAL(x), pmax, REAL(coefs), REAL(var1), REAL(var2)); SEXP ans = PROTECT(allocVector(VECSXP, 3)); SET_VECTOR_ELT(ans, 0, coefs); SET_VECTOR_ELT(ans, 1, var1); SET_VECTOR_ELT(ans, 2, var2); UNPROTECT(5); return ans; }
sample LPComplexODF::process_frame(int signal_size, sample* signal) { sample sum = 0.0; sample amp = 0.0; sample prediction = 0.0; sample distance = 0.0; // do a FFT of the current frame memcpy(in, &signal[0], sizeof(sample)*frame_size); window_frame(in); fftw_execute(p); for(int bin = 0; bin < num_bins; bin++) { distance = sqrt((out[bin][0]-prev_frame[bin][0])*(out[bin][0]-prev_frame[bin][0]) + (out[bin][1]-prev_frame[bin][1])*(out[bin][1]-prev_frame[bin][1])); /* get LP coefficients */ burg(order, distances[bin], order, order, coefs); /* get the difference between current and predicted values */ linear_prediction(order, distances[bin], order, coefs, 1, &prediction); sum += fabs(distance - prediction); /* update distances */ for(int j = 0; j < order-1; j++) { distances[bin][j] = distances[bin][j+1]; } distances[bin][order-1] = distance; /* update previous frame */ prev_frame[bin][0] = out[bin][0]; prev_frame[bin][1] = out[bin][1]; } return sum; }
static autoFormant Sound_to_Formant_any_inline (Sound me, double dt_in, int numberOfPoles, double halfdt_window, int which, double preemphasisFrequency, double safetyMargin) { double dt = dt_in > 0.0 ? dt_in : halfdt_window / 4.0; double duration = my nx * my dx, t1; double dt_window = 2.0 * halfdt_window; long nFrames = 1 + (long) floor ((duration - dt_window) / dt); long nsamp_window = (long) floor (dt_window / my dx), halfnsamp_window = nsamp_window / 2; if (nsamp_window < numberOfPoles + 1) Melder_throw (U"Window too short."); t1 = my x1 + 0.5 * (duration - my dx - (nFrames - 1) * dt); // centre of first frame if (nFrames < 1) { nFrames = 1; t1 = my x1 + 0.5 * duration; dt_window = duration; nsamp_window = my nx; } autoFormant thee = Formant_create (my xmin, my xmax, nFrames, dt, t1, (numberOfPoles + 1) / 2); // e.g. 11 poles -> maximally 6 formants autoNUMvector <double> window (1, nsamp_window); autoNUMvector <double> frame (1, nsamp_window); autoNUMvector <double> cof (1, numberOfPoles); // superfluous if which==2, but nobody uses that anyway autoMelderProgress progress (U"Formant analysis..."); /* Pre-emphasis. */ Sound_preEmphasis (me, preemphasisFrequency); /* Gaussian window. */ for (long i = 1; i <= nsamp_window; i ++) { double imid = 0.5 * (nsamp_window + 1), edge = exp (-12.0); window [i] = (exp (-48.0 * (i - imid) * (i - imid) / (nsamp_window + 1) / (nsamp_window + 1)) - edge) / (1.0 - edge); } for (long iframe = 1; iframe <= nFrames; iframe ++) { double t = Sampled_indexToX (thee.peek(), iframe); long leftSample = Sampled_xToLowIndex (me, t); long rightSample = leftSample + 1; long startSample = rightSample - halfnsamp_window; long endSample = leftSample + halfnsamp_window; double maximumIntensity = 0.0; if (startSample < 1) startSample = 1; if (endSample > my nx) endSample = my nx; for (long i = startSample; i <= endSample; i ++) { double value = Sampled_getValueAtSample (me, i, Sound_LEVEL_MONO, 0); if (value * value > maximumIntensity) { maximumIntensity = value * value; } } if (maximumIntensity == HUGE_VAL) Melder_throw (U"Sound contains infinities."); thy d_frames [iframe]. intensity = maximumIntensity; if (maximumIntensity == 0.0) continue; // Burg cannot stand all zeroes /* Copy a pre-emphasized window to a frame. */ for (long j = 1, i = startSample; j <= nsamp_window; j ++) frame [j] = Sampled_getValueAtSample (me, i ++, Sound_LEVEL_MONO, 0) * window [j]; if (which == 1) { burg (frame.peek(), endSample - startSample + 1, cof.peek(), numberOfPoles, & thy d_frames [iframe], 0.5 / my dx, safetyMargin); } else if (which == 2) { if (! splitLevinson (frame.peek(), endSample - startSample + 1, numberOfPoles, & thy d_frames [iframe], 0.5 / my dx)) { Melder_clearError (); Melder_casual (U"(Sound_to_Formant:)" U" Analysis results of frame ", iframe, U" will be wrong." ); } } Melder_progress ((double) iframe / (double) nFrames, U"Formant analysis: frame ", iframe); } Formant_sort (thee.peek()); return thee; }
int maxent ( MiscParams *misc , int ncases , int degree , Signal *sig , int *nsigs , Signal ***signals , char *error ) { int i, j, n, ivar, nvars ; double *data, *temp, *work, *x, mean, var, diff, *pcorr ; double real, imag, theta, maxspec ; Signal **sptr ; nvars = misc->names->nreal ; if (! nvars) { strcpy ( error , "No signal names specified" ) ; return 1 ; } n = sig->n ; x = sig->sig ; MEMTEXT ( "MAXENT: data, work" ) ; data = (double *) MALLOC ( ncases * sizeof(double) ) ; work = (double *) MALLOC ( (3 * degree + 2 * n) * sizeof(double) ) ; if ((data == NULL) || (work == NULL)) { strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } /* Compute the spectrum */ burg ( n , x , degree , work+degree , work , work+2*degree , work+3*degree , work+3*degree+sig->n ) ; mean = var = 0.0 ; for (i=0 ; i<n ; i++) mean += x[i] ; mean /= n ; for (i=0 ; i<n ; i++) { diff = x[i] - mean ; var += diff * diff ; } var /= (n * degree) ; pcorr = work+degree ; // Partial autocorrelations for (i=0 ; i<degree ; i++) var *= (1.0 - pcorr[i] * pcorr[i]) ; if (var < 1.e-40) var = 1.e-40 ; maxspec = 0.0 ; for (i=0 ; i<ncases ; i++) { theta = PI * (double) i / (double) ncases ; real = 1.0 ; imag = 0.0 ; for (j=0 ; j<degree ; j++) { real -= work[j] * cos ( (j+1) * theta ) ; imag -= work[j] * sin ( (j+1) * theta ) ; } data[i] = var / (real * real + imag * imag + 1.e-40) ; if (data[i] > maxspec) maxspec = data[i] ; } /* Optional step: Normalize so max is almost 1.0 for better display. */ maxspec = 0.99999999999 / maxspec ; for (i=0 ; i<ncases ; i++) data[i] *= maxspec ; /* Count how many of these signals have names not already in use. Then allocate additional memory for their pointers. */ MEMTEXT ( "MAXENT: signals array" ) ; if (*nsigs) { // If signals already exist ivar = *nsigs ; // This many signals so far sptr = *signals ; // Array of pointers to them for (i=0 ; i<misc->names->n ; i++) { // Check every new name if (! misc->names->len[i]) // Some may be NULL continue ; // Obviously skip them for (j=*nsigs-1 ; j>=0 ; j--) { // Check every existing signal if (! strcmp ( misc->names->start[i] , sptr[j]->name )) // There? break ; // If found, quit looking } if (j < 0) // Means not there ++ivar ; // So count this new entry } sptr = (Signal **) REALLOC ( sptr , ivar * sizeof(Signal *) ) ; } else sptr = (Signal **) MALLOC ( nvars * sizeof(Signal *) ) ; if (sptr == NULL) { FREE ( data ) ; strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } *signals = sptr ; /* Now create new signals for each variable. If a signal of the same name exists, delete it first. */ ivar = 0 ; for (i=0 ; i<misc->names->n ; i++) { // Check all names if (! misc->names->len[i]) // Some may be NULL continue ; // Obviously skip them for (j=*nsigs-1 ; j>=0 ; j--) { // Search existing signals for same name if (! strcmp ( misc->names->start[i] , sptr[j]->name )) { // There? MEMTEXT ( "MAXENT: delete duplicate signal" ) ; delete ( sptr[j] ) ; // If so, delete this signal break ; // And quit looking } } if (j < 0) { // Means new, unique name j = *nsigs ; // Tack it onto end of signal array ++*nsigs ; // And count it } if (ivar) { // In this case, must allocate for new signal MEMTEXT ( "MAXENT: temp signal" ) ; temp = (double *) MALLOC ( ncases * sizeof(double) ) ; if (temp == NULL) { strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } memcpy ( temp , data , ncases * sizeof(double) ) ; } else temp = data ; MEMTEXT ( "MAXENT: new Signal" ) ; sptr[j] = new Signal ( misc->names->start[i] , ncases , temp ) ; if ((sptr[j] == NULL) || ! sptr[j]->n) { if (sptr[j] != NULL) { delete sptr[j] ; sptr[j] = NULL ; } strcpy ( error , "Insufficient memory to create signal" ) ; return 1 ; } ++ivar ; sptr[j]->type = SpectrumSignal ; sptr[j]->source_n = n ; } // For all names MEMTEXT ( "MAXENT: work" ) ; FREE ( work ) ; return 0 ; }