ExoPlayer:自定义音频处理器 - 均衡器
ExoPlayer: Custom AudioProcessor - Equalizer
我正在为 Android 开发基于 ExoPlayer 的媒体播放器,我正在尝试编写自己的均衡器。
我对 ExoPlayer 进行了相当深入的研究,我认为操作样本以应用 Equalier 更改的最佳位置是自定义 AudioProcessor
。
我使用 ChannelMappingAudioProcessor
作为起点,并克隆了我认为相关的方面:
class EqualizerAudioProcessor : BaseAudioProcessor() {
private lateinit var outputChannels: IntArray
override fun configure(sampleRateHz: Int, channelCount: Int, encoding: Int): Boolean {
outputChannels = IntArray(channelCount)
for (i in 0 until channelCount) {
outputChannels[i] = i
}
return true
}
override fun isActive(): Boolean {
return true
}
override fun getOutputChannelCount(): Int {
return outputChannels.size
}
override fun queueInput(inputBuffer: ByteBuffer) {
var position = inputBuffer.position()
val limit = inputBuffer.limit()
val frameCount = (limit - position) / (2 * channelCount)
val outputSize = frameCount * outputChannels.size * 2
val buffer = replaceOutputBuffer(outputSize)
while (position < limit) {
for (element in outputChannels) {
var sample = inputBuffer.getShort(position + 2 * element)
// Todo: Manipulate sample
buffer.putShort(sample)
}
position += channelCount * 2
}
inputBuffer.position(limit)
buffer.flip()
}
override fun onReset() {
}
}
似乎如果我 enable
这个 AudioProcessor
,播放不会发生(它似乎卡在 'paused state',就好像样本没有被传递一样,有趣的是,queueInput()
没有被调用。如果我禁用 AudioProcessor
,播放正常。
我希望有人能帮助我理解我是否在此处犯了错误,以及如何使它正常工作。
作为参考,ExoPlayer 实例初始化如下:
private fun initPlayer(context: Context): ExoPlayer {
val audioProcessor = EqualizerAudioProcessor()
val renderersFactory = object : DefaultRenderersFactory(context) {
override fun buildAudioProcessors(): Array<AudioProcessor> {
return arrayOf(audioProcessor)
}
}
val player: SimpleExoPlayer = ExoPlayerFactory.newSimpleInstance(
context,
renderersFactory,
DefaultTrackSelector(),
DefaultLoadControl()
)
player.addListener(object : Player.EventListener {
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
callback?.onPlayStateChanged(playWhenReady)
}
})
return player
}
提前致谢
问题是你必须在AudioProcessor
的configure()
中调用setInputFormat()
,否则queueInput()
将不会被调用。
我正在为 Android 开发基于 ExoPlayer 的媒体播放器,我正在尝试编写自己的均衡器。
我对 ExoPlayer 进行了相当深入的研究,我认为操作样本以应用 Equalier 更改的最佳位置是自定义 AudioProcessor
。
我使用 ChannelMappingAudioProcessor
作为起点,并克隆了我认为相关的方面:
class EqualizerAudioProcessor : BaseAudioProcessor() {
private lateinit var outputChannels: IntArray
override fun configure(sampleRateHz: Int, channelCount: Int, encoding: Int): Boolean {
outputChannels = IntArray(channelCount)
for (i in 0 until channelCount) {
outputChannels[i] = i
}
return true
}
override fun isActive(): Boolean {
return true
}
override fun getOutputChannelCount(): Int {
return outputChannels.size
}
override fun queueInput(inputBuffer: ByteBuffer) {
var position = inputBuffer.position()
val limit = inputBuffer.limit()
val frameCount = (limit - position) / (2 * channelCount)
val outputSize = frameCount * outputChannels.size * 2
val buffer = replaceOutputBuffer(outputSize)
while (position < limit) {
for (element in outputChannels) {
var sample = inputBuffer.getShort(position + 2 * element)
// Todo: Manipulate sample
buffer.putShort(sample)
}
position += channelCount * 2
}
inputBuffer.position(limit)
buffer.flip()
}
override fun onReset() {
}
}
似乎如果我 enable
这个 AudioProcessor
,播放不会发生(它似乎卡在 'paused state',就好像样本没有被传递一样,有趣的是,queueInput()
没有被调用。如果我禁用 AudioProcessor
,播放正常。
我希望有人能帮助我理解我是否在此处犯了错误,以及如何使它正常工作。
作为参考,ExoPlayer 实例初始化如下:
private fun initPlayer(context: Context): ExoPlayer {
val audioProcessor = EqualizerAudioProcessor()
val renderersFactory = object : DefaultRenderersFactory(context) {
override fun buildAudioProcessors(): Array<AudioProcessor> {
return arrayOf(audioProcessor)
}
}
val player: SimpleExoPlayer = ExoPlayerFactory.newSimpleInstance(
context,
renderersFactory,
DefaultTrackSelector(),
DefaultLoadControl()
)
player.addListener(object : Player.EventListener {
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
callback?.onPlayStateChanged(playWhenReady)
}
})
return player
}
提前致谢
问题是你必须在AudioProcessor
的configure()
中调用setInputFormat()
,否则queueInput()
将不会被调用。