user967493
user967493

Reputation: 143

Convert audio into raw PCM data of type [Double]

I'm trying to convert a recorded audio file into raw PCM data of type [Double]. I found a way to load and convert audio to PCM data of the type [Float32] like this:

    // load audio from path
    let file = try! AVAudioFile(forReading: self.soundFileURL)
    // declare format
    let format = AVAudioFormat(commonFormat: .PCMFormatFloat32, sampleRate: file.fileFormat.sampleRate, channels: 1, interleaved: false)
    // initialize audiobuffer with the length of the audio file
    let buf = AVAudioPCMBuffer(PCMFormat: format, frameCapacity: UInt32(file.length))
    // write to file
    try! file.readIntoBuffer(buf)
    // copy to array
    let floatArray = Array(UnsafeBufferPointer(start: buf.floatChannelData[0], count:Int(buf.frameLength)))

The problem is, I need the data as [Double] and AVAudioPCMBuffer() only knows the .PCMFormatFloat32. Does anybody know a workaround? Thank you.

Upvotes: 2

Views: 3515

Answers (3)

DNG
DNG

Reputation: 649

updated to Swift 5

        do {
            let file = try AVAudioFile(forReading: soundFileURL)
            if let format = AVAudioFormat(commonFormat: .pcmFormatFloat64, sampleRate: file.fileFormat.sampleRate, channels: file.fileFormat.channelCount, interleaved: false), let buf = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: AVAudioFrameCount(file.length)){
                try file.read(into: buf)
                let abl = Array(UnsafeBufferPointer(start: buf.audioBufferList, count: Int(buf.audioBufferList.pointee.mNumberBuffers)))

                let buffer = buf.audioBufferList[0].mBuffers
                let mDataList = Array(UnsafeMutableRawBufferPointer(start: buffer.mData, count: Int(buffer.mDataByteSize)))
            }
        } catch{
            print("Audio Error: \(error)")
        }

Upvotes: 5

BLICK
BLICK

Reputation: 41

that code doesn't work anymore maybe.
here is new working code.

Swift 3.2

let file = try! AVAudioFile(forReading: soundFileURL)
let format = AVAudioFormat(commonFormat: .PCMFormatFloat64, sampleRate: file.fileFormat.sampleRate, channels: file.fileFormat.channelCount, interleaved: false)
let buf = AVAudioPCMBuffer(PCMFormat: format, frameCapacity: AVAudioFrameCount(file.length))
try! file.readIntoBuffer(buf)
let abl = Array(UnsafeBufferPointer(start: buf.audioBufferList, count: Int(buf.audioBufferList.pointee.mNumberBuffers)))
let buffer = audioBufferList[0].mBuffers
let mDataList = Array(UnsafeMutableRawBufferPointer(start: buffer.mData, count: Int(buffer.mDataByteSize)))

Upvotes: 1

Gordon Childs
Gordon Childs

Reputation: 36169

But AVAudioFormat does know .PCMFormatFloat64:

let format = AVAudioFormat(commonFormat: .PCMFormatFloat64, sampleRate: file.fileFormat.sampleRate, channels: 1, interleaved: false)

Maybe you mean AVAudioPCMBuffer doesn't have a float64ChannelData convenience property?

That's fine, you can use AVAudioPCMBuffer's superclass, AVAudioBuffer has everying you need to be able to get at the raw Double/Float64 samples:

let abl = buf.audioBufferList.memory
let doubles = UnsafePointer<Double>(abl.mBuffers.mData)
doubles[0] // etc...

In full:

let file = try! AVAudioFile(forReading: self.soundFileURL)
let format = AVAudioFormat(commonFormat: .PCMFormatFloat64, sampleRate: file.fileFormat.sampleRate, channels: 1, interleaved: false)

let buf = AVAudioPCMBuffer(PCMFormat: format, frameCapacity: UInt32(file.length))
try! file.readIntoBuffer(buf)
let abl = buf.audioBufferList.memory
let doubles = UnsafePointer<Float64>(abl.mBuffers.mData)

Upvotes: 4

Related Questions