Android TTS接口分析和调用实现

这篇文章会分享下speech包源码,我们会更明白speech包接口的来龙去脉。本篇文章我们主要讲解调用的关键接口,其他的不做过多讲解,避免文章太冗长。

一、speech包的源码结构
speech源码路径:/frameworks/base/core/java/android/speech
先来看一下speech包的源码结构:
在这里插入图片描述

这里面,比较关键的有:TextToSpeech、TextToSpeechService、ITextToSpeechService、ITextToSpeechCallback、SynthesisCallback及其实现类(PlaybackSynthesisCallback和FileSynthesisCallback)。前两个一个是调用tts的接口,一个是实现tts的能力,后几个则是将它俩关联起来。

二、TextToSpeech的接口剖析
这里,我们只对构造方法、speck、synthesizeToFile进行剖析,其它的诸如setLanguage、getEngines不再写出来。
1.构造方法
构造方法有三个:
TextToSpeech(Context context, OnInitListener listener)
TextToSpeech(Context context, OnInitListener listener, String engine)
TextToSpeech(Context context, OnInitListener listener, String engine,String packageName, boolean useFallback)
看代码会发现,前两个最终还是调用了第三个。

在这里插入图片描述
前面一些赋值容易明白,关键信息在initTts()里。

在这里插入图片描述

看注释也能明白,initTts会按照这样一个顺序:指定的tts引擎(通过包名,构造方法中的参数engine)、默认的tts引擎、最常用的tts引擎。但这些对于我们理解speech源码不是最关键的,关键的在于connectToEngine(engine),有没有发现,三种创建引擎的方式最终都调它了。如果connectToEngine返回false了,也就通过 dispatchOnInit(ERROR)告诉调用者失败了。那就看下connectToEngine吧。

在这里插入图片描述

到这里,我们就明白了,原来是bind一个Service。指定了action为Engine.INTENT_ACTION_TTS_SERVICE,这就是在TextToSpeechService的实现类在mainfest中声明该action的原因。Connection太长,只看onServiceConnected吧。

在这里插入图片描述

在这里,拿到了mService的实例,bind的是远程Service,TextToSpeech的其它接口,也是再调用 ITextToSpeechService下的接口。然后通过mOnSetupConnectionAsyncTask中的dispatchOnInit(result)来回调初始化成功。
构造方法就先说到这里。

2.speak(text,queueMode,params,utteranceId)
看代码会发现,最终调用了service.speak(getCallerIdentity(), text, queueMode, getParams(params),utteranceId)。明白这一点就先可以了。

3.synthesizeToFile(text,params,file,utteranceId)
类似于speak,synthesizeToFile最终调用的service.synthesizeToFileDescriptor(getCallerIdentity(), text,fileDescriptor, getParams(params), utteranceId)。
接下来,我们将进入TextToSpeechService,去探究下service.speak和service.synthesizeToFileDescriptor。

三、TextToSpeech的接口如何通过TextToSpeechService来实现
这部分比较长,慢慢看。
1.mBinder
通过对TextToSpeech构造方法的剖析,知道了它是通过绑定远程Service来实现的,而远程Service是继承的TextToSpeechService,所以重点看它就行了。首先要看下它的onBind。

在这里插入图片描述

mBinder 的实例化非常长,毕竟要把ITextToSpeechService的各个接口实现完。这里只讲speak和synthesizeToFileDescriptor。

在这里插入图片描述

这样,一下子就明白了,speak的实现又调了mSynthHandler.enqueueSpeechItem,mSynthHandler就是一个Handler,字面理解该接口,就是将text的语音合成加入了队列。synthesizeToFileDescriptor的实现竟也是调了mSynthHandler.enqueueSpeechItem。

2.speak
上面已经说了,其实现是调mSynthHandler.enqueueSpeechItem,继续。

在这里插入图片描述

先看前面的,TextToSpeech的speak接口的参数mode在这里体现了,如果是TextToSpeech.QUEUE_FLUSH,会调用stopForApp停掉其它tts的播放,这里就不把代码贴出来了。我们关注的是speechItem.play()。

在这里插入图片描述

playImpl,要看SynthesisSpeechItemV1下的实现了。

在这里插入图片描述
终于看到了我们熟悉的onSynthesizeText(SynthesisRequest request,SynthesisCallback callback)。reques就是封装的tts合成请求的参数,在SynthesisSpeechItemV1的构造方法中封装的,callback是调用createSynthesisCallback创建的。

在这里插入图片描述

3.synthesizeToFileDescriptor
上面我们已经说了,synthesizeToFileDescriptor和speak的区别,就在于SpeechItemV1的子类不同。speak是SynthesisSpeechItemV1,synthesizeToFileDescriptor是SynthesisToFileOutputStreamSpeechItemV1。二者到了playImpl的区别,也主要在于callback的不同,其创建方法是:

在这里插入图片描述

到这里,明白了,TextToSpeech的接口是如何通过TextToSpeechService来实现。接下来,我们该关心如何将TextToSpeechService的实现回调回去。

四、TextToSpeechService的实现如何回调回去
1.speak
这里看一下PlaybackSynthesisCallback中的start、audioAvailable和done。
关注几个实例:UtteranceProgressDispatcher mDispatcher、AudioPlaybackHandler mAudioTrackHandler和SynthesisPlaybackQueueItem mItem,它们均是在TextToSpeech中实例化的。第一个关系到最终到UtteranceProgressListener的回调,后两个关系到音频的播放。
贴出来三个方法:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

先说回调,可以在PlaybackSynthesisCallback的done中看到,调用了mDispatcher.dispatchOnSuccess,进一步看是调用了ITextToSpeechCallback.onSuccess,再调用了UtteranceProgressListener的onDone。其它也是也是如此,不再细说。注意的是,onStart不是直接在PlaybackSynthesisCallback中,而是在SynthesisPlaybackQueueItem中,毕竟这时候才是开始播放。
再说播放,AudioPlaybackHandler 虽然不是继承自Handler,但其作用与其类似,是管理各个tts合成请求是的队列。SynthesisPlaybackQueueItem 继承自Runnable的子类,播放是在这完成的,它会创建一个BlockingAudioTrack,具体播放不再叙述。
2.synthesizeToFile
它的callback是FileSynthesisCallback。
大体与PlaybackSynthesisCallback类似,只是它不是播放,而是写入指定的文件。这里面需要关注的实例有:UtteranceProgressDispatcher mDispatcher和FileChannel mFileChannel,后者就是写文件的。
三个方法:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

以上我们分析了Android speech包的架构设计思想,以及如何调用的流程,至于具体的Tts引擎还需要另外集成,下篇我们会以百度TTS为例来讲解,需要明白的是集成了TTS引擎后你调用TextToSpeech接口才会有功能实现,目前只是android系统的TTS空壳,好了,本篇就说到这。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值