static void espeakdata_SetVoiceByName (const char *name, const char *variantName) { espeak_VOICE voice_selector; memset (& voice_selector, 0, sizeof voice_selector); voice_selector.name = Melder_peek32to8 (Melder_cat (Melder_peek8to32 (name), U"+", Melder_peek8to32 (variantName))); // include variant name in voice stack ?? if (LoadVoice (name, 1)) { LoadVoice (variantName, 2); DoVoiceChange (voice); SetVoiceStack (& voice_selector, variantName); } }
char32 * Melder_getenv (const char32 *variableName) { #if defined (macintosh) || defined (UNIX) || defined (__MINGW32__) || defined (__CYGWIN__) return Melder_peek8to32 (getenv (Melder_peek32to8 (variableName))); #elif defined (_WIN32) static char32 buffer [11] [255]; static int ibuffer = 0; if (++ ibuffer == 11) ibuffer = 0; long n = GetEnvironmentVariableW (variableName, buffer [ibuffer], 255); BUG if (n == ERROR_ENVVAR_NOT_FOUND) return nullptr; return & buffer [ibuffer] [0]; #else return nullptr; #endif }
Graphics Graphics_create_postscriptjob (MelderFile file, int resolution, enum kGraphicsPostscript_spots spots, enum kGraphicsPostscript_paperSize paperSize, enum kGraphicsPostscript_orientation rotation, double magnification) { autoGraphicsPostscript me = Thing_new (GraphicsPostscript); time_t today; my postScript = true, my yIsZeroAtTheTop = false, my languageLevel = 2; my job = true, my eps = false, my printer = false; my d_printf = (int (*)(void *, const char*, ...)) fprintf; Graphics_init (me.peek(), resolution); // virtual resolution; may differ from that of the printer; OK if always 600 dpi my photocopyable = spots == kGraphicsPostscript_spots_PHOTOCOPYABLE; if (my photocopyable) { my spotsDensity = 85; my spotsAngle = 35; } else { my spotsDensity = 106; my spotsAngle = 46; } if (paperSize == kGraphicsPostscript_paperSize_A3) my paperWidth = 842 / 72.0, my paperHeight = 1191 / 72.0; else if (paperSize == kGraphicsPostscript_paperSize_US_LETTER) my paperWidth = 612 / 72.0, my paperHeight = 792 / 72.0; else my paperWidth = 595 / 72.0, my paperHeight = 842 / 72.0; my landscape = rotation == kGraphicsPostscript_orientation_LANDSCAPE; my magnification = magnification; my includeFonts = true; my d_file = Melder_fopen (file, "w"); /* * The Device Coordinates are the PostScript user coordinates. * They are chosen in such a way that a distance of 1 in device coordinates * equals one dot if the printer's resolution is 'resolution' dots per inch. * Take a sensible default margin: half an inch on all sides. */ my d_x1DC = my d_x1DCmin = resolution / 2; my d_x2DC = my d_x2DCmax = (my paperWidth - 0.5) * resolution; my d_y1DC = my d_y1DCmin = resolution / 2; my d_y2DC = my d_y2DCmax = (my paperHeight - 0.5) * resolution; /* * Now don't just set x1wNDC etc, but force computation of the scaling as well. */ Graphics_setWsWindow ((Graphics) me.peek(), 0, my paperWidth - 1.0, 13.0 - my paperHeight, 12.0); /* * We will adhere to version 3.0 of the Document Structuring Conventions for print jobs. */ my d_printf (my d_file, "%%!PS-Adobe-3.0\n"); my d_printf (my d_file, "%%%%Creator: Praat Shell 4.2\n"); my d_printf (my d_file, "%%%%Title: %s\n", Melder_peek32to8 (MelderFile_name (file))); today = time (nullptr); my d_printf (my d_file, "%%%%CreationDate: %s", ctime (& today)); // contains newline symbol my d_printf (my d_file, "%%%%PageOrder: Special\n"); my d_printf (my d_file, "%%%%Pages: (atend)\n"); my d_printf (my d_file, "%%%%EndComments\n"); downloadPrologAndSetUp (me.peek()); initPage (me.peek()); return (Graphics) me.transfer(); }
void Melder_system (const char32 *command) { if (! command) command = U""; #if defined (macintosh) || defined (UNIX) if (system (Melder_peek32to8 (command)) != 0) Melder_throw (U"System command failed."); #elif defined (_WIN32) STARTUPINFO siStartInfo; PROCESS_INFORMATION piProcInfo; char32 *comspec = Melder_getenv (U"COMSPEC"); // e.g. "C:\WINDOWS\COMMAND.COM" or "C:\WINNT\windows32\cmd.exe" if (! comspec) { comspec = Melder_getenv (U"ComSpec"); } autoMelderString buffer; if (comspec) { MelderString_copy (& buffer, comspec); } else { OSVERSIONINFOEX osVersionInfo; memset (& osVersionInfo, 0, sizeof (OSVERSIONINFOEX)); osVersionInfo. dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); if (! GetVersionEx ((OSVERSIONINFO *) & osVersionInfo)) { osVersionInfo. dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (! GetVersionEx ((OSVERSIONINFO *) & osVersionInfo)) Melder_throw (U"System command cannot find system version."); } switch (osVersionInfo. dwPlatformId) { case VER_PLATFORM_WIN32_NT: { MelderString_copy (& buffer, U"cmd.exe"); } break; case VER_PLATFORM_WIN32_WINDOWS: { MelderString_copy (& buffer, U"command.com"); } break; default: { MelderString_copy (& buffer, U"command.com"); } } } MelderString_append (& buffer, U" /c ", command); memset (& siStartInfo, 0, sizeof (siStartInfo)); siStartInfo. cb = sizeof (siStartInfo); if (! CreateProcess (nullptr, Melder_peek32toW (buffer.string), nullptr, nullptr, true, CREATE_NO_WINDOW, nullptr, nullptr, & siStartInfo, & piProcInfo)) Melder_throw (U"Cannot create subprocess."); WaitForSingleObject (piProcInfo. hProcess, -1); CloseHandle (piProcInfo. hProcess); CloseHandle (piProcInfo. hThread); #endif }
/* BSD systems provide ftruncate, several others supply chsize, and a few may provide a (possibly undocumented) fcntl option F_FREESP. Under MS-DOS, you can sometimes use write(fd, "", 0). However, there is no portable solution, nor a way to delete blocks at the beginning. */ static void MelderFile_truncate (MelderFile me, long size) { #if defined(_WIN32) HANDLE hFile; DWORD fdwAccess = GENERIC_READ | GENERIC_WRITE, fPos; DWORD fdwShareMode = 0; /* File cannot be shared */ LPSECURITY_ATTRIBUTES lpsa = nullptr; DWORD fdwCreate = OPEN_EXISTING; LARGE_INTEGER fileSize; MelderFile_close (me); hFile = CreateFileW (Melder_peek32toW (my path), fdwAccess, fdwShareMode, lpsa, fdwCreate, FILE_ATTRIBUTE_NORMAL, nullptr); if (hFile == INVALID_HANDLE_VALUE) { Melder_throw (U"Can't open file ", me, U"."); } // Set current file pointer to position 'size' fileSize.LowPart = size; fileSize.HighPart = 0; /* Limit the file size to 2^32 - 2 bytes */ fPos = SetFilePointer (hFile, fileSize.LowPart, &fileSize.HighPart, FILE_BEGIN); if (fPos == 0xFFFFFFFF) { Melder_throw (U"Can't set the position at size ", size, U"for file ", me, U"."); } // Limit the file size as the current position of the file pointer. SetEndOfFile (hFile); CloseHandle (hFile); #elif defined(linux) || defined(macintosh) MelderFile_close (me); if (truncate (Melder_peek32to8 (my path), size) == -1) Melder_throw (U"Truncating failed for file ", MelderFile_messageName (me), U" (", Melder_peek8to32 (strerror (errno)), U")."); #else Melder_throw (U"Don't know what to do."); #endif }
static void testData (Daata data) { fprintf (stderr, "testData: %p %s\n", data, Melder_peek32to8 (data -> name)); }
TextGrid TextGrid_readFromTIMITLabelFile (MelderFile file, int phnFile) { try { double dt = 1.0 / 16000; /* 1 / (TIMIT samplingFrequency) */ double xmax = dt; autofile f = Melder_fopen (file, "r"); // Ending time will only be known after all labels have been read. // We start with a sufficiently long duration (one hour) and correct this later. autoTextGrid me = TextGrid_create (0, 3600, U"wrd", 0); IntervalTier timit = (IntervalTier) my tiers -> item[1]; long linesRead = 0; char line[200], label[200]; while (fgets (line, 199, f)) { long it1, it2; linesRead++; if (sscanf (line, "%ld%ld%s", &it1, &it2, label) != 3) { Melder_throw (U"Incorrect number of items."); } if (it1 < 0 || it2 <= it1) { Melder_throw (U"Incorrect time at line ", linesRead); } xmax = it2 * dt; double xmin = it1 * dt; long ni = timit -> intervals -> size - 1; if (ni < 1) { ni = 1; // Some files do not start with a first line "0 <number2> h#". // Instead they start with "<number1> <number2> h#", where number1 > 0. // We override number1 with 0. */ if (xmin > 0 && phnFile) { xmin = 0; } } TextInterval interval = (TextInterval) timit -> intervals -> item[ni]; if (xmin < interval -> xmax && linesRead > 1) { xmin = interval -> xmax; Melder_warning (U"File \"", MelderFile_messageName (file), U"\": Start time set to previous end " U"time for label at line ", linesRead, U"."); } // standard: new TextInterval const char *labelstring = (strncmp (label, "h#", 2) ? label : TIMIT_DELIMITER); IntervalTier_add (timit, xmin, xmax, Melder_peek8to32 (labelstring)); } // Now correct the end times, based on last read interval. // (end time was set to large value!) if (timit -> intervals -> size < 2) { Melder_throw (U"Empty TextGrid"); } Collection_removeItem (timit -> intervals, timit -> intervals -> size); TextInterval interval = (TextInterval) timit -> intervals -> item[timit -> intervals -> size]; timit -> xmax = interval -> xmax; my xmax = xmax; if (phnFile) { // Create tier 2 with IPA symbols autoIntervalTier ipa = Data_copy (timit); Thing_setName (ipa.peek(), U"ipa"); // First change the data in ipa for (long i = 1; i <= ipa -> intervals -> size; i++) { interval = (TextInterval) timit -> intervals -> item[i]; TextInterval_setText ( (TextInterval) ipa -> intervals -> item[i], Melder_peek8to32 (timitLabelToIpaLabel (Melder_peek32to8 (interval -> text)))); } Collection_addItem (my tiers, ipa.transfer()); // Then: add to collection Thing_setName (timit, U"phn"); // rename wrd } f.close (file); return me.transfer(); } catch (MelderError) { Melder_throw (U"TextGrid not read from file ", file, U"."); } }
autoSound SpeechSynthesizer_to_Sound (SpeechSynthesizer me, const char32 *text, autoTextGrid *tg, autoTable *events) { try { int fsamp = espeak_Initialize (AUDIO_OUTPUT_SYNCHRONOUS, 0, nullptr, // 5000ms espeakINITIALIZE_PHONEME_EVENTS|espeakINITIALIZE_PHONEME_IPA); if (fsamp == -1) { Melder_throw (U"Internal espeak error."); } int synth_flags = espeakCHARS_WCHAR; if (my d_inputTextFormat == SpeechSynthesizer_INPUT_TAGGEDTEXT) { synth_flags |= espeakSSML; } if (my d_inputTextFormat != SpeechSynthesizer_INPUT_TEXTONLY) { synth_flags |= espeakPHONEMES; } option_phoneme_events = espeakINITIALIZE_PHONEME_EVENTS; // extern int option_phoneme_events; if (my d_outputPhonemeCoding == SpeechSynthesizer_PHONEMECODINGS_IPA) { option_phoneme_events |= espeakINITIALIZE_PHONEME_IPA; } espeak_SetParameter (espeakRATE, my d_wordsPerMinute, 0); espeak_SetParameter (espeakPITCH, my d_pitchAdjustment, 0); espeak_SetParameter (espeakRANGE, my d_pitchRange, 0); const char32 *voiceLanguageCode = SpeechSynthesizer_getVoiceLanguageCodeFromName (me, my d_voiceLanguageName); const char32 *voiceVariantCode = SpeechSynthesizer_getVoiceVariantCodeFromName (me, my d_voiceVariantName); espeakdata_SetVoiceByName ((const char *) Melder_peek32to8 (voiceLanguageCode), (const char *) Melder_peek32to8 (voiceVariantCode)); espeak_SetParameter (espeakWORDGAP, my d_wordgap * 100, 0); // espeak wordgap is in units of 10 ms espeak_SetParameter (espeakCAPITALS, 0, 0); espeak_SetParameter (espeakPUNCTUATION, espeakPUNCT_NONE, 0); espeak_SetSynthCallback (synthCallback); my d_events = Table_createWithColumnNames (0, U"time type type-t t-pos length a-pos sample id uniq"); #ifdef _WIN32 wchar_t *textW = Melder_peek32toW (text); espeak_Synth (textW, wcslen (textW) + 1, 0, POS_CHARACTER, 0, synth_flags, nullptr, me); #else espeak_Synth (text, str32len (text) + 1, 0, POS_CHARACTER, 0, synth_flags, nullptr, me); #endif espeak_Terminate (); autoSound thee = buffer_to_Sound (my d_wav, my d_numberOfSamples, my d_internalSamplingFrequency); if (my d_samplingFrequency != my d_internalSamplingFrequency) { thee = Sound_resample (thee.get(), my d_samplingFrequency, 50); } my d_numberOfSamples = 0; // re-use the wav-buffer if (tg) { double xmin = Table_getNumericValue_Assert (my d_events.get(), 1, 1); if (xmin > thy xmin) { xmin = thy xmin; } double xmax = Table_getNumericValue_Assert (my d_events.get(), my d_events -> rows.size, 1); if (xmax < thy xmax) { xmax = thy xmax; } autoTextGrid tg1 = Table_to_TextGrid (my d_events.get(), text, xmin, xmax); *tg = TextGrid_extractPart (tg1.get(), thy xmin, thy xmax, 0); } if (events) { Table_setEventTypeString (my d_events.get()); *events = my d_events.move(); } my d_events.reset(); return thee; } catch (MelderError) { espeak_Terminate (); Melder_throw (U"Text not played."); } }
int64 Melder_atoi (const char32 *string) { return strtoll (Melder_peek32to8 (string), nullptr, 10); }
double Melder_atof (const char32 *string) { return Melder_a8tof (Melder_peek32to8 (string)); }