Strings espeakdata_voices_getNames (Table me, long column) { try { if (column < 0 || column > 2) { Melder_throw (U"Illegal columnn."); } autoStrings thee = Thing_new (Strings); thy strings = NUMvector <char32 *> (1, my rows -> size); thy numberOfStrings = 0; for (long irow = 1; irow <= my rows -> size; irow++) { thy strings[irow] = Melder_dup (Table_getStringValue_Assert (me, irow, column)); thy numberOfStrings++; } return thee.transfer(); } catch (MelderError) { Melder_throw (U"Espeakdata: voices not initialized."); } }
void structTableEditor :: v_draw () { Table table = static_cast<Table> (data); double spacing = 2.0; // millimetres at both edges double columnWidth, cellWidth; /* * We fit 200 rows in 40 inches, which is 14.4 points per row. */ long rowmin = topRow, rowmax = rowmin + 197; long colmin = leftColumn, colmax = colmin + (kTableEditor_MAXNUM_VISIBLE_COLUMNS - 1); if (rowmax > table -> rows.size) rowmax = table -> rows.size; if (colmax > table -> numberOfColumns) colmax = table -> numberOfColumns; Graphics_clearWs (graphics.get()); Graphics_setTextAlignment (graphics.get(), Graphics_CENTRE, Graphics_HALF); Graphics_setWindow (graphics.get(), 0.0, 1.0, rowmin + 197.5, rowmin - 2.5); Graphics_setColour (graphics.get(), Graphics_SILVER); Graphics_fillRectangle (graphics.get(), 0.0, 1.0, rowmin - 2.5, rowmin - 0.5); Graphics_setColour (graphics.get(), Graphics_BLACK); Graphics_line (graphics.get(), 0.0, rowmin - 0.5, 1.0, rowmin - 0.5); Graphics_setWindow (graphics.get(), 0.0, Graphics_dxWCtoMM (graphics.get(), 1.0), rowmin + 197.5, rowmin - 2.5); /* * Determine the width of the column with the row numbers. */ columnWidth = Graphics_textWidth (graphics.get(), U"row"); for (long irow = rowmin; irow <= rowmax; irow ++) { cellWidth = Graphics_textWidth (graphics.get(), Melder_integer (irow)); if (cellWidth > columnWidth) columnWidth = cellWidth; } columnLeft [0] = columnWidth + 2 * spacing; Graphics_setColour (graphics.get(), Graphics_SILVER); Graphics_fillRectangle (graphics.get(), 0.0, columnLeft [0], rowmin - 0.5, rowmin + 197.5); Graphics_setColour (graphics.get(), Graphics_BLACK); Graphics_line (graphics.get(), columnLeft [0], rowmin - 0.5, columnLeft [0], rowmin + 197.5); /* * Determine the width of the columns. */ for (long icol = colmin; icol <= colmax; icol ++) { const char32 *columnLabel = table -> columnHeaders [icol]. label; columnWidth = Graphics_textWidth (graphics.get(), Melder_integer (icol)); if (! columnLabel) columnLabel = U""; cellWidth = Graphics_textWidth (graphics.get(), columnLabel); if (cellWidth > columnWidth) columnWidth = cellWidth; for (long irow = rowmin; irow <= rowmax; irow ++) { const char32 *cell = Table_getStringValue_Assert (table, irow, icol); Melder_assert (cell); if (cell [0] == U'\0') cell = U"?"; cellWidth = Graphics_textWidth (graphics.get(), cell); if (cellWidth > columnWidth) columnWidth = cellWidth; } columnRight [icol - colmin] = columnLeft [icol - colmin] + columnWidth + 2 * spacing; if (icol < colmax) columnLeft [icol - colmin + 1] = columnRight [icol - colmin]; } /* Text can be "graphic" or not. */ Graphics_setPercentSignIsItalic (our graphics.get(), our p_useTextStyles); Graphics_setNumberSignIsBold (our graphics.get(), our p_useTextStyles); Graphics_setCircumflexIsSuperscript (our graphics.get(), our p_useTextStyles); Graphics_setUnderscoreIsSubscript (our graphics.get(), our p_useTextStyles); /* * Show the row numbers. */ Graphics_text (graphics.get(), columnLeft [0] / 2, rowmin - 1, U"row"); for (long irow = rowmin; irow <= rowmax; irow ++) { Graphics_text (graphics.get(), columnLeft [0] / 2, irow, irow); } /* * Show the column labels. */ for (long icol = colmin; icol <= colmax; icol ++) { double mid = (columnLeft [icol - colmin] + columnRight [icol - colmin]) / 2; const char32 *columnLabel = table -> columnHeaders [icol]. label; if (! columnLabel || columnLabel [0] == U'\0') columnLabel = U"?"; Graphics_text (graphics.get(), mid, rowmin - 2, icol); Graphics_text (graphics.get(), mid, rowmin - 1, columnLabel); } /* * Show the cell contents. */ for (long irow = rowmin; irow <= rowmax; irow ++) { for (long icol = colmin; icol <= colmax; icol ++) { double mid = (columnLeft [icol - colmin] + columnRight [icol - colmin]) / 2; const char32 *cell = Table_getStringValue_Assert (table, irow, icol); Melder_assert (cell); if (cell [0] == U'\0') cell = U"?"; Graphics_text (graphics.get(), mid, irow, cell); } } }
static autoTextGrid Table_to_TextGrid (Table me, const char32 *text, double xmin, double xmax) { //Table_createWithColumnNames (0, L"time type type-t t-pos length a-pos sample id uniq"); try { long length, textLength = str32len (text); long numberOfRows = my rows.size; long timeColumnIndex = Table_getColumnIndexFromColumnLabel (me, U"time"); long typeColumnIndex = Table_getColumnIndexFromColumnLabel (me, U"type"); long tposColumnIndex = Table_getColumnIndexFromColumnLabel (me, U"t-pos"); long idColumnIndex = Table_getColumnIndexFromColumnLabel (me, U"id"); autoTextGrid thee = TextGrid_create (xmin, xmax, U"sentence clause word phoneme", U""); TextGrid_setIntervalText (thee.get(), 1, 1, text); long p1c = 1, p1w = 1; double time_phon_p = xmin; bool wordEnd = false; autoMelderString mark; IntervalTier clauses = (IntervalTier) thy tiers->at [2]; IntervalTier words = (IntervalTier) thy tiers->at [3]; IntervalTier phonemes = (IntervalTier) thy tiers->at [4]; for (long i = 1; i <= numberOfRows; i++) { double time = Table_getNumericValue_Assert (me, i, timeColumnIndex); int type = Table_getNumericValue_Assert (me, i, typeColumnIndex); long pos = Table_getNumericValue_Assert (me, i, tposColumnIndex); if (type == espeakEVENT_SENTENCE) { // Only insert a new boundary, no text // text will be inserted at end sentence event if (time > xmin && time < xmax) { IntervalTier_addBoundaryUnsorted (clauses, clauses -> intervals.size, time, U"", true); } p1c = pos; } else if (type == espeakEVENT_END) { // End of clause: insert new boundary, and fill left interval with text length = pos - p1c + 1; MelderString_ncopy (&mark, text + p1c - 1, length); MelderString_trimWhiteSpaceAtEnd (& mark); if (time > xmin && time < xmax) { IntervalTier_addBoundaryUnsorted (clauses, clauses -> intervals.size, time, mark.string, true); } else { TextGrid_setIntervalText (thee.get(), 2, clauses -> intervals.size, mark.string); } p1c = pos; // End of clause always signals "end of a word" if (pos <= textLength) { length = pos - p1w + 1; MelderString_ncopy (&mark, text + p1w - 1, length); MelderString_trimWhiteSpaceAtEnd (& mark); if (time > xmin && time < xmax) { IntervalTier_addBoundaryUnsorted (words, words -> intervals.size, time, mark.string, true); } else { TextGrid_setIntervalText (thee.get(), 3, words -> intervals.size, mark.string); } // now the next word event should not trigger setting the left interval text wordEnd = false; } } else if (type == espeakEVENT_WORD) { if (pos < p1w) { continue; } if (time > xmin && time < xmax) { length = pos - p1w; if (pos == textLength) { length++; } MelderString_ncopy (&mark, text + p1w - 1, length); MelderString_trimWhiteSpaceAtEnd (& mark); IntervalTier_addBoundaryUnsorted (words, words -> intervals.size, time, ( wordEnd ? mark.string : U"" ), true); } wordEnd = true; p1w = pos; } else if (type == espeakEVENT_PHONEME) { const char32 *id = Table_getStringValue_Assert (me, i, idColumnIndex); if (time > time_phon_p) { // Insert new boudary and label interval with the id // TODO: Translate the id to the correct notation TextInterval ti = phonemes -> intervals.at [phonemes -> intervals.size]; if (time > ti -> xmin && time < ti -> xmax) { IntervalTier_addBoundaryUnsorted (phonemes, phonemes -> intervals.size, time, id, false); } } else { // Just in case the phoneme starts at xmin we only need to set interval text TextGrid_setIntervalText (thee.get(), 4, phonemes -> intervals.size, id); } time_phon_p = time; } } clauses -> intervals. sort (); words -> intervals. sort (); phonemes -> intervals. sort (); IntervalTier_mergeSpecialIntervals (phonemes); // Merge neighbouring empty U"" and U"\001" intervals IntervalTier_removeVeryShortIntervals (words); IntervalTier_removeVeryShortIntervals (clauses); /* Use empty intervals in phoneme tier for more precision in the word tier */ IntervalTier_insertEmptyIntervalsFromOtherTier (words, phonemes); IntervalTier_mergeSpecialIntervals (words); // Merge neighbouring empty U"" and U"\001" intervals return thee; } catch (MelderError) { Melder_throw (U"TextGrid not created from Table with events."); } }
static autoTextGrid Table_to_TextGrid (Table me, const char32 *text, double xmin, double xmax) { //Table_createWithColumnNames (0, L"time type type-t t-pos length a-pos sample id uniq"); try { long length, textLength = str32len (text); long numberOfRows = my rows -> size; long timeColumnIndex = Table_getColumnIndexFromColumnLabel (me, U"time"); long typeColumnIndex = Table_getColumnIndexFromColumnLabel (me, U"type"); long tposColumnIndex = Table_getColumnIndexFromColumnLabel (me, U"t-pos"); long idColumnIndex = Table_getColumnIndexFromColumnLabel (me, U"id"); autoTextGrid thee = TextGrid_create (xmin, xmax, U"sentence clause word phoneme", U""); TextGrid_setIntervalText (thee.peek(), 1, 1, text); long p1c = 1, p1w = 1; double t1p = xmin; bool wordEnd = false; autoMelderString mark; IntervalTier itc = (IntervalTier) thy tiers -> item[2]; IntervalTier itw = (IntervalTier) thy tiers -> item[3]; IntervalTier itp = (IntervalTier) thy tiers -> item[4]; for (long i = 1; i <= numberOfRows; i++) { double time = Table_getNumericValue_Assert (me, i, timeColumnIndex); int type = Table_getNumericValue_Assert (me, i, typeColumnIndex); long pos = Table_getNumericValue_Assert (me, i, tposColumnIndex); if (type == espeakEVENT_SENTENCE) { // Only insert a new boundary, no text // text will be inserted at end sentence event if (time > xmin and time < xmax) { IntervalTier_addBoundaryUnsorted (itc, itc -> intervals -> size, time, U"", true); } p1c = pos; } else if (type == espeakEVENT_END) { // End of clause: insert new boundary, and fill left interval with text length = pos - p1c + 1; MelderString_ncopy (&mark, text + p1c - 1, length); MelderString_trimWhiteSpaceAtEnd (&mark); if (time > xmin and time < xmax) { IntervalTier_addBoundaryUnsorted (itc, itc -> intervals -> size, time, mark.string, true); } else { TextGrid_setIntervalText (thee.peek(), 2, itc -> intervals -> size, mark.string); } p1c = pos; // End of clause always signals "end of a word" if (pos <= textLength) { length = pos - p1w + 1; MelderString_ncopy (&mark, text + p1w - 1, length); MelderString_trimWhiteSpaceAtEnd (&mark); if (time > xmin and time < xmax) { IntervalTier_addBoundaryUnsorted (itw, itw -> intervals -> size, time, mark.string, true); } else { TextGrid_setIntervalText (thee.peek(), 3, itw -> intervals -> size, mark.string); } // now the next word event should not trigger setting the left interval text wordEnd = false; } } else if (type == espeakEVENT_WORD) { if (pos < p1w) { continue; } if (time > xmin and time < xmax) { length = pos - p1w; if (pos == textLength) length++; MelderString_ncopy (&mark, text + p1w - 1, length); MelderString_trimWhiteSpaceAtEnd (&mark); IntervalTier_addBoundaryUnsorted (itw, itw -> intervals -> size, time, (wordEnd ? mark.string : U""), true); } wordEnd = true; p1w = pos; } else if (type == espeakEVENT_PHONEME) { const char32 *id = Table_getStringValue_Assert (me, i, idColumnIndex); if (time > t1p) { // Insert new boudary and label interval with the id // TODO: Translate the id to the correct notation TextInterval ti = (TextInterval) itp -> intervals -> item[itp -> intervals -> size]; if (time > ti -> xmin and time < ti -> xmax) { IntervalTier_addBoundaryUnsorted (itp, itp -> intervals -> size, time, id, false); } } else { // Just in case the phoneme starts at xmin we only need to set interval text TextGrid_setIntervalText (thee.peek(), 4, itp -> intervals -> size, id); } t1p = time; } } Sorted_sort (itc -> intervals); Sorted_sort (itw -> intervals); Sorted_sort (itp -> intervals); return thee; } catch (MelderError) { Melder_throw (U"TextGrid not created from Table with events."); } }