[Huawei Developers] John Wo:
[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/671/191/2640091000001671191.20201106094408.89688451387230403298068582068449:50511119004725:2800:B653A539375A6A27895ECAE7F1B461F97B98D258E438C3959D812080122914F1.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/671/191/2640091000001671191.20201106094408.89688451387230403298068582068449:50511119004725:2800:B653A539375A6A27895ECAE7F1B461F97B98D258E438C3959D812080122914F1.png[/IMG]​

Introduction

This article talks about how to convert text to Text to speech (TTS) can convert text information into audio output. Rich timbres are provided and the volume and speed can be adjusted, thereby natural voices can be produced. This service uses the deep neural network (DNN) synthesis mode and can be quickly integrated through the on-device SDK to generate audio data in real time. In the current version, two standard male voices and six standard female voices are available.

TTS is available only on Huawei phones.

The text in a single request can contain a maximum of 500 characters and is encoded using UTF-8.

TTS in French, Spanish, German, and Italian is deployed only in Asia, Africa, Latin America, and Europe.

TTS depends on on-cloud APIs. During commissioning and usage, ensure that the device can access the Internet.

Default specifications of the real-time output audio data are as follows: PCM mono, 16-bit depth, and 16 kHz audio sampling rate.

Follow all the steps mentioned in Basic Setup to start HMS integration on B4A Platform.

Refer to previous Article

Enable ML Kit in App gallery connect.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/671/191/2640091000001671191.20201109040627.14287825006833561063324886056572:50511119004725:2800:5ED9484E686C3ACE8CBF420DD67EC091D5246284416F7B7FE46C7870943E59D3.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/671/191/2640091000001671191.20201109040627.14287825006833561063324886056572:50511119004725:2800:5ED9484E686C3ACE8CBF420DD67EC091D5246284416F7B7FE46C7870943E59D3.png[/IMG]

Tips & Tricks:

In case voice is not audible please make ensure that ML-Kit is enabled or not in App Gallery Connect.

Creating Wrapper Class

1. Downloading the AAR Packages and JSON File

Sign in to HUAWEI Developer and download the AAR packages required.

AAR packages related to HMS TTS kit is displayed as below

Agconnect-core:

https://developer.huawei.com/repo/com/huawei/agconnect/agconnect-core/1.0.0.300/agconnect-core-1.0.0.300.aar

HMSSDKBase:

https://developer.huawei.com/repo/com/huawei/hms/base/4.0.1.300/base-4.0.1.300.aar

Ml-computer-agc-inner:

https://developer.huawei.com/repo/com/huawei/hms/ml-computer-agc-inner/2.0.1.300/ml-computer-agc-inner-2.0.1.300.aar

Ml-computer-commonutils-inner:

https://developer.huawei.com/repo/com/huawei/hms/ml-computer-commonutils-inner/2.0.1.300/ml-computer-commonutils-inner-2.0.1.300.aar

Ml-computer-ha-inner:

https://developer.huawei.com/repo/com/huawei/hms/ml-computer-ha-inner/2.0.0.300/ml-computer-ha-inner-2.0.0.300.aar

Tasks:

https://developer.huawei.com/repo/com/huawei/hmf/tasks/1.4.1.300/tasks-1.4.1.300.aar

Network-common:

https://developer.huawei.com/repo/com/huawei/hms/network-common/4.0.2.301/network-common-4.0.2.301.aar

Network-grs:

https://developer.huawei.com/repo/com/huawei/hms/network-grs/4.0.2.301/network-grs-4.0.2.301.aar

Ml-computer-grs-inner:

https://developer.huawei.com/repo/com/huawei/hms/ml-computer-grs-inner/2.0.0.300/ml-computer-grs-inner-2.0.0.300.aar

Ml-computer-net:

https://developer.huawei.com/repo/com/huawei/hms/ml-computer-net/1.0.4.300/ml-computer-net-1.0.4.300.aar

Okhttp:

https://jar-download.com/artifacts/com.squareup.okhttp3/okhttp/3.12.0/source-code

Okio:

https://mvnrepository.com/artifact/com.squareup.okio/okio/1.15.0

Ml-computer-voice-tts:

https://developer.huawei.com/repo/com/huawei/hms/ml-computer-voice-tts/2.0.0.401/ml-computer-voice-tts-2.0.0.401.aar

2. Open AAR packages with rar tool and rename the class.jar and AndroidManifest.xml files. And save those jar file inside libs folder (It is recommended that the two files be renamed consistently with the AAR package names.)

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/671/191/2640091000001671191.20201106154357.00134578793787684346212176033907:50511119004725:2800:31475D7066DCC34DA5D3211BC560B630446E69D07E92AD36112FE4CD26CCB501.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/671/191/2640091000001671191.20201106154357.00134578793787684346212176033907:50511119004725:2800:31475D7066DCC34DA5D3211BC560B630446E69D07E92AD36112FE4CD26CCB501.png[/IMG]​

3. Copy required permissions in the <manifest> section in B4A IDE

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106150820.98914525777006910367868942980367:50511119004725:2800:A7FA2D8F8CE94FE50A628CFE814358FFC42250665A012462F73A03B38B4D88CD.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106150820.98914525777006910367868942980367:50511119004725:2800:A7FA2D8F8CE94FE50A628CFE814358FFC42250665A012462F73A03B38B4D88CD.png[/IMG]​

4. Copy all configurations in the <application> section

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106150836.81604830360609604214928150340382:50511119004725:2800:17A28BF75C1897963533216F5A1C03CFCC947A19DC0BF07C0543750F80D8B4BF.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106150836.81604830360609604214928150340382:50511119004725:2800:17A28BF75C1897963533216F5A1C03CFCC947A19DC0BF07C0543750F80D8B4BF.png[/IMG]​

5. Change ${applicationId} to $PACKAGE$.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106151048.46125216812329947966372315779211:50511119012851:2800:78EBCC8380A2086A1D272F482E2397C146F83EBA7B763253FDD6859BFBDC0510.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106151048.46125216812329947966372315779211:50511119012851:2800:78EBCC8380A2086A1D272F482E2397C146F83EBA7B763253FDD6859BFBDC0510.png[/IMG]​

6. Download the configuration file (agconnect-services.json) from App Gallery Connect and Add the JSON File to the assets Folder of the AAR file as shown below.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106151154.57542895627854176944685621365832:50511119004725:2800:8D0B5CE2B0C59B87BF29CF8DD4D9928A395E74B6FB4C07D030302C315655C2BF.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106151154.57542895627854176944685621365832:50511119004725:2800:8D0B5CE2B0C59B87BF29CF8DD4D9928A395E74B6FB4C07D030302C315655C2BF.png[/IMG][/CENTER]

B4A will automatically incorporate files in the assets folder of an AAR package to the assets folder of your main project.

Encapsulating Java Files Using SLC

1. Create Library as parent and then create bin, libs and src as subfolder in the project directory.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/671/191/2640091000001671191.20201106154954.61668777801475805152764533238040:50511119004725:2800:6D1A0AF998811F9DE4ECF7C106CFC364DC7C9214D475074BC3D49F01E9F695DF.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/671/191/2640091000001671191.20201106154954.61668777801475805152764533238040:50511119004725:2800:6D1A0AF998811F9DE4ECF7C106CFC364DC7C9214D475074BC3D49F01E9F695DF.png[/IMG]​

2. Develop java project inside the following path, Choose Library Folder > src > b4x > tts > demo

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106151258.17655794271989647184806065900716:50511119004725:2800:65282F53082C40387C4234319317604ECF35B05137532EB38AE226B24D1464D2.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/000/002/333/0890091000000002333.20201106151258.17655794271989647184806065900716:50511119004725:2800:65282F53082C40387C4234319317604ECF35B05137532EB38AE226B24D1464D2.png[/IMG]​

3. Import the following two lines of code to each Java file

import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.*;
import anywheresoftware.b4a.IOnActivityResult;

4. Add necessary annotations to the Java files

@DependsOn(values={
"base-4.0.1.300.aar",
"agconnect-core-1.0.1.300.aar",
"tasks-1.3.1.302.aar",
"network-common-4.0.2.301.aar",
"network-grs-4.0.2.301.aar",
"ml-computer-net-2.0.1.300.aar",
"ml-computer-grs-inner-2.0.1.300.aar",
"okhttp-3.12.0.jar",
"okio-1.15.0.jar",
"ml-computer-voice-tts-2.0.1.300.aar",
"ml-computer-agc-inner-2.0.1.300.aar",
"ml-computer-commonutils-inner-2.0.1.300.aar",
"ml-computer-ha-inner-2.0.1.300.aar"
})

5. Modify the context.

B4A does not recognize the Context class. Therefore, when parsing a class that contains the [MENTION=4733894]verci[/MENTION]on(1.0f) annotation, it will report an error if a method of the class has referenced Context. In this case, you need to change Context to the B4A object BA

@ShortName("ttsWork")
@Events(values = {"TTSStop (token As String)"})
public class ttsWork {
public static String eventName = "listener";
public static final String TAG = "tts_Kit";
public static void init(Context context) {
AGConnectServicesConfig.fromContext(context).overlayWith(new LazyInputStream(context) {
@Override
public InputStream get(Context context) {
try {
return context.getAssets().open("agconnect-services.json");
} catch (IOException e) {
e.printStackTrace();
BA.Log(e.toString());
}
return null;
}
});
}

private static IOnActivityResult ion;

public static void ListenFortts(final Context context, String text) {
MLApplication.getInstance().setApiKey("API_KEY");

MLTtsConfig mlConfigs = new MLTtsConfig().setLanguage(MLTtsConstants.TTS_EN_US).setPerson(MLTtsConstants.TTS_SPEAKER_FEMALE_EN).setSpeed(1.0f).setVolume(1.0f);
MLTtsEngine mlTtsEngine = new MLTtsEngine(mlConfigs);
Log.d(" text from ui ", text);
mlTtsEngine.updateConfig(mlConfigs);
mlTtsEngine.setTtsCallback(callback);
String sourceText = "Welcome";
String id = mlTtsEngine.speak(text, MLTtsEngine.QUEUE_APPEND);
}

static MLTtsCallback callback = new MLTtsCallback() {
@Override
public void onError(String taskId, MLTtsError err) {

}

@Override
public void onWarn(String taskId, MLTtsWarn warn) {

}
@Override
public void onRangeStart(String taskId, int start, int end) {

}
@Override
public void onAudioAvailable(String taskId, MLTtsAudioFragment audioFragment, int offset, Pair<Integer, Integer> range, Bundle bundle)
{

}
@Override
public void onEvent(String taskId, int eventId, Bundle bundle) {
// Log.v(" stop service ","text1111");
switch (eventId) {

case MLTtsConstants.EVENT_PLAY_START:

Log.v(" stop service ", "textplaystart");
ba.raiseEventFromUI(this, eventName + "_TTSText", "text");
Log.v(" stop service ", "text11");

break;
case MLTtsConstants.EVENT_PLAY_STOP:
boolean isInterrupted = bundle.getBoolean(MLTtsConstants.EVENT_PLAY_STOP_INTERRUPTED);
Log.v(" stop service ", "textplaystop");
ba.raiseEventFromUI(this, eventName + "_TTSStop", "Service Stopped");
Log.v(" stop service ", "text11");
break;
case MLTtsConstants.EVENT_PLAY_RESUME:
break;
case MLTtsConstants.EVENT_PLAY_PAUSE:
break;
case MLTtsConstants.EVENT_SYNTHESIS_START:
break;
case MLTtsConstants.EVENT_SYNTHESIS_END:
break;
case MLTtsConstants.EVENT_SYNTHESIS_COMPLETE:
boolean isInterrupted1 = bundle.getBoolean(MLTtsConstants.EVENT_SYNTHESIS_INTERRUPTED);
break;
default:
break;
}
}
};
}