The problem: In Android, when I set the language for Google text to speech to Spanish, the spoken text is with an English voice. (a) Why isn't it in a Spanish "voice", and (b) If my code isn't correct, what more do I need to do to make it speak with a Spanish voice.
The English voice it uses means that "hola mundo" sounds like "howlaa mundow", as if an English person was trying to say the letters. This means the voice synthesizer being used is an English one (happens to be female). I can understand it, but all the Spanish vowel sounds and a few consonants (like the fact that "h" isn't pronounced) are wrong.
Here is a minimal version of my code which produces this error. I am using a Nexus 5X API 26 emulator. The code seems to think the text to speech engine is installed, and speech is synthesized, but with the error mentioned above. In the method "onInit()" (a callback which runs as soon as the Engine is loaded) I have asserted that the Locale for Spain exists. Therefore, the code won't play the voice if this isn't installed, so the fact I hear anything at all means the code believes it is "speaking in Spanish".
(Please note: This code has been updated to check the return values of setLanguage in a switch to make sure the language really was set correctly - and it is)
package com.example.testtexttospeech;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.util.Locale;
import java.util.Set;
public class MainActivity extends Activity implements View.OnClickListener, TextToSpeech.OnInitListener
{
private static final String TAG = MainActivity.class.getSimpleName();
private TextToSpeech spanishTTS;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button speakButton = (Button)findViewById(R.id.speak_button);
speakButton.setOnClickListener(this);
// make sure Text To Speech Data is available.
Intent ttsDataAvailIntent = new Intent();
ttsDataAvailIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(ttsDataAvailIntent, TextToSpeech.Engine.CHECK_VOICE_DATA_PASS);
}
private void speakSpanish(String speech)
{
if (spanishTTS != null)
{
spanishTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null, "");
}
else
{
Toast.makeText(this, "Spanish TTS is not available.", Toast.LENGTH_LONG).show();
}
}
public boolean isSpanishTTSAvailable()
{
return this.spanishTTS != null;
}
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS)
{
spanishTTS = new TextToSpeech(this, this);
}
else {
Intent installTTSIntent = new Intent();
installTTSIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installTTSIntent);
}
}
public void onInit(int initStatus)
{
// Get the set of available languages and log them
Set<Locale> availableSet = spanishTTS.getAvailableLanguages();
for(Locale locale : availableSet)
{
Log.i(TAG,"Local available: " + locale.toString());
}
final Locale spanishLocale = new Locale("es", "ES");
// make sure the spanish local is available
assert(availableSet.contains(spanishLocale));
if (initStatus == TextToSpeech.SUCCESS)
{
int result = spanishTTS.setLanguage(spanishLocale);
switch (result)
{
case TextToSpeech.LANG_AVAILABLE: // fall-through intentional
case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
case TextToSpeech.LANG_COUNTRY_AVAILABLE: {
Log.i(TAG,"Language set successfully");
break;
}
default: // fall-through intentional
case TextToSpeech.LANG_MISSING_DATA:
case TextToSpeech.LANG_NOT_SUPPORTED: {
Toast.makeText(this, "Language " + spanishLocale.toString() + " is not available.", Toast.LENGTH_LONG).show();
spanishTTS.stop();
spanishTTS.shutdown();
spanishTTS = null;
}
}
}
}
@Override
public void onDestroy()
{
if (spanishTTS != null)
{
spanishTTS.stop();
spanishTTS.shutdown();
}
super.onDestroy();
}
public void onClick(View v)
{
EditText enteredText = (EditText)findViewById(R.id.text_entered_et);
String words = enteredText.getText().toString();
speakSpanish(words);
}
}