Exoplayer使用记录4-调节音轨中某个频道的声音

Exoplayer使用记录4-调节音轨中某个频道的声音

By Xdestiny. 2018/2/5

概述

又是个奇葩需求…有个7.1音轨,想要具体调节其中某个频道的声音。

解决思路

还是上Issue上搜吧…果然有人问过同样的问题
Implement volume controlling AudioProcessor, with independent control of channel volumes
具体来说就是要写一个用于修改单通道声音audioprocessor。需要注意的是,在调用自定义的processor前,exoplayer会先调用一个重采样processor以及一个映射processor。因此自定义处理的均是处理bit16的音频
此外还遇到了个奇怪的问题。由于测试时最后还是通过立体声的形式放出来,同样的代码对于立体声,AAC4.0工作正常,但对于5.1, 7.1就有问题。为此我还提了一个Issue给ExoPlayer。后来发现,再写一个混音器放在后面就OK。当然,如果后面接的直接就是5.1或者7.1的播放设备就得去掉这个混音器了。

具体代码

class MyAudioProcessor: AudioProcessor {

    private val TAG = "MyAudioProcessor"
    private var m_channelCnt = Format.NO_VALUE
    private var m_sampleRate = Format.NO_VALUE
    private var m_encoding = C.ENCODING_INVALID
    private var m_inputEnd = false
    private var m_buffer: ByteBuffer = EMPTY_BUFFER
    private var m_outputBuffer: ByteBuffer = EMPTY_BUFFER
    private var volume: Array<Float> = Array(8, { _ -> 1.0f}) // 控制具体每个频道的音量大小

    fun SetVolume(idx: Int, vol: Float){
        if(idx >= volume.size)
            throw IllegalArgumentException()
        volume[idx] = vol
    }

    fun GetVolume(idx: Int): Float{
        if(idx >= volume.size)
            throw IllegalArgumentException()
        return volume[idx]
    }

    override fun isActive(): Boolean {
        return m_encoding != C.ENCODING_INVALID
    }

    override fun queueEndOfStream() {
        m_inputEnd = true
    }

    override fun configure(sampleRateHz: Int, channelCount: Int, encoding: Int): Boolean {
        Log.d(TAG, "channel cnt = $channelCount")
        m_channelCnt = channelCount
        m_sampleRate = sampleRateHz
        m_encoding = encoding
        return true
    }

    override fun getOutputEncoding(): Int {
        return m_encoding
    }

    override fun flush() {
        m_outputBuffer = EMPTY_BUFFER
        m_inputEnd = false
    }

    override fun queueInput(buffer: ByteBuffer) {
        //最后只输出立体声混音结果
        var position = buffer.position()
        val limit = buffer.limit()
        val size = limit - position

        if (m_buffer.capacity() < size)
            m_buffer = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder())
        else
            m_buffer.clear()

        when(m_encoding){
            C.ENCODING_PCM_16BIT->{
                while(position < limit){
                    var retL = 0.0f
                    var retR = 0.0f
                    for(i in 0..m_channelCnt - 1){
                        if(i%2 == 0)
                            retL += buffer.getShort(position + i * 2) * volume[i]
                        else
                            retR += buffer.getShort(position + i * 2) * volume[i]
                    }
                    position += m_channelCnt * 2

                    m_buffer.putShort((retL / m_channelCnt).toShort())
                    m_buffer.putShort((retR / m_channelCnt).toShort())
                }
            }
            else->{
                throw IllegalStateException()
            }
        }
        buffer.position(limit)
        m_buffer.flip()
        m_outputBuffer = m_buffer
    }

    override fun isEnded(): Boolean {
        return m_inputEnd && m_outputBuffer === AudioProcessor.EMPTY_BUFFER
    }

    override fun getOutput(): ByteBuffer {
        val outputBuffer = m_outputBuffer
        m_outputBuffer = EMPTY_BUFFER
        return outputBuffer
    }

    override fun reset() {
        flush()
        m_buffer = AudioProcessor.EMPTY_BUFFER
        m_sampleRate = Format.NO_VALUE
        m_channelCnt = Format.NO_VALUE
        m_encoding = C.ENCODING_INVALID
    }

    override fun getOutputChannelCount(): Int {
        //最后只输出立体声混音结果
        return 2
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值