Skip to content

Commit e814c49

Browse files
committed
New JavaScript api for TTS
Since it is unlikely that a beginner will handle this api, I moved the functions on the android side to JavaScript with as little modification as possible. Since the function conversion rules have been simplified, the api can be extended with consistent rules even if other TTS functions are needed on the JavaScript side in the future.
1 parent 1deddb9 commit e814c49

2 files changed

Lines changed: 147 additions & 0 deletions

File tree

AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4205,5 +4205,49 @@ public boolean ankiIsActiveNetworkMetered() {
42054205
return true;
42064206
}
42074207
}
4208+
4209+
//Voice reading
4210+
JavaScriptTTS mTalker = new JavaScriptTTS (AbstractFlashcardViewer.this);
4211+
4212+
@JavascriptInterface
4213+
public int ankiTtsSpeak(String text, int queueMode) {
4214+
return mTalker.speak(text, queueMode);
4215+
}
4216+
4217+
@JavascriptInterface
4218+
public int ankiTtsSpeak(String text) {
4219+
return mTalker.speak(text);
4220+
}
4221+
4222+
@JavascriptInterface
4223+
public int ankiTtsSetLanguage(String loc) {
4224+
return mTalker.setLanguage(loc);
4225+
}
4226+
4227+
@JavascriptInterface
4228+
public int ankiTtsSetPitch(float pitch) {
4229+
return mTalker.setPitch(pitch);
4230+
}
4231+
4232+
@JavascriptInterface
4233+
public int ankiTtsSetPitch(double pitch) {
4234+
return mTalker.setPitch((float)pitch);
4235+
}
4236+
4237+
@JavascriptInterface
4238+
public int ankiTtsSetSpeechRate(float speechRate) {
4239+
return mTalker.setSpeechRate(speechRate);
4240+
}
4241+
4242+
@JavascriptInterface
4243+
public int ankiTtsSetSpeechRate(double speechRate) {
4244+
return mTalker.setSpeechRate((float)speechRate);
4245+
}
4246+
4247+
@JavascriptInterface
4248+
public void ankiTtsStop() {
4249+
mTalker.stop();
4250+
}
4251+
42084252
}
42094253
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package com.ichi2.anki;
2+
3+
import android.content.Context;
4+
import android.os.Bundle;
5+
import android.speech.tts.TextToSpeech;
6+
import java.util.Locale;
7+
8+
// Since it is assumed that only advanced users will use the JavaScript api,
9+
// here, Android's TextToSpeech is converted for JavaScript almost as it is, giving priority to free behavior.
10+
// https://developer.android.com/reference/android/speech/tts/TextToSpeech
11+
//
12+
//
13+
14+
public class JavaScriptTTS implements TextToSpeech.OnInitListener {
15+
16+
private TextToSpeech mTts;
17+
private boolean mTtsOk;
18+
private static final Bundle mTtsParams = new Bundle();
19+
20+
//The constructor will create a TextToSpeech instance.
21+
JavaScriptTTS(Context context) {
22+
mTts = new TextToSpeech(context, this);
23+
}
24+
25+
@Override
26+
//OnInitListener method to receive the TTS engine status
27+
public void onInit(int status) {
28+
if (status == TextToSpeech.SUCCESS) {
29+
mTtsOk = true;
30+
}
31+
else {
32+
mTtsOk = false;
33+
}
34+
}
35+
36+
// A method to speak something
37+
// The QueMode value is 1 for QUEUE_ADD and 0 for QUEUE_FLUSH.
38+
public int speak(String text, int queueMode) {
39+
return mTts.speak(text, queueMode, mTtsParams, "stringId");
40+
}
41+
42+
// If only a string is given, set QUEUE_FLUSH to the default behavior.
43+
public int speak(String text) {
44+
return mTts.speak(text, TextToSpeech.QUEUE_FLUSH, mTtsParams, "stringId");
45+
}
46+
47+
// Sets the text-to-speech language.
48+
//The TTS engine will try to use the closest match to the specified language as represented by the Locale, but there is no guarantee that the exact same Locale will be used.
49+
public int setLanguage(String loc) {
50+
// The Int values will be returned
51+
// Code indicating the support status for the locale. See LANG_AVAILABLE, LANG_COUNTRY_AVAILABLE, LANG_COUNTRY_VAR_AVAILABLE, LANG_MISSING_DATA and LANG_NOT_SUPPORTED.
52+
return mTts.setLanguage(localeFromStringIgnoringScriptAndExtensions(loc));
53+
}
54+
55+
// Sets the speech pitch for the TextToSpeech engine. This has no effect on any pre-recorded speech.
56+
// float: Speech pitch. 1.0 is the normal pitch, lower values lower the tone of the synthesized voice, greater values increase it.
57+
public int setPitch(float pitch) {
58+
// The following Int values will be returned
59+
// ERROR(-1) SUCCESS(0)
60+
return mTts.setPitch(pitch);
61+
}
62+
63+
// Sets the speech rate. This has no effect on any pre-recorded speech.
64+
public int setSpeechRate(float speechRate) {
65+
// The following Int values will be returned
66+
// ERROR(-1) SUCCESS(0)
67+
return mTts.setSpeechRate(speechRate);
68+
}
69+
70+
// Interrupts the current utterance (whether played or rendered to file) and discards other utterances in the queue.
71+
public void stop() {
72+
// The following Int values will be returned
73+
// ERROR(-1) SUCCESS(0)
74+
mTts.stop();
75+
}
76+
77+
/**
78+
* Convert a string representation of a locale, in the format returned by Locale.toString(),
79+
* into a Locale object, disregarding any script and extensions fields (i.e. using solely the
80+
* language, country and variant fields).
81+
* <p>
82+
* Returns a Locale object constructed from an empty string if the input string is null, empty
83+
* or contains more than 3 fields separated by underscores.
84+
*/
85+
private static Locale localeFromStringIgnoringScriptAndExtensions(String localeCode) {
86+
if (localeCode == null) {
87+
return new Locale("");
88+
}
89+
90+
String[] fields = localeCode.split("_");
91+
switch (fields.length) {
92+
case 1:
93+
return new Locale(fields[0]);
94+
case 2:
95+
return new Locale(fields[0], fields[1]);
96+
case 3:
97+
return new Locale(fields[0], fields[1], fields[2]);
98+
default:
99+
return new Locale("");
100+
}
101+
}
102+
103+
}

0 commit comments

Comments
 (0)