FileInMemory FileInMemory_create (MelderFile file) { try { if (! MelderFile_readable (file)) { Melder_throw ("File not readable."); } long length = MelderFile_length (file); if (length <= 0) { Melder_throw ("File is empty."); } autoFileInMemory me = Thing_new (FileInMemory); my d_path = Melder_wcsdup (file -> path); my d_id = Melder_wcsdup (MelderFile_name (file)); my d_numberOfBytes = length; my d_data = NUMvector <char> (0, my d_numberOfBytes); // one extra for 0-byte at end if text MelderFile_open (file); for (long i = 0; i < my d_numberOfBytes; i++) { unsigned int number = bingetu1 (file -> filePointer); my d_data[i] = number; } my d_data[my d_numberOfBytes] = 0; // one extra MelderFile_close (file); return me.transfer(); } catch (MelderError) { Melder_throw ("FileInMemory not created from \"", Melder_fileToPath (file), "\"."); } }
void structFileInMemory :: v_copy (thou) { thouart (FileInMemory); FileInMemory_Parent :: v_copy (thee); therror thy d_path = Melder_wcsdup (d_path); thy d_id = Melder_wcsdup (d_id); thy d_numberOfBytes = d_numberOfBytes; thy d_data = NUMvector<char> (0, d_numberOfBytes); memcpy (thy d_data, d_data, d_numberOfBytes+1); }
LogisticRegression LogisticRegression_create (const wchar *dependent1, const wchar *dependent2) { try { autoLogisticRegression me = Thing_new (LogisticRegression); Regression_init (me.peek()); my dependent1 = Melder_wcsdup (dependent1); my dependent2 = Melder_wcsdup (dependent2); return me.transfer(); } catch (MelderError) { Melder_throw ("LogisticRegression not created."); } }
FileInMemory FileInMemory_createWithData (long numberOfBytes, const char *data, const wchar_t *path, const wchar_t *id) { try { autoFileInMemory me = Thing_new (FileInMemory); my d_path = Melder_wcsdup (path); my d_id = Melder_wcsdup (id); my d_numberOfBytes = numberOfBytes; my d_data = const_cast<char *> (data); // copy pointer to data only return me.transfer (); } catch (MelderError) { Melder_throw ("FileInMemory not create from data."); } }
TableOfReal EditDistanceTable_to_TableOfReal (EditDistanceTable me) { try { autoTableOfReal thee = TableOfReal_create (my numberOfRows, my numberOfColumns); for (long j = 1; j <= my numberOfColumns; j++) { thy columnLabels[j] = Melder_wcsdup (my columnLabels[j]); } for (long i = 1; i <= my numberOfRows; i++) { thy rowLabels[i] = Melder_wcsdup (my rowLabels[i]); } NUMmatrix_copyElements<double> (my data, thy data, 1, my numberOfRows, 1, my numberOfColumns); return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": no TableOfReal created."); } }
static void copyColumnLabels (TableOfReal me, TableOfReal thee) { Melder_assert (me != thee); Melder_assert (my numberOfColumns == thy numberOfColumns); for (long icol = 1; icol <= my numberOfColumns; icol ++) { thy columnLabels [icol] = Melder_wcsdup (my columnLabels [icol]); } }
static void copyRowLabels (TableOfReal me, TableOfReal thee) { Melder_assert (me != thee); Melder_assert (my numberOfRows == thy numberOfRows); for (long irow = 1; irow <= my numberOfRows; irow ++) { thy rowLabels [irow] = Melder_wcsdup (my rowLabels [irow]); } }
Distributions Transition_to_Distributions_conflate (Transition me) { try { autoDistributions thee = Distributions_create (my numberOfStates, 1); /* * Copy labels. */ for (long i = 1; i <= my numberOfStates; i ++) { thy rowLabels [i] = Melder_wcsdup (my stateLabels [i]); } /* * Average rows. */ for (long i = 1; i <= my numberOfStates; i ++) { for (long j = 1; j <= my numberOfStates; j ++) thy data [i] [1] += my data [j] [i]; thy data [i] [1] /= my numberOfStates; } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not conflated to Distributions."); } }
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."); } }
Distributions Strings_to_Distributions (Strings me) { try { autoDistributions thee = Distributions_create (my numberOfStrings, 1); long idist = 0; for (long i = 1; i <= my numberOfStrings; i ++) { wchar *string = my strings [i]; long where = 0; long j = 1; for (; j <= idist; j ++) if (wcsequ (thy rowLabels [j], string)) { where = j; break; } if (where) { thy data [j] [1] += 1.0; } else { thy rowLabels [++ idist] = Melder_wcsdup (string); thy data [idist] [1] = 1.0; } } thy numberOfRows = idist; TableOfReal_sortByLabel (thee.peek(), 1, 0); return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": distribution not computed."); } }
ERP ERPTier_extractERP (ERPTier me, long eventNumber) { try { long numberOfEvents = my events -> size; if (numberOfEvents < 1) Melder_throw ("No events."); ERPTier_checkEventNumber (me, eventNumber); ERPPoint event = my event (eventNumber); long numberOfChannels = event -> erp -> ny; long numberOfSamples = event -> erp -> nx; autoERP thee = Thing_new (ERP); event -> erp -> structSound :: v_copy (thee.peek()); for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { double *oldChannel = event -> erp -> z [ichannel]; double *newChannel = thy z [ichannel]; for (long isample = 1; isample <= numberOfSamples; isample ++) { newChannel [isample] = oldChannel [isample]; } } thy channelNames = NUMvector <wchar_t *> (1, thy ny); for (long ichan = 1; ichan <= thy ny; ichan ++) { thy channelNames [ichan] = Melder_wcsdup (my channelNames [ichan]); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": ERP not extracted."); } }
Strings Strings_readFromRawTextFile (MelderFile file) { try { autoMelderReadText text = MelderReadText_createFromFile (file); /* * Count number of strings. */ long n = MelderReadText_getNumberOfLines (text.peek()); /* * Create. */ autoStrings me = Thing_new (Strings); if (n > 0) my strings = NUMvector <wchar_t *> (1, n); my numberOfStrings = n; /* * Read strings. */ for (long i = 1; i <= n; i ++) { wchar_t *line = MelderReadText_readLine (text.peek()); my strings [i] = Melder_wcsdup (line); } return me.transfer(); } catch (MelderError) { Melder_throw ("Strings not read from raw text file ", file, "."); } }
static void copyRow (TableOfReal me, long myRow, TableOfReal thee, long thyRow) { Melder_assert (me != thee); Melder_assert (my numberOfColumns == thy numberOfColumns); thy rowLabels [thyRow] = Melder_wcsdup (my rowLabels [myRow]); for (long icol = 1; icol <= my numberOfColumns; icol ++) { thy data [thyRow] [icol] = my data [myRow] [icol]; } }
static void copyColumn (TableOfReal me, long myCol, TableOfReal thee, long thyCol) { Melder_assert (me != thee); Melder_assert (my numberOfRows == thy numberOfRows); thy columnLabels [thyCol] = Melder_wcsdup (my columnLabels [myCol]); for (long irow = 1; irow <= my numberOfRows; irow ++) { thy data [irow] [thyCol] = my data [irow] [myCol]; } }
EditDistanceTable EditDistanceTable_create (Strings target, Strings source) { try { autoEditDistanceTable me = Thing_new (EditDistanceTable); long nsources = source -> numberOfStrings, ntargets = target -> numberOfStrings; TableOfReal_init (me.peek(), ntargets + 1, nsources + 1); TableOfReal_setColumnLabel (me.peek(), 1, L""); for (long j = 1; j <= nsources; j++) { my columnLabels[j + 1] = Melder_wcsdup (source -> strings[j]); } TableOfReal_setRowLabel (me.peek(), 1, L""); for (long i = 1; i <= ntargets; i++) { my rowLabels[i + 1] = Melder_wcsdup (target -> strings[i]); } my d_warpingPath = WarpingPath_create (ntargets + nsources + 1); my d_editCostsTable = EditCostsTable_createDefault (); EditDistanceTable_findPath (me.peek(), 0); return me.transfer(); } catch (MelderError) { Melder_throw ("EditDistanceTable not created."); } }
void TableOfReal_setColumnLabel (TableOfReal me, long columnNumber, const wchar_t *label) { try { if (columnNumber < 1 || columnNumber > my numberOfColumns) return; autostring newLabel = Melder_wcsdup (label); /* * Change without error. */ Melder_free (my columnLabels [columnNumber]); my columnLabels [columnNumber] = newLabel.transfer(); } catch (MelderError) { Melder_throw (me, ": label of column ", columnNumber, " not set."); } }
void TableOfReal_setRowLabel (TableOfReal me, long rowNumber, const wchar_t *label) { try { if (rowNumber < 1 || rowNumber > my numberOfRows) return; autostring newLabel = Melder_wcsdup (label); /* * Change without error. */ Melder_free (my rowLabels [rowNumber]); my rowLabels [rowNumber] = newLabel.transfer(); } catch (MelderError) { Melder_throw (me, ": label of row ", rowNumber, " not set."); } }
Strings TableOfReal_extractRowLabelsAsStrings (TableOfReal me) { try { autoStrings thee = Thing_new (Strings); thy strings = NUMvector <wchar_t *> (1, my numberOfRows); thy numberOfStrings = my numberOfRows; for (long irow = 1; irow <= my numberOfRows; irow ++) { thy strings [irow] = Melder_wcsdup (my rowLabels [irow] ? my rowLabels [irow] : L""); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": row labels not extracted."); } }
Strings TableOfReal_extractColumnLabelsAsStrings (TableOfReal me) { try { autoStrings thee = Thing_new (Strings); thy strings = NUMvector <wchar_t *> (1, my numberOfColumns); thy numberOfStrings = my numberOfColumns; for (long icol = 1; icol <= my numberOfColumns; icol ++) { thy strings [icol] = Melder_wcsdup (my columnLabels [icol] ? my columnLabels [icol] : L""); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": column labels not extracted."); } }
void Regression_addParameter (I, const wchar *label, double minimum, double maximum, double value) { iam (Regression); try { autoRegressionParameter thee = Thing_new (RegressionParameter); thy label = Melder_wcsdup (label); thy minimum = minimum; thy maximum = maximum; thy value = value; Collection_addItem (my parameters, thee.transfer()); } catch (MelderError) { Melder_throw (me, ": parameter not added."); } }
Table TableOfReal_to_Table (TableOfReal me, const wchar_t *labelOfFirstColumn) { try { autoTable thee = Table_createWithoutColumnNames (my numberOfRows, my numberOfColumns + 1); Table_setColumnLabel (thee.peek(), 1, labelOfFirstColumn); for (long icol = 1; icol <= my numberOfColumns; icol ++) { wchar_t *columnLabel = my columnLabels [icol]; thy columnHeaders [icol + 1]. label = Melder_wcsdup (columnLabel && columnLabel [0] ? columnLabel : L"?"); } for (long irow = 1; irow <= thy rows -> size; irow ++) { wchar_t *stringValue = my rowLabels [irow]; TableRow row = static_cast <TableRow> (thy rows -> item [irow]); row -> cells [1]. string = Melder_wcsdup (stringValue && stringValue [0] ? stringValue : L"?"); for (long icol = 1; icol <= my numberOfColumns; icol ++) { double numericValue = my data [irow] [icol]; row -> cells [icol + 1]. string = Melder_wcsdup (Melder_double (numericValue)); } } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not converted to Table."); } }
void structScriptEditor :: init (Editor environment, const wchar_t *initialText) { if (environment != NULL) { environmentName = Melder_wcsdup (environment -> name); editorClass = environment -> classInfo; } structTextEditor::init (initialText); interpreter = Interpreter_createFromEnvironment (environment); if (theScriptEditors == NULL) { theScriptEditors = Collection_create (NULL, 10); Collection_dontOwnItems (theScriptEditors); } Collection_addItem (theScriptEditors, this); }
Strings Distributions_to_Strings (Distributions me, long column, long numberOfStrings) { try { autoStrings thee = Thing_new (Strings); thy numberOfStrings = numberOfStrings; thy strings = NUMvector <wchar*> (1, numberOfStrings); for (long istring = 1; istring <= numberOfStrings; istring ++) { wchar *string; Distributions_peek (me, column, & string); thy strings [istring] = Melder_wcsdup (string); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": Strings not generated."); } }
static void OTGrammarCandidate_init (OTGrammarCandidate me, int ncons, int v1, int v2) { wchar_t buffer [100]; swprintf (buffer, 100, L"%lst%ls", vowels [v1], vowels [v2]); my output = Melder_wcsdup (buffer); my marks = NUMvector <int> (1, my numberOfConstraints = ncons); /* * Count vowel-gesture violations. */ countVowelViolations (my marks, ncons, v1); countVowelViolations (my marks, ncons, v2); /* * Count contour-gesture violations. */ if (isatr (v1) != isatr (v2)) my marks [5] ++; }
static EEG EEG_copyWithoutSound (EEG me) { try { autoEEG thee = EEG_create (my xmin, my xmax); thy d_numberOfChannels = my d_numberOfChannels; thy d_textgrid = (TextGrid) Data_copy (my d_textgrid); autostringvector channelNames (1, my d_numberOfChannels); for (long i = 1; i <= my d_numberOfChannels; i++) { channelNames[i] = Melder_wcsdup (my d_channelNames[i]); } thy d_channelNames = channelNames.transfer(); return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not copied."); } }
static void fillTableau (OTGrammarTableau me, long numberOfSyllables, int underlyingWeightPattern [], int overtFormsHaveSecondaryStress, int includeCodas) { wchar_t input [100]; static int numberOfCandidates_noCodas [1+7] = { 0, 1, 6, 24, 88, 300, 984, 3136 }; static int numberOfCandidates_codas [1+7] = { 0, 1, 24, 192, 1408, 9600, 984, 3136 }; wcscpy (input, L"|"); for (long isyll = 1; isyll <= numberOfSyllables; isyll ++) { static const wchar_t *syllable_noCodas [] = { L"", L"L", L"H" }; static const wchar_t *syllable_codas [] = { L"", L"cv", L"cv:", L"cvc" }; if (isyll > 1) wcscat (input, includeCodas ? L"." : L" "); wcscat (input, ( includeCodas ? syllable_codas : syllable_noCodas ) [underlyingWeightPattern [isyll]]); } wcscat (input, L"|"); my input = Melder_wcsdup (input); my candidates = NUMvector <structOTGrammarCandidate> (1, ( includeCodas ? numberOfCandidates_codas : numberOfCandidates_noCodas ) [numberOfSyllables]); for (long mainStressed = 1; mainStressed <= numberOfSyllables; mainStressed ++) { int stress [10]; stress [mainStressed] = 1; for (int secondary1 = FALSE; secondary1 <= TRUE; secondary1 ++) { stress [mainStressed <= 1 ? 2 : 1] = secondary1 ? 2 : 0; if (numberOfSyllables == 2) { fillOvertStressPattern (me, 2, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress); } else for (int secondary2 = FALSE; secondary2 <= TRUE; secondary2 ++) { stress [mainStressed <= 2 ? 3 : 2] = secondary2 ? 2 : 0; if (numberOfSyllables == 3) { fillOvertStressPattern (me, 3, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress); } else for (int secondary3 = FALSE; secondary3 <= TRUE; secondary3 ++) { stress [mainStressed <= 3 ? 4 : 3] = secondary3 ? 2 : 0; if (numberOfSyllables == 4) { fillOvertStressPattern (me, 4, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress); } else for (int secondary4 = FALSE; secondary4 <= TRUE; secondary4 ++) { stress [mainStressed <= 4 ? 5 : 4] = secondary4 ? 2 : 0; if (numberOfSyllables == 5) { fillOvertStressPattern (me, 5, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress); } else for (int secondary5 = FALSE; secondary5 <= TRUE; secondary5 ++) { stress [mainStressed <= 5 ? 6 : 5] = secondary5 ? 2 : 0; if (numberOfSyllables == 6) { fillOvertStressPattern (me, 6, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress); } else for (int secondary6 = FALSE; secondary6 <= TRUE; secondary6 ++) { stress [mainStressed <= 6 ? 7 : 6] = secondary6 ? 2 : 0; fillOvertStressPattern (me, 7, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress); } } } } } } } }
static ERPTier EEG_PointProcess_to_ERPTier (EEG me, PointProcess events, double fromTime, double toTime) { try { autoERPTier thee = Thing_new (ERPTier); Function_init (thee.peek(), fromTime, toTime); thy numberOfChannels = my numberOfChannels - EEG_getNumberOfExtraSensors (me); Melder_assert (thy numberOfChannels > 0); thy channelNames = NUMvector <wchar_t *> (1, thy numberOfChannels); for (long ichan = 1; ichan <= thy numberOfChannels; ichan ++) { thy channelNames [ichan] = Melder_wcsdup (my channelNames [ichan]); } long numberOfEvents = events -> nt; thy events = SortedSetOfDouble_create (); double soundDuration = toTime - fromTime; double samplingPeriod = my sound -> dx; long numberOfSamples = floor (soundDuration / samplingPeriod) + 1; if (numberOfSamples < 1) Melder_throw (L"Time window too short."); double midTime = 0.5 * (fromTime + toTime); double soundPhysicalDuration = numberOfSamples * samplingPeriod; double firstTime = midTime - 0.5 * soundPhysicalDuration + 0.5 * samplingPeriod; // distribute the samples evenly over the time domain for (long ievent = 1; ievent <= numberOfEvents; ievent ++) { double eegEventTime = events -> t [ievent]; autoERPPoint event = Thing_new (ERPPoint); event -> number = eegEventTime; event -> erp = Sound_create (thy numberOfChannels, fromTime, toTime, numberOfSamples, samplingPeriod, firstTime); double erpEventTime = 0.0; double eegSample = 1 + (eegEventTime - my sound -> x1) / samplingPeriod; double erpSample = 1 + (erpEventTime - firstTime) / samplingPeriod; long sampleDifference = round (eegSample - erpSample); for (long ichannel = 1; ichannel <= thy numberOfChannels; ichannel ++) { for (long isample = 1; isample <= numberOfSamples; isample ++) { long jsample = isample + sampleDifference; event -> erp -> z [ichannel] [isample] = jsample < 1 || jsample > my sound -> nx ? 0.0 : my sound -> z [ichannel] [jsample]; } } Collection_addItem (thy events, event.transfer()); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": ERP analysis not performed."); } }
static void addCandidate (OTGrammarTableau me, long numberOfSyllables, int stress [], int footedToTheLeft [], int footedToTheRight [], int surfaceWeightPattern [], int overtFormsHaveSecondaryStress) { static const wchar_t *syllable [] = { L"L", L"L1", L"L2", L"H", L"H1", L"H2", L"K", L"K1", L"K2", L"J", L"J1", L"J2" }; static const wchar_t *syllableWithoutSecondaryStress [] = { L"L", L"L1", L"L", L"H", L"H1", L"H", L"K", L"K1", L"K", L"J", L"J1", L"J" }; wchar_t output [100]; wcscpy (output, L"["); for (long isyll = 1; isyll <= numberOfSyllables; isyll ++) { if (isyll > 1) wcscat (output, L" "); wcscat (output, ( overtFormsHaveSecondaryStress ? syllable : syllableWithoutSecondaryStress ) [stress [isyll] + 3 * (surfaceWeightPattern [isyll] - 1)]); } wcscat (output, L"] \\-> /"); for (long isyll = 1; isyll <= numberOfSyllables; isyll ++) { if (isyll > 1) wcscat (output, L" "); if (footedToTheRight [isyll] || (! footedToTheLeft [isyll] && stress [isyll] != 0)) wcscat (output, L"("); wcscat (output, syllable [stress [isyll] + 3 * (surfaceWeightPattern [isyll] - 1)]); if (footedToTheLeft [isyll] || (! footedToTheRight [isyll] && stress [isyll] != 0)) wcscat (output, L")"); } wcscat (output, L"/"); my candidates [++ my numberOfCandidates]. output = Melder_wcsdup (output); }
Strings Distributions_to_Strings_exact (Distributions me, long column) { try { long total = 0; long istring = 0; if (column > my numberOfColumns) Melder_throw ("No column ", column, "."); if (my numberOfRows < 1) Melder_throw ("No candidates."); for (long irow = 1; irow <= my numberOfRows; irow ++) { double value = my data [irow] [column]; if (value != floor (value)) Melder_throw ("Non-integer value ", value, " in row ", irow, "."); if (value < 0.0) Melder_throw ("Found a negative value ", value, " in row ", irow, "."); total += value; } if (total <= 0) Melder_throw ("Column total not positive."); autoStrings thee = Thing_new (Strings); thy numberOfStrings = total; thy strings = NUMvector <wchar*> (1, total); for (long irow = 1; irow <= my numberOfRows; irow ++) { long number = my data [irow] [column]; wchar *string = my rowLabels [irow]; if (! string) Melder_throw ("No string in row ", irow, "."); for (long i = 1; i <= number; i ++) { thy strings [++ istring] = Melder_wcsdup (string); } } Strings_randomize (thee.peek()); return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": Strings not generated."); } }
ERP ERPTier_to_ERP_mean (ERPTier me) { try { long numberOfEvents = my events -> size; if (numberOfEvents < 1) Melder_throw ("No events."); ERPPoint firstEvent = my event (1); long numberOfChannels = firstEvent -> erp -> ny; long numberOfSamples = firstEvent -> erp -> nx; autoERP mean = Thing_new (ERP); firstEvent -> erp -> structSound :: v_copy (mean.peek()); for (long ievent = 2; ievent <= numberOfEvents; ievent ++) { ERPPoint event = my event (ievent); for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { double *erpChannel = event -> erp -> z [ichannel]; double *meanChannel = mean -> z [ichannel]; for (long isample = 1; isample <= numberOfSamples; isample ++) { meanChannel [isample] += erpChannel [isample]; } } } double factor = 1.0 / numberOfEvents; for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { double *meanChannel = mean -> z [ichannel]; for (long isample = 1; isample <= numberOfSamples; isample ++) { meanChannel [isample] *= factor; } } mean -> channelNames = NUMvector <wchar_t *> (1, mean -> ny); for (long ichan = 1; ichan <= mean -> ny; ichan ++) { mean -> channelNames [ichan] = Melder_wcsdup (my channelNames [ichan]); } return mean.transfer(); } catch (MelderError) { Melder_throw (me, ": mean not computed."); } }