项目中有一个需求需要实现播报一连串的语音叫号。
如果有免费的tts文字转语音功能就好了,但是这些功能都是收费的,于是只能一个个有限的语音拼接起来。
使用SoundPool播放语音是异步的,如果不加控制没法达到效果,按顺序依次播放:请 XXX 号到XXXX 窗口 XX。
借助Rxjava很简单的就实现了这个功能,如下:
/** * @author yangyongzhen * @date 2021/6/11 * @version 1.0.0 * @desc 语音播报 */ fun playTakeMealVoice(bean: OrderedHistorySecRecord){ var orderno = bean.orderno val windowid = dyPara?.windowId var listVoice = arrayListOf<Int>() val numbers = mapOf( "0" to R.raw.n0, "1" to R.raw.n1, "2" to R.raw.n2, "3" to R.raw.n3, "4" to R.raw.n4, "5" to R.raw.n5, "6" to R.raw.n6, "7" to R.raw.n7, "8" to R.raw.n8, "9" to R.raw.n9) listVoice.add(R.raw.qing) if (orderno != null) { for ((index, chars) in orderno.withIndex()) { numbers["$chars"]?.let { listVoice.add(it) } } } listVoice.add(R.raw.hao) listVoice.add(R.raw.dao) if (windowid != null) { for ((index, chars) in windowid.withIndex()) { numbers["$chars"]?.let { listVoice.add(it) } } } listVoice.add(R.raw.chuangkou) listVoice.add(R.raw.qucan) var count = listVoice.size.toLong() Observable.interval(500, TimeUnit.MILLISECONDS).take(count).subscribe(object: Observer<Long> { override fun onComplete() { Log.d(TAG,"onComplete"); } override fun onSubscribe(d: Disposable) { Log.d(TAG,"onSubscribe:") } override fun onNext(t: Long) { Log.d(TAG,"onNext:$t") SoundUtil.playMusic(iBillyView.getActivity(), listVoice[t.toInt()]) } override fun onError(e: Throwable) { Log.d(TAG,"onError:" + e.message) } }) }
以下是封装的SoundUtil工具类。
object SoundUtil { private var soundId: Int = 0 private var soundPool: SoundPool? = null private val soundMap = hashMapOf<Int, Int>() fun playMusic(context: Context, mid: Int) { if (soundPool == null) { val mAudioAttributes = AudioAttributes.Builder().setLegacyStreamType(AudioManager.STREAM_MUSIC) .build() soundPool = SoundPool.Builder().setMaxStreams(10).setAudioAttributes(mAudioAttributes).build() } try { if (soundMap.containsKey(mid)) { soundPool!!.play(soundMap[mid]!!, 1.0f, 1.0f, 1, 0, 1.0f) } else { soundId = soundPool!!.load(context, mid, 1) soundPool!!.setOnLoadCompleteListener { pool, _, _ -> soundMap[mid] = soundId // 加载完成 try { pool.play(soundId, 1.0f, 1.0f, 1, 0, 1.0f) } catch (e: Exception) { } } } } catch (ex: Exception) { ex.printStackTrace() } } fun releaseMusic() { if (soundPool != null) { soundPool!!.release() soundPool = null } soundMap.clear() } }
想打断语音播报怎么办?也很简单。
在playTakeMealVoice所在的类里面,定义个伴生对象companion object,里面声明个disposable
在每次播放前先来个 disposable?.dispose()
companion object { var disposable:Disposable?=null }
fun playTakeMealVoice(orderno:String?,winid:String?){ Log.d(TAG,"playTakeMealVoice") disposable?.dispose()
在每次的订阅中,来个赋值:
...... Observable.interval(500, TimeUnit.MILLISECONDS).take(count).subscribeOn(Schedulers.io()).subscribe(object: Observer<Long> { override fun onComplete() { Log.d(TAG,"onComplete"); } override fun onSubscribe(d: Disposable) { Log.d(TAG,"onSubscribe:") disposable = d //来个赋值 } ......