Exemple #1
0
Daata Data_readFromBinaryFile (MelderFile file) {
	try {
		autofile f = Melder_fopen (file, "rb");
		char line [200];
		int n = fread (line, 1, 199, f); line [n] = '\0';
		char *end = strstr (line, "ooBinaryFile");
		autoDaata me;
		int formatVersion;
		if (end) {
			fseek (f, strlen ("ooBinaryFile"), 0);
			autostring8 klas = bingets1 (f);
			me.reset (static_cast <Daata> (Thing_newFromClassName (Melder_peek8to32 (klas.peek()), & formatVersion)));
		} else {
			end = strstr (line, "BinaryFile");
			if (! end) {
				Melder_throw (U"File ", file, U" is not a Data binary file.");
			}
			*end = '\0';
			me.reset (static_cast <Daata> (Thing_newFromClassName (Melder_peek8to32 (line), nullptr)));
			formatVersion = -1;   // old version: override version number, which was set to 0 by newFromClassName
			rewind (f);
			fread (line, 1, end - line + strlen ("BinaryFile"), f);
		}
		MelderFile_getParentDir (file, & Data_directoryBeingRead);
		Data_readBinary (me.peek(), f, formatVersion);
		file -> format = structMelderFile :: Format :: binary;
		f.close (file);
		return me.transfer();
	} catch (MelderError) {
		Melder_throw (U"Data not read from binary file ", file, U".");
	}
}
Exemple #2
0
	static gboolean _GuiGtkDrawingArea_exposeCallback (GuiObject widget, GdkEventExpose *expose, gpointer void_me) {
		trace (U"begin");
		iam (GuiDrawingArea);
		Melder_assert (me);
		// TODO: that helps against the damaged regions outside the rect where the
		// Graphics drawing is done, but where does that margin come from in the
		// first place?? Additionally this causes even more flickering
		//gdk_window_clear_area ((GTK_WIDGET (widget)) -> window, expose->area.x, expose->area.y, expose->area.width, expose->area.height);
		if (my d_exposeCallback) {
			struct structGuiDrawingArea_ExposeEvent event { me, 0 };
			event. x = expose -> area. x;
			event. y = expose -> area. y;
			event. width = expose -> area. width;
			event. height = expose -> area. height;
			try {
				//GdkRectangle rect = { event. x, event. y, event. width, event. height };
				//gdk_window_begin_paint_rect ((GTK_WIDGET (widget)) -> window, & rect);
				trace (U"send the expose callback");
				trace (U"locale is ", Melder_peek8to32 (setlocale (LC_ALL, nullptr)));
				my d_exposeCallback (my d_exposeBoss, & event);
				trace (U"the expose callback finished");
				trace (U"locale is ", Melder_peek8to32 (setlocale (LC_ALL, nullptr)));
				//gdk_window_end_paint ((GTK_WIDGET (widget)) -> window);
				//gdk_window_flush ((GTK_WIDGET (widget)) -> window);
				//gdk_flush ();
			} catch (MelderError) {
				Melder_flushError (U"Redrawing not completed");
			}
			trace (U"the expose callback handled drawing");
			return true;
		}
		trace (U"GTK will handle redrawing");
		return false;
	}
