gpt4 book ai didi

objective-c - 使用 AVAudioEngine 播放 WAV 数据

转载 作者:行者123 更新时间:2023-11-28 07:29:31 27 4
gpt4 key购买 nike

目前,我在音频线程上遇到了一个EXC_BAD_ACCESS 错误,我正在尝试推断出了什么问题。

当将 .wav 文件数据从 Data 转换为 AVAudioPCMBuffer 时,是否需要先剥离 RIFF header ?

import AVFoundation

public class Player : NSObject {
let engine = AVAudioEngine()

public override init() {
super.init()
do {
let _ = engine.mainMixerNode
try engine.start()
} catch {
print("Player error: \(error)")
}
}

@objc public func play(_ data: Data) {
let format = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: 48000, channels: 2, interleaved: true)!
let buffer = data.toPCMBuffer(format: format)!

let player = AVAudioPlayerNode()
engine.attach(player)
engine.connect(player, to: engine.mainMixerNode, format: nil)

player.scheduleBuffer(buffer, at: nil, completionCallbackType: .dataPlayedBack) {
callbackType in
// Nothing in here.
}
player.play()
}
}

这是 toPCMBuffer 扩展:

// Taken from: https://stackoverflow.com/a/52731480/2228559
extension Data {
func toPCMBuffer(format: AVAudioFormat) -> AVAudioPCMBuffer? {
let streamDesc = format.streamDescription.pointee
let frameCapacity = UInt32(count) / streamDesc.mBytesPerFrame
guard let buffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: frameCapacity) else { return nil }

buffer.frameLength = buffer.frameCapacity
let audioBuffer = buffer.audioBufferList.pointee.mBuffers

withUnsafeBytes { addr in
audioBuffer.mData?.copyMemory(from: addr, byteCount: Int(audioBuffer.mDataByteSize))
}

return buffer
}
}

注意:我不能使用 AVAudioFile,因为 .wav 文件数据是通过网络加载的。

最佳答案

IDK,但如果我播放交错的 AVAudioPCMBuffer,我的 mac 会崩溃,如果音频不是 float 据,则会出现乱码,因此您可以转换为非交错的 float 据:

@objc public func play(_ data: Data) {
let sampleRate: Double = 48000

let interleavedFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: sampleRate, channels: 2, interleaved: true)!
let interleavedBuffer = data.toPCMBuffer(format: interleavedFormat)!

let nonInterleavedFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: sampleRate, channels: 2, interleaved: false)!
let nonInterleavedBuffer = AVAudioPCMBuffer(pcmFormat: nonInterleavedFormat, frameCapacity: interleavedBuffer.frameCapacity)!
nonInterleavedBuffer.frameLength = interleavedBuffer.frameLength

let converter = AVAudioConverter(from: interleavedFormat, to: nonInterleavedFormat)!
try! converter.convert(to: nonInterleavedBuffer, from: interleavedBuffer)

let player = AVAudioPlayerNode()

engine.attach(player)
engine.connect(player, to: engine.mainMixerNode, format: nil)

player.scheduleBuffer(nonInterleavedBuffer, at: nil, completionCallbackType: .dataPlayedBack) {
callbackType in
// Nothing in here.
}

player.play()
}

extension Data {
func toPCMBuffer(format: AVAudioFormat) -> AVAudioPCMBuffer? {
assert(format.isInterleaved)

let streamDesc = format.streamDescription.pointee
let frameCapacity = UInt32(count) / streamDesc.mBytesPerFrame
guard let buffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: frameCapacity) else { return nil }

buffer.frameLength = buffer.frameCapacity

let b = UnsafeMutableBufferPointer(start: buffer.int16ChannelData![0], count: buffer.stride * Int(frameCapacity))
let bytesCopied = self.copyBytes(to: b)
assert(bytesCopied == count)

return buffer
}
}

关于objective-c - 使用 AVAudioEngine 播放 WAV 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55306996/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com