static autoPCA NUMdmatrix_to_PCA (double **m, long numberOfRows, long numberOfColumns, bool byColumns) { try { if (! NUMdmatrix_hasFiniteElements(m, 1, numberOfRows, 1, numberOfColumns)) { Melder_throw (U"At least one of the matrix elements is not finite or undefined."); } if (NUMfrobeniusnorm (numberOfRows, numberOfColumns, m) == 0.0) { Melder_throw (U"All values in your table are zero."); } autoNUMmatrix<double> mcopy; long numberOfRows2, numberOfColumns2; if (byColumns) { if (numberOfColumns < numberOfRows) { Melder_warning (U"The number of columns in your table is less than the number of rows. "); } numberOfRows2 = numberOfColumns, numberOfColumns2 = numberOfRows; mcopy.reset (1, numberOfRows2, 1, numberOfColumns2); for (long i = 1; i <= numberOfRows2; i ++) { // transpose for (long j = 1; j <= numberOfColumns2; j++) { mcopy [i] [j] = m [j] [i]; } } } else { if (numberOfRows < numberOfColumns) { Melder_warning (U"The number of rows in your table is less than the number of columns. "); } numberOfRows2 = numberOfRows, numberOfColumns2 = numberOfColumns; mcopy.reset (1, numberOfRows2, 1, numberOfColumns2); NUMmatrix_copyElements<double>(m, mcopy.peek(), 1, numberOfRows2, 1, numberOfColumns2); } autoPCA thee = Thing_new (PCA); thy centroid = NUMvector<double> (1, numberOfColumns2); NUMcentreColumns (mcopy.peek(), 1, numberOfRows2, 1, numberOfColumns2, thy centroid); Eigen_initFromSquareRoot (thee.get(), mcopy.peek(), numberOfRows2, numberOfColumns2); thy labels = NUMvector<char32 *> (1, numberOfColumns2); PCA_setNumberOfObservations (thee.get(), numberOfRows2); /* The covariance matrix C = A'A / (N-1). However, we have calculated the eigenstructure for A'A. This has no consequences for the eigenvectors, but the eigenvalues have to be divided by (N-1). */ for (long i = 1; i <= thy numberOfEigenvalues; i++) { thy eigenvalues [i] /= (numberOfRows2 - 1); } return thee; } catch (MelderError) { Melder_throw (U"No PCA created from ", byColumns ? U"columns." : U"rows."); } }
ERPTier ERPTier_extractEventsWhereColumn_string (ERPTier me, Table table, long columnNumber, int which_Melder_STRING, const wchar_t *criterion) { try { Table_checkSpecifiedColumnNumberWithinRange (table, columnNumber); if (my events -> size != table -> rows -> size) Melder_throw (me, " & ", table, ": the number of rows in the table (", table -> rows -> size, ") doesn't match the number of events (", my events -> size, ")."); autoERPTier thee = Thing_new (ERPTier); Function_init (thee.peek(), my xmin, my xmax); thy numberOfChannels = my numberOfChannels; thy channelNames = NUMvector <wchar_t *> (1, thy numberOfChannels); for (long ichan = 1; ichan <= thy numberOfChannels; ichan ++) { thy channelNames [ichan] = Melder_wcsdup (my channelNames [ichan]); } thy events = SortedSetOfDouble_create (); for (long ievent = 1; ievent <= my events -> size; ievent ++) { ERPPoint oldEvent = my event (ievent); TableRow row = table -> row (ievent); if (Melder_stringMatchesCriterion (row -> cells [columnNumber]. string, which_Melder_STRING, criterion)) { autoERPPoint newEvent = Data_copy (oldEvent); Collection_addItem (thy events, newEvent.transfer()); } } if (thy events -> size == 0) { Melder_warning ("No event matches criterion."); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": events not extracted."); } }
void structGraphicsScreen :: v_getMouseLocation (double *xWC, double *yWC) { #if cairo GdkEvent *gevent = gdk_display_get_event (d_display); if (gevent != NULL) { if (gevent -> type == GDK_BUTTON_RELEASE) { theMouseDown = false; } gdk_event_free (gevent); } gint xDC, yDC; gdk_window_get_pointer (d_window, & xDC, & yDC, NULL); Graphics_DCtoWC (this, xDC, yDC, xWC, yWC); #elif cocoa #elif win POINT pos; if (! GetCursorPos (& pos)) { Melder_warning (L"Cannot get cursor position."); return; } ScreenToClient (d_winWindow, & pos); Graphics_DCtoWC (this, pos. x, pos. y, xWC, yWC); #elif mac if (HIGetMousePosition != NULL && false) { // AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER //Melder_casual ("HIGetMousePosition exists"); HIPoint mouseLoc; HIGetMousePosition (kHICoordSpaceWindow, GetWindowFromPort (d_macPort), & mouseLoc); Graphics_DCtoWC (this, mouseLoc. x, mouseLoc. y, xWC, yWC); } else { Point mouseLoc; GetMouse (& mouseLoc); // AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5 Graphics_DCtoWC (this, mouseLoc. h, mouseLoc. v, xWC, yWC); } #endif }
autoERPTier ERPTier_extractEventsWhereColumn_number (ERPTier me, Table table, long columnNumber, int which_Melder_NUMBER, double criterion) { try { Table_checkSpecifiedColumnNumberWithinRange (table, columnNumber); Table_numericize_Assert (table, columnNumber); // extraction should work even if cells are not defined if (my events -> size != table -> rows -> size) Melder_throw (me, U" & ", table, U": the number of rows in the table (", table -> rows -> size, U") doesn't match the number of events (", my events -> size, U")."); autoERPTier thee = Thing_new (ERPTier); Function_init (thee.peek(), my xmin, my xmax); thy numberOfChannels = my numberOfChannels; thy channelNames = NUMvector <char32 *> (1, thy numberOfChannels); for (long ichan = 1; ichan <= thy numberOfChannels; ichan ++) { thy channelNames [ichan] = Melder_dup (my channelNames [ichan]); } thy events = SortedSetOfDouble_create (); for (long ievent = 1; ievent <= my events -> size; ievent ++) { ERPPoint oldEvent = my event (ievent); TableRow row = table -> row (ievent); if (Melder_numberMatchesCriterion (row -> cells [columnNumber]. number, which_Melder_NUMBER, criterion)) { autoERPPoint newEvent = Data_copy (oldEvent); Collection_addItem_move (thy events.get(), newEvent.move()); } } if (thy events -> size == 0) { Melder_warning (U"No event matches criterion."); } return thee; } catch (MelderError) { Melder_throw (me, U": events not extracted."); } }
autoERPTier ERPTier_extractEventsWhereColumn_string (ERPTier me, Table table, long columnNumber, int which_Melder_STRING, const char32 *criterion) { try { Table_checkSpecifiedColumnNumberWithinRange (table, columnNumber); if (my points.size != table -> rows.size) Melder_throw (me, U" & ", table, U": the number of rows in the table (", table -> rows.size, U") doesn't match the number of events (", my points.size, U")."); autoERPTier thee = Thing_new (ERPTier); Function_init (thee.get(), my xmin, my xmax); thy numberOfChannels = my numberOfChannels; thy channelNames = NUMvector <char32 *> (1, thy numberOfChannels); for (long ichan = 1; ichan <= thy numberOfChannels; ichan ++) { thy channelNames [ichan] = Melder_dup (my channelNames [ichan]); } for (long ievent = 1; ievent <= my points.size; ievent ++) { ERPPoint oldEvent = my points.at [ievent]; TableRow row = table -> rows.at [ievent]; if (Melder_stringMatchesCriterion (row -> cells [columnNumber]. string, which_Melder_STRING, criterion)) { autoERPPoint newEvent = Data_copy (oldEvent); thy points. addItem_move (newEvent.move()); } } if (thy points.size == 0) { Melder_warning (U"No event matches criterion."); } return thee; } catch (MelderError) { Melder_throw (me, U": events not extracted."); } }
void NUMlinprog_run (NUMlinprog me) { try { glp_smcp parm; glp_init_smcp (& parm); parm. msg_lev = GLP_MSG_OFF; my status = glp_simplex (my linearProgram, & parm); switch (my status) { case GLP_EBADB: Melder_throw (U"Unable to start the search, because the initial basis is invalid."); case GLP_ESING: Melder_throw (U"Unable to start the search, because the basis matrix is singular."); case GLP_ECOND: Melder_throw (U"Unable to start the search, because the basis matrix is ill-conditioned."); case GLP_EBOUND: Melder_throw (U"Unable to start the search, because some variables have incorrect bounds."); case GLP_EFAIL: Melder_throw (U"Search prematurely terminated due to solver failure."); case GLP_EOBJLL: Melder_throw (U"Search prematurely terminated: lower limit reached."); case GLP_EOBJUL: Melder_throw (U"Search prematurely terminated: upper limit reached."); case GLP_EITLIM: Melder_throw (U"Search prematurely terminated: iteration limit exceeded."); case GLP_ETMLIM: Melder_throw (U"Search prematurely terminated: time limit exceeded."); case GLP_ENOPFS: Melder_throw (U"The problem has no primal feasible solution."); case GLP_ENODFS: Melder_throw (U"The problem has no dual feasible solution."); default: break; } my status = glp_get_status (my linearProgram); switch (my status) { case GLP_INFEAS: Melder_throw (U"Solution is infeasible."); case GLP_NOFEAS: Melder_throw (U"Problem has no feasible solution."); case GLP_UNBND: Melder_throw (U"Problem has unbounded solution."); case GLP_UNDEF: Melder_throw (U"Solution is undefined."); default: break; } if (my status == GLP_FEAS) { Melder_warning (U"Linear programming solution is feasible but not optimal."); } } catch (MelderError) { Melder_throw (U"Linear programming: not run."); } }
autoMatrix Matrix_solveEquation (Matrix me, double /* tolerance */) { try { long nr = my ny, nc = my nx - 1; if (nc == 0) { Melder_throw (U"Matrix_solveEquation: there must be at least 2 columns in the matrix."); } if (nr < nc) { Melder_warning (U"Matrix_solveEquation: solution is not unique (fewer equations than unknowns)."); } autoNUMmatrix<double> u (1, nr, 1, nc); autoNUMvector<double> b (1, nr); autoNUMvector<double> x (1, nc); autoMatrix thee = Matrix_create (0.5, 0.5 + nc, nc, 1, 1, 0.5, 1.5, 1, 1, 1); for (long i = 1; i <= nr; i++) { for (long j = 1; j <= nc; j++) { u[i][j] = my z[i][j]; } b[i] = my z[i][my nx]; } NUMsolveEquation (u.peek(), nr, nc, b.peek(), 0, x.peek()); for (long j = 1; j <= nc; j++) { thy z[1][j] = x[j]; } return thee; } catch (MelderError) { Melder_throw (U"Matrix equation not solved."); } }
autoConfusion Confusion_groupStimuli (Confusion me, const char32 *labels, const char32 *newLabel, long newpos) { try { long ncondense = Melder_countTokens (labels); autoNUMvector<long> irow (1, my numberOfRows); for (long i = 1; i <= my numberOfRows; i++) { irow[i] = i; } for (char32 *token = Melder_firstToken (labels); token != nullptr; token = Melder_nextToken ()) { for (long i = 1; i <= my numberOfRows; i++) { if (Melder_equ (token, my rowLabels[i])) { irow[i] = 0; break; } } } long nfound = 0; for (long i = 1; i <= my numberOfRows; i++) { if (irow[i] == 0) { nfound ++; } } if (nfound == 0) { Melder_throw (U"Invalid stimulus labels."); } if (nfound != ncondense) { Melder_warning (U"One or more of the given stimulus labels are suspect."); } long newnstim = my numberOfRows - nfound + 1; if (newpos < 1) { newpos = 1; } if (newpos > newnstim) { newpos = newnstim; } autoConfusion thee = Confusion_create (newnstim, my numberOfColumns); NUMstrings_copyElements (my columnLabels, thy columnLabels, 1, my numberOfColumns); TableOfReal_setRowLabel (thee.get(), newpos, newLabel); long inewrow = 1; for (long i = 1; i <= my numberOfRows; i++) { long rowpos = newpos; if (irow[i] > 0) { if (inewrow == newpos) { inewrow++; } rowpos = inewrow; inewrow++; TableOfReal_setRowLabel (thee.get(), rowpos, my rowLabels[i]); } for (long j = 1; j <= my numberOfColumns; j++) { thy data[rowpos][j] += my data[i][j]; } } return thee; } catch (MelderError) { Melder_throw (me, U": stimuli not grouped."); } }
void Graphics_setWsViewport (Graphics me, long x1DC, long x2DC, long y1DC, long y2DC) { if (x1DC < my d_x1DCmin || x2DC > my d_x2DCmax || y1DC < my d_y1DCmin || y2DC > my d_y2DCmax) { Melder_warning (U"Graphics_setWsViewport: coordinates too large:\n", x1DC, U"..", x2DC, U" x ", y1DC, U"..", y2DC, U" goes outside ", my d_x1DCmin, U"..", my d_x2DCmax, U" x ", my d_y1DCmin, U"..", my d_y2DCmax, U"." ); x1DC = my d_x1DCmin; x2DC = my d_x2DCmax; y1DC = my d_y1DCmin; y2DC = my d_y2DCmax; } my d_x1DC = x1DC; my d_x2DC = x2DC; my d_y1DC = y1DC; my d_y2DC = y2DC; #if win if (my screen && my printer) { GraphicsScreen mescreen = (GraphicsScreen) me; /* * Map page coordinates to paper coordinates. */ mescreen -> d_x1DC -= GetDeviceCaps (mescreen -> d_gdiGraphicsContext, PHYSICALOFFSETX); mescreen -> d_x2DC -= GetDeviceCaps (mescreen -> d_gdiGraphicsContext, PHYSICALOFFSETX); mescreen -> d_y1DC -= GetDeviceCaps (mescreen -> d_gdiGraphicsContext, PHYSICALOFFSETY); mescreen -> d_y2DC -= GetDeviceCaps (mescreen -> d_gdiGraphicsContext, PHYSICALOFFSETY); } #endif computeTrafo (me); }
autoConfusion Confusion_groupResponses (Confusion me, const char32 *labels, const char32 *newLabel, long newpos) { try { long ncondense = Melder_countTokens (labels); autoNUMvector<long> icol (1, my numberOfColumns); for (long i = 1; i <= my numberOfColumns; i++) { icol[i] = i; } for (char32 *token = Melder_firstToken (labels); token != 0; token = Melder_nextToken ()) { for (long i = 1; i <= my numberOfColumns; i++) { if (Melder_equ (token, my columnLabels[i])) { icol[i] = 0; break; } } } long nfound = 0; for (long i = 1; i <= my numberOfColumns; i++) { if (icol[i] == 0) { nfound ++; } } if (nfound == 0) { Melder_throw (U"Invalid response labels."); } if (nfound != ncondense) { Melder_warning (U"One or more of the given response labels are suspect."); } long newnresp = my numberOfColumns - nfound + 1; if (newpos < 1) { newpos = 1; } if (newpos > newnresp) { newpos = newnresp; } autoConfusion thee = Confusion_create (my numberOfRows, newnresp); NUMstrings_copyElements (my rowLabels, thy rowLabels, 1, my numberOfRows); TableOfReal_setColumnLabel (thee.get(), newpos, newLabel); long inewcol = 1; for (long i = 1; i <= my numberOfColumns; i++) { long colpos = newpos; if (icol[i] > 0) { if (inewcol == newpos) { inewcol++; } colpos = inewcol; inewcol++; TableOfReal_setColumnLabel (thee.get(), colpos, my columnLabels[i]); } for (long j = 1; j <= my numberOfRows; j++) { thy data[j][colpos] += my data[j][i]; } } return thee; } catch (MelderError) { Melder_throw (me, U": responses not grouped."); } }
void FormantFilter_drawFilterFunctions (FormantFilter me, Graphics g, double bandwidth, int toFreqScale, int fromFilter, int toFilter, double zmin, double zmax, int dbScale, double ymin, double ymax, int garnish) { if (! checkLimits (me, FilterBank_HERTZ, toFreqScale, & fromFilter, & toFilter, & zmin, & zmax, dbScale, & ymin, & ymax)) { return; } if (bandwidth <= 0) { Melder_warning (U"Bandwidth must be greater than zero."); } long n = 1000; autoNUMvector<double>a (1, n); Graphics_setInner (g); Graphics_setWindow (g, zmin, zmax, ymin, ymax); for (long j = fromFilter; j <= toFilter; j++) { double df = (zmax - zmin) / (n - 1); double fc = my y1 + (j - 1) * my dy; long ibegin, iend; for (long i = 1; i <= n; i++) { double f = zmin + (i - 1) * df; double z = scaleFrequency (f, toFreqScale, FilterBank_HERTZ); if (z == NUMundefined) { a[i] = NUMundefined; } else { a[i] = NUMformantfilter_amplitude (fc, bandwidth, z); if (dbScale) { a[i] = to_dB (a[i], 10, ymin); } } } setDrawingLimits (a.peek(), n, ymin, ymax, &ibegin, &iend); if (ibegin <= iend) { double fmin = zmin + (ibegin - 1) * df; double fmax = zmax - (n - iend) * df; Graphics_function (g, a.peek(), ibegin, iend, fmin, fmax); } } Graphics_unsetInner (g); if (garnish) { double distance = dbScale ? 10 : 1; char32 const *ytext = dbScale ? U"Amplitude (dB)" : U"Amplitude"; Graphics_drawInnerBox (g); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_marksLeftEvery (g, 1, distance, 1, 1, 0); Graphics_textLeft (g, 1, ytext); Graphics_textBottom (g, 1, GetFreqScaleText (toFreqScale)); } }
void FilterBank_drawFrequencyScales (I, Graphics g, int horizontalScale, double xmin, double xmax, int verticalScale, double ymin, double ymax, int garnish) { iam (FilterBank); int myFreqScale = FilterBank_getFrequencyScale (me); if (xmin < 0 || xmax < 0 || ymin < 0 || ymax < 0) { Melder_warning (U"Frequencies must be >= 0."); return; } if (xmin >= xmax) { double xmint = my ymin; double xmaxt = my ymax; if (ymin < ymax) { xmint = scaleFrequency (ymin, verticalScale, myFreqScale); xmaxt = scaleFrequency (ymax, verticalScale, myFreqScale); } xmin = scaleFrequency (xmint, myFreqScale, horizontalScale); xmax = scaleFrequency (xmaxt, myFreqScale, horizontalScale); } if (ymin >= ymax) { ymin = scaleFrequency (xmin, horizontalScale, verticalScale); ymax = scaleFrequency (xmax, horizontalScale, verticalScale); } long n = 2000; autoNUMvector<double> a (1, n); Graphics_setInner (g); Graphics_setWindow (g, xmin, xmax, ymin, ymax); double df = (xmax - xmin) / (n - 1); for (long i = 1; i <= n; i++) { double f = xmin + (i - 1) * df; a[i] = scaleFrequency (f, horizontalScale, verticalScale); } long ibegin, iend; setDrawingLimits (a.peek(), n, ymin, ymax, & ibegin, & iend); if (ibegin <= iend) { double fmin = xmin + (ibegin - 1) * df; double fmax = xmax - (n - iend) * df; Graphics_function (g, a.peek(), ibegin, iend, fmin, fmax); } Graphics_unsetInner (g); if (garnish) { Graphics_drawInnerBox (g); Graphics_marksLeft (g, 2, 1, 1, 0); Graphics_textLeft (g, 1, GetFreqScaleText (verticalScale)); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_textBottom (g, 1, GetFreqScaleText (horizontalScale)); } }
static int checkLimits (Matrix me, int fromFreqScale, int toFreqScale, int *fromFilter, int *toFilter, double *zmin, double *zmax, int dbScale, double *ymin, double *ymax) { if (*fromFilter == 0) { *fromFilter = 1; } if (*toFilter == 0) { *toFilter = my ny; } if (*toFilter < *fromFilter) { *fromFilter = 1; *toFilter = my ny; } if (*fromFilter < 1) { *fromFilter = 1; } if (*toFilter > my ny) { *toFilter = my ny; } if (*fromFilter > *toFilter) { Melder_warning (U"Filter numbers must be in range [1, ", my ny, U"]"); return 0; } if (*zmin < 0 || *zmax < 0) { Melder_warning (U"Frequencies must be positive."); return 0; } if (*zmax <= *zmin) { *zmin = scaleFrequency (my ymin, fromFreqScale, toFreqScale); *zmax = scaleFrequency (my ymax, fromFreqScale, toFreqScale); } if (*ymax <= *ymin) { *ymax = 1; *ymin = 0; if (dbScale) { *ymax = 0; *ymin = -60; } } return 1; }
autoPCA TableOfReal_to_PCA (I) { iam (TableOfReal); try { long m = my numberOfRows, n = my numberOfColumns; if (! TableOfReal_areAllCellsDefined (me, 0, 0, 0, 0)) { Melder_throw (U"Undefined cells."); } if (m < 2) { Melder_throw (U"There is not enough data to perform a PCA.\nYour table has less than 2 rows."); } if (m < n) { Melder_warning (U"The number of rows in your table is less than the \nnumber of columns. "); } if (NUMfrobeniusnorm (m, n, my data) == 0) { Melder_throw (U"All values in your table are zero."); } autoPCA thee = Thing_new (PCA); autoNUMmatrix<double> a (NUMmatrix_copy (my data, 1, m, 1, n), 1, 1); thy centroid = NUMvector<double> (1, n); for (long j = 1; j <= n; j++) { double colmean = a[1][j]; for (long i = 2; i <= m; i++) { colmean += a[i][j]; } colmean /= m; for (long i = 1; i <= m; i++) { a[i][j] -= colmean; } thy centroid[j] = colmean; } Eigen_initFromSquareRoot (thee.peek(), a.peek(), m, n); thy labels = NUMvector<char32 *> (1, n); NUMstrings_copyElements (my columnLabels, thy labels, 1, n); PCA_setNumberOfObservations (thee.peek(), m); /* The covariance matrix C = A'A / (N-1). However, we have calculated the eigenstructure for A'A. This has no consequences for the eigenvectors, but the eigenvalues have to be divided by (N-1). */ for (long i = 1; i <= thy numberOfEigenvalues; i++) { thy eigenvalues[i] /= (m - 1); } return thee; } catch (MelderError) { Melder_throw (me, U": PCA not created."); } }
static void cb_optionChanged (GuiObject w, XtPointer void_me, XtPointer call) { iam (GuiOptionMenu); (void) call; for (int i = 1; i <= my d_options -> size; i ++) { GuiMenuItem item = static_cast <GuiMenuItem> (my d_options -> item [i]); if (item -> d_widget == w) { XtVaSetValues (my d_xmCascadeButton, XmNlabelString, Melder_peekWcsToUtf8 (item -> d_widget -> name), NULL); XmToggleButtonSetState (item -> d_widget, TRUE, FALSE); if (Melder_debug == 11) { Melder_warning (i, " \"", item -> d_widget -> name, "\""); } } else { XmToggleButtonSetState (item -> d_widget, FALSE, FALSE); } } }
static void LongSound_init (LongSound me, MelderFile file) { MelderFile_copy (file, & my file); MelderFile_open (file); // BUG: should be auto, but that requires an implemented .transfer() my f = file -> filePointer; my audioFileType = MelderFile_checkSoundFile (file, & my numberOfChannels, & my encoding, & my sampleRate, & my startOfData, & my nx); if (my audioFileType == 0) Melder_throw (U"File not recognized (LongSound only supports AIFF, AIFC, WAV, NeXT/Sun, NIST and FLAC)."); if (my encoding == Melder_SHORTEN || my encoding == Melder_POLYPHONE) Melder_throw (U"LongSound does not support sound files compressed with \"shorten\"."); if (my nx < 1) Melder_throw (U"Audio file contains 0 samples."); my xmin = 0.0; my dx = 1 / my sampleRate; my xmax = my nx * my dx; my x1 = 0.5 * my dx; my numberOfBytesPerSamplePoint = Melder_bytesPerSamplePoint (my encoding); my bufferLength = prefs_bufferLength; for (;;) { my nmax = my bufferLength * my numberOfChannels * my sampleRate * (1 + 3 * MARGIN); try { my buffer = NUMvector <int16> (0, my nmax * my numberOfChannels); break; } catch (MelderError) { my bufferLength *= 0.5; // try 30, 15, or 7.5 seconds if (my bufferLength < 5.0) // too short to be good throw; Melder_clearError (); // delete out-of-memory message } } my imin = 1; my imax = 0; my flacDecoder = nullptr; if (my audioFileType == Melder_FLAC) { my flacDecoder = FLAC__stream_decoder_new (); FLAC__stream_decoder_init_FILE (my flacDecoder, my f, _LongSound_FLAC_write, nullptr, _LongSound_FLAC_error, me); } my mp3f = nullptr; if (my audioFileType == Melder_MP3) { my mp3f = mp3f_new (); mp3f_set_file (my mp3f, my f); mp3f_set_callback (my mp3f, _LongSound_MP3_convert, me); if (! mp3f_analyze (my mp3f)) Melder_throw (U"Unable to analyze MP3 file."); Melder_warning (U"Time measurements in MP3 files can be off by several tens of milliseconds. " U"Please convert to WAV file if you need time precision or annotation."); } }
Formant LPC_to_Formant (LPC me, double margin) { try { double samplingFrequency = 1.0 / my samplingPeriod; long nmax = my maxnCoefficients, err = 0; long interval = nmax > 20 ? 1 : 10; if (nmax > 99) { Melder_throw ("We cannot find the roots of a polynomial of order > 99."); } if (margin >= samplingFrequency / 4) { Melder_throw ("Margin must be smaller than ", samplingFrequency / 4, "."); } autoFormant thee = Formant_create (my xmin, my xmax, my nx, my dx, my x1, (nmax + 1) / 2); autoMelderProgress progress (L"LPC to Formant"); for (long i = 1; i <= my nx; i++) { Formant_Frame formant = & thy d_frames[i]; LPC_Frame lpc = & my d_frames[i]; // Initialisation of Formant_Frame is taken care of in Roots_into_Formant_Frame! try { LPC_Frame_into_Formant_Frame (lpc, formant, my samplingPeriod, margin); } catch (MelderError) { Melder_clearError(); err++; } if ( (interval == 1 || (i % interval) == 1)) { Melder_progress ( (double) i / my nx, L"LPC to Formant: frame ", Melder_integer (i), L" out of ", Melder_integer (my nx), L"."); } } Formant_sort (thee.peek()); if (err > 0) { Melder_warning (Melder_integer (err), L" formant frames out of ", Melder_integer (my nx), L" suspect."); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": no Formant created."); } }
autoSoundList TextGrid_Sound_extractNonemptyIntervals (TextGrid me, Sound sound, long tierNumber, bool preserveTimes) { try { IntervalTier tier = TextGrid_checkSpecifiedTierIsIntervalTier (me, tierNumber); autoSoundList list = SoundList_create (); for (long iseg = 1; iseg <= tier -> intervals.size; iseg ++) { TextInterval segment = tier -> intervals.at [iseg]; if (segment -> text && segment -> text [0] != U'\0') { autoSound interval = Sound_extractPart (sound, segment -> xmin, segment -> xmax, kSound_windowShape_RECTANGULAR, 1.0, preserveTimes); Thing_setName (interval.get(), segment -> text ? segment -> text : U"untitled"); list -> addItem_move (interval.move()); } } if (list->size == 0) Melder_warning (U"No non-empty intervals were found."); return list; } catch (MelderError) { Melder_throw (me, U" & ", sound, U": non-empty intervals not extracted."); } }
Collection TextGrid_Sound_extractNonemptyIntervals (TextGrid me, Sound sound, long tierNumber, int preserveTimes) { try { IntervalTier tier = TextGrid_checkSpecifiedTierIsIntervalTier (me, tierNumber); autoCollection collection = Collection_create (NULL, tier -> intervals -> size); for (long iseg = 1; iseg <= tier -> intervals -> size; iseg ++) { TextInterval segment = (TextInterval) tier -> intervals -> item [iseg]; if (segment -> text != NULL && segment -> text [0] != '\0') { autoSound interval = Sound_extractPart (sound, segment -> xmin, segment -> xmax, kSound_windowShape_RECTANGULAR, 1.0, preserveTimes); Thing_setName (interval.peek(), segment -> text ? segment -> text : L"untitled"); Collection_addItem (collection.peek(), interval.transfer()); } } if (collection -> size == 0) Melder_warning (L"No non-empty intervals were found."); return collection.transfer(); } catch (MelderError) { Melder_throw (me, " & ", sound, ": non-empty intervals not extracted."); } }
void Discriminant_drawConcentrationEllipses (Discriminant me, Graphics g, double scale, bool confidence, char32 *label, int discriminantDirections, long d1, long d2, double xmin, double xmax, double ymin, double ymax, int fontSize, int garnish) { long numberOfFunctions = Discriminant_getNumberOfFunctions (me); if (! discriminantDirections) { SSCPList_drawConcentrationEllipses (my groups.get(), g, scale, confidence, label, d1, d2, xmin, xmax, ymin, ymax, fontSize, garnish); return; } if (numberOfFunctions <= 1) { Melder_warning (U"Discriminant_drawConcentrationEllipses: Nothing drawn " U"because there is only one dimension in the discriminant space."); return; } // Project SSCPs on eigenvectors. if (d1 == 0 && d2 == 0) { d1 = 1; d2 = MIN (numberOfFunctions, d1 + 1); } else if (d1 < 0 || d2 > numberOfFunctions) { return; } double *v1 = my eigen -> eigenvectors [d1]; double *v2 = my eigen -> eigenvectors [d2]; autoSSCPList thee = SSCPList_toTwoDimensions (my groups.get(), v1, v2); SSCPList_drawConcentrationEllipses (thee.get(), g, scale, confidence, label, 1, 2, xmin, xmax, ymin, ymax, fontSize, 0); if (garnish) { char32 llabel[40]; Graphics_drawInnerBox (g); Graphics_marksLeft (g, 2, true, true, false); Melder_sprint (llabel,40, U"function ", d2); Graphics_textLeft (g, true, llabel); Graphics_marksBottom (g, 2, true, true, false); Melder_sprint (llabel,40, U"function ", d1); Graphics_textBottom (g, true, llabel); } }
void Matrix_scale (Matrix me, int choice) { double min, max, extremum; long nZero = 0; if (choice == 2) { /* by row */ for (long i = 1; i <= my ny; i++) { Matrix_getWindowExtrema (me, 1, my nx, i, i, &min, &max); extremum = fabs (max) > fabs (min) ? fabs (max) : fabs (min); if (extremum == 0.0) { nZero++; } else for (long j = 1; j <= my nx; j++) { my z[i][j] /= extremum; } } } else if (choice == 3) { /* by col */ for (long j = 1; j <= my nx; j++) { Matrix_getWindowExtrema (me, j, j, 1, my ny, &min, &max); extremum = fabs (max) > fabs (min) ? fabs (max) : fabs (min); if (extremum == 0.0) { nZero++; } else for (long i = 1; i <= my ny; i++) { my z[i][j] /= extremum; } } } else if (choice == 1) { /* overall */ Matrix_getWindowExtrema (me, 1, my nx, 1, my ny, &min, &max); extremum = fabs (max) > fabs (min) ? fabs (max) : fabs (min); if (extremum == 0.0) { nZero++; } else { for (long i = 1; i <= my ny; i++) { for (long j = 1; j <= my nx; j++) { my z[i][j] /= extremum; } } } } else { Melder_flushError (U"Matrix_scale: choice must be > 0 && <= 3."); return; } if (nZero) { Melder_warning (U"Matrix_scale: extremum == 0, (part of) matrix unscaled."); } }
// xmin, xmax in hz versus bark/mel or lin void BandFilterSpectrogram_drawFrequencyScale (BandFilterSpectrogram me, Graphics g, double xmin, double xmax, double ymin, double ymax, int garnish) { if (xmin < 0 || xmax < 0 || ymin < 0 || ymax < 0) { Melder_warning (U"Frequencies must be >= 0."); return; } // scale is in hertz if (xmin >= xmax) { // autoscaling xmin = 0; xmax = my v_frequencyToHertz (my ymax); } if (ymin >= ymax) { // autoscaling ymin = my ymin; ymax = my ymax; } long n = 2000; Graphics_setInner (g); Graphics_setWindow (g, xmin, xmax, ymin, ymax); double dx = (xmax - xmin) / (n - 1); double x1 = xmin, y1 = my v_hertzToFrequency (x1); for (long i = 2; i <= n; i++) { double x2 = x1 + dx, y2 = my v_hertzToFrequency (x2); if (NUMdefined (y1) && NUMdefined (y2)) { double xo1, yo1, xo2, yo2; if (NUMclipLineWithinRectangle (x1, y1, x2, y2, xmin, ymin, xmax, ymax, &xo1, &yo1, &xo2, &yo2)) { Graphics_line (g, xo1, yo1, xo2, yo2); } } x1 = x2; y1 = y2; } Graphics_unsetInner (g); if (garnish) { Graphics_drawInnerBox (g); Graphics_marksLeft (g, 2, 1, 1, 0); Graphics_textLeft (g, 1, Melder_cat (U"Frequency (", my v_getFrequencyUnit (), U")")); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_textBottom (g, 1, U"Frequency (Hz)"); } }
autoResultsMFC ExperimentMFC_extractResults (ExperimentMFC me) { try { if (my trial == 0 || my trial <= my numberOfTrials) Melder_warning (U"The experiment was not finished. Only the first ", my trial - 1 + my pausing, U" responses are valid."); autoResultsMFC thee = ResultsMFC_create (my numberOfTrials); for (long trial = 1; trial <= my numberOfTrials; trial ++) { char32 *pipe = my stimulus [my stimuli [trial]]. visibleText ? str32chr (my stimulus [my stimuli [trial]]. visibleText, U'|') : nullptr; thy result [trial]. stimulus = Melder_dup (Melder_cat (my stimulus [my stimuli [trial]]. name, pipe)); //if (my responses [trial] < 1) Melder_throw (U"No response for trial ", trial, U".") thy result [trial]. response = Melder_dup (my responses [trial] ? my response [my responses [trial]]. name : U""); thy result [trial]. goodness = my goodnesses [trial]; thy result [trial]. reactionTime = my reactionTimes [trial]; } return thee; } catch (MelderError) { Melder_throw (me, U": results not extracted."); } }
autoSoundList TextGrid_Sound_extractIntervalsWhere (TextGrid me, Sound sound, long tierNumber, int comparison_Melder_STRING, const char32 *text, bool preserveTimes) { try { IntervalTier tier = TextGrid_checkSpecifiedTierIsIntervalTier (me, tierNumber); autoSoundList list = SoundList_create (); long count = 0; for (long iseg = 1; iseg <= tier -> intervals.size; iseg ++) { TextInterval segment = tier -> intervals.at [iseg]; if (Melder_stringMatchesCriterion (segment -> text, comparison_Melder_STRING, text)) { autoSound interval = Sound_extractPart (sound, segment -> xmin, segment -> xmax, kSound_windowShape_RECTANGULAR, 1.0, preserveTimes); Thing_setName (interval.get(), Melder_cat (sound -> name ? sound -> name : U"", U"_", text, U"_", ++ count)); list -> addItem_move (interval.move()); } } if (list->size == 0) Melder_warning (U"No label that ", kMelder_string_getText (comparison_Melder_STRING), U" the text \"", text, U"\" was found."); return list; } catch (MelderError) { Melder_throw (me, U" & ", sound, U": intervals not extracted."); } }
LinearRegression Table_to_LinearRegression (Table me) { try { long numberOfIndependentVariables = my numberOfColumns - 1, numberOfParameters = my numberOfColumns; long numberOfCells = my rows -> size, icell, ivar; if (numberOfParameters < 1) /* Includes intercept. */ Melder_throw (U"Not enough columns (has to be more than 1)."); if (numberOfCells < numberOfParameters) { Melder_warning (U"Solution is not unique (more parameters than cases)."); } autoNUMmatrix <double> u (1, numberOfCells, 1, numberOfParameters); autoNUMvector <double> b (1, numberOfCells); autoNUMvector <double> x (1, numberOfParameters); autoLinearRegression thee = LinearRegression_create (); for (ivar = 1; ivar <= numberOfIndependentVariables; ivar ++) { double minimum = Table_getMinimum (me, ivar); double maximum = Table_getMaximum (me, ivar); Regression_addParameter (thee.peek(), my columnHeaders [ivar]. label, minimum, maximum, 0.0); } for (icell = 1; icell <= numberOfCells; icell ++) { for (ivar = 1; ivar < numberOfParameters; ivar ++) { u [icell] [ivar] = Table_getNumericValue_Assert (me, icell, ivar); } u [icell] [numberOfParameters] = 1.0; /* For the intercept. */ b [icell] = Table_getNumericValue_Assert (me, icell, my numberOfColumns); // the dependent variable } NUMsolveEquation (u.peek(), numberOfCells, numberOfParameters, b.peek(), NUMeps * numberOfCells, x.peek()); thy intercept = x [numberOfParameters]; for (ivar = 1; ivar <= numberOfIndependentVariables; ivar ++) { RegressionParameter parm = static_cast<RegressionParameter> (thy parameters -> item [ivar]); parm -> value = x [ivar]; } return thee.transfer(); } catch (MelderError) { Melder_throw (me, U": linear regression not performed."); } }
Polygon Polygon_createSimple (wchar_t *xystring) { try { long numberOfPoints; autoNUMvector<double> xys (NUMstring_to_numbers (xystring, &numberOfPoints), 1); if (numberOfPoints < 6) { Melder_throw ("There must be at least 3 points (= x,y pairs) in the Polygon"); } if (numberOfPoints % 2 != 0) { Melder_throw ("One value is missing."); } numberOfPoints /= 2; // x,y pairs autoPolygon me = Polygon_create (numberOfPoints); for (long i = 1; i <= numberOfPoints; i++) { my x[i] = xys[2 * i - 1]; my y[i] = xys[2 * i]; if (i > 1 && my x[i] == my x[i - 1] && my y[i] == my y[i - 1]) { Melder_warning ("Two successives vertices are equal."); } } return me.transfer(); } catch (MelderError) { Melder_throw ("Polygon not created."); } }
Collection TextGrid_Sound_extractIntervalsWhere (TextGrid me, Sound sound, long tierNumber, int comparison_Melder_STRING, const wchar_t *text, int preserveTimes) { try { IntervalTier tier = TextGrid_checkSpecifiedTierIsIntervalTier (me, tierNumber); autoCollection collection = Collection_create (NULL, tier -> intervals -> size); long count = 0; for (long iseg = 1; iseg <= tier -> intervals -> size; iseg ++) { TextInterval segment = (TextInterval) tier -> intervals -> item [iseg]; if (Melder_stringMatchesCriterion (segment -> text, comparison_Melder_STRING, text)) { autoSound interval = Sound_extractPart (sound, segment -> xmin, segment -> xmax, kSound_windowShape_RECTANGULAR, 1.0, preserveTimes); wchar_t name [1000]; swprintf (name, 1000, L"%ls_%ls_%ld", sound -> name ? sound -> name : L"", text, ++ count); Thing_setName (interval.peek(), name); Collection_addItem (collection.peek(), interval.transfer()); } } if (collection -> size == 0) Melder_warning ("No label that ", kMelder_string_getText (comparison_Melder_STRING), " the text \"", text, "\" was found."); return collection.transfer(); } catch (MelderError) { Melder_throw (me, " & ", sound, ": intervals not extracted."); } }
static LogisticRegression _Table_to_LogisticRegression (Table me, long *factors, long numberOfFactors, long dependent1, long dependent2) { long numberOfParameters = numberOfFactors + 1; long numberOfCells = my rows -> size, numberOfY0 = 0, numberOfY1 = 0, numberOfData = 0; double logLikelihood = 1e300, previousLogLikelihood = 2e300; if (numberOfParameters < 1) // includes intercept Melder_throw ("Not enough columns (has to be more than 1)."); /* * Divide up the contents of the table into a number of independent variables (x) and two dependent variables (y0 and y1). */ autoNUMmatrix <double> x (1, numberOfCells, 0, numberOfFactors); // column 0 is the intercept autoNUMvector <double> y0 (1, numberOfCells); autoNUMvector <double> y1 (1, numberOfCells); autoNUMvector <double> meanX (1, numberOfFactors); autoNUMvector <double> stdevX (1, numberOfFactors); autoNUMmatrix <double> smallMatrix (0, numberOfFactors, 0, numberOfParameters); autoLogisticRegression thee = LogisticRegression_create (my columnHeaders [dependent1]. label, my columnHeaders [dependent2]. label); for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { double minimum = Table_getMinimum (me, factors [ivar]); double maximum = Table_getMaximum (me, factors [ivar]); Regression_addParameter (thee.peek(), my columnHeaders [factors [ivar]]. label, minimum, maximum, 0.0); } for (long icell = 1; icell <= numberOfCells; icell ++) { y0 [icell] = Table_getNumericValue_Assert (me, icell, dependent1); y1 [icell] = Table_getNumericValue_Assert (me, icell, dependent2); numberOfY0 += y0 [icell]; numberOfY1 += y1 [icell]; numberOfData += y0 [icell] + y1 [icell]; x [icell] [0] = 1.0; /* Intercept. */ for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { x [icell] [ivar] = Table_getNumericValue_Assert (me, icell, factors [ivar]); meanX [ivar] += x [icell] [ivar] * (y0 [icell] + y1 [icell]); } } if (numberOfY0 == 0 && numberOfY1 == 0) Melder_throw ("No data in either class. Cannot determine result."); if (numberOfY0 == 0) Melder_throw ("No data in class ", my columnHeaders [dependent1]. label, ". Cannot determine result."); if (numberOfY1 == 0) Melder_throw ("No data in class ", my columnHeaders [dependent2]. label, ". Cannot determine result."); /* * Normalize the data. */ for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { meanX [ivar] /= numberOfData; for (long icell = 1; icell <= numberOfCells; icell ++) { x [icell] [ivar] -= meanX [ivar]; } } for (long icell = 1; icell <= numberOfCells; icell ++) { for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { stdevX [ivar] += x [icell] [ivar] * x [icell] [ivar] * (y0 [icell] + y1 [icell]); } } for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { stdevX [ivar] = sqrt (stdevX [ivar] / numberOfData); for (long icell = 1; icell <= numberOfCells; icell ++) { x [icell] [ivar] /= stdevX [ivar]; } } /* * Initial state of iteration: the null model. */ thy intercept = log ((double) numberOfY1 / (double) numberOfY0); // initial state of intercept: best guess for average log odds for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { RegressionParameter parm = static_cast<RegressionParameter> (thy parameters -> item [ivar]); parm -> value = 0.0; // initial state of dependence: none } long iteration = 1; for (; iteration <= 100; iteration ++) { previousLogLikelihood = logLikelihood; for (long ivar = 0; ivar <= numberOfFactors; ivar ++) { for (long jvar = ivar; jvar <= numberOfParameters; jvar ++) { smallMatrix [ivar] [jvar] = 0.0; } } /* * Compute the current log likelihood. */ logLikelihood = 0.0; for (long icell = 1; icell <= numberOfCells; icell ++) { double fittedLogit = thy intercept, fittedP, fittedQ, fittedLogP, fittedLogQ, fittedPQ, fittedVariance; for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { RegressionParameter parm = static_cast<RegressionParameter> (thy parameters -> item [ivar]); fittedLogit += parm -> value * x [icell] [ivar]; } /* * Basically we have fittedP = 1.0 / (1.0 + exp (- fittedLogit)), * but that works neither for fittedP values near 0 nor for values near 1. */ if (fittedLogit > 15.0) { /* * For large fittedLogit, fittedLogP = ln (1/(1+exp(-fittedLogit))) = -ln (1+exp(-fittedLogit)) =~ - exp(-fittedLogit) */ fittedLogP = - exp (- fittedLogit); fittedLogQ = - fittedLogit; fittedPQ = exp (- fittedLogit); fittedP = exp (fittedLogP); fittedQ = 1.0 - fittedP; } else if (fittedLogit < -15.0) { fittedLogP = fittedLogit; fittedLogQ = - exp (fittedLogit); fittedPQ = exp (fittedLogit); fittedP = exp (fittedLogP); fittedQ = 1 - fittedP; } else { fittedP = 1.0 / (1.0 + exp (- fittedLogit)); fittedLogP = log (fittedP); fittedQ = 1.0 - fittedP; fittedLogQ = log (fittedQ); fittedPQ = fittedP * fittedQ; } logLikelihood += -2 * (y1 [icell] * fittedLogP + y0 [icell] * fittedLogQ); /* * Matrix shifting stuff. * Suppose a + b Sk + c Tk = ln (pk / qk), * where {a, b, c} are the coefficients to be optimized, * Sk and Tk are properties of stimulus k, * and pk and qk are the fitted probabilities for y1 and y0, respectively, given stimulus k. * Then ln pk = - ln (1 + qk / pk) = - ln (1 + exp (- (a + b Sk + c Tk))) * d ln pk / da = 1 / (1 + exp (a + b Sk + c Tk)) = qk * d ln pk / db = qk Sk * d ln pk / dc = qk Tk * d ln qk / da = - pk * Now LL = Sum(k) (y1k ln pk + y0k ln qk) * so that dLL/da = Sum(k) (y1k d ln pk / da + y0k ln qk / da) = Sum(k) (y1k qk - y0k pk) */ fittedVariance = fittedPQ * (y0 [icell] + y1 [icell]); for (long ivar = 0; ivar <= numberOfFactors; ivar ++) { /* * The last column gets the gradient of LL: dLL/da, dLL/db, dLL/dc. */ smallMatrix [ivar] [numberOfParameters] += x [icell] [ivar] * (y1 [icell] * fittedQ - y0 [icell] * fittedP); for (long jvar = ivar; jvar <= numberOfFactors; jvar ++) { smallMatrix [ivar] [jvar] += x [icell] [ivar] * x [icell] [jvar] * fittedVariance; } } } if (fabs (logLikelihood - previousLogLikelihood) < 1e-11) { break; } /* * Make matrix symmetric. */ for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { for (long jvar = 0; jvar < ivar; jvar ++) { smallMatrix [ivar] [jvar] = smallMatrix [jvar] [ivar]; } } /* * Invert matrix in the simplest way, and shift and wipe the last column with it. */ for (long ivar = 0; ivar <= numberOfFactors; ivar ++) { double pivot = smallMatrix [ivar] [ivar]; /* Save diagonal. */ smallMatrix [ivar] [ivar] = 1.0; for (long jvar = 0; jvar <= numberOfParameters; jvar ++) { smallMatrix [ivar] [jvar] /= pivot; } for (long jvar = 0; jvar <= numberOfFactors; jvar ++) { if (jvar != ivar) { double temp = smallMatrix [jvar] [ivar]; smallMatrix [jvar] [ivar] = 0.0; for (long kvar = 0; kvar <= numberOfParameters; kvar ++) { smallMatrix [jvar] [kvar] -= temp * smallMatrix [ivar] [kvar]; } } } } /* * Update the parameters from the last column of smallMatrix. */ thy intercept += smallMatrix [0] [numberOfParameters]; for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { RegressionParameter parm = static_cast<RegressionParameter> (thy parameters -> item [ivar]); parm -> value += smallMatrix [ivar] [numberOfParameters]; } } if (iteration > 100) { Melder_warning (L"Logistic regression has not converged in 100 iterations. The results are unreliable."); } for (long ivar = 1; ivar <= numberOfFactors; ivar ++) { RegressionParameter parm = static_cast<RegressionParameter> (thy parameters -> item [ivar]); parm -> value /= stdevX [ivar]; thy intercept -= parm -> value * meanX [ivar]; } return thee.transfer(); }
BarkFilter Sound_to_BarkFilter (Sound me, double analysisWidth, double dt, double f1_bark, double fmax_bark, double df_bark) { try { double t1, nyquist = 0.5 / my dx, samplingFrequency = 2 * nyquist; double windowDuration = 2 * analysisWidth; /* gaussian window */ double zmax = NUMhertzToBark2 (nyquist); double fmin_bark = 0; long nt, frameErrorCount = 0; // Check defaults. if (f1_bark <= 0) { f1_bark = 1; } if (fmax_bark <= 0) { fmax_bark = zmax; } if (df_bark <= 0) { df_bark = 1; } fmax_bark = MIN (fmax_bark, zmax); long nf = floor ( (fmax_bark - f1_bark) / df_bark + 0.5); if (nf <= 0) { Melder_throw ("The combination of filter parameters is not valid."); } Sampled_shortTermAnalysis (me, windowDuration, dt, & nt, & t1); autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency); autoSound window = Sound_createGaussian (windowDuration, samplingFrequency); autoBarkFilter thee = BarkFilter_create (my xmin, my xmax, nt, dt, t1, fmin_bark, fmax_bark, nf, df_bark, f1_bark); autoMelderProgress progess (L"BarkFilter analysis"); for (long i = 1; i <= nt; i++) { double t = Sampled_indexToX (thee.peek(), i); Sound_into_Sound (me, sframe.peek(), t - windowDuration / 2); Sounds_multiply (sframe.peek(), window.peek()); if (! Sound_into_BarkFilter_frame (sframe.peek(), thee.peek(), i)) { frameErrorCount++; } if ( (i % 10) == 1) { Melder_progress ( (double) i / nt, L"BarkFilter analysis: frame ", Melder_integer (i), L" from ", Melder_integer (nt), L"."); therror } } if (frameErrorCount > 0) { Melder_warning (L"Analysis results of ", Melder_integer (frameErrorCount), L" frame(s) out of ", Melder_integer (nt), L" will be suspect."); } double ref = FilterBank_DBREF * gaussian_window_squared_correction (window -> nx); NUMdmatrix_to_dBs (thy z, 1, thy ny, 1, thy nx, ref, FilterBank_DBFAC, FilterBank_DBFLOOR); return thee.transfer(); } catch (MelderError) {
FormantFilter Sound_and_Pitch_to_FormantFilter (Sound me, Pitch thee, double analysisWidth, double dt, double f1_hz, double fmax_hz, double df_hz, double relative_bw) { try { double t1, windowDuration = 2 * analysisWidth; /* gaussian window */ double nyquist = 0.5 / my dx, samplingFrequency = 2 * nyquist, fmin_hz = 0; long nt, f0_undefined = 0; if (my xmin > thy xmin || my xmax > thy xmax) Melder_throw ("The domain of the Sound is not included in the domain of the Pitch."); double f0_median = Pitch_getQuantile (thee, thy xmin, thy xmax, 0.5, kPitch_unit_HERTZ); if (f0_median == NUMundefined || f0_median == 0) { f0_median = 100; Melder_warning (L"Pitch values undefined. Bandwith fixed to 100 Hz. "); } if (f1_hz <= 0) { f1_hz = 100; } if (fmax_hz <= 0) { fmax_hz = nyquist; } if (df_hz <= 0) { df_hz = f0_median / 2; } if (relative_bw <= 0) { relative_bw = 1.1; } fmax_hz = MIN (fmax_hz, nyquist); long nf = floor ( (fmax_hz - f1_hz) / df_hz + 0.5); Sampled_shortTermAnalysis (me, windowDuration, dt, &nt, &t1); autoFormantFilter him = FormantFilter_create (my xmin, my xmax, nt, dt, t1, fmin_hz, fmax_hz, nf, df_hz, f1_hz); // Temporary objects autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency); autoSound window = Sound_createGaussian (windowDuration, samplingFrequency); autoMelderProgress progress (L"Sound & Pitch: To FormantFilter"); for (long i = 1; i <= nt; i++) { double t = Sampled_indexToX (him.peek(), i); double b, f0 = Pitch_getValueAtTime (thee, t, kPitch_unit_HERTZ, 0); if (f0 == NUMundefined || f0 == 0) { f0_undefined++; f0 = f0_median; } b = relative_bw * f0; Sound_into_Sound (me, sframe.peek(), t - windowDuration / 2); Sounds_multiply (sframe.peek(), window.peek()); Sound_into_FormantFilter_frame (sframe.peek(), him.peek(), i, b); if ( (i % 10) == 1) { Melder_progress ( (double) i / nt, L"Frame ", Melder_integer (i), L" out of ", Melder_integer (nt), L"."); } } double ref = FilterBank_DBREF * gaussian_window_squared_correction (window -> nx); NUMdmatrix_to_dBs (his z, 1, his ny, 1, his nx, ref, FilterBank_DBFAC, FilterBank_DBFLOOR); return him.transfer(); } catch (MelderError) { Melder_throw ("FormantFilter not created from Pitch & FormantFilter."); } }