Skip to content

Instantly share code, notes, and snippets.

@mingsai
Created July 3, 2015 00:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mingsai/5f8bbd0a99dca559d39e to your computer and use it in GitHub Desktop.
Save mingsai/5f8bbd0a99dca559d39e to your computer and use it in GitHub Desktop.
A swift delegate for managing an AVAudioRecorder and it's related events.
//
// MNGRecorderHandler.swift
//
//
// Created by Tommie Carter on 6/29/15.
// Copyright © 2015 MING Technology. All rights reserved.
//
import AVFoundation
struct MNGAudioRecorderEvents {
static let RecordingFinished = "RecordingFinished"
static let RecordingSaved = "RecordingSaved"
static let RecordingStarted = "RecordingStarted"
static let RecordingStopped = "RecordingStopped"
static let RecordingPaused = "RecordingPaused"
static let RecordingInterrupted = "RecordingInterrupted"
static let RecordingInterruptionEnded = "RecordingInterruptionEnded"
static let RecordingErrorOccurred = "RecordingErrorOccurred"
static let RecordingCancelationRequested = "RecordingCancelationRequested"
static let RecordingCanceled = "RecordingCanceled"
}
class MNGAudioRecorderHandler: NSObject, AVAudioRecorderDelegate {
struct Constants {
static let ExtensionM4A = ".m4a"
static let SelectorCancelRecording = Selector("cancelRecording:")
}
let recordSettings = [
AVFormatIDKey:Int(kAudioFormatAppleLossless),
AVEncoderBitRateKey:NSNumber(int:64000),
AVEncoderAudioQualityKey:AVAudioQuality.Max.rawValue,
AVNumberOfChannelsKey:NSNumber(int: 2),
AVLinearPCMIsNonInterleaved:false,
AVLinearPCMBitDepthKey:NSNumber(int: 32),
AVLinearPCMIsBigEndianKey:false,
AVLinearPCMIsFloatKey:false,
AVSampleRateKey:NSNumber(float: 44100.0) //44100.0
] as [String:AnyObject]
var audioRecorder: AVAudioRecorder!
var meterTimer:NSTimer!
var audioFilename:String! {
get {
return NSProcessInfo.processInfo().globallyUniqueString.stringByAppendingString(Constants.ExtensionM4A)
}
}
var recordingFilePath:String!
// {
// get {
// return NSTemporaryDirectory() + self.audioFilename
// }
// }
override init() {
super.init()
self.recordingFilePath = NSTemporaryDirectory() + self.audioFilename
//file:///private/var/mobile/Containers/Data/Application/4DD09F1D-EA2E-4FBC-BF5D-C527FB488CDD/tmp/8FCC62A1-A2E7-41A2-9FEC-91787CBB61CA-4075-000006B0AFF6E890.m4a
let url = NSURL(fileURLWithPath: self.recordingFilePath)
do {
if self.audioRecorder == nil {
self.audioRecorder = try AVAudioRecorder( URL: url, settings: recordSettings )
self.audioRecorder.prepareToRecord()
self.audioRecorder.meteringEnabled = true
}
} catch let e as NSError {
print (e.localizedDescription)
}
}
//MARK: Audio Recorder Delegate Methods
func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) {
//
}
func audioRecorderEncodeErrorDidOccur(recorder: AVAudioRecorder, error: NSError?) {
//
}
func audioRecorderBeginInterruption(recorder: AVAudioRecorder) {
//
}
func audioRecorderEndInterruption(recorder: AVAudioRecorder) {
//
}
func audioRecorderEndInterruption(recorder: AVAudioRecorder, withFlags flags: Int) {
//
}
func audioRecorderEndInterruption(recorder: AVAudioRecorder, withOptions flags: Int) {
//
}
func deleteTemporaryRecording() {
do {
try NSFileManager.defaultManager().removeItemAtPath(self.recordingFilePath)
} catch let e as NSError {
print(e.localizedDescription)
}
}
func deleteAllRecordings() {
let docsDir =
NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let fileManager = NSFileManager.defaultManager()
//let error: NSError?
do {
let files = try fileManager.contentsOfDirectoryAtPath(docsDir) as [String]
let recordings = files.filter( { (name: String) -> Bool in
return name.hasSuffix("m4a")
})
for var i = 0; i < recordings.count; i++ {
let path = docsDir + "/" + recordings[i]
do {
try fileManager.removeItemAtPath(path)
print("removing \(path)")
} catch let e as NSError {
print(e.localizedDescription)
}
}
} catch let e as NSError {
print(e.localizedDescription)
}
}
//MARK: Event Notifications
func registerEventObservers () {
defaultCenter.addObserver(self, selector: Constants.SelectorCancelRecording, name: MNGAudioRecorderEvents.RecordingCancelationRequested, object: nil)
}
func deRegisterEventObservers() {
defaultCenter.removeObserver(self, name: MNGAudioRecorderEvents.RecordingCancelationRequested, object: nil)
}
func askForNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"background:",
name: UIApplicationWillResignActiveNotification,
object:nil)
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"foreground:",
name:UIApplicationWillEnterForegroundNotification,
object:nil)
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"routeChange:",
name:AVAudioSessionRouteChangeNotification,
object:nil)
}
func background(notification:NSNotification) {
print("background")
}
func foreground(notification:NSNotification) {
print("foreground")
}
func routeChange(notification:NSNotification) {
// let userInfo:Dictionary<String,String!> = notification.userInfo as Dictionary<String,String!>
// let userInfo = notification.userInfo as Dictionary<String,[AnyObject]!>
// var reason = userInfo[AVAudioSessionRouteChangeReasonKey]
// var userInfo: [NSObject : AnyObject]? { get }
//let AVAudioSessionRouteChangeReasonKey: NSString!
/*
if let reason = notification.userInfo[AVAudioSessionRouteChangeReasonKey] as? NSNumber {
}
if let info = notification.userInfo as? Dictionary<String,String> {
if let rs = info["AVAudioSessionRouteChangeReasonKey"] {
var reason = rs.toInt()!
if rs.integerValue == Int(AVAudioSessionRouteChangeReason.NewDeviceAvailable.toRaw()) {
}
switch reason {
case AVAudioSessionRouteChangeReason
print("new device")
}
}
}
var description = userInfo[AVAudioSessionRouteChangePreviousRouteKey]
*/
/*
// var reason = info.valueForKey(AVAudioSessionRouteChangeReasonKey) as UInt
//var reason = info.valueForKey(AVAudioSessionRouteChangeReasonKey) as AVAudioSessionRouteChangeReason.Raw
//var description = info.valueForKey(AVAudioSessionRouteChangePreviousRouteKey) as String
print(description)
switch reason {
case AVAudioSessionRouteChangeReason.NewDeviceAvailable.toRaw():
print("new device")
case AVAudioSessionRouteChangeReason.OldDeviceUnavailable.toRaw():
print("old device unavail")
//case AVAudioSessionRouteChangeReasonCategoryChange
//case AVAudioSessionRouteChangeReasonOverride
//case AVAudioSessionRouteChangeReasonWakeFromSleep
//case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory
default:
print("something or other")
}
*/
}
//MARK: Event Handler Methods
func startRecording (notification:NSNotification) {
}
func cancelRecording (notification:NSNotification) {
}
func playRecording (url:NSURL) {
//play recording
}
func saveRecordingToCoreData (title:String, comments:String) {
let anAudioStory = AudioStory.createInStore(dbStore) as! AudioStory
anAudioStory.data = NSData(contentsOfURL: NSURL(fileURLWithPath: self.recordingFilePath))
anAudioStory.title = title
anAudioStory.comments = comments
}
func saveRecordingToDisk () {
let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docsDir: AnyObject = dirPaths[0]
let soundFilePath = docsDir.stringByAppendingPathComponent(self.audioFilename)
let filemanager = NSFileManager.defaultManager()
if filemanager.fileExistsAtPath(soundFilePath) {
// probably won't happen. want to do something about it?
print("sound exists")
//clear file from temporary directory
do {
try filemanager.removeItemAtPath(recordingFilePath)} catch let e as NSError {
print(e.localizedDescription)
}
} else {
//move file from temporary to docs
do {
try filemanager.moveItemAtPath(recordingFilePath, toPath: soundFilePath) } catch let e as NSError { print(e.localizedDescription) }
}
}
func recordWithPermission(setup:Bool) {
let session:AVAudioSession = AVAudioSession.sharedInstance()
// ios 8 and later
if (session.respondsToSelector("requestRecordPermission:")) {
AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in
if granted {
print("Permission to record granted")
session.configureSpokenRecordingSession()
//self.setSessionPlayAndRecord()
// if setup {
// self.setupRecorder()
// }
self.audioRecorder.record()
self.meterTimer = NSTimer.scheduledTimerWithTimeInterval(0.1,
target:self,
selector:"updateAudioMeter:",
userInfo:nil,
repeats:true)
} else {
print("Permission to record not granted")
}
})
} else {
print("requestRecordPermission unrecognized")
}
}
// transferred to extension
// func setSessionPlayback() {
// let session:AVAudioSession = AVAudioSession.sharedInstance()
// //var error: NSError?
// do {
// try session.setCategory(AVAudioSessionCategoryPlayback)
//
// } catch let e as NSError {
// print(e.localizedDescription)
// print("could not set session category")
//
// }
//
// do {
// try session.setActive(true)
// } catch let e as NSError {
// print(e.localizedDescription)
// print("could not make session active")
// }
// }
//
// func setSessionPlayAndRecord() {
// let session:AVAudioSession = AVAudioSession.sharedInstance()
//
// do {
// try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
// print ("session category set to \(session.category)")
// } catch let e as NSError {
// print("could not set session category")
// print(e.localizedDescription)
// }
// do {
// try session.setActive(true)
// print ("session active status set to \(session)")
//
//
// } catch let e as NSError {
// print("could not make session active")
// print(e.localizedDescription)
// }
// }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment