swift2 AVAudioRecorder - ios

I am trying the following code using swift 2, which should be fine in swift 1.
class NewSoundViewController: UIViewController {
required init(coder aDecoder: NSCoder) {
let audioURL = NSURL.fileURLWithPathComponents([
NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0],
"MyAudio.m4a"
])
do {
let session = AVAudioSession.sharedInstance()
try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
} catch {
print("Session errors.")
}
do {
let recordSettings: [String: AnyObject] = [
AVFormatIDKey: kAudioFormatMPEG4AAC,
AVSampleRateKey: 44100.0,
AVNumberOfChannelsKey: 2,
]
self.audioRecorder = try AVAudioRecorder(URL: audioURL!, settings: recordSettings)
self.audioRecorder.meteringEnabled = true
self.audioRecorder.prepareToRecord()
} catch let error as NSError{
print(error.description)
} catch {
print("Other errors")
}
super.init(coder: aDecoder)
}
I got compiling error
Type 'AudioFormatID' does not conform to protocol 'AnyObject'`
at the line AVFormatIDKey: kAudioFormatMPEG4AAC,.
If I comment out the line, I passed build, but got a runtime error
Error Domain=NSOSStatusErrorDomain Code=1718449215 "The operation couldn’t be completed. (OSStatus error 1718449215.)"
I also tried AVFormatIDKey: NSNumber(unsignedInt: kAudioFormatMPEG4AAC),, and got runtime error. Xcode seemed go to debug mode It red highlighted self.audioRecorder = try AVAudioRecorder(URL: audioURL!, settings: recordSettings) and said
Thread 1: EXC_BAD_ACCESS(code=1, address=0x0)
Can anyone please help me?

I also tried AVFormatIDKey: NSNumber(unsignedInt: kAudioFormatMPEG4AAC)
Well, that is the correct thing to say. Basically you are asking two questions here; the compiler error you've already solved. Now you're having a runtime error, but that's completely different matter.
As for the runtime error, it's probably just a figment of trying to test on the Simulator. I ran your code on the device (after fixing the line in question so that it would compile) and it's fine.
EDIT In a comment, you revealed that you tested this on a device running iOS 8.3. That's the problem! You need to test on a device, and it needs to be a device running iOS 9. Then you'll find that your code runs without crashing.

I had the same issue with the settings. AVFormatIDKey was not accepted with the error mentioned in the original post.
The recordSettings needs to be explicitly casted in Swift 2.
These are my settings for recording that works. If I just skipped the AVFormatIDKey, the microphone only worked for a fraction of a second.
let recordSettings = [AVSampleRateKey : NSNumber(float: Float(44100.0)),
AVFormatIDKey : NSNumber(int: Int32(kAudioFormatAppleLossless)),
AVNumberOfChannelsKey : NSNumber(int: 1),
AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Medium.rawValue)),
AVEncoderBitRateKey : NSNumber(int: Int32(320000))]
You don't need to upgrade the device to iOS 9. I built and ran this for iOS 8.4

I had a similar issue and it turns out that when I updated from swift 1.2 to 2.0 the signature of "settings" changed to a non optional [String : AnyObject]
//Swift 1.2
AVAudioRecorder(URL: audioURL!, settings: nil)
if I pass an empty dictionary it doesn't crash for me anymore and works as before.
//Swift 2.0
AVAudioRecorder(URL: audioURL!, settings: [:])

Related

CommonCrypto XCode 9.0 unable to create key from data

The following code fails with OSStatus -50 (secParam) both in my manual code and in other libraries (SwiftyRSA, Heimdall) on XCode 9.0, ios 10+. Any ideas as to why or any way to obtain more info?
let keyDict: [CFString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPublic,
kSecAttrKeySizeInBits: NSNumber(value: 4096),
kSecAttrIsSensitive: false,
kSecAttrIsExtractable: true,
kSecAttrCanEncrypt: true
]
var errP: Unmanaged<CFError>?
key = SecKeyCreateWithData(
publicKeyData as CFData, keyDict as CFDictionary, &errP
)
Well, there have been an error creating keychain items with iOS10. And it was a problem in simulator, but worked on device.
As quick solution you had to enable keychain sharing. Original bug I reported was marked as Duplicate and it is closed now. Maybe regression in iOS11?

iOS 11 Xcode 9: CoreML linker command failed with exit code 1 (use -v to see invocation)

I'm trying to capture photo using AVFoundation
Here is my code:
#objc func didTapCameraView() {
self.cameraView.isUserInteractionEnabled = false
let settings = AVCapturePhotoSettings()
let previewPixelType = settings.availablePreviewPhotoPixelFormatTypes.first!
let previewFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
kCVPixelBufferWidthKey as String: 160,
kCVPixelBufferHeightKey as String: 160]
settings.previewPhotoFormat = previewFormat
if flashControlState == .off {
settings.flashMode = .off
} else {
settings.flashMode = .on
}
cameraOutput.capturePhoto(with: settings, delegate: self)
}
but I'm getting same error every time.
If I comment the code inside methods then it builds fine.
Let me know what I missed.
Update:
using iPhone 6 iOS11
Build architectures
Snapshot while using physical device
I found the explanation from Apple develop forum, Check this link
This bug will be fixed later(unfortunately it still exists in ode 9 GM Version).
Quote from Apple forum, we can use this workaround:
As a workaround you can use the SwiftPrivate versions of these API by prepending each API with double underscore (__). For example, change AVCaptureDevice.Format.supportedColorSpaces to AVCaptureDevice.Format.__supportedColorSpaces.
I tested it and it works, and they said such workaround is considered legitimate and is not considered SPI use.

Can't record on iPad: Error Domain=NSOSStatusErrorDomain Code=1718449215 "(null)"

I am running on iPad iOS 9.3.4 (latest version as of this writing).
I am running this code:
let settings = [
AVFormatIDKey: NSNumber(unsignedInt: kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100.0,
AVNumberOfChannelsKey: 2 as NSNumber,
AVEncoderAudioQualityKey: AVAudioQuality.High.rawValue
]
do {
audioRecorder = try AVAudioRecorder(URL: audioURL, settings: settings)
audioRecorder.delegate = self
audioRecorder.record()
} catch let error as NSError{
print(error.description)
}
I am catching this error:
Error Domain=NSOSStatusErrorDomain Code=1718449215 "(null)"
When I try to use AVAudioRecorder with Objective-C - I am able to record with no problems. The problem seems to only occur with Swift and only on a device - no issue in simulator.
If I switch out kAudioFormatMPEG4AAC with kAudioFormatLinearPCM, I am able to record - but when I try to play back the recording nothing plays - seems like it hasn't recorded well.
Has anyone been able to record with AVAudioRecorder in Swift lately and have the recording play back on a real iPad? I would like to just have that code.
Output file path extension must be in sync with AVFormatIDKey
For .wav
let recordSettings:[String:Any] = [AVFormatIDKey:kAudioFormatLinearPCM,
AVEncoderAudioQualityKey:AVAudioQuality.max.rawValue,
AVEncoderBitRateKey:320000,
AVNumberOfChannelsKey:2,
AVSampleRateKey:44100.0 ] as [String : Any]
For .m4a
let recordSettings:[String:Any] = [AVFormatIDKey:kAudioFormatAppleLossless,
AVEncoderAudioQualityKey:AVAudioQuality.max.rawValue,
AVEncoderBitRateKey:320000,
AVNumberOfChannelsKey:2,
AVSampleRateKey:44100.0 ] as [String : Any]
Looks like I never set the recording session as being active. I wish the error description was better though.
override init() {
super.init()
recordingSession = AVAudioSession.sharedInstance()
do {
try recordingSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
try recordingSession.setActive(true)
recordingSession.requestRecordPermission() { (allowed: Bool) -> Void in
dispatch_async(dispatch_get_main_queue()) {
if allowed {
// success
} else {
// TBD: Show a message to the user that they need to give permission in settings app to proceed
}
}
}
} catch {
// TBD: Show a message to the user that they need to give permission in settings app to proceed
}
}

Why do I get AudioConverterNew error when using prepareToRecord?

When I use the code:
#IBAction func recordAudio(sender: UIButton) {
recordButton.enabled = false
stopButton.hidden = false
recordingInProgress.hidden = false
//recording the user's voice
let dirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let recordingName = "my_audio.wav"
let pathArray = [dirPath, recordingName]
let filePath = NSURL.fileURLWithPathComponents(pathArray)
print(filePath)
let session = AVAudioSession.sharedInstance()
try! session.setCategory(AVAudioSessionCategoryPlayAndRecord)
try! audioRecorder = AVAudioRecorder(URL: filePath!, settings: [:])
audioRecorder.delegate = self
audioRecorder.meteringEnabled = true
audioRecorder.prepareToRecord()
audioRecorder.record()
}
I get an error return that reads:
2016-01-23 23:42:04.338 Pitch Perfect[3608:1266093] 23:42:04.338 ERROR: 1066: AudioConverterNew returned -50
It prints out 7 times. All of these errors are being thrown by the last two lines (at least, it appears that way when I use random print statements to troubleshoot). [Pitch Perfect is the name of my app].
Six of these error messages are being thrown by the following line:
audioRecorder.prepareToRecord()
One of these error messages is being thrown by the following line:
audioRecorder.record()
Does anyone know why this would occur? I'm using a Mac running OS X 10.11.3. I'm running Xcode 7.2.
One idea that has occurred to me is that, perhaps, my microphone is not functioning properly. I can't find any place which discusses an error 1066 or AudioConverterNew return of -50 though, so I really have no idea.
Solved my own problem. After continued error checking of my code, I determined this was not a code error, but rather, a system error. I have an external monitor attached to my MacBook Pro. A quick look in System Preferences -> Sound -> Input revealed that my Mac was set to use the microphone on the external display (it doesn't have one...). I selected "Internal Microphone" as my INPUT device, then rebuilt my code in the simulator. Viola! It worked!!

AVAudioRecorder settings empty after constructor call

I'm trying to record audio using the microphone and AVAudioRecorder.
It works on iOS 8 but my code does not work anymore on iOS 9.
The recordSettings dictionary is set properly, then I give it to the
AVAudioRecorder:URL:settings constructor.
But, just after, recorder.settings is empty, an assertion failure is thrown
let recordSettings: [String: AnyObject] = [
AVNumberOfChannelsKey: NSNumber(integer: 2),
AVFormatIDKey: NSNumber(integer: Int(kAudioFormatMPEG4AAC)),
AVEncoderBitRateKey: NSNumber(integer: 64)]
var recorder: AVAudioRecorder!
do {
recorder = try AVAudioRecorder(URL: tempURL, settings:recordSettings) // recordSettings.count = 3
assert(recorder.settings.count != 0, "Audio Recorder does not provide settings") // assertion failure threw
} catch let error as NSError {
print("error when intitializing recorder: \(error)")
return
}
Anyone can help me ? Is it a bug ?
EDIT : In my entire code I did not test recorder.settings just after. I did instantiate recorder like my code above, then I did that :
recorder.delegate = self
recorder.prepareToRecord()
recorder.meteringEnabled = true
And it crashes in this line :
for i in 1...(recorder.settings[AVNumberOfChannelsKey] as! Int) {
...
}
It crashes because recorder.settings[AVNumberOfChannelsKey] is nil
I'm not sure why you're checking the settings property, but
from the AVAudioRecorder header file, on the settings property:
these settings are fully valid only when prepareToRecord has been called
so you must call prepareToRecord() first BUT it will fail/return false, because your bitrate is way too low! Its unit is bits per second, not kilobits per second:
AVEncoderBitRateKey: NSNumber(integer: 64000)
This worked on iOS 8 because your too-low bitrate was simply discarded. Looks like it became an error in iOS 9.

Resources