AVAudioPCMBuffer以编程方式构建,不以立体声播放

时间:2016-02-20 05:55:43

标签: swift core-audio avaudioengine avaudioplayernode avaudiopcmbuffer

我正在尝试以编程方式在Swift中填充AVAudioPCMBuffer以构建节拍器。这是我正在尝试构建的第一个真正的应用程序,所以它也是我的第一个音频应用程序。现在我正在尝试不同的框架和方法来准确地获取节拍器循环。

我正在尝试使用度量/条的长度构建AVAudioPCMBuffer,以便我可以使用AVAudioPlayerNode的scheduleBuffer方法的.Loops选项。我首先将我的文件(2 ch,44100 Hz,Float32,非inter,* .wav和* .m4a都有相同的问题)加载到缓冲区中,然后将由空帧分隔的帧逐帧复制到barBuffer中。下面的循环是我如何实现这一点。

如果我安排原始缓冲区播放,它将以立体声方式播放,但是当我安排barBuffer时,我只获得左声道。正如我所说,我是编程的初学者,并且没有音频编程经验,所以这可能是我对32位浮点通道或这种数据类型UnsafePointer<UnsafeMutablePointer<float>>缺乏了解。当我在swift中查看floatChannelData属性时,描述会让人觉得应该复制两个通道。

var j = 0
for i in 0..<Int(capacity) {
    barBuffer.floatChannelData.memory[j] = buffer.floatChannelData.memory[i]
    j += 1
}
j += Int(silenceLengthInSamples)
// loop runs 4 times for 4 beats per bar. 

编辑:由于hotpaw2,我删除了明显的错误i += 1。但是,当播放barBuffer时,右声道仍然缺失。

2 个答案:

答案 0 :(得分:1)

这看起来像是对Swift的误解&#34;对于&#34;循环。 Swift&#34; for&#34;循环自动递增&#34; i&#34;数组索引。但是你在循环体中再次递增它,这意味着你最终会跳过初始缓冲区中的每个其他样本(右声道)。

答案 1 :(得分:1)

swift中的不安全指针习惯了很奇怪。

floatChannelData.memory[j]仅访问第一个数据通道。要访问其他频道,您有几个选择:

使用advancedBy

// Where current channel is at 0

// Get a channel pointer aka UnsafePointer<UnsafeMutablePointer<Float>> 
let channelN = floatChannelData.advancedBy( channelNumber )

// Get channel data aka UnsafeMutablePointer<Float>
let channelNData = channelN.memory

// Get first two floats of channel channelNumber
let floatOne = channelNData.memory
let floatTwo = channelNData.advancedBy(1).memory

使用下标

// Get channel data aka UnsafeMutablePointer<Float>
let channelNData = floatChannelData[ channelNumber ]

// Get first two floats of channel channelNumber
let floatOne = channelNData[0]
let floatTwo = channelNData[1]

使用下标更加清晰,然后是手动推进的步骤 访问内存是隐含的。

对于你的循环,尝试访问缓冲区的所有通道:

for i in 0..<Int(capacity) {
    for n in 0..<Int(buffer.format.channelCount) {
         barBuffer.floatChannelData[n][j] = buffer.floatChannelData[n][i]
    }
}

希望这有帮助!