Exemple #3
0
void _CollectionOfDaata_v_readText (_CollectionOfDaata* me, MelderReadText text, int formatVersion) {
	if (formatVersion < 0) {
		long l_size;
		autostring8 line = Melder_32to8 (MelderReadText_readLine (text));
		if (! line.peek() || ! sscanf (line.peek(), "%ld", & l_size) || l_size < 0)
			Melder_throw (U"Collection::readText: cannot read size.");
		my _grow (l_size);
		for (long i = 1; i <= l_size; i ++) {
			long itemNumberRead;
			int n = 0, length, stringsRead;
			char klas [200], nameTag [2000];
			do {
				line.reset (Melder_32to8 (MelderReadText_readLine (text)));
				if (! line.peek())
					Melder_throw (U"Missing object line.");
			} while (strncmp (line.peek(), "Object ", 7));
			stringsRead = sscanf (line.peek(), "Object %ld: class %s %s%n", & itemNumberRead, klas, nameTag, & n);
			if (stringsRead < 2)
				Melder_throw (U"Collection::readText: cannot read header of object ", i, U".");
			if (itemNumberRead != i)
				Melder_throw (U"Collection::readText: read item number ", itemNumberRead,
					U" while expecting ", i, U".");
			if (stringsRead == 3 && ! strequ (nameTag, "name"))
				Melder_throw (U"Collection::readText: wrong header at object ", i, U".");
			my at [i] = (Daata) Thing_newFromClassName (Melder_peek8to32 (klas), nullptr).releaseToAmbiguousOwner();
			my size ++;
			if (! Thing_isa (my at [i], classDaata) || ! Data_canReadText (my at [i]))
				Melder_throw (U"Cannot read item of class ", Thing_className (my at [i]), U" in collection.");
			Data_readText (my at [i], text, -1);
			if (stringsRead == 3) {
				if (line [n] == U' ') n ++;   // skip space character
				length = strlen (line.peek()+n);
				if (length > 0 && (line.peek()+n) [length - 1] == '\n')
					(line.peek()+n) [length - 1] = '\0';
				Thing_setName (my at [i], Melder_peek8to32 (line.peek()+n));
			}
		}
	} else {
		int32_t l_size = texgeti4 (text);
		my _grow (l_size);
		for (int32_t i = 1; i <= l_size; i ++) {
			autostring32 className = texgetw2 (text);
			int elementFormatVersion;
			my at [i] = (Daata) Thing_newFromClassName (className.peek(), & elementFormatVersion).releaseToAmbiguousOwner();
			my size ++;
			if (! Thing_isa (my at [i], classDaata) || ! Data_canReadText (my at [i]))
				Melder_throw (U"Cannot read item of class ", Thing_className (my at [i]), U" in collection.");
			autostring32 objectName = texgetw2 (text);
			Thing_setName (my at [i], objectName.peek());
			Data_readText (my at [i], text, elementFormatVersion);
		}
	}
}
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);
	}
}
Exemple #5
0
void Transition_drawAsNumbers (Transition me, Graphics g, int iformat, int precision) {
	double maxTextWidth = 0, maxTextHeight = 0;
	Graphics_setInner (g);
	Graphics_setWindow (g, 0.5, my numberOfStates + 0.5, 0, 1);
	double leftMargin = Graphics_dxMMtoWC (g, 1);
	double lineSpacing = Graphics_dyMMtoWC (g, 1.5 * Graphics_inqFontSize (g) * 25.4 / 72);
	Graphics_setTextAlignment (g, Graphics_CENTRE, Graphics_BOTTOM);
	for (long col = 1; col <= my numberOfStates; col ++) {
		if (my stateLabels && my stateLabels [col] && my stateLabels [col] [0]) {
			Graphics_text (g, col, 1, my stateLabels [col]);
			if (maxTextHeight == 0.0) maxTextHeight = lineSpacing;
		}
	}
	for (long row = 1; row <= my numberOfStates; row ++) {
		double y = 1 - lineSpacing * (row - 1 + 0.7);
		Graphics_setTextAlignment (g, Graphics_RIGHT, Graphics_HALF);
		if (my stateLabels && my stateLabels [row]) {
			double textWidth = Graphics_textWidth (g, my stateLabels [row]);
			if (textWidth > maxTextWidth) maxTextWidth = textWidth;
			Graphics_text (g, 0.5 - leftMargin, y, my stateLabels [row]);
		}
		Graphics_setTextAlignment (g, Graphics_CENTRE, Graphics_HALF);
		for (long col = 1; col <= my numberOfStates; col ++) {
			char text [40];
			print4 (text, my data [row] [col], iformat, 0, precision);
			Graphics_text (g, col, y, Melder_peek8to32 (text));
		}
	}
	if (maxTextWidth != 0.0)
		Graphics_line (g, 0.5 - maxTextWidth - leftMargin, 1, my numberOfStates + 0.5, 1);
	if (maxTextHeight != 0.0)
		Graphics_line (g, 0.5, 1 + maxTextHeight, 0.5, 1 - lineSpacing * (my numberOfStates + 0.2));
	Graphics_unsetInner (g);
}
Table espeakdata_voices_to_Table (FilesInMemory me) {
	try {
		autoTable thee = Table_createWithColumnNames (my size, U"id name");
		for (long ifile = 1; ifile <= my size; ifile++) {
			FileInMemory fim = (FileInMemory) my item[ifile];
			Table_setStringValue (thee.peek(), ifile, 1, fim -> d_id);
			const char *p = strstr (fim -> d_data, "name");
			if (p == NULL) continue;
			// copy the name part to the following new line
			char buf[40], *bufp = buf;
			long len = 0;
			while ((*bufp++ = *p++) != '\n' && len < 39) { len++; }
			// remove trailing white space
			*bufp = 0;
			while (ESPEAK_ISSPACE (buf[len]) && len > 0) {
				buf[len] = 0; len--;
			}
			// skip leading white space
			bufp = & buf[4];
			while (ESPEAK_ISSPACE (*bufp)) { *bufp++; }
			Table_setStringValue (thee.peek(), ifile, 2, Melder_peek8to32 (bufp));
			TableRow row = static_cast <TableRow> (thy rows -> item [ifile]);
			wint_t c0 = row -> cells [2]. string[0];
			row -> cells [2]. string[0] = towupper (c0);
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (U"Espeakdata: voice table not initialized.");
	}
}
Exemple #7
0
void structThing :: v_info ()
{
	MelderInfo_writeLine (U"Object type: ", Thing_className (this));
	MelderInfo_writeLine (U"Object name: ", this -> name ? this -> name : U"<no name>");
	time_t today = time (nullptr);
	MelderInfo_writeLine (U"Date: ", Melder_peek8to32 (ctime (& today)));   // includes a newline
}
static int synthCallback (short *wav, int numsamples, espeak_EVENT *events)
{
	char phoneme_name[9];
	if (wav == 0) return 1;
	
	// It is essential that the SpeechSynthesizer is identified here by the user_data,
	// because the espeakEVENT_LIST_TERMINATED event may still be accompanied by
	// a piece of audio data!!
	
	SpeechSynthesizer me = (SpeechSynthesizer) (events -> user_data);
	while (events -> type != espeakEVENT_LIST_TERMINATED) {
		if (events -> type == espeakEVENT_SAMPLERATE) {
			my d_internalSamplingFrequency = events -> id.number;
		} else {
			//my events = Table "time type type-t t-pos length a-pos sample id uniq";
			//                    1    2     3      4     5     6     7      8   9
			Table_appendRow (my d_events.get());
			long irow = my d_events -> rows.size;
			double time = events -> audio_position * 0.001;
			Table_setNumericValue (my d_events.get(), irow, 1, time);
			Table_setNumericValue (my d_events.get(), irow, 2, events -> type);
			// Column 3 will be filled afterwards
			Table_setNumericValue (my d_events.get(), irow, 4, events -> text_position);
			Table_setNumericValue (my d_events.get(), irow, 5, events -> length);
			Table_setNumericValue (my d_events.get(), irow, 6, events -> audio_position);
			Table_setNumericValue (my d_events.get(), irow, 7, events -> sample);
			if (events -> type == espeakEVENT_MARK || events -> type == espeakEVENT_PLAY) {
				Table_setStringValue (my d_events.get(), irow, 8, Melder_peek8to32 (events -> id.name));
			} else {
				// Ugly hack because id.string is not 0-terminated if 8 chars long!
				memcpy (phoneme_name, events -> id.string, 8);
				phoneme_name[8] = 0;
				Table_setStringValue (my d_events.get(), irow, 8, Melder_peek8to32 (phoneme_name));
			}
			Table_setNumericValue (my d_events.get(), irow, 9, events -> unique_identifier);
		}
		events++;
	}
	if (me) {
		NUMvector_supplyStorage<int> (&my d_wav, 1, &my d_wavCapacity, my d_numberOfSamples, numsamples);
		for (long i = 1; i <= numsamples; i++) {
			my d_wav [my d_numberOfSamples + i] = wav [i - 1];
		}
		my d_numberOfSamples += numsamples;
	}
	return 0;
}
void praat_reportTextProperties () {
	MelderInfo_open ();
	MelderInfo_writeLine (U"Text properties of this edition of Praat on this computer:\n");
	MelderInfo_writeLine (U"Locale: ", Melder_peek8to32 (setlocale (LC_ALL, nullptr)));
	MelderInfo_writeLine (U"A \"char\" is ",                                      8, U" bits.");
	MelderInfo_writeLine (U"A \"char16_t\" is ",           sizeof (char16_t)    * 8, U" bits.");
	MelderInfo_writeLine (U"A \"wchar_t\" is ",            sizeof (wchar_t)     * 8, U" bits.");
	MelderInfo_writeLine (U"A \"char32_t\" is ",           sizeof (char32_t)    * 8, U" bits.");
	MelderInfo_close ();
}
Exemple #10
0
void EditDistanceTable_draw (EditDistanceTable me, Graphics graphics, int iformat, int precision, double angle) {
    long rowmin = 1, rowmax = my numberOfRows;
    Graphics_setInner (graphics);
    Graphics_setWindow (graphics, 0.5, my numberOfColumns + 0.5, 0, 1);
    double leftMargin = getLeftMargin (graphics);   // not earlier!
    double lineSpacing = getLineSpacing (graphics);   // not earlier!
    double maxTextWidth = getMaxRowLabelWidth (me, graphics, rowmin, rowmax);
    double y = 1 + 0.1 * lineSpacing;
    autoNUMmatrix<bool> onPath (1, my numberOfRows, 1, my numberOfColumns);
    for (long i = 1; i <= my warpingPath -> pathLength; i++) {
        structPairOfInteger poi = my warpingPath -> path[i];
        onPath[poi.y] [poi.x] = true;
    }

    for (long irow = my numberOfRows; irow > 0; irow --) {
        Graphics_setTextAlignment (graphics, Graphics_RIGHT, Graphics_HALF);
        if (my rowLabels && my rowLabels [irow] && my rowLabels [irow] [0])
            Graphics_text (graphics, 0.5 - leftMargin, y, my rowLabels [irow]);
        Graphics_setTextAlignment (graphics, Graphics_CENTRE, Graphics_HALF);
        for (long icol = 1; icol <= my numberOfColumns; icol ++) {
            char text [40];
            print4 (text, my data [irow] [icol], iformat, 0, precision);
            Graphics_setBold (graphics, onPath[irow][icol]);
            Graphics_text (graphics, icol, y, Melder_peek8to32 (text));
            if (onPath[irow][icol]) {
                Graphics_rectangle (graphics, icol-0.5, icol+0.5, y - 0.5*lineSpacing, y + 0.5*lineSpacing);
            }
        }
        y -= lineSpacing;
        Graphics_setBold (graphics, false);
    }

    double left = 0.5;
    if (maxTextWidth > 0.0) left -= maxTextWidth + 2 * leftMargin;
    Graphics_line (graphics, left, y, my numberOfColumns + 0.5, y);

    Graphics_setTextRotation (graphics, angle);
    if (angle < 0) {
        y -= 0.3*lineSpacing;
        Graphics_setTextAlignment (graphics, Graphics_LEFT, Graphics_HALF);
    } else if (angle > 0) {
        Graphics_setTextAlignment (graphics, Graphics_RIGHT, Graphics_HALF);
        y -= 0.3*lineSpacing;
    } else {
        Graphics_setTextAlignment (graphics, Graphics_CENTRE, Graphics_TOP);
    }
    for (long icol = 1; icol <= my numberOfColumns; icol ++) {
        if (my columnLabels && my columnLabels [icol] && my columnLabels [icol] [0])
            Graphics_text (graphics, icol, y, my columnLabels [icol]);
    }
    Graphics_setTextRotation (graphics, 0);
    y -= lineSpacing;
    Graphics_line (graphics, 0.5, y, 0.5, 1 + 0.5 * lineSpacing);
    Graphics_unsetInner (graphics);
}
Exemple #11
0
void _CollectionOfDaata_v_readBinary (_CollectionOfDaata* me, FILE *f, int formatVersion) {
	if (formatVersion < 0) {
		int32 l_size = bingeti4 (f);
		if (l_size < 0)
			Melder_throw (U"Empty collection.");
		my _grow (l_size);
		for (int32_t i = 1; i <= l_size; i ++) {
			char klas [200], name [2000];
			if (fscanf (f, "%s%s", klas, name) < 2)   // BUG
				Melder_throw (U"Cannot read class and name.");
			my at [i] = (Daata) Thing_newFromClassName (Melder_peek8to32 (klas), nullptr).releaseToAmbiguousOwner();
			my size ++;
			if (! Thing_isa (my at [i], classDaata))
				Melder_throw (U"Cannot read item of class ", Thing_className (my at [i]), U".");
			if (fgetc (f) != ' ')
				Melder_throw (U"Cannot read space.");
			Data_readBinary (my at [i], f, -1);
			if (strcmp (name, "?"))
				Thing_setName (my at [i], Melder_peek8to32 (name));
		}
	} else {
		int32_t l_size = bingeti4 (f);
		if (Melder_debug == 44)
			Melder_casual (U"structCollection :: v_readBinary: Reading ", l_size, U" objects");
		my _grow (l_size);
		for (int32_t i = 1; i <= l_size; i ++) {
			autostring8 klas = bingets1 (f);
			if (Melder_debug == 44)
				Melder_casual (U"structCollection :: v_readBinary: Reading object of type ", Melder_peek8to32 (klas.peek()));
			int elementFormatVersion;
			my at [i] = (Daata) Thing_newFromClassName (Melder_peek8to32 (klas.peek()), & elementFormatVersion).releaseToAmbiguousOwner();
			my size ++;
			if (! Thing_isa (my at [i], classDaata) || ! Data_canReadBinary (my at [i]))
				Melder_throw (U"Objects of class ", Thing_className (my at [i]), U" cannot be read.");
			autostring32 name = bingetw2 (f);
			if (Melder_debug == 44)
				Melder_casual (U"structCollection :: v_readBinary: Reading object with name ", name.peek());
			Thing_setName (my at [i], name.peek());
			Data_readBinary (my at [i], f, elementFormatVersion);
		}
	}
}
Exemple #12
0
	static void _GuiGtkButton_activateCallback (GuiObject widget, gpointer void_me) {
		iam (GuiButton);
		struct structGuiButtonEvent event = { me, 0 };
		if (my d_activateCallback != NULL) {
			try {
				my d_activateCallback (my d_activateBoss, & event);
			} catch (MelderError) {
				Melder_flushError (U"Your click on button \"", Melder_peek8to32 (GTK_WIDGET (widget) -> name), U"\" was not completely handled.");
			}
		}
	}
Exemple #13
0
	static void _GuiGtkButton_activateCallback (GuiObject widget, gpointer userData) {
		GuiButton me = (GuiButton) userData;
		struct structGuiButtonEvent event { me, false, false, false, false };
		if (my d_activateCallback) {
			try {
				my d_activateCallback (my d_activateBoss, & event);
			} catch (MelderError) {
				Melder_flushError (U"Your click on button \"", Melder_peek8to32 (GTK_WIDGET (widget) -> name), U"\" was not completely handled.");
			}
		}
	}
Exemple #14
0
void * _Thing_check (Thing me, ClassInfo klas, const char *fileName, int line) {
	if (! me)
		Melder_fatal (U"(_Thing_check:)"
			U" null object passed to a function\n"
			U"in file ", Melder_peek8to32 (fileName),
			U" at line ", line,
			U"."
		);
	ClassInfo classInfo = my classInfo;
	while (classInfo != klas && classInfo) classInfo = classInfo -> parent;
	if (! classInfo)
		Melder_fatal (U"(_Thing_check:)"
			U" Object of wrong class (", my classInfo -> className,
			U") passed to a function\n"
			U"in file ", Melder_peek8to32 (fileName),
			U" at line ", line,
			U"."
		);
	return me;
}
Exemple #15
0
	static void _guiGtkMenuItem_activateCallback (GuiObject widget, gpointer void_me) {
		iam (GuiMenuItem);
		if (my d_callbackBlocked) return;
		if (G_OBJECT_TYPE (widget) == GTK_TYPE_RADIO_MENU_ITEM && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) return;
		struct structGuiMenuItemEvent event { me, false, false, false, false };
		if (my d_callback) {
			try {
				my d_callback (my d_boss, & event);
			} catch (MelderError) {
				Melder_flushError (U"Your choice of menu item \"", Melder_peek8to32 (GTK_WIDGET (widget) -> name), U"\" was not completely handled.");
			}
		}
	}
void praat_statistics_prefsChanged () {
	if (! statistics.dateOfFirstSession [0]) {
		time_t today = time (nullptr);
		char32 *newLine;
		str32cpy (statistics.dateOfFirstSession, Melder_peek8to32 (ctime (& today)));
		newLine = str32chr (statistics.dateOfFirstSession, U'\n');
		if (newLine) *newLine = '\0';
	}
	if (theCurrentPraatApplication -> batch)
		statistics.batchSessions += 1;
	else
		statistics.interactiveSessions += 1;
}
Exemple #17
0
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
}
Exemple #18
0
static void menu_cb_printRange (Manual me, EDITOR_ARGS_FORM) {
	EDITOR_FORM (U"Print range", 0)
		SENTENCE (U"Left or inside header", U"")
		SENTENCE (U"Middle header", U"")
		SENTENCE (U"Right or outside header", U"Manual")
		SENTENCE (U"Left or inside footer", U"")
		SENTENCE (U"Middle footer", U"")
		SENTENCE (U"Right or outside footer", U"")
		BOOLEAN (U"Mirror even/odd headers", true)
		LABEL (U"", U"Print all pages whose title starts with:")
		TEXTFIELD (U"Print pages starting with", U"Intro")
		INTEGER (U"First page number", U"1")
		BOOLEAN (U"Suppress \"Links to this page\"", false)
	EDITOR_OK
		ManPages manPages = (ManPages) my data;
		time_t today = time (nullptr);
		char dateA [50];
		#ifdef UNIX
			struct tm *tm = localtime (& today);
			strftime (dateA, 50, "%B %e, %Y", tm);
		#else
			strcpy (dateA, ctime (& today));
		#endif
		char32 *date = Melder_peek8to32 (dateA), *newline;
		newline = str32chr (date, U'\n'); if (newline) *newline = U'\0';
		SET_STRING (U"Left or inside header", date)
		SET_STRING (U"Right or outside header", my name)
		if (my d_printingPageNumber) SET_INTEGER (U"First page number", my d_printingPageNumber + 1)
		if (my path >= 1 && my path <= manPages -> pages.size) {
			ManPage page = manPages -> pages.at [my path];
			SET_STRING (U"Print pages starting with", page -> title);
		}
	EDITOR_DO
		my insideHeader = GET_STRING (U"Left or inside header");
		my middleHeader = GET_STRING (U"Middle header");
		my outsideHeader = GET_STRING (U"Right or outside header");
		my insideFooter = GET_STRING (U"Left or inside footer");
		my middleFooter = GET_STRING (U"Middle footer");
		my outsideFooter = GET_STRING (U"Right or outside footer");
		my mirror = GET_INTEGER (U"Mirror even/odd headers");
		my printPagesStartingWith = GET_STRING (U"Print pages starting with");
		my d_printingPageNumber = GET_INTEGER (U"First page number");
		my suppressLinksHither = GET_INTEGER (U"Suppress \"Links to this page\"");
		Printer_print (print, me);
	EDITOR_END
}
/*
	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
}
Exemple #20
0
Strings WordList_to_Strings (WordList me) {
	try {
		unsigned char *word = (unsigned char *) my string;   // BUG: explain this
		autoStrings thee = Thing_new (Strings);
		thy numberOfStrings = WordList_count (me);
		if (thy numberOfStrings > 0) {
			thy strings = NUMvector <char32 *> (1, thy numberOfStrings);
		}
		for (long i = 1; i <= thy numberOfStrings; i ++) {
			unsigned char *kar = word;
			for (; *kar != '\n'; kar ++) { }
			long length = kar - word;
			thy strings [i] = Melder_calloc (char32, length + 1);
			str32ncpy (thy strings [i], Melder_peek8to32 ((const char *) word), length);
			thy strings [i] [length] = U'\0';
			word += length + 1;
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": not converted to Strings.");
	}
}
void SpeechSynthesizerVoice_initFromEspeakVoice (SpeechSynthesizerVoice me, voice_t *evoice) {
	my d_v_name = Melder_dup (Melder_peek8to32 (evoice -> v_name));

	my d_phoneme_tab_ix = evoice -> phoneme_tab_ix;
	my d_pitch_base = evoice -> pitch_base;
	my d_pitch_range = evoice -> pitch_range;

	my d_speedf1 = evoice -> speedf1;
	my d_speedf2 = evoice -> speedf2;
	my d_speedf3 = evoice -> speedf3;

	my d_speed_percent = evoice -> speed_percent;
	my d_flutter = evoice -> flutter;
	my d_roughness = evoice -> roughness;
	my d_echo_delay = evoice -> echo_delay;
	my d_echo_amp = evoice -> echo_amp;
	my d_n_harmonic_peaks = evoice -> n_harmonic_peaks;
	my d_peak_shape = evoice -> peak_shape;
	my d_voicing = evoice -> voicing;
	my d_formant_factor = evoice -> formant_factor;
	my d_consonant_amp = evoice -> consonant_amp;
	my d_consonant_ampv = evoice -> consonant_ampv;
	my d_samplingFrequency = evoice -> samplerate;
	for (long i = 0; i < 7; i++) {
		my d_klattv[i] = evoice -> klattv[i];
	}
	for (long i = 0; i <= my d_numberOfFormants; i++) {
		my d_freq[i] = evoice -> freq[i];
		my d_height[i] = evoice -> height[i];
		my d_width[i] = evoice -> width[i];
		my d_freqadd[i] = evoice -> freqadd[i];
		my d_freq2[i] = evoice -> freq2[i];
		my d_height2[i] = evoice -> height2[i];
		my d_width2[i] = evoice -> width2[i];
		my d_breath[i] = evoice -> breath[i];
		my d_breathw[i] = evoice -> breathw[i];
	}
}
Exemple #22
0
int Praat_tests (int itest, char32 *arg1, char32 *arg2, char32 *arg3, char32 *arg4) {
	int64 n = Melder_atoi (arg1);
	double t;
	(void) arg1;
	(void) arg2;
	(void) arg3;
	(void) arg4;
	Melder_clearInfo ();
	Melder_stopwatch ();
	switch (itest) {
		case kPraatTests_TIME_RANDOM_FRACTION: {
			for (int64 i = 1; i <= n; i ++)
				(void) NUMrandomFraction ();
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_RANDOM_GAUSS: {
			for (int64 i = 1; i <= n; i ++)
				(void) NUMrandomGauss (0.0, 1.0);
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_SORT: {
			long m = Melder_atoi (arg2);
			long *array = NUMvector <long> (1, m);
			for (int64 i = 1; i <= m; i ++)
				array [i] = NUMrandomInteger (1, 100);
			Melder_stopwatch ();
			for (int64 i = 1; i <= n; i ++)
				NUMsort_l (m, array);
			t = Melder_stopwatch ();
			NUMvector_free (array, 1);
		} break;
		case kPraatTests_TIME_INTEGER: {
			double sum = 0;
			for (int64 i = 1; i <= n; i ++)
				sum += i * (i - 1) * (i - 2);
			t = Melder_stopwatch ();
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_FLOAT: {
			double sum = 0.0, fn = n;
			for (double fi = 1.0; fi <= fn; fi = fi + 1.0)
				sum += fi * (fi - 1.0) * (fi - 2.0);
			t = Melder_stopwatch ();
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_FLOAT_TO_UNSIGNED_BUILTIN: {
			uint64_t sum = 0;
			double fn = n;
			for (double fi = 1.0; fi <= fn; fi = fi + 1.0)
				sum += (uint32_t) fi;
			t = Melder_stopwatch ();   // 2.59   // 1.60
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_FLOAT_TO_UNSIGNED_EXTERN: {
			uint64_t sum = 0;
			double fn = n;
			for (double fi = 1.0; fi <= fn; fi = fi + 1.0)
				sum += (uint32_t) ((int32_t) (fi - 2147483648.0) + 2147483647L + 1);
			t = Melder_stopwatch ();   // 1.60
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_UNSIGNED_TO_FLOAT_BUILTIN: {
			double sum = 0.0;
			uint32_t nu = (uint32_t) n;
			for (uint32_t iu = 1; iu <= nu; iu ++)
				sum += (double) iu;
			t = Melder_stopwatch ();   // 1.35
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_UNSIGNED_TO_FLOAT_EXTERN: {
			double sum = 0.0;
			uint32_t nu = (uint32_t) n;
			for (uint32_t iu = 1; iu <= nu; iu ++)
				sum += (double) (int32_t) (iu - 2147483647L - 1) + 2147483648.0;
			t = Melder_stopwatch ();   // 0.96
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_STRING_MELDER_32: {
			autoMelderString string;
			char32 word [] { U"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				MelderString_copy (& string, word);
				for (int j = 1; j <= 30; j ++)
					MelderString_append (& string, word);
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_S: {
			std::string s = "";
			char word [] { "abc" };
			word [2] = (char) NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_C: {
			std::basic_string<char> s = "";
			char word [] { "abc" };
			word [2] = (char) NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_WS: {
			std::wstring s = L"";
			wchar_t word [] { L"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_WC: {
			std::basic_string<wchar_t> s = L"";
			wchar_t word [] { L"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_32: {
			std::basic_string<char32_t> s = U"";
			char32 word [] { U"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_U32STRING: {
			#if ! defined (macintosh) || ! useCarbon
			std::u32string s = U"";
			char32 word [] { U"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			#endif
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRCPY: {
			char buffer [100];
			char word [] { "abc" };
			word [2] = (char) NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				strcpy (buffer, word);
				for (int j = 1; j <= 30; j ++)
					strcpy (buffer + strlen (buffer), word);
			}
			t = Melder_stopwatch ();
			MelderInfo_writeLine (Melder_peek8to32 (buffer));
		} break;
		case kPraatTests_TIME_WCSCPY: {
			wchar_t buffer [100];
			wchar_t word [] { L"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				wcscpy (buffer, word);
				for (int j = 1; j <= 30; j ++)
					wcscpy (buffer + wcslen (buffer), word);
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STR32CPY: {
			char32 buffer [100];
			char32 word [] { U"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				str32cpy (buffer, word);
				for (int j = 1; j <= 30; j ++)
					str32cpy (buffer + str32len (buffer), word);
			}
			t = Melder_stopwatch ();
			MelderInfo_writeLine (buffer);
		} break;
		case kPraatTests_TIME_GRAPHICS_TEXT_TOP: {
			autoPraatPicture picture;
			for (int64 i = 1; i <= n; i ++) {
				Graphics_textTop (GRAPHICS, false, U"hello world");
			}
			t = Melder_stopwatch ();
		} break;
	}
	MelderInfo_writeLine (Melder_single (t / n * 1e9), U" nanoseconds");
	MelderInfo_close ();
	return 1;
}
Exemple #23
0
Sound Sound_recordFixedTime (int inputSource, double gain, double balance, double sampleRate, double duration) {
	bool inputUsesPortAudio = MelderAudio_getInputUsesPortAudio ();
	PaStream *portaudioStream = NULL;
	#if defined (macintosh)
	#elif defined (_WIN32)
		HWAVEIN hWaveIn = 0;
	#else
		int fd = -1;   /* Other systems use stream I/O with a file descriptor. */
		int fd_mixer = -1;
	#endif
	try {
		long numberOfSamples, i;
		int mulaw = FALSE;
		int can16bit = TRUE;
		int fakeMonoByStereo = FALSE;   /* Will be set to TRUE for systems (like MacOS X) that do not allow direct mono recording. */

		/* Declare system-dependent data structures. */

		static bool paInitialized = false;
		volatile struct Sound_recordFixedTime_Info info = { 0 };
		PaStreamParameters streamParameters = { 0 };
		#if defined (macintosh)
			(void) gain;
			(void) balance;
		#elif defined (_WIN32)
			WAVEFORMATEX waveFormat;
			WAVEHDR waveHeader;
			MMRESULT err;
			(void) inputSource;
			(void) gain;
			(void) balance;
		#elif defined (linux)
			#define min(a,b) a > b ? b : a
			int dev_mask;
			int fd_mixer = -1;
			int val;
		#endif

		/* Check representation of shorts. */

		if (sizeof (short) != 2)
			Melder_throw (U"Cannot record a sound on this computer.");

		/* Check sampling frequency. */

		bool supportsSamplingFrequency = true;
		if (inputUsesPortAudio) {
			#if defined (macintosh)
				if (sampleRate != 44100 && sampleRate != 48000 && sampleRate != 96000) supportsSamplingFrequency = false;
			#endif
		} else {
			#if defined (macintosh)
				if (sampleRate != 44100) supportsSamplingFrequency = false;
			#elif defined (linux)
				if (sampleRate != 8000 && sampleRate != 11025 &&
						sampleRate != 16000 && sampleRate != 22050 &&
						sampleRate != 32000 && sampleRate != 44100 &&
						sampleRate != 48000) supportsSamplingFrequency = false;
			#elif defined (_WIN32)
				if (sampleRate != 8000 && sampleRate != 11025 &&
						sampleRate != 16000 && sampleRate != 22050 &&
						sampleRate != 32000 && sampleRate != 44100 &&
						sampleRate != 48000 && sampleRate != 96000) supportsSamplingFrequency = false;
			#endif
		}
		if (! supportsSamplingFrequency)
			Melder_throw (U"Your audio hardware does not support a sampling frequency of ", sampleRate, U" Hz.");

		/*
		 * Open phase 1.
		 * On some systems, the info is filled in before the audio port is opened.
		 * On other systems, the info is filled in after the port is opened.
		 */
		if (inputUsesPortAudio) {
			if (! paInitialized) {
				PaError err = Pa_Initialize ();
				if (err)
					Melder_throw (U"Pa_Initialize: ", Melder_peek8to32 (Pa_GetErrorText (err)));
				paInitialized = true;
			}
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
			#else
				/* We must open the port now, because we use an ioctl to set the info to an open port. */
				fd = open (DEV_AUDIO, O_RDONLY);
				if (fd == -1) {
					if (errno == EBUSY)
						Melder_throw (U"Audio device in use by another program.");
					else
						#ifdef linux
							Melder_throw (U"Cannot open audio device.\nPlease switch on PortAudio in the Sound Recording Preferences.");
						#else
							Melder_throw (U"Cannot open audio device.");
						#endif
				}
				/* The device immediately started recording into its buffer, but probably at the wrong rate etc. */
				/* Pause and flush this rubbish. */
				#if defined (linux)
					ioctl (fd, SNDCTL_DSP_RESET, NULL);
				#endif
			#endif
		}

		/* Set the input source; the default is the microphone. */

		if (inputUsesPortAudio) {
			if (inputSource < 1 || inputSource > Pa_GetDeviceCount ())
				Melder_throw (U"Unknown device #", inputSource, U".");
			streamParameters. device = inputSource - 1;
		} else {
			#if defined (macintosh)
			#elif defined (linux)
				fd_mixer = open ("/dev/mixer", O_WRONLY);		
				if (fd_mixer == -1)
					Melder_throw (U"Cannot open /dev/mixer.");
				dev_mask = inputSource == 1 ? SOUND_MASK_MIC : SOUND_MASK_LINE;
				if (ioctl (fd_mixer, SOUND_MIXER_WRITE_RECSRC, & dev_mask) == -1)
					Melder_throw (U"Cannot set recording device in mixer");
			#endif
		}

		/* Set gain and balance. */

		if (inputUsesPortAudio) {
			/* Taken from Audio Control Panel. */
		} else {
			#if defined (macintosh) || defined (_WIN32)
				/* Taken from Audio Control Panel. */
			#elif defined (linux)
				val = (gain <= 0.0 ? 0 : gain >= 1.0 ? 100 : floor (gain * 100 + 0.5));  
				balance = balance <= 0 ? 0 : balance >= 1 ? 1 : balance;
				if (balance >= 0.5) {
					val = (int)(((int)(val*balance/(1-balance)) << 8) | val);
				} else {
					val = (int)(val | ((int)(val*(1-balance)/balance) << 8));
				}
				val = (int)((min(2-2*balance,1))*val) | ((int)((min(2*balance,1))*val) << 8);
				if (inputSource == 1) {			
					/* MIC */		       
					if (ioctl (fd_mixer, MIXER_WRITE (SOUND_MIXER_MIC), & val) == -1)
						Melder_throw (U"Cannot set gain and balance.");
				} else {
					/* LINE */
					if (ioctl (fd_mixer, MIXER_WRITE (SOUND_MIXER_LINE), & val) == -1)
						Melder_throw (U"Cannot set gain and balance.");
				}
				close (fd_mixer);
				fd_mixer = -1;
			#endif
		}

		/* Set the sampling frequency. */

		if (inputUsesPortAudio) {
			// Set while opening.
		} else {
			#if defined (macintosh)
			#elif defined (linux)
				int sampleRate_int = (int) sampleRate;
				if (ioctl (fd, SNDCTL_DSP_SPEED, & sampleRate_int) == -1)
					Melder_throw (U"Cannot set sampling frequency to ", sampleRate, U" Hz.");
			#elif defined (_WIN32)
				waveFormat. nSamplesPerSec = sampleRate;
			#endif
		}

		/* Set the number of channels to 1 (mono), if possible. */

		if (inputUsesPortAudio) {
			streamParameters. channelCount = 1;
		} else {
			#if defined (macintosh)
			#elif defined (linux)
				val = 1;
				if (ioctl (fd, SNDCTL_DSP_CHANNELS, & val) == -1)
					Melder_throw (U"Cannot set to mono.");
			#elif defined (_WIN32)
				waveFormat. nChannels = 1;
			#endif
		}

		/* Set the encoding to 16-bit linear (or to 8-bit linear, if 16-bit is not available). */

		if (inputUsesPortAudio) {
			streamParameters. sampleFormat = paInt16;
		} else {
			#if defined (macintosh)
			#elif defined (linux)
				#if __BYTE_ORDER == __BIG_ENDIAN
					val = AFMT_S16_BE;
				#else
					val = AFMT_S16_LE;
				#endif
				if (ioctl (fd, SNDCTL_DSP_SETFMT, & val) == -1)
					Melder_throw (U"Cannot set 16-bit linear.");
			#elif defined (_WIN32)
				waveFormat. wFormatTag = WAVE_FORMAT_PCM;
				waveFormat. wBitsPerSample = 16;
				waveFormat. nBlockAlign = waveFormat. nChannels * waveFormat. wBitsPerSample / 8;
				waveFormat. nAvgBytesPerSec = waveFormat. nBlockAlign * waveFormat. nSamplesPerSec;
			#endif
		}

		/* Create a buffer for recording, and the resulting sound. */

		numberOfSamples = lround (sampleRate * duration);
		if (numberOfSamples < 1)
			Melder_throw (U"Duration too short.");
		autoNUMvector <short> buffer (1, numberOfSamples * (fakeMonoByStereo ? 2 : 1));
		autoSound me = Sound_createSimple (1, numberOfSamples / sampleRate, sampleRate);   // STEREO BUG
		Melder_assert (my nx == numberOfSamples);

		/*
		 * Open phase 2.
		 * This starts recording now.
		 */

		if (inputUsesPortAudio) {
			streamParameters. suggestedLatency = Pa_GetDeviceInfo (inputSource - 1) -> defaultLowInputLatency;
			#if defined (macintosh)
				PaMacCoreStreamInfo macCoreStreamInfo = { 0 };
				macCoreStreamInfo. size = sizeof (PaMacCoreStreamInfo);
				macCoreStreamInfo. hostApiType = paCoreAudio;
				macCoreStreamInfo. version = 0x01;
				macCoreStreamInfo. flags = paMacCoreChangeDeviceParameters | paMacCoreFailIfConversionRequired;
				streamParameters. hostApiSpecificStreamInfo = & macCoreStreamInfo;
			#endif
			info. numberOfSamples = numberOfSamples;
			info. numberOfSamplesRead = 0;
			info. buffer = buffer.peek();
			PaError err = Pa_OpenStream (& portaudioStream, & streamParameters, NULL,
				sampleRate, 0, paNoFlag, portaudioStreamCallback, (void *) & info);
			if (err)
				Melder_throw (U"open ", Melder_peek8to32 (Pa_GetErrorText (err)));
			Pa_StartStream (portaudioStream);
			if (err)
				Melder_throw (U"start ", Melder_peek8to32 (Pa_GetErrorText (err)));
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
				waveFormat. cbSize = 0;
				err = waveInOpen (& hWaveIn, WAVE_MAPPER, & waveFormat, 0, 0, CALLBACK_NULL);
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while opening.");
			#endif
		}
for (i = 1; i <= numberOfSamples; i ++) trace (U"Started ", buffer [i]);

		/* Read the sound into the buffer. */

		if (inputUsesPortAudio) {
			// The callback will do this. Just wait.
			while (/*getNumberOfSamplesRead (& info)*/ info. numberOfSamplesRead < numberOfSamples) {
				//Pa_Sleep (1);
				//Melder_casual ("filled %ld/%ld", getNumberOfSamplesRead (& info), numberOfSamples);
			}
for (i = 1; i <= numberOfSamples; i ++) trace (U"Recorded ", buffer [i]);
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
				waveHeader. dwFlags = 0;
				waveHeader. lpData = (char *) & buffer [1];
				waveHeader. dwBufferLength = numberOfSamples * 2;
				waveHeader. dwLoops = 0;
				waveHeader. lpNext = NULL;
				waveHeader. reserved = 0;
				err = waveInPrepareHeader (hWaveIn, & waveHeader, sizeof (WAVEHDR));
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while preparing header.");
				err = waveInAddBuffer (hWaveIn, & waveHeader, sizeof (WAVEHDR));
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while listening.");
				err = waveInStart (hWaveIn);
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while starting.");
					while (! (waveHeader. dwFlags & WHDR_DONE)) { Pa_Sleep (1); }
				err = waveInUnprepareHeader (hWaveIn, & waveHeader, sizeof (WAVEHDR));
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while unpreparing header.");
			#else
				if (mulaw)
					read (fd, (char *) & buffer [1], numberOfSamples);
				else {
					long bytesLeft = 2 * numberOfSamples, dbytes, bytesRead = 0;
					while (bytesLeft) {
						//Melder_casual ("Reading %ld bytes", bytesLeft > 4000 ? 4000 : bytesLeft);
						dbytes = read (fd, & ((char *) buffer.peek()) [2 + bytesRead], bytesLeft > 4000 ? 4000 : bytesLeft);
						//Melder_casual("Read %ld bytes", dbytes);
						if (dbytes <= 0) break;
						bytesLeft -= dbytes;
						bytesRead += dbytes;
					};
				}
			#endif
		}

		/* Copy the buffered data to the sound object, and discard the buffer. */

		if (fakeMonoByStereo)
			for (i = 1; i <= numberOfSamples; i ++)
				my z [1] [i] = ((long) buffer [i + i - 1] + buffer [i + i]) * (1.0 / 65536);
		else if (mulaw)
			for (i = 1; i <= numberOfSamples; i ++)
				my z [1] [i] = ulaw2linear [((unsigned char *) buffer.peek()) [i]] * (1.0 / 32768);
		else if (can16bit)
			for (i = 1; i <= numberOfSamples; i ++)
				my z [1] [i] = buffer [i] * (1.0 / 32768);
		else
			for (i = 1; i <= numberOfSamples; i ++)
				my z [1] [i] = ((int) ((unsigned char *) buffer.peek()) [i + 1] - 128) * (1.0 / 128);

		/* Close the audio device. */

		if (inputUsesPortAudio) {
			Pa_StopStream (portaudioStream);
			Pa_CloseStream (portaudioStream);
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
				err = waveInClose (hWaveIn);
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while closing.");
			#else
				close (fd);
			#endif
		}

		/* Hand the resulting sound to the caller. */

		return me.transfer();
	} catch (MelderError) {
		if (inputUsesPortAudio) {
			if (portaudioStream) Pa_StopStream (portaudioStream);
			if (portaudioStream) Pa_CloseStream (portaudioStream);
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
				if (hWaveIn != 0) waveInClose (hWaveIn);
			#else
				if (fd_mixer != -1) close (fd_mixer);
				if (fd != -1) close (fd);
			#endif
		}
		Melder_throw (U"Sound not recorded.");
	}
}
Exemple #24
0
static void update (CategoriesEditor me, long from, long to, const long *select, long nSelect) {
	long size = ((Categories) my data) -> size;

	if (size == 0) {
		autoSimpleString str = SimpleString_create (CategoriesEditor_EMPTYLABEL);
		Collection_addItem_move ((Categories) my data, str.move());
		update (me, 0, 0, nullptr, 0);
		return;
	}
	if (from == 0 && from == to) {
		from = 1; to = size;
	}
	if (from < 1 || from > size) {
		from = size;
	}
	if (to < 1 || to > size) {
		to = size;
	}
	if (from > to) {
		long ti = from; from = to; to = ti;
	}

	// Begin optimization: add the items from a table instead of separately.
	try {
		autostring32vector table (from, to);
		long itemCount = GuiList_getNumberOfItems (my list);
		for (long i = from; i <= to; i++) {
			char wcindex[20];
			snprintf (wcindex,20, "%5ld ", i);
			table[i] = Melder_dup_f (Melder_cat (Melder_peek8to32 (wcindex), OrderedOfString_itemAtIndex_c ((OrderedOfString) my data, i)));
		}
		if (itemCount > size) { // some items have been removed from Categories?
			for (long j = itemCount; j > size; j --) {
				GuiList_deleteItem (my list, j);
			}
			itemCount = size;
		}
		if (to > itemCount) {
			for (long j = 1; j <= to - itemCount; j ++) {
				GuiList_insertItem (my list, table [itemCount + j], 0);
			}
		}
		if (from <= itemCount) {
			long n = (to < itemCount ? to : itemCount);
			for (long j = from; j <= n; j++) {
				GuiList_replaceItem (my list, table[j], j);
			}
		}
	} catch (MelderError) {
		throw;
	}

	// End of optimization

	// HIGHLIGHT

	GuiList_deselectAllItems (my list);
	if (size == 1) { /* the only item is always selected */
		const char32 *catg = OrderedOfString_itemAtIndex_c ((OrderedOfString) my data, 1);
		GuiList_selectItem (my list, 1);
		updateWidgets (me);   // instead of "notify". BUG?
		GuiText_setString (my text, catg);
	} else if (nSelect > 0) {
		// Select but postpone highlighting

		for (long i = 1; i <= nSelect; i++) {
			GuiList_selectItem (my list, select[i] > size ? size : select[i]);
		}
	}

	// VIEWPORT

	{
		long top = GuiList_getTopPosition (my list), bottom = GuiList_getBottomPosition (my list);
		long visible = bottom - top + 1;
		if (nSelect == 0) {
			top = my position - visible / 2;
		} else if (select[nSelect] < top) {
			// selection above visible area
			top = select[1];
		} else if (select[1] > bottom) {
			// selection below visible area
			top = select[nSelect] - visible + 1;
		} else {
			long deltaTopPos = -1, nUpdate = to - from + 1;
			if ( (from == select[1] && to == select[nSelect]) || // Replace
			        (nUpdate > 2 && nSelect == 1) /* Inserts */) {
				deltaTopPos = 0;
			} else if (nUpdate == nSelect + 1 && select[1] == from + 1) { // down
				deltaTopPos = 1;
			}
			top += deltaTopPos;
		}
		if (top + visible > size) {
			top = size - visible + 1;
		}
		if (top < 1) {
			top = 1;
		}
		GuiList_setTopPosition (my list, top);
	}
}
Exemple #25
0
int Praat_tests (int itest, char32 *arg1, char32 *arg2, char32 *arg3, char32 *arg4) {
	int64 n = Melder_atoi (arg1);
	double t = 0.0;
	(void) arg1;
	(void) arg2;
	(void) arg3;
	(void) arg4;
	Melder_clearInfo ();
	Melder_stopwatch ();
	switch (itest) {
		case kPraatTests_TIME_RANDOM_FRACTION: {
			for (int64 i = 1; i <= n; i ++)
				(void) NUMrandomFraction ();
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_RANDOM_GAUSS: {
			for (int64 i = 1; i <= n; i ++)
				(void) NUMrandomGauss (0.0, 1.0);
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_SORT: {
			long m = Melder_atoi (arg2);
			long *array = NUMvector <long> (1, m);
			for (int64 i = 1; i <= m; i ++)
				array [i] = NUMrandomInteger (1, 100);
			Melder_stopwatch ();
			for (int64 i = 1; i <= n; i ++)
				NUMsort_l (m, array);
			t = Melder_stopwatch ();
			NUMvector_free (array, 1);
		} break;
		case kPraatTests_TIME_INTEGER: {
			int64 sum = 0;
			for (int64 i = 1; i <= n; i ++)
				sum += i * (i - 1) * (i - 2);
			t = Melder_stopwatch ();
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_FLOAT: {
			double sum = 0.0, fn = n;
			for (double fi = 1.0; fi <= fn; fi = fi + 1.0)
				sum += fi * (fi - 1.0) * (fi - 2.0);
			t = Melder_stopwatch ();
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_FLOAT_TO_UNSIGNED_BUILTIN: {
			uint64_t sum = 0;
			double fn = n;
			for (double fi = 1.0; fi <= fn; fi = fi + 1.0)
				sum += (uint32) fi;
			t = Melder_stopwatch ();   // 2.59   // 1.60
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_FLOAT_TO_UNSIGNED_EXTERN: {
			uint64_t sum = 0;
			double fn = n;
			for (double fi = 1.0; fi <= fn; fi = fi + 1.0)
				sum += (uint32) ((int32) (fi - 2147483648.0) + 2147483647L + 1);
			t = Melder_stopwatch ();   // 1.60
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_UNSIGNED_TO_FLOAT_BUILTIN: {
			double sum = 0.0;
			uint32 nu = (uint32) n;
			for (uint32 iu = 1; iu <= nu; iu ++)
				sum += (double) iu;
			t = Melder_stopwatch ();   // 1.35
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_UNSIGNED_TO_FLOAT_EXTERN: {
			double sum = 0.0;
			uint32 nu = (uint32) n;
			for (uint32 iu = 1; iu <= nu; iu ++)
				sum += (double) (int32) (iu - 2147483647L - 1) + 2147483648.0;
			t = Melder_stopwatch ();   // 0.96
			MelderInfo_writeLine (sum);
		} break;
		case kPraatTests_TIME_STRING_MELDER_32: {
			autoMelderString string;
			char32 word [] { U"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				MelderString_copy (& string, word);
				for (int j = 1; j <= 30; j ++)
					MelderString_append (& string, word);
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_MELDER_32_ALLOC: {
			char32 word [] { U"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				autoMelderString string;
				MelderString_copy (& string, word);
				for (int j = 1; j <= 30; j ++)
					MelderString_append (& string, word);
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_S: {
			std::string s = "";
			char word [] { "abc" };
			word [2] = (char) NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_C: {
			std::basic_string<char> s = "";
			char word [] { "abc" };
			word [2] = (char) NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_WS: {
			std::wstring s = L"";
			wchar_t word [] { L"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_WC: {
			std::basic_string<wchar_t> s = L"";
			wchar_t word [] { L"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_32: {
			std::basic_string<char32_t> s = U"";
			char32 word [] { U"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRING_CPP_U32STRING: {
			std::u32string s = U"";
			char32 word [] { U"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				s = word;
				for (int j = 1; j <= 30; j ++)
					s += word;
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STRCPY: {
			char buffer [100];
			char word [] { "abc" };
			word [2] = (char) NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				strcpy (buffer, word);
				for (int j = 1; j <= 30; j ++)
					strcpy (buffer + strlen (buffer), word);
			}
			t = Melder_stopwatch ();
			MelderInfo_writeLine (Melder_peek8to32 (buffer));
		} break;
		case kPraatTests_TIME_WCSCPY: {
			wchar_t buffer [100];
			wchar_t word [] { L"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				wcscpy (buffer, word);
				for (int j = 1; j <= 30; j ++)
					wcscpy (buffer + wcslen (buffer), word);
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_TIME_STR32CPY: {
			char32 buffer [100];
			char32 word [] { U"abc" };
			word [2] = NUMrandomInteger ('a', 'z');
			for (int64 i = 1; i <= n; i ++) {
				str32cpy (buffer, word);
				for (int j = 1; j <= 30; j ++)
					str32cpy (buffer + str32len (buffer), word);
			}
			t = Melder_stopwatch ();
			MelderInfo_writeLine (buffer);
		} break;
		case kPraatTests_TIME_GRAPHICS_TEXT_TOP: {
			autoPraatPicture picture;
			for (int64 i = 1; i <= n; i ++) {
				Graphics_textTop (GRAPHICS, false, U"hello world");
			}
			t = Melder_stopwatch ();
		} break;
		case kPraatTests_THING_AUTO: {
			int numberOfThingsBefore = theTotalNumberOfThings;
			{
				Melder_casual (U"1\n");
				autoDaata data = Thing_new (Daata);
				Thing_setName (data.get(), U"hello");
				Melder_casual (U"2\n");
				testData (data.get());
				testAutoData (data.move());
				autoDaata data18 = Thing_new (Daata);
				testAutoData (data18.move());
				fprintf (stderr, "3\n");
				autoDaata data2 = newAutoData ();
				fprintf (stderr, "4\n");
				autoDaata data3 = newAutoData ();
				fprintf (stderr, "5\n");
				//data2 = data;   // disabled l-value copy assignment from same class
				fprintf (stderr, "6\n");
				autoOrdered ordered = Thing_new (Ordered);
				fprintf (stderr, "7\n");
				//data = ordered;   // disabled l-value copy assignment from subclass
				data = ordered.move();
				//ordered = data;   // disabled l-value copy assignment from superclass
				//ordered = data.move();   // assignment from superclass to subclass is rightfully refused by compiler
				fprintf (stderr, "8\n");
				data2 = newAutoData ();
				fprintf (stderr, "8a\n");
				autoDaata data5 = newAutoData ();
				fprintf (stderr, "8b\n");
				data2 = data5.move();
				fprintf (stderr, "9\n");
				//ordered = data;   // rightfully refused by compiler
				fprintf (stderr, "10\n");
				//autoOrdered ordered2 = Thing_new (Daata);   // rightfully refused by compiler
				fprintf (stderr, "11\n");
				autoDaata data4 = Thing_new (Ordered);   // constructor
				fprintf (stderr, "12\n");
				//autoDaata data6 = data4;   // disabled l-value copy constructor from same class
				fprintf (stderr, "13\n");
				autoDaata data7 = data4.move();
				fprintf (stderr, "14\n");
				autoOrdered ordered3 = Thing_new (Ordered);
				autoDaata data8 = ordered3.move();
				fprintf (stderr, "15\n");
				//autoDaata data9 = ordered;   // disabled l-value copy constructor from subclass
				fprintf (stderr, "16\n");
				autoDaata data10 = data7.move();
				fprintf (stderr, "17\n");
				autoDaata data11 = Thing_new (Daata);   // constructor, move assignment, null destructor
				fprintf (stderr, "18\n");
				data11 = Thing_new (Ordered);
				fprintf (stderr, "19\n");
				testAutoDataRef (data11);
				fprintf (stderr, "20\n");
				//data11 = nullptr;   // disabled implicit assignment of pointer to autopointer
				fprintf (stderr, "21\n");
			}
			int numberOfThingsAfter = theTotalNumberOfThings;
			fprintf (stderr, "Number of things: before %d, after %d\n", numberOfThingsBefore, numberOfThingsAfter);
			#if 1
				MelderCallback<void,structDaata>::FunctionType f;
				typedef void (*DataFunc) (Daata);
				typedef void (*OrderedFunc) (Ordered);
				DataFunc dataFun;
				OrderedFunc orderedFun;
				MelderCallback<void,structDaata> dataFun2 (dataFun);
				MelderCallback<void,structOrdered> orderedFun2 (orderedFun);
				MelderCallback<void,structDaata> dataFun3 (orderedFun);
				//MelderCallback<void,structOrdered> orderedFun3 (dataFun);   // rightfully refused by compiler
				autoDaata data = Thing_new (Daata);
				dataFun3 (data.get());
			#endif
		} break;
	}
	MelderInfo_writeLine (Melder_single (t / n * 1e9), U" nanoseconds");
	MelderInfo_close ();
	return 1;
}
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".");
	}
}
char * espeakdata_get_dict_data (const char *name, unsigned int *size) {
	long lsize;
	char *data = FilesInMemory_getCopyOfData (espeakdata_dicts, Melder_peek8to32 (name), &lsize);
	*size = (unsigned int) lsize;
	return data;
}
const char * espeakdata_get_voice (const char *vname, long *numberOfBytes) {
	return FilesInMemory_getData (espeakdata_voices, Melder_peek8to32 (vname), numberOfBytes);
}
Exemple #29
0
voice_t *LoadVoice(const char *vname, int control)
{//===============================================
// control, bit 0  1= no_default
//          bit 1  1 = change tone only, not language
//          bit 2  1 = don't report error on LoadDictionary
//          bit 4  1 = vname = full path

	FILE *f_voice = NULL;
	char *p;
	int  key;
	int  ix;
	int  n;
	int  value;
	int  value2;
	int  langix = 0;
	int  tone_only = control & 2;
	int  language_set = 0;
	int  phonemes_set = 0;
	int  stress_amps_set = 0;
	int  stress_lengths_set = 0;
	int  stress_add_set = 0;
	int  conditional_rules = 0;
	LANGUAGE_OPTIONS *langopts = NULL;

	Translator *new_translator = NULL;

	char voicename[40];
	char language_name[40];
	char translator_name[40];
	char new_dictionary[40];
	char phonemes_name[40];
	char option_name[40];
	const char *language_type;
	char buf[sizeof(path_home)+30];
	char path_voices[sizeof(path_home)+12];

	int dict_min = 0;
	int stress_amps[8];
	int stress_lengths[8];
	int stress_add[8];
	char names[8][40];
	char name1[40];
	char name2[80];
	const char *voice_dir;

	int pitch1;
	int pitch2;

	static char voice_identifier[40];  // file name for  current_voice_selected
	static char voice_name[40];        // voice name for current_voice_selected
	static char voice_languages[100];  // list of languages and priorities for current_voice_selected

	// which directory to look for a named voice. List of voice names, must end in a space.
	static const char *voices_asia =
		"az bn fa fa-pin hi hy hy-west id ka kn ku ml ms ne pa ta te tr vi vi-hue vi-sgn zh zh-yue ";
	static const char *voices_europe =
		"an bg bs ca cs cy da de el en en-us es et fi fr fr-be ga hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";
	strncpy0 (voicename, vname, sizeof(voicename));

#ifdef DATA_FROM_SOURCECODE_FILES
	long numberOfBytes;
	const char * data;
	if (tone_only) {
		data = espeakdata_get_voiceVariant (vname, &numberOfBytes);
	} else {
		language_type = "en";
		data = espeakdata_get_voice (vname, &numberOfBytes);
		language_type = vname;
	}
	if (data == 0) {
		language_type = "en";    // default
		data = espeakdata_get_voice ("en/en", &numberOfBytes);
	}
	language_type = "en";
#else
	if(control & 0x10)
	{
		strcpy(buf,vname);
		if(GetFileLength(buf) <= 0)
			return(NULL);
	}
	else
	{
		if(voicename[0]==0)
			strcpy(voicename,"default");

		sprintf(path_voices,"%s%cvoices%c",path_home,PATHSEP,PATHSEP);
		sprintf(buf,"%s%s",path_voices,voicename);  // first, look in the main voices directory

		if(GetFileLength(buf) <= 0)
		{
			// then look in the appropriate subdirectory
			if((voicename[0]=='m') && (voicename[1]=='b'))
			{
				voice_dir = "mb";   // mbrola voices
			}
			else
			{
				sprintf(name2, "%s ", voicename);
				if(strstr(voices_europe, voicename) != NULL)
					voice_dir = "europe";
				else if(strstr(voices_asia, voicename) != NULL)
					voice_dir = "asia";
				else
					voice_dir = "other";

				sprintf(buf,"%s%s%c%s", path_voices,voice_dir,PATHSEP,voicename);

				if(GetFileLength(buf) <= 0)
				{
					// if not found, look in "test" sub-directory
					sprintf(buf,"%stest%c%s",path_voices,PATHSEP,voicename);
				}
			}
		}
	}

	f_voice = fopen(buf,"r");

	language_type = "en";    // default
	if(f_voice == NULL)
	{
		if(control & 3)
			return(NULL);  // can't open file

		if(SelectPhonemeTableName(voicename) >= 0)
			language_type = voicename;
	}
#endif

	if(!tone_only && (translator != NULL))
	{
		DeleteTranslator(translator);
		translator = NULL;
	}

	strcpy(translator_name,language_type);
	strcpy(new_dictionary,language_type);
	strcpy(phonemes_name,language_type);


	if(!tone_only)
	{
		voice = &voicedata;
		strncpy0(voice_identifier,vname,sizeof(voice_identifier));
		voice_name[0] = 0;
		voice_languages[0] = 0;

		current_voice_selected.identifier = voice_identifier;
		current_voice_selected.name = voice_name;
		current_voice_selected.languages = voice_languages;
	}
	else
	{
		// append the variant file name to the voice identifier
		if((p = strchr(voice_identifier,'+')) != NULL)
			*p = 0;    // remove previous variant name
		sprintf(buf,"+%s",&vname[3]);    // TODO was vname[0], omit  !v/  from the variant filename
		strcat(voice_identifier,buf);
		langopts = &translator->langopts;
	}
	VoiceReset(tone_only);

	if(!tone_only)
		SelectPhonemeTableName(phonemes_name);  // set up phoneme_tab

#ifdef DATA_FROM_SOURCECODE_FILES
	long index = 0;
	const char *start = data;
	while (!! (start = espeakdata_get_voicedata (start, numberOfBytes, buf, sizeof(buf), &index))) {
#else
	while((f_voice != NULL) && (fgets_strip(buf,sizeof(buf),f_voice) != NULL)) {
#endif
		// isolate the attribute name
		for(p=buf; (*p != 0) && !isspace(*p); p++);
		*p++ = 0;

		if(buf[0] == 0) continue;

		key = LookupMnem(keyword_tab, buf);

		switch(key)
		{
		case V_LANGUAGE:
		{
			unsigned int len;
			int priority;

			if(tone_only)
				break;

			priority = DEFAULT_LANGUAGE_PRIORITY;
			language_name[0] = 0;

			sscanf(p,"%s %d",language_name,&priority);
			if(strcmp(language_name,"variant") == 0)
				break;

			len = strlen(language_name) + 2;
			// check for space in languages[]
			if(len < (sizeof(voice_languages)-langix-1))
			{
				voice_languages[langix] = priority;

				strcpy(&voice_languages[langix+1],language_name);
				langix += len;
			}

			// only act on the first language line
			if(language_set == 0)
			{
				language_type = strtok(language_name,"-");
				language_set = 1;
				strcpy(translator_name,language_type);
				strcpy(new_dictionary,language_type);
				strcpy(phonemes_name,language_type);
				SelectPhonemeTableName(phonemes_name);

				if(new_translator != NULL)
					DeleteTranslator(new_translator);

				new_translator = SelectTranslator(translator_name);
				langopts = &new_translator->langopts;
				strncpy0(voice->language_name, language_name, sizeof(voice->language_name));
			}
		}
		break;

		case V_NAME:
			if(tone_only == 0)
			{
				while(isspace(*p)) p++;
				strncpy0(voice_name,p,sizeof(voice_name));
			}
			break;

		case V_GENDER:
		{
			int age = 0;
			char vgender[80];
			sscanf(p,"%s %d",vgender,&age);
			current_voice_selected.gender = LookupMnem(genders,vgender);
			current_voice_selected.age = age;
		}
		break;

		case V_TRANSLATOR:
			if(tone_only) break;

			sscanf(p,"%s",translator_name);

			if(new_translator != NULL)
				DeleteTranslator(new_translator);

			new_translator = SelectTranslator(translator_name);
			langopts = &new_translator->langopts;
			break;

		case V_DICTIONARY:        // dictionary
			sscanf(p,"%s",new_dictionary);
			break;

		case V_PHONEMES:        // phoneme table
			sscanf(p,"%s",phonemes_name);
			break;

		case V_FORMANT:
			VoiceFormant(p);
			break;

		case V_PITCH:
		{
			double factor;
			// default is  pitch 82 118
			n = sscanf(p,"%d %d",&pitch1,&pitch2);
			voice->pitch_base = (pitch1 - 9) << 12;
			voice->pitch_range = (pitch2 - pitch1) * 108;
			factor = (double)(pitch1 - 82)/82;
			voice->formant_factor = (int)((1+factor/4) * 256);  // nominal formant shift for a different voice pitch
		}
		break;

		case V_STRESSLENGTH:   // stressLength
			stress_lengths_set = Read8Numbers(p,stress_lengths);
			break;

		case V_STRESSAMP:   // stressAmp
			stress_amps_set = Read8Numbers(p,stress_amps);
			break;

		case V_STRESSADD:   // stressAdd
			stress_add_set = Read8Numbers(p,stress_add);
			break;

		case V_INTONATION:   // intonation
			sscanf(p,"%d %d",&option_tone_flags,&option_tone2);
			if((option_tone_flags & 0xff) != 0)
				langopts->intonation_group = option_tone_flags & 0xff;
			break;

		case V_TUNES:
			n = sscanf(p,"%s %s %s %s %s %s",names[0],names[1],names[2],names[3],names[4],names[5]);
			langopts->intonation_group = 0;
			for(ix=0; ix<n; ix++)
			{
				if(strcmp(names[ix],"NULL")==0)
					continue;

				if((value = LookupTune(names[ix])) < 0)
					fprintf(stderr,"Unknown tune '%s'\n",names[ix]);
				else
					langopts->tunes[ix] = value;
			}
			break;

		case V_DICTRULES:   // conditional dictionary rules and list entries
		case V_NUMBERS:
		case V_STRESSOPT:
			// expect a list of numbers
			while(*p != 0)
			{
				while(isspace(*p)) p++;
				n = -1;
				if((n = atoi(p)) > 0)
				{
					p++;
					if(n < 32)
					{
						if(key==V_DICTRULES)
							conditional_rules |= (1 << n);
						else if(key==V_NUMBERS)
							langopts->numbers |= (1 << n);
						else if(key==V_STRESSOPT)
							langopts->stress_flags |= (1 << n);
					}
					else
					{
						if((key==V_NUMBERS) && (n < 64))
							langopts->numbers |= (1 << (n-32));
						else
							fprintf(stderr,"Bad option number %d\n", n);
					}
				}
				while(isalnum(*p)) p++;
			}
			ProcessLanguageOptions(langopts);
			break;

		case V_REPLACE:
			if(phonemes_set == 0)
			{
				// must set up a phoneme table before we can lookup phoneme mnemonics
				SelectPhonemeTableName(phonemes_name);
				phonemes_set = 1;
			}
			PhonemeReplacement(key,p);
			break;

		case V_WORDGAP:   // words
			sscanf(p,"%d %d",&langopts->word_gap, &langopts->vowel_pause);
			break;

		case V_STRESSRULE:
			sscanf(p,"%d %d %d %d",&langopts->stress_rule,
				   &langopts->stress_flags,
				   &langopts->unstressed_wd1,
				   &langopts->unstressed_wd2);
			break;

		case V_CHARSET:
			if((sscanf(p,"%d",&value)==1) && (value < N_CHARSETS))
				new_translator->charset_a0 = charsets[value];
			break;

		case V_OPTION:
			value2 = 0;
			if(((sscanf(p,"%s %d %d",option_name,&value,&value2) >= 2) && ((ix = LookupMnem(options_tab, option_name)) >= 0)) ||
				((sscanf(p,"%d %d %d",&ix,&value,&value2) >= 2) && (ix < N_LOPTS)))
			{
				langopts->param[ix] = value;
				langopts->param2[ix] = value2;
			}
			else
			{
				fprintf(stderr,"Bad voice option: %s %s\n",buf,p);
			}
			break;

		case V_ECHO:
			// echo.  suggest: 135mS  11%
			value = 0;
			voice->echo_amp = 0;
			sscanf(p,"%d %d",&voice->echo_delay,&voice->echo_amp);
			break;

		case V_FLUTTER:   // flutter
			if(sscanf(p,"%d",&value)==1)
				voice->flutter = value * 32;
			break;

		case V_ROUGHNESS:   // roughness
			if(sscanf(p,"%d",&value)==1)
				voice->roughness = value;
			break;

		case V_CLARITY:  // formantshape
			if(sscanf(p,"%d",&value)==1)
			{
				if(value > 4)
				{
					voice->peak_shape = 1;  // squarer formant peaks
					value = 4;
				}
				voice->n_harmonic_peaks = 1+value;
			}
			break;

		case V_TONE:
		{
			int tone_data[12];
			ReadTonePoints(p,tone_data);
			SetToneAdjust(voice,tone_data);
		}
		break;

		case V_VOICING:
			if(sscanf(p,"%d",&value)==1)
				voice->voicing = (value * 64)/100;
			break;

		case V_BREATH:
			voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
			for(ix=1; ix<8; ix++)
			{
				if(ix % 2)
					voice->breath[ix] = -voice->breath[ix];
			}
			break;

		case V_BREATHW:
			voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
			break;

		case V_CONSONANTS:
			value = sscanf(p,"%d %d",&voice->consonant_amp, &voice->consonant_ampv);
			break;

		case V_SPEED:
			sscanf(p,"%d",&voice->speed_percent);
			break;

		case V_MBROLA:
		{
			int srate = 16000;

			name2[0] = 0;
			sscanf(p,"%s %s %d",name1,name2,&srate);
			if(LoadMbrolaTable(name1,name2,srate) != EE_OK)
			{
				fprintf(stderr,"mbrola voice not found\n");
			}
			voice->samplerate = srate;
		}
		break;

		case V_KLATT:
			voice->klattv[0] = 1;  // default source: IMPULSIVE
			Read8Numbers(p,voice->klattv);
			voice->klattv[KLATT_Kopen] -= 40;
			break;

		case V_FAST:
			Read8Numbers(p,speed.fast_settings);
			SetSpeed(3);
			break;

		case V_DICTMIN:
			sscanf(p,"%d",&dict_min);
			break;

		case V_ALPHABET2:
			{
				ALPHABET *alphabet;
				name1[0] = name2[0] = 0;
				sscanf(p, "%s %s", name1, name2);

				if(strcmp(name1, "latin") == 0)
				{
					strncpy0(langopts->ascii_language,name2,sizeof(langopts->ascii_language));
				}
				else if((alphabet = AlphabetFromName(name1)) != 0)
				{
					langopts->alt_alphabet = alphabet->offset;
					langopts->alt_alphabet_lang = StringToWord2(name2);
				}
				else
				{
					fprintf(stderr,"alphabet name '%s' not found\n", name1);
				}
			}
			break;

		case V_DICTDIALECT:
			// specify a dialect to use for foreign words, eg, en-us for _^_EN
			if(sscanf(p, "%s", name1) == 1)
			{
				if((ix = LookupMnem(dict_dialects, name1)) > 0)
				{
					langopts->dict_dialect |= (1 << ix);
				}
				else
				{
					fprintf(stderr, "dictdialect name '%s' not recognized\n", name1);
				}
			}
			break;

		default:
			if((key & 0xff00) == 0x100)
			{
				sscanf(p,"%d",&langopts->param[key &0xff]);
			}
			else
			{
				fprintf(stderr,"Bad voice attribute: %s\n",buf);
			}
			break;
		}
	}
	if(f_voice != NULL)
		fclose(f_voice);

	if((new_translator == NULL) && (!tone_only))
	{
		// not set by language attribute
		new_translator = SelectTranslator(translator_name);
	}

	SetSpeed(3);   // for speed_percent

	for(ix=0; ix<N_PEAKS; ix++)
	{
		voice->freq2[ix] = voice->freq[ix];
		voice->height2[ix] = voice->height[ix];
		voice->width2[ix] = voice->width[ix];
	}

	if(tone_only)
	{
		new_translator = translator;
	}
	else
	{
		if((ix = SelectPhonemeTableName(phonemes_name)) < 0)
		{
			Melder_throw (U"Unknown phoneme table: ", Melder_peek8to32 (phonemes_name));
		}
		voice->phoneme_tab_ix = ix;
		new_translator->phoneme_tab_ix = ix;
		new_translator->dict_min_size = dict_min;
		LoadDictionary(new_translator, new_dictionary, control & 4);
		if(dictionary_name[0]==0)
			return(NULL);   // no dictionary loaded

		new_translator->dict_condition = conditional_rules;

		voice_languages[langix] = 0;
	}

	langopts = &new_translator->langopts;


	if((value = langopts->param[LOPT_LENGTH_MODS]) != 0)
	{
		SetLengthMods(new_translator,value);
	}

	voice->width[0] = (voice->width[0] * 105)/100;

	if(!tone_only)
	{
		translator = new_translator;
	}


	// relative lengths of different stress syllables
	for(ix=0; ix<stress_lengths_set; ix++)
	{
		translator->stress_lengths[ix] = stress_lengths[ix];
	}
	for(ix=0; ix<stress_add_set; ix++)
	{
		translator->stress_lengths[ix] += stress_add[ix];
	}
	for(ix=0; ix<stress_amps_set; ix++)
	{
		translator->stress_amps[ix] = stress_amps[ix];
		translator->stress_amps_r[ix] = stress_amps[ix] -1;
	}

	return(voice);
}  //  end of LoadVoice


static char *ExtractVoiceVariantName(char *vname, int variant_num, int add_dir)
{//===========================================================================
// Remove any voice variant suffix (name or number) from a voice name
// Returns the voice variant name

	char *p;
	static char variant_name[40];
	char variant_prefix[5];

	variant_name[0] = 0;
	sprintf(variant_prefix,"!v%c",PATHSEP);
	if(add_dir == 0)
		variant_prefix[0] = 0;

	if(vname != NULL)
	{
		if((p = strchr(vname,'+')) != NULL)
		{
			// The voice name has a +variant suffix
			variant_num = 0;
			*p++ = 0;   // delete the suffix from the voice name
			if(IsDigit09(*p))
			{
				variant_num = atoi(p);  // variant number
			}
			else
			{
				// voice variant name, not number
				sprintf(variant_name, "%s%s", variant_prefix, p);
			}
		}
	}

	if(variant_num > 0)
	{
		if(variant_num < 10)
			sprintf(variant_name,"%sm%d",variant_prefix, variant_num);  // male
		else
			sprintf(variant_name,"%sf%d",variant_prefix, variant_num-10);  // female
	}

	return(variant_name);
}  //  end of ExtractVoiceVariantName
const char * espeakdata_get_voiceVariant (const char *vname, long *numberOfBytes) {
	char *plus = strstr ((char *) vname, "+"); // prototype says: strstr (const char *, const char *)
	const char *name = plus != NULL ? ++plus : vname;
	return FilesInMemory_getData (espeakdata_variants, Melder_peek8to32 (name), numberOfBytes);;
}