870920 Menu

AudioTransportSource详解

AudioTransportSource

图 3 11 AudioTransportSource类的继承层次

AudioTransportSource可对另一个PositionableAudioSource所产生的音频流进行中转和控制,其内部使用一个BufferingAudioSource对象。因此,由该类中转并控制的音频流可进行缓冲处理及并发生成。换句话说,AudioTransportSource相当于BufferingAudioSource的功能增强版,除了缓冲和并发之外,还可对来源音频流进行更多控制。在增强BufferingAudioSource的功能时,Jules并没有采取派生子类的方式,而是将该类组合到与其平级的AudioTransportSource类中。优先使用组合而非继承,这是非常重要的设计原则。

AudioTransportSource与它的另外两个平级“兄弟”不同,其构造函数无参。创建对象后,需调用核心函数setSource()设置本类所需的PositionableAudioSource等对象与变量值。这一点看似繁琐了一步,实则大有讲究。根本目的是:创建本类对象后,在该对象的整个生命期内,可随时调用setSource()更改该对象所持有的数据,以实现更灵活的输出(典型的聚合,而非组合)。

此外:AudioTransportSource除了继承PositionableAudioSource之外,还继承了ChangeBroadcaster可变生成类,因此,任何继承了ChangeListener的类均可由本类对象addChangeListener()来绑定,绑定后,该类即可在changeListenerCallback()函数中捕获并处理本类所产生的可变消息。

AudioTransportSource的核心函数(设置本类要中转和控制的来源,一并设置所需的其他参数):
 setSource (PositionableAudioSource指针, 缓冲大小 = 0, TimeSliceThread指针 = nullptr, 来源的采样率 = 0.0, 最大通道数 = 2)

AudioTransportSource 新增的其他成员函数
 setPosition (int64值) 从给定位置处输出,内部调用setNextReadPosition()
 getCurrentPosition () 获取音频流的当前时间点,时间单位:秒
 getLengthInSeconds () 返回每秒的采样数
 hasStreamFinished () 如果来源所产生的数据流已由本类耗尽,则返回true
 start () 开始产生音频流,一并发送可变消息
 stop () 暂停产生音频流,一并发送可变消息
 isPlaying () 如果当前正在产生音频流, 则返回true
 setGain (float值) 对所产生的音频流进行增益
 getGain () 返回当前设置的增益值

AudioTransportSource 继承自基类PositionableAudioSource的成员函数
 setNextReadPosition (int64值) getNextAudioBlock()产生音频流后,从给定位置处输出
 getNextReadPosition () 获取上个函数所设置的位置
 getTotalLength () 返回数据流的总长度(总的采样数)
 setLooping (bool值) 设置是否循环输出音频流
 isLooping () 检测当前是否处于循环模式
 prepareToPlay (采样数,采样率) 准备在后台线程上产生音频流
 releaseResources () 停止生成音频流
 getNextAudioBlock (…) 生成音频流,所产生的数据保存到本函数的参数中

AudioTransportSource 继承自基类ChangeBroadcaster的成员函数
 addChangeListener (ChangeListener指针) 绑定捕获器,以处理本类发送的可变消息
 removeChangeListener (ChangeListener指针) 移除已绑定的某个捕获器
 removeAllChangeListeners () 移除所有已绑定的捕获器
 sendChangeMessage () 发送可变消息,异步回调
 sendSynchronousChangeMessage () 发送可变消息,同步回调
 dispatchPendingMessages () 立即回调所发送的消息

AudioTransportSource是实现音频播放的关键环节之一,实际编程时,往往在setSource()函数中将来源设置为本类的平级类AudioFormatReaderSource的指针,而AudioFormatReaderSource所产生的音频流,基于其构造参数AudioFormatReader所持有的数据(内存地址),该地址由AudioFormat等类的成员函数所创建,恰指向音频文件或音频CD中的数据(实为指向这些数据的InputStream内存地址(指针))。

因此,音频文件或音频CD中的数据经过AudioFormatReaderSource类的处理后,使用后台线程以缓冲的形式流入AudioTransportSource(由setSource()所设置)。AudioTransportSource再以缓冲的形式,在后台线程上将这些数据输出给下一个环节(比如AudioSourcePlayer),最终完成音频播放的整个流程。最终输出时,AudioTransportSource可进行一些基本控制,比如:停止、开始、音量增益等等(如需循环,则调用AudioFormatReaderSource对象的setLooping (true)函数) 。