Kevin
Kevin

Reputation: 341

Converting M4A file into Raw data

I am trying to read the raw values of a sound file. I am pretty new to IOS development. I am ultimately trying to take a fast fourier transform of the audio file. The output of the data looks like a sound wave, but when I take the fft of a beep sound provided hereenter link description here I do not get an obvious frequency from the fft, which leads me to believe I am not getting the real raw data. I have constructed the following code using a combination of several stack overflow posts. Am I reading the file incorrectly?

class AudioAnalyzer {
init(file_path: NSURL) {
    var assetOptions = [
        AVURLAssetPreferPreciseDurationAndTimingKey : 1,
        AVFormatIDKey : kAudioFormatLinearPCM
    ]
    println(file_path)
    var videoAsset=AVURLAsset(URL: file_path, options: assetOptions)
    var error:NSError?

    var videoAssetReader=AVAssetReader(asset: videoAsset, error: &error)

    if error != nil
    {
        println(error)
    }

    var tracksArray=videoAsset?.tracksWithMediaType(AVMediaTypeAudio)
    var videotrack = tracksArray?[0] as! AVAssetTrack
    var fps = videotrack.nominalFrameRate

    var videoTrackOutput=AVAssetReaderTrackOutput(track:videotrack as AVAssetTrack , outputSettings: nil)

    if videoAssetReader.canAddOutput(videoTrackOutput)
    {
        videoAssetReader.addOutput(videoTrackOutput)
        videoAssetReader.startReading()
    }

    if videoAssetReader.status == AVAssetReaderStatus.Reading {

        var sampleBuffer  = videoTrackOutput.copyNextSampleBuffer()
        var audioBuffer = CMSampleBufferGetDataBuffer(sampleBuffer)
        let samplesInBuffer = CMSampleBufferGetNumSamples(sampleBuffer)
        var currentZ = Double(samplesInBuffer)

        let buffer: CMBlockBufferRef = CMSampleBufferGetDataBuffer(sampleBuffer)

        var lengthAtOffset: size_t = 0
        var totalLength: size_t = 0
        var data: UnsafeMutablePointer<Int8> = nil
        var output:  Array<Float> = [];
        if( CMBlockBufferGetDataPointer( buffer, 0, &lengthAtOffset, &totalLength, &data ) != noErr ) {
            println("some sort of error happened")
        } else {
            for i in stride(from: 0, to: totalLength, by: 2) {
                var myint = Int16(data[i]) << 8 | Int16(data[i+1])
                var myFloat = Float(myint)
                output.append(myFloat);
            }
            println(output)
        }
    }
}
}

Upvotes: 1

Views: 1254

Answers (1)

Gordon Childs
Gordon Childs

Reputation: 36072

Your AVAssetReaderTrackOutput is giving you raw packet data. For LPCM output, pass in some outputSettings:

var settings = [NSObject : AnyObject]()
settings[AVFormatIDKey] = kAudioFormatLinearPCM
settings[AVLinearPCMBitDepthKey] = 16
settings[AVLinearPCMIsFloatKey] = false

var videoTrackOutput=AVAssetReaderTrackOutput(track:videotrack as AVAssetTrack , outputSettings: settings)

p.s. I'd feel much better if you renamed videoTrackOutput to audioTrackOutput.

Upvotes: 1

Related Questions