Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
852 views
in Technique[技术] by (71.8m points)

ios - How can I generate an array of floats from an audio file in Swift

I would like to load mp3 and wav audio files as arrays of floats or doubles, similar to the io.wavfile.read function in scipy. I can do this with microphone data or playing audio by writing the audio stream to a buffer. However, I'm not sure how to load all of an audio file's data at once.

-- Update

For anyone working with audio signal data in the future, here's a function that does the trick. It's based on Rhythmic Fistman's answer.

    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))
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

AVAudioFile built-in to iOS (and OS X), is very convenient and will also do format conversions for you:

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)
")

Sadly, for doubles it doesn't seem to be enough to substitute .PCMFormatFloat32 with .PCMFormatFloat64 because AVAudioPCMBuffer doesn't have a float64ChannelData method.

update because I don't know swift well

You can avoid copying the array by working with the UnsafeBufferPointer, which is a perfectly good collection type:

let floatArray = UnsafeBufferPointer(start: buf.floatChannelData[0], count:Int(buf.frameLength))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...