【问题标题】:AVAudioPlayerNode multichannel audio controlAVAudioPlayerNode 多声道音频控制
【发布时间】:2017-05-28 00:13:03
【问题描述】:

我已成功使用AVAudioPlayerNode 播放立体声和单声道文件。我想使用具有 3 个以上通道的文件(环绕文件)并能够以非线性方式路由音频。例如,我可以将文件通道 0 分配给输出通道 2,将文件通道 4 分配给输出通道 1。

音频接口的输出数量未知(2-40),这就是为什么我需要能够允许用户按照他们认为合适的方式路由音频。而WWDC 2015 507 中让用户在 Audio Midi Setup 中更改路由的解决方案并不是一个可行的解决方案。

我只能想到 1 种可能性(我对其他人持开放态度):为每个频道创建一个播放器,并为每个播放器加载仅一个频道的缓冲区 similar to this post。但即使通过海报承认,也存在问题。

所以我正在寻找一种方法将文件的每个通道复制到 AudioBuffer 中,例如:

let file = try AVAudioFile(forReading: audioURL)
let fullBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, 
                                  frameCapacity: AVAudioFrameCount(file.length))

try file.read(into: fullBuffer)

// channel 0
let buffer0 = AVAudioPCMBuffer(pcmFormat: file.processingFormat,
                               frameCapacity: AVAudioFrameCount(file.length))

// this doesn't work, unable to get fullBuffer channel and copy
// error on subscripting mBuffers
buffer0.audioBufferList.pointee.mBuffers.mData = fullBuffer.audioBufferList.pointee.mBuffers[0].mData

// repeat above buffer code for each channel from the fullBuffer

【问题讨论】:

    标签: swift mono core-audio surround avaudiopcmbuffer


    【解决方案1】:

    我能够弄清楚,所以这里是使它工作的代码。注意:下面的代码分隔了一个立体声(2 声道)文件。这可以很容易地扩展到处理未知数量的频道。

    let file = try AVAudioFile(forReading: audioURL)
    
    let formatL = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: file.processingFormat.sampleRate, channels: 1, interleaved: false)
    let formatR = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: file.processingFormat.sampleRate, channels: 1, interleaved: 
    
    let fullBuffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: AVAudioFrameCount(file.length))
    let bufferLeft = AVAudioPCMBuffer(pcmFormat: formatL, frameCapacity: AVAudioFrameCount(file.length))
    let bufferRight = AVAudioPCMBuffer(pcmFormat: formatR, frameCapacity: AVAudioFrameCount(file.length))
    
    try file.read(into: fullBuffer)
    bufferLeft.frameLength = fullBuffer.frameLength
    bufferRight.frameLength = fullBuffer.frameLength
    
    for i in 0..<Int(file.length) {
        bufferLeft.floatChannelData![0][i] = fullBuffer.floatChannelData![0][i]
        bufferRight.floatChannelData![0][i] = fullBuffer.floatChannelData![1][i]
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-26
      相关资源
      最近更新 更多