示例#1
0
static int compile_line(char *linebuf, char *dict_line, int *hash)
{//===============================================================
// Compile a line in the language_list file
	unsigned char  c;
	char *p;
	char *word;
	char *phonetic;
	unsigned int  ix;
	int  step;
	unsigned int  n_flag_codes = 0;
	int  flag_offset;
	int  length;
	int  multiple_words = 0;
	char *multiple_string = NULL;
	char *multiple_string_end = NULL;
	
	int len_word;
	int len_phonetic;
	int text_not_phonemes;   // this word specifies replacement text, not phonemes
	unsigned int  wc;
	int all_upper_case;
	
	char *mnemptr;
	char *comment;
	unsigned char flag_codes[100];
	char encoded_ph[200];
	unsigned char bad_phoneme[4];
static char nullstring[] = {0};

	comment = NULL;
	text_not_phonemes = 0;
	phonetic = word = nullstring;

if(memcmp(linebuf,"_-",2)==0)
{
step=1;  // TEST
}
	p = linebuf;
//	while(isspace2(*p)) p++;

#ifdef deleted
	if(*p == '$')
	{
		if(memcmp(p,"$textmode",9) == 0)
		{
			text_mode = 1;
			return(0);
		}
		if(memcmp(p,"$phonememode",12) == 0)
		{
			text_mode = 0;
			return(0);
		}
	}
#endif

	step = 0;
	
	c = 0;
	while(c != '\n')
	{
		c = *p;
	
		if((c == '?') && (step==0))
		{
			// conditional rule, allow only if the numbered condition is set for the voice
			flag_offset = 100;

			p++;
			if(*p == '!')
			{
				// allow only if the numbered condition is NOT set
				flag_offset = 132;
				p++;
			}

			ix = 0;
			if(isdigit(*p))
			{
				ix += (*p-'0');
				p++;
			}
			if(isdigit(*p))
			{
				ix = ix*10 + (*p-'0');
				p++;
			}
			flag_codes[n_flag_codes++] = ix + flag_offset;
			c = *p;
		}
		
		if((c == '$') && isalnum(p[1]))
		{
			/* read keyword parameter */
			mnemptr = p;
			while(!isspace2(c = *p)) p++;
			*p = 0;
	
			ix = LookupMnem(mnem_flags,mnemptr);
			if(ix > 0)
			{
				if(ix == 200)
				{
					text_mode = 1;
				}
				else
				if(ix == 201)
				{
					text_mode = 0;
				}
				else
				if(ix == BITNUM_FLAG_TEXTMODE)
				{
					text_not_phonemes = 1;
				}
				else
				{
					flag_codes[n_flag_codes++] = ix;
				}
			}
			else
			{
				fprintf(f_log,"%5d: Unknown keyword: %s\n",linenum,mnemptr);
				error_count++;
			}
		}
	
		if((c == '/') && (p[1] == '/') && (multiple_words==0))
		{
			c = '\n';   /* "//" treat comment as end of line */
			comment = p;
		}
	
		switch(step)
		{
		case 0:
			if(c == '(')
			{
				multiple_words = 1;
				word = p+1;
				step = 1;
			}
			else
			if(!isspace2(c))
			{
				word = p;
				step = 1;
			}
			break;
	
		case 1:
			if((c == '-') && (word[0] != '_'))
			{
				flag_codes[n_flag_codes++] = BITNUM_FLAG_HYPHENATED;
				c = ' ';
			}
			if(isspace2(c))
			{
				p[0] = 0;   /* terminate english word */

				if(multiple_words)
				{
					multiple_string = multiple_string_end = p+1;
					step = 2;
				}
				else
				{
					step = 3;
				}
			}
			else
			if((c == ')') && multiple_words)
			{
				p[0] = 0;
				step = 3;
				multiple_words = 0;
			}
			break;

		case 2:
			if(isspace2(c))
			{
				multiple_words++;
			}
			else
			if(c == ')')
			{
				p[0] = ' ';   // terminate extra string
				multiple_string_end = p+1;
				step = 3;
			}
			break;
	
		case 3:
			if(!isspace2(c))
			{
				phonetic = p;
				step = 4;
			}
			break;
	
		case 4:
			if(isspace2(c))
			{
				p[0] = 0;   /* terminate phonetic */
				step = 5;
			}
			break;
	
		case 5:
			break;
		}
		p++;
	}
	
	if(word[0] == 0)
	{
#ifdef OPT_FORMAT
		if(comment != NULL)
			fprintf(f_log,"%s",comment);
		else
			fputc('\n',f_log);
#endif
		return(0);   /* blank line */
	}

	if(text_mode)
		text_not_phonemes = 1;

	if(text_not_phonemes != translator->langopts.textmode)
	{
		flag_codes[n_flag_codes++] = BITNUM_FLAG_TEXTMODE;
	}

	if(text_not_phonemes)
	{
		// this is replacement text, so don't encode as phonemes. Restrict the length of the replacement word
		strncpy0(encoded_ph,phonetic,N_WORD_BYTES-4);
	}
	else
	{
		EncodePhonemes(phonetic,encoded_ph,bad_phoneme);
		if(strchr(encoded_ph,phonSWITCH) != 0)
		{
			flag_codes[n_flag_codes++] = BITNUM_FLAG_ONLY_S;  // don't match on suffixes (except 's') when switching languages
		}

		// check for errors in the phonemes codes
		for(ix=0; ix<sizeof(encoded_ph); ix++)
		{
			c = encoded_ph[ix];
			if(c == 0)   break;
		
			if(c == 255)
			{
				/* unrecognised phoneme, report error */
				fprintf(f_log,"%5d: Bad phoneme [%c] (0x%x) in: %s  %s\n",linenum,bad_phoneme[0],bad_phoneme[0],word,phonetic);
				error_count++;
			}
		}
	}

	if(sscanf(word,"U+%x",&wc) == 1)
	{
		// Character code
		ix = utf8_out(wc, word);
		word[ix] = 0;
	}
	else
	if(word[0] != '_')
	{
		// convert to lower case, and note if the word is all-capitals
		int c2;

		all_upper_case = 1;
		p = word;
		for(p=word;;)
		{
			// this assumes that the lower case char is the same length as the upper case char
			// OK, except for Turkish "I", but use towlower() rather than towlower2()
			ix = utf8_in(&c2,p);
			if(c2 == 0)
				break;
			if(iswupper(c2))
			{
				utf8_out(towlower(c2),p);
			}
			else
			{
				all_upper_case = 0;
			}
			p += ix;
		}
		if(all_upper_case)
		{
			flag_codes[n_flag_codes++] = BITNUM_FLAG_ALLCAPS;
		}
	}

	len_word = strlen(word);

	if(transpose_offset > 0)
	{
		len_word = TransposeAlphabet(word, transpose_offset, transpose_min, transpose_max);
	}

	*hash = HashDictionary(word);
	len_phonetic = strlen(encoded_ph);
	
	dict_line[1] = len_word;   // bit 6 indicates whether the word has been compressed
	len_word &= 0x3f;

	memcpy(&dict_line[2],word,len_word);

	if(len_phonetic == 0)
	{
		// no phonemes specified. set bit 7
		dict_line[1] |= 0x80;
		length = len_word + 2;
	}
	else
	{
		length = len_word + len_phonetic + 3;
		strcpy(&dict_line[(len_word)+2],encoded_ph);
	}
	
	for(ix=0; ix<n_flag_codes; ix++)
	{
		dict_line[ix+length] = flag_codes[ix];
	}
	length += n_flag_codes;

	if((multiple_string != NULL) && (multiple_words > 0))
	{
		if(multiple_words > 10)
		{
			fprintf(f_log,"%5d: Two many parts in a multi-word entry: %d\n",linenum,multiple_words);
		}
		else
		{
			dict_line[length++] = 80 + multiple_words;
			ix = multiple_string_end - multiple_string;
			memcpy(&dict_line[length],multiple_string,ix);
			length += ix;
		}
	}
	dict_line[0] = length;

#ifdef OPT_FORMAT
	spaces = 16;
	for(ix=0; ix<n_flag_codes; ix++)
	{
		if(flag_codes[ix] >= 100)
		{
			fprintf(f_log,"?%d ",flag_codes[ix]-100);
			spaces -= 3;
		}
	}

	fprintf(f_log,"%s",word);
	spaces -= strlen(word);
	DecodePhonemes(encoded_ph,decoded_ph);
	while(spaces-- > 0) fputc(' ',f_log);
	spaces += (14 - strlen(decoded_ph));
	
	fprintf(f_log," %s",decoded_ph);
	while(spaces-- > 0) fputc(' ',f_log);
	for(ix=0; ix<n_flag_codes; ix++)
	{
		if(flag_codes[ix] < 100)
			fprintf(f_log," %s",lookup_mnem(mnem_flags,flag_codes[ix]));
	}
	if(comment != NULL)
		fprintf(f_log," %s",comment);
	else
		fputc('\n',f_log);
#endif

	return(length);
}  /* end of compile_line */
示例#2
0
static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*leafname)
{//===================================================================================
// Read a Voice file, allocate a VOICE_DATA and set data from the
// file's  language, gender, name  lines

	char linebuf[120];
	char vname[80];
	char vgender[80];
	char vlanguage[80];
	char languages[300];  // allow space for several alternate language names and priorities


	unsigned int len;
	int langix = 0;
	int n_languages = 0;
	char *p;
	espeak_VOICE *voice_data;
	int priority;
	int age;
	int n_variants = 4;    // default, number of variants of this voice before using another voice
	int gender;

#ifdef PLATFORM_WINDOWS
	char fname_buf[sizeof(path_home)+15];
	if(memcmp(leafname,"mb-",3) == 0)
	{
		// check whether the mbrola speech data is present for this voice
		memcpy(vname,&leafname[3],3);
		vname[3] = 0;
		sprintf(fname_buf,"%s/mbrola/%s",path_home,vname);

		if(GetFileLength(fname_buf) <= 0)
			return(0);
	}
#endif

	vname[0] = 0;
	vgender[0] = 0;
	age = 0;

	while(fgets_strip(linebuf,sizeof(linebuf),f_in) != NULL)
	{
		if(memcmp(linebuf,"name",4)==0)
		{
			p = &linebuf[4];
			while(isspace(*p)) p++;
			strncpy0(vname,p,sizeof(vname));
		}
		else if(memcmp(linebuf,"language",8)==0)
		{
			priority = DEFAULT_LANGUAGE_PRIORITY;
			vlanguage[0] = 0;

			sscanf(&linebuf[8],"%s %d",vlanguage,&priority);
			len = strlen(vlanguage) + 2;
			// check for space in languages[]
			if(len < (sizeof(languages)-langix-1))
			{
				languages[langix] = priority;

				strcpy(&languages[langix+1],vlanguage);
				langix += len;
				n_languages++;
			}
		}
		else if(memcmp(linebuf,"gender",6)==0)
		{
			sscanf(&linebuf[6],"%s %d",vgender,&age);
		}
		else if(memcmp(linebuf,"variants",8)==0)
		{
			sscanf(&linebuf[8],"%d",&n_variants);
		}
	}
	languages[langix++] = 0;

	gender = LookupMnem(genders,vgender);

	if(n_languages == 0)
	{
		return(NULL);    // no language lines in the voice file
	}

	p = (char *)calloc(sizeof(espeak_VOICE) + langix + strlen(fname) + strlen(vname) + 3, 1);
	voice_data = (espeak_VOICE *)p;
	p = &p[sizeof(espeak_VOICE)];

	memcpy(p,languages,langix);
	voice_data->languages = p;

	strcpy(&p[langix],fname);
	voice_data->identifier = &p[langix];
	voice_data->name = &p[langix];

	if(vname[0] != 0)
	{
		langix += strlen(fname)+1;
		strcpy(&p[langix],vname);
		voice_data->name = &p[langix];
	}

	voice_data->age = age;
	voice_data->gender = gender;
	voice_data->variant = 0;
	voice_data->xx1 = n_variants;
	return(voice_data);
}  // end of ReadVoiceFile
示例#3
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 gu 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 eu 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));
	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;
	}

	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]);    // 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


	while((f_voice != NULL) && (fgets_strip(buf,sizeof(buf),f_voice) != NULL))
	{
		// 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)
		{
			fprintf(stderr,"Unknown phoneme table: '%s'\n",phonemes_name);
			ix = 0;
		}
		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
示例#4
0
文件: voices.c 项目: Jalakas/navit
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;
	keywtab_t *k;
	char *p;
	int  key;
	int  ix;
	int  n;
	int  value;
	int  error = 0;
	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];
	const char *language_type;
	char buf[200];
	char path_voices[sizeof(path_home)+12];
	char langname[4];

	int stress_amps[8];
	int stress_lengths[8];
	int stress_add[8];

	int pitch1;
	int pitch2;

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

	strcpy(voicename,vname);
	if(voicename[0]==0)
		strcpy(voicename,"default");

	if(control & 0x10)
	{
		strcpy(buf,vname);
		if(GetFileLength(buf) <= 0)
			return(NULL);
	}
	else
	{
		sprintf(path_voices,"%s%cvoices%c",path_home,PATHSEP,PATHSEP);
		sprintf(buf,"%s%s",path_voices,voicename);

		if(GetFileLength(buf) <= 0)
		{
			// look for the voice in a sub-directory of the language name
			langname[0] = voicename[0];
			langname[1] = voicename[1];
			langname[2] = 0;
			sprintf(buf,"%s%s%c%s",path_voices,langname,PATHSEP,voicename);

			if(GetFileLength(buf) <= 0)
			{
				// 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;
	}

	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;

		voice_selected.identifier = voice_identifier;
		voice_selected.name = voice_name;
		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]);    // 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


	while((f_voice != NULL) && (fgets_strip(buf,sizeof(buf),f_voice) != NULL))
	{
		// isolate the attribute name
		for(p=buf; (*p != 0) && !isspace(*p); p++);
		*p++ = 0;

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

		key = 0;
		for(k=keyword_tab; k->mnem != NULL; k++)
		{
			if(strcmp(buf,k->mnem)==0)
			{
				key = k->data;
				break;
			}
		}

		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;
				}
			}
			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;
				char vgender[80];
				sscanf(p,"%s %d",vgender,&age);
				voice_selected.gender = LookupMnem(genders,vgender);
				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_DICTRULES:   // conditional dictionary rules and list entries
			while(*p != 0)
			{
				while(isspace(*p)) p++;
				n = -1;
				if(((n = atoi(p)) > 0) && (n < 32))
				{
					p++;
					conditional_rules |= (1 << n);
				}
				while(isalnum(*p)) p++;
			}
			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_NUMBERS:
			sscanf(p,"%d %d",&langopts->numbers,&langopts->numbers2);
			break;

		case V_OPTION:
			if(sscanf(p,"%d %d",&ix,&value) == 2)
			{
				if((ix >= 0) && (ix < N_LOPTS))
					langopts->param[ix] = value;
			}
			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_MBROLA:
			{
				int srate = 16000;
				char name[40];
				char phtrans[40];

				phtrans[0] = 0;
				sscanf(p,"%s %s %d",name,phtrans,&srate);
				LoadMbrolaTable(name,phtrans,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(2);
			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);
	}

	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)
		{
			fprintf(stderr,"Unknown phoneme table: '%s'\n",phonemes_name);
		}
		voice->phoneme_tab_ix = ix;
		error = 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