I am learning to write an app that is intended to perform TTS on given strings, and have tried an example modified from web:
Coding as follows:
// setup TTS part 1
mTts = new TextToSpeech(Lesson2_dialog_revision_simple.this, this); // TextToSpeech.OnInitListener
speakBtn.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
StringTokenizer loveTokens = new StringTokenizer("他們 one two是 three ",",.");
int i = 0;
loveArray = new String[loveTokens.countTokens()];
while(loveTokens.hasMoreTokens())
{
loveArray[i++] = loveTokens.nextToken();
}
speakText();
}
});
}
// setup TTS part 2
#Override
public void onUtteranceCompleted(String utteranceId)
{
Log.v(TAG, "Get completed message for the utteranceId " + utteranceId);
lastUtterance = Integer.parseInt(utteranceId);
}
// setup TTS part 3
#Override
public void onInit(int status)
{
if(status == TextToSpeech.SUCCESS)
{
int result = mTts.setLanguage(Locale.CHINESE); // <====== set speech location
if(result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED)
{
Toast.makeText(Lesson2_dialog_revision_simple.this, "Language is not supported", Toast.LENGTH_LONG).show();
speakBtn.setEnabled(false);
}
else
{
speakBtn.setEnabled(true);
mTts.setOnUtteranceCompletedListener(this);
}
}
}
// setup TTS part 4
private void speakText()
{
lastUtterance++;
if(lastUtterance >= loveArray.length)
{
lastUtterance = 0;
}
Log.v(TAG, "the begin utterance is " + lastUtterance);
for(int i = lastUtterance; i < loveArray.length; i++)
{
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, String.valueOf(i));
mTts.speak(loveArray[i], TextToSpeech.QUEUE_ADD, params);
}
}
Questions:
Everything is ok if the int result = mTts.setLanguage(Locale.US); in part 3 above is set as US and to read out "one two three" in English perfectly. (in the above example, it will skip all the chinese words and just read out one two three)
However, if I change the string to read out Chinese by setting language as setLanguage(Locale.CHINESE), it immediately toasts out that "Language is not supported".
I would like to ask
the current TTS still does not support Chinese? I would even more prefer Cantonese rather than Chinese.
The phone is ABLE to recognize Cantonese when I inputting messages via speech (Cantonese). Is it actually there are some other way to perform TTS with output being Cantonese?
Thanks!!
1 - The Google TTS Engine at its current version does not support Cantonese as output yet. Putonghua works fine.
2 - Ekho is a TTS Engine that supports Cantonese.
You might want to give a try on the TTS app I developed that works with Ekho and Google TTS Engine: Voice Out TTS
As far as I know there's no specific Locale in JAVA to distinguish between Cantonese or Putonghua because Cantonese is a Chinese dialect. The Locale in JAVA refers only to the writings (Simplified or Traditional).
For example you can read a string written in Traditional Chinese with Cantonese or Putonghua.
#Pearmak: you can check the language that are supported in your device
int i = mTts.isLanguageAvailable(Locale.ENGLISH);
where mTts is object of TextToSpeech
If you get the value of i >=0 then that language is supported on you device otherwise not.
You may also pass the language locale string.
int i = mTts.isLanguageAvailable(new Locale("zh_CN")); //for chinese simplified
Yue, a tiny Chinese text to speech (TTS) synthesis engine of Cantonese, Mandarin for offline embedded system. Yue is extremely small size, offline, independent, and PCM audio output no needs of server or network connection. It has high naturalness of synthesised voice for hybrid text input, the Cantonese and Mandarin speech synthesis for same text input, with Yale, Jyutping and Pinyin romanization. The engine can continues produce and play voice for long text, the length of the text without limit. It has build-in intelligent detecter that can handle any traditional Chinese, simplified Chinese, English, number and punctuations, symbol mixed text input. Yue is written in ANSI C, no dependent of third part library, running on ARM, AVR embedded system such as watch, toy, robot and iPhone, Android, … mobile platforms, of course normal desktops, ebook, news paper reader, story teller. Yue can be loaded into memory and embedded in other programs, because of its extremely small size, it is well suited to embedded systems, and is also suitable for desktop operating systems. The engine can have bindings for a large number of programming languages.
The link:http://www.sevenuc.com/en/tts.html
Google TTS recently added support for Cantonese (and also Mandarin). http://www.androidpolice.com/2015/07/24/google-tts-now-supports-four-new-languages-including-cantonese-and-mandarin/
some phones have the cantonese locale that you can use with TTS.
try
new Locale("yue", "HK"); //yue for 粤语
Once you have set the system language to Cantonese, then you can use setLanguage(Locale.getDefault()).
Related
I am trying to follow this tutorial for my Android wearables app:
https://www.sitepoint.com/using-android-text-to-speech-to-create-a-smart-assistant/
Here is the code for my Activity file:
import android.speech.tts.TextToSpeech;
public class ScoresActivity extends Activity {
private TextToSpeech tts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scores);
// Text to speech setup
tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
System.out.println("status: " + status); // Always returns -1
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.US);
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
}
speak("Hello");
} else {
Log.e("TTS", "Initilization Failed!");
}
}
});
}
I always see this error message in the Logs:
Is it even possible to run the Android SDK's text-to-speech library on wearable devices? I tried running this code on a mobile Android app and everything worked fine.
Yes this is possible as they even have docs for this feauture in Adding Voice Capabilities:
Voice actions are an important part of the wearable experience. They let users carry out actions hands-free and quickly. Wear provides two types of voice actions:
System-provided These voice actions are task-based and are built into the Wear platform. You filter for them in the activity that you
want to start when the voice action is spoken. Examples include "Take
a note" or "Set an alarm".
App-provided These voice actions are app-based, and you declare them just like a launcher icon. Users say "Start " to use these voice
actions and an activity that you specify starts.
You can also check this SO post for additional reference.
Depends which device you have. I think it needs to have android wear 2.0 and then possibly a speaker would make it more likely. Im only saying that based on knowing my nixon mission does not have tts installed but the lg urbane 2 does. Very annoying as tts could be used over bluetooth.
Would be good to get a full listed of supported devices.
I have a class that uses the Android TTS API to transcribe text to audio. I can control the pitch and speed; but I noticed the engine requires a text string and also a hash object. I noticed some words are pronounced too quickly to be easily recognized, and inflection seems too unnatural. Is there a way I can control these two things; possibly through the HashMap? The following is how I'm using the engine:
mTts = new TextToSpeech(Globals.context, this); // context, listener
}
#Override
public void onInit(int status) {
HashMap<String, String> myHashRender = new HashMap();
myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, speech);
mTts.setPitch(0.8f);
mTts.setSpeechRate(0.6f);
mTts.synthesizeToFile(speech, myHashRender, fileOutPath);
while (mTts.isSpeaking()) try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
mTts.stop();
mTts.shutdown();
Google TTS does not currently support that, but here is what you can do: During parsing of your text, you can change parts of it to get the intonation and inflection you want.
For example, if you encounter the word 'Hey' you rewrite it on the fly to 'Heeeey' before you send it to the TTS engine to get a different pronounciation.
It is not pretty but it is a workaround.
Google TTS does not currently support changing inflection, nor does it
support inline prosody tags as defined in SSML. - alanv Jun 5 at 20:30
Google TTS does not currently support changing inflection, nor does it support inline prosody tags as defined in SSML. While there are parameters you can set, none of them control inflection or per-word prosody.
There may be other engines that do support these features. eSpeak, for example, does support SSML tags and has an Android port available on Play Store.
original question
I have a standard texttospeech, android.speech.tts.TextToSpeech
I initialize it and set a language by using tts.setLanguage(Locale.getDefault())
That default Locale is de_DE (for germany, correct).
Right after setting it, i ask the tts to give me its language tts.getLanguage()
now it tells me that its set to "deu_DEU"
There is no Locale with that setting. So i cant even check if its set to the right language because i cant find the Locale object that has the matching values.
Issue might be related to Android 4.3, but i didnt find any info.
Background is, that i need to show values with the same decimal symbol, but tts needs the correct symbol or it says "dot" in german which makes NO sense at all.
Conclusion:
A Locale is a container that contains a string that is composed of a language, a country and an optional string. Every text-to-speech engine can return a custom Locale like "eng_USA_texas".
Furthermore the Locale that is returned by the tts engine can only be a "close match" to the wanted Locale. So "en_US" instead of "en_UK".
However, Locale has a method called getLanguage() and it returns the first part of above mentioned string. "en" or "eng". Those Language codes are regulated by ISO and one can hope that everyone sticks to it. (see link in the accepted answer)
So checking for tts.getLanguage().getLanguage().startsWith("en") should always be true if its some form of english language setting and the ISO standards are fulfilled.
It is important to mention that Locales should not be compared by locale_a == locale_b as both can be different objects yet have the same content, they are containers of sort.
Always compare with locale_a.equals(locale_b)
I hope this helps people sort out some problems with tts and language
You're right, it's frustrating how the locale codes the TTS object uses are different to those of the device locale. I don't understand why this decision was made.
To add further complication, the TTS Engine can supply all kinds of different locales, such as eng_US_sarah or en-US-female etc. It's down to the TTS Engine how these are stored and displayed.
I've had to write additional code to iterate through the returned locales and attempt to match them to the locale the system can use, or vica-versa.
To start with, take a look at how the engines you have installed are returning their locale information. You can then start to collate in your code a list to associate 'deu_DEU' to 'de_De'.
This is often simplistic by using split("_") & startsWith(String), but unfortunately not for all locales.
Here's some base code I've used to analyse the installed TTS Engines' locale structure.
private void getEngines() {
final Intent ttsIntent = new Intent();
ttsIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
final PackageManager pm = getActivity().getPackageManager();
final List<ResolveInfo> list = pm.queryIntentActivities(ttsIntent, PackageManager.GET_META_DATA);
final ArrayList<Intent> intentArray = new ArrayList<Intent>(list.size());
for (int i = 0; i < list.size(); i++) {
final Intent getIntent = new Intent();
getIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
getIntent.setPackage(list.get(i).activityInfo.applicationInfo.packageName);
getIntent.getStringArrayListExtra(TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES);
intentArray.add(getIntent);
}
for (int i = 0; i < intentArray.size(); i++) {
startActivityForResult(intentArray.get(i), i);
}
}
#Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
try {
if (data != null) {
System.out.print(data.getStringArrayListExtra("availableVoices").toString());
}
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
From the above ISO-3 codes and the device locale format, you should be able to come up with something for the locales you are concerned with.
I've been intending to submit an enhancement request to AOSP for a while, as all TTS Engines need to use constant values and extras such as gender etc need to be added to use the TTS Engines to their full capabilities.
EDIT: Further to your edit, note the wording regarding setLanguage(). The individual TTS Engine will try and match as close as possible to the requested locale, but that applied locale may be completely wrong, depending on how lenient the Engine provider is in their code and their response.
After creating an object of TextToSpeech class, you should configure it (or check it's available state/values) into TextToSpeech.OnInitListener's onInit() callback. You will get reliable information there about your TextToSpeech object.
Check my answer here:
https://stackoverflow.com/a/65620221/7835969
I'm making use of Text to Speech - TTS in my Android app.. I've pasted the code below.. TTS is working fine, however the voice/text it speaks is not very clear.. It speaks really quick, so that it is not fully understandable.. I tried setting Locale.US, and used setPitch or setSpeechRate but it is not really convincing. I felt that there is some problem with my phone (Samsung S2).. So tried installing Google Translate TTS app from Google Play store.. In that app the voice was really clear.
My app will be used by Kids.. so want to make sure that the voice is really clear.
I'm breaking my head for the past few days to fix this problem.. Would be great if you could give me some pointers on where I'm doing wrong or how to improve??
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.getDefault());
//tts.setSpeechRate((float) 0.8);
//tts.setPitch(1.0f);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
} else {
speakOut(0);
}
} else {
Intent installIntent = new Intent();
installIntent.setAction(
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
private void speakOut(int position) {
tts.speak("Some text goes here", TextToSpeech.QUEUE_FLUSH, null);
}
Note: I tried setting value as 0.5f,0.8f etc., in both setPitch and setSpeechRate but still all the voice is not really clear as in GoogleTranslate App.
Your code looks fine.
All tts libraries are shared across the system. Samsung comes with its own tts library. Rest of phones use Pico TTS. The great thing is that your app is independent from the library and you can download as many TTS libs as you want so that when you request the TTS intent the user will be prompt a pop-up to select which of their TTS synth they want for your app.
For me Pico TTS was working fine. Velocity / speech rate was normal, I just put the tone (pitch) a bit up to de-robotize the feeling a bit.
tts.setPitch(1.1f);
Try with Pico TTS and answer back.
Android is providing a cool feature (from Android 1.6) called Text to Speech (TTS) which speaks the text in different languages. I have written a code on TTS. It is working fine. But now I want to set Language of TTS to "Bengali ". But TTS currently does not support "Bengali". Is there any way to set Language of TTS to "Bengali" .
tts = new TextToSpeech(TextToSpeechSultan.this,new TextToSpeech.OnInitListener() {
public void onInit(int status)
{
if(status != TextToSpeech.ERROR)
{
tts.setLanguage(Locale.US);
}
}
});
No, unfortunately Bengali or Hindi is not supported by Android. See the list of Locales supported below
http://developer.android.com/reference/java/util/Locale.html
Many other languages are also not supported by the looks of it.