我想将mp3和wav音频文件作为浮点数或双精度数组加载,类似于scipy中的io.wavfile.read函数。我可以通过将音频流写入缓冲区来使用麦克风数据或播放音频。但是,我不确定如何一次加载所有音频文件的数据。
- 更新
对于将来使用音频信号数据的任何人来说,这是一个可以解决问题的功能。它基于Rhythmic Fistman的回答。
func loadAudioSignal(audioURL: NSURL) -> (signal: [Float], rate: Double, frameCount: Int) {
let file = try! AVAudioFile(forReading: audioURL)
let format = AVAudioFormat(commonFormat: .PCMFormatFloat32, sampleRate: file.fileFormat.sampleRate, channels: file.fileFormat.channelCount, interleaved: false)
let buf = AVAudioPCMBuffer(PCMFormat: format, frameCapacity: UInt32(file.length))
try! file.readIntoBuffer(buf) // You probably want better error handling
let floatArray = Array(UnsafeBufferPointer(start: buf.floatChannelData[0], count:Int(buf.frameLength)))
return (signal: floatArray, rate: file.fileFormat.sampleRate, frameCount: Int(file.length))
}
答案 0 :(得分:11)
AVAudioFile
非常方便,也可以为您进行格式转换:
import AVFoundation
// ...
let url = NSBundle.mainBundle().URLForResource("your audio file", withExtension: "wav")
let file = try! AVAudioFile(forReading: url!)
let format = AVAudioFormat(commonFormat: .PCMFormatFloat32, sampleRate: file.fileFormat.sampleRate, channels: 1, interleaved: false)
let buf = AVAudioPCMBuffer(PCMFormat: format, frameCapacity: 1024)
try! file.readIntoBuffer(buf)
// this makes a copy, you might not want that
let floatArray = Array(UnsafeBufferPointer(start: buf.floatChannelData[0], count:Int(buf.frameLength)))
print("floatArray \(floatArray)\n")
可悲的是,对于双打来说,将.PCMFormatFloat32
替换为.PCMFormatFloat64
似乎不够,因为AVAudioPCMBuffer
没有float64ChannelData
方法。
更新因为我不太清楚
您可以通过使用UnsafeBufferPointer
来避免复制数组,这是一个非常好的集合类型:
let floatArray = UnsafeBufferPointer(start: buf.floatChannelData[0], count:Int(buf.frameLength))
答案 1 :(得分:2)
要找到关于UnsafeBufferPointer
的所有信息真的很棘手
在这里,我要发布 Swift 5.0
的更新代码if let url = Bundle.main.url(forResource: "silence", withExtension: "mp3") {
let file = try! AVAudioFile(forReading: url)
if let format = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: file.fileFormat.sampleRate, channels: 1, interleaved: false) {
if let buf = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: 1024) {
try! file.read(into: buf)
// this makes a copy, you might not want that
let floatArray = UnsafeBufferPointer(start: buf.floatChannelData![0], count:Int(buf.frameLength))
// convert to data
var data = Data()
for buf in floatArray {
data.append(withUnsafeBytes(of: buf) { Data($0) })
}
// use the data if required.
}
}
}
希望它会对您有所帮助:)
答案 2 :(得分:0)
我已将代码从@rhythmicfistman更新为Swift5
。大约需要进行一系列更改:在swift
世界中,事情显然发生了巨大变化。
func readWavIntoFloats(fname: String, ext: String) -> [Float] {
let url = Bundle.main.url(forResource: fname, withExtension: ext)
let file = try! AVAudioFile(forReading: url!)
let format = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: file.fileFormat.sampleRate, channels: 1, interleaved: false) ?? <#default value#>
let buf = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: 1024)!
try! file.read(into: buf)
// this makes a copy, you might not want that
let floatArray = Array(UnsafeBufferPointer(start: buf.floatChannelData?[0], count:Int(buf.frameLength)))
return floatArray
}
答案 3 :(得分:0)
以上答案对我不起作用,我在使用Swift5,在这里找到了对我有用的扩展:https://gist.github.com/jtodaone/f2fa59c19794811dbe989dff65a772bc
这也是我在Playground上使用代码的方式
import UIKit
import AVFoundation
let filePath: String = Bundle.main.path(forResource: "nameOfFile", ofType: "wav")!
print("\(filePath)")
let fileURL: NSURL = NSURL(fileURLWithPath: filePath)
let audioFile = try AVAudioFile(forReading: fileURL as URL)
let audioFormat = audioFile.processingFormat
let audioFrameCount = UInt32(audioFile.length)
let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: audioFrameCount)
try audioFile.read(into: audioFileBuffer!)
extension AudioBuffer {
func array() -> [Float] {
return Array(UnsafeBufferPointer(self))
}
}
extension AVAudioPCMBuffer {
func array() -> [Float] {
return self.audioBufferList.pointee.mBuffers.array()
}
}
extension Array where Element: FloatingPoint {
mutating func buffer() -> AudioBuffer {
return AudioBuffer(mNumberChannels: 1, mDataByteSize: UInt32(self.count * MemoryLayout<Element>.size), mData: &self)
}
}
let array = audioFileBuffer?.array()
print(array?.count) //Optional(2705408)