TTS源码解析

TTS全称为“TextToSpeech”,是Android原生在文本转语音服务。本文将从TTS使用过程,对TTS源码进行分析。

主要涉及的源码有:

framework\base\core\java\android\speech\tts\TextToSpeech.java

framework\base/core\java/android\speech\tts\TextToSpeechService.java

external\svox\pico\src\com\svox\pico\PicoService.java

external\svox\pico\compat\src\com\android\tts\compat\CompatTtsService.java

external\svox\pico\compat\src\com\android\tts\compat\SynthProxy.java

external\svox\pico\compat\jni\com_android_tts_compat_SynthProxy.cpp

external\svox\pico\tts\com_svox_picottsengine.cpp

1、TTS初始化

首先来看TextToSpeech的构造函数


紧接着执行initTts操作,初始化TTS:



首先连接到用户请求的tts引擎服务,接着是默认引擎,最后是高性能引擎,从代码可以看出高性能引擎优先级最高,默认引擎其次。连接代码如下:



Engine.INTENT_ACTION_TTS_SERVICE的值为"android.intent.action.TTS_SERVICE";其连接到的服务为action为"android.intent.action.TTS_SERVICE"的服务,在external\svox\pico目录中的AndroidManifest.xml文件可以发现:


所以可以得到这里连接到的服务就是PicoService,其具体代码如下:其继承于CompatTtsService。



我们再来看看CompatTtsService这个类,这个类为抽象类,它的父类为TextToSpeechService,其有一个成员SynthProxy类,该类负责调用TTS的C++层代码。



我们来看看CompatTtsService的onCreate()方法,该方法中主要对SynthProxy进行了初始化



我们紧接着看看SynthProxy的构造函数都干了什么,我也不知道干了什么,但是里面有个静态代码块,其加载了ttscompat动态库,所以它肯定只是一个代理,实际功能由C++本地方法实现

在构造函数中,调用了native_setup方法来初始化引擎,其实现在C++层(com_android_tts_compat_SynthProxy.cpp)。代码如下:

上面红线init方法在com_svox_picottsengine.cpp中:



至此,TTS引擎的初始化就完成了,接下来分析TTS的调用。

2、TTS的调用

我们在应用层一般调用TextToSpeech中的speak()方法,我们来看看其执行流程:


接着调用runAction():


然后调用mServiceConnection中的runAction方法,其具体代码如下:


可以发现最后会回调action.run(mService)方法。接着执行service.playAudio();这里的service为PicoService,其继承于抽象类CompatTtsService,而CompatTtsService继承于抽象类TextToSpeechService.所以会执行TextToSpeechService中的playAudio(),该方法位于TextToSpeechService中mBinder中。该方法如下:



接着执行mSynthHandler.enqueueSpeechItem(queueMode, item),其代码如下:



我们主要看speechItem.play()该方法在Speechitem类中,其为TextToSpeechService内部类



在TextToSpeechService中的playAudio()中代码可以知道这里的speechitem为SynthesisSpeechItemV1。因此在play中执行的playimpl()方法为SynthesisSpeechItemV1类中的playimpl()方法,其代码如下:



在playImpl方法中会执行onSynthesizeText方法,这是个抽象方法,记住其传递了一个synthesisCallback,后面会讲到。哪该方法具体实现是在哪里呢,没错,就是在TextToSpeechService的子类CompatTtsService中。来看看它怎么实现的:


mNativeSynth为SynthProxy的一个对象,之前说了他是一个代理类,他的speak方法如下:



看到没?什么都没做,就是调用native_speak方法,看它的名字就知道是一个本地方法,那么该方法又是在哪实现呢?就是在com_android_tts_compat_SynthProxy.cpp中,该文件中有下面的映射数组(只截取了一部分):

java中对应的native_speak方法对应的C++层代码方法为com_android_tts_compat_SynthProxy_speak方法,接下来来看看该方法是怎么实现的:


该方法中调用了TTS引擎中的synthesizeText方法,那么该方法是怎么实现的呢?该方法位于com_svox_picottsengine.cpp中,主要代码(代码太长,只贴部分)如下:



其中picoSynthDoneCBPtr()为回调函数,其为TTS初始化过程传入的:


而TTS的init初始化在native_setup中被调用


那么__ttsSynthDoneCB又是什么呢?其实现如下:


callRequestAudioAvailable()方法如下:


这个地方调用env->CallIntMethod()方法,在C++层调用java方法,那么这个方法在哪呢?这里的env就是之前说的synthesisCallback,synthesisCallback为PlaybackSynthesisCallback类的对象,那么将会执行PlaybackSynthesisCallback中的audioAvailable()


至此,TTS的调用就结束了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值