Skip to content

Instantly share code, notes, and snippets.

@iluvcapra
Last active August 29, 2015 14:26
Show Gist options
  • Save iluvcapra/624cc86c545ef16f156e to your computer and use it in GitHub Desktop.
Save iluvcapra/624cc86c545ef16f156e to your computer and use it in GitHub Desktop.
//
// AVAudioFile_Digest.swift
// Bag of Holding
//
// Created by Jamie Hardt on 7/30/15.
// Copyright © 2015 Jamie Hardt. All rights reserved.
//
import Foundation
import AVFoundation
func writeSamplesFromBuffer(buffer: AVAudioPCMBuffer, toStream : NSOutputStream) {
assert(buffer.format.interleaved == true)
var rawBuffer = UnsafePointer<UInt8>(buffer.int32ChannelData.memory)
var toWrite = sizeof(Int32) * Int(buffer.format.channelCount) * Int(buffer.frameLength)
while toWrite > 0 {
let written = toStream.write(rawBuffer, maxLength: toWrite)
rawBuffer = rawBuffer.advancedBy(written)
toWrite -= written
}
}
let AudioDataWriterAVAudioFileError = "AudioDataWriterAVAUdioFileError"
func writeAudioDataFromURL(url : NSURL,
usingFormat format: AVAudioCommonFormat,
toStream: NSOutputStream) throws {
let audioFile = try AVAudioFile(forReading: url,
commonFormat: format,
interleaved: true)
let pcmBuffer = AVAudioPCMBuffer(PCMFormat:
audioFile.processingFormat,
frameCapacity: 0x400)
toStream.open()
let writerQueue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
dispatch_async(writerQueue) {
do {
while true {
try audioFile.readIntoBuffer(pcmBuffer)
if pcmBuffer.frameLength == 0 { break }
writeSamplesFromBuffer(pcmBuffer, toStream: toStream)
}
} catch let error as NSError {
toStream.setProperty(error, forKey: AudioDataWriterAVAudioFileError)
} catch let error {
fatalError("Fatal error: \(error) while reading audio file \(audioFile) at URL \(url)")
}
toStream.close()
}
}
func digestForStream(stream : NSInputStream,
digestType type : CFStringRef, length : Int) throws -> NSData {
let transform = SecTransformCreateGroupTransform().takeRetainedValue()
let readXform = SecTransformCreateReadTransformWithReadStream(stream as CFReadStreamRef).takeRetainedValue()
var error : Unmanaged<CFErrorRef>? = nil
let digestXform : SecTransformRef = try {
let d = SecDigestTransformCreate(type, length, &error)
if d == nil {
throw error!.takeUnretainedValue()
} else {
return d.takeRetainedValue()
}
}()
SecTransformConnectTransforms(readXform, kSecTransformOutputAttributeName,
digestXform, kSecTransformInputAttributeName,
transform, &error)
if let e = error { throw e.takeUnretainedValue() }
if let output = SecTransformExecute(transform, &error) as? NSData {
return output
} else {
throw error!.takeUnretainedValue()
}
}
func sha256DigestForInterleavedAudioAtURL(url : NSURL,
convertedToSampleFormat sampleFormat: AVAudioCommonFormat) throws -> NSData {
let streamBufSize = 0x1000
var rs : NSInputStream? = nil
var ws : NSOutputStream? = nil
NSStream.getBoundStreamsWithBufferSize(streamBufSize,
inputStream: &rs, outputStream: &ws)
guard let readStream = rs, writeStream = ws else {
fatalError("Failed to create file read streams")
}
try writeAudioDataFromURL(url,
usingFormat: sampleFormat, toStream: writeStream)
let retVal = try digestForStream(readStream, digestType: kSecDigestSHA2 , length: 256)
if let error = writeStream.propertyForKey(AudioDataWriterAVAudioFileError) as? NSError {
throw error
}
return retVal
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment