Playing a single midi note from gs_instruments in iOS / Swift - ios

I'm looking to play a single midi note on an iOS app using Swift.
Here's what I have so far, but unfortunately this crashes with an error.
func initAudio(){
let engine = AVAudioEngine()
self.sampler = AVAudioUnitSampler()
engine.attachNode(self.sampler!)
engine.connect(self.sampler!, to: engine.outputNode, format: nil)
guard let soundbank = NSBundle.mainBundle().URLForResource("gs_instruments", withExtension: "dls") else {
print("Could not initalize soundbank.")
return
}
let melodicBank:UInt8 = UInt8(kAUSampler_DefaultMelodicBankMSB)
let gmHarpsichord:UInt8 = 6
do {
try self.sampler!.loadSoundBankInstrumentAtURL(soundbank, program: gmHarpsichord, bankMSB: melodicBank, bankLSB: 0)
}catch {
print("An error occurred \(error)")
return
}
self.sampler!.startNote(60, withVelocity: 64, onChannel: 0)
}
Here's the error message:
Unable to start playing the low note. Error code: -10867 'ç’ˇˇ'
2015-11-25 15:10:07.419 Demo[774:139850] 15:10:07.418 ERROR: [0x19eaf4000] AVAudioUnitMIDIInstrument.mm:103: -[AVAudioUnitMIDIInstrument startNote:withVelocity:onChannel:]: error -10867
2015-11-25 15:10:07.419 Demo[774:139850] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'error -10867'

Solution
The AVAudioEngine needs to be started before usage (error -10867 means "not initialized").
Add try engine.start() inside the Do-Catch:
do {
try engine.start()
try self.sampler!.loadSoundBankInstrumentAtURL(soundbank, program: gmHarpsichord, bankMSB: melodicBank, bankLSB: 0)
}catch {
print("An error occurred \(error)")
return
}
About the error code
In your error message there's this line:
2015-11-25 15:10:07.419 Demo[774:139850] 15:10:07.418 ERROR: [0x19eaf4000] AVAudioUnitMIDIInstrument.mm:103: -[AVAudioUnitMIDIInstrument startNote:withVelocity:onChannel:]: error -10867
We see that the emitter of the error code is AVAudioUnitMIDIInstrument, which inherits from AVAudioUnit: these things come from the "AudioUnit" framework which is located in OS X's System folder.
AudioUnit 's error codes are defined in this header file:
/System/Library/Frameworks/AudioUnit.framework/Versions/A/Headers/AUComponent.h
The part that is relevant for us:
CF_ENUM(OSStatus) {
kAudioUnitErr_InvalidProperty = -10879,
kAudioUnitErr_InvalidParameter = -10878,
kAudioUnitErr_InvalidElement = -10877,
kAudioUnitErr_NoConnection = -10876,
kAudioUnitErr_FailedInitialization = -10875,
kAudioUnitErr_TooManyFramesToProcess = -10874,
kAudioUnitErr_InvalidFile = -10871,
kAudioUnitErr_UnknownFileType = -10870,
kAudioUnitErr_FileNotSpecified = -10869,
kAudioUnitErr_FormatNotSupported = -10868,
kAudioUnitErr_Uninitialized = -10867,
kAudioUnitErr_InvalidScope = -10866,
kAudioUnitErr_PropertyNotWritable = -10865,
kAudioUnitErr_CannotDoInCurrentContext = -10863,
kAudioUnitErr_InvalidPropertyValue = -10851,
kAudioUnitErr_PropertyNotInUse = -10850,
kAudioUnitErr_Initialized = -10849,
kAudioUnitErr_InvalidOfflineRender = -10848,
kAudioUnitErr_Unauthorized = -10847,
kAudioComponentErr_InstanceInvalidated = -66749,
};

You should still get this to work by connecting the sampler to the AVAudioEngine graph, ie calling AVAudioEngine.attachNode.
The reason this fails specifically is that the engine reference contained inside the sampler is not yet initialized. Calling attachNode does that, and thus it is ok to call startEngine later on.

Related

iOS - TwilioVideo - Unable to connect on call with remote participant

I am developing app with video calling functionality and I am using Twilio Video for that.
Currently using TwilioVideo SDK v4.6.2 and iOS Version 14.x and Above
I am not able to connect to the TwilioVideo room
Below is my code:
func connect() {
guard let accessToken = self.accessToken, let roomName = self.roomName else {
return
}
prepareAudio()
prepareCamera()
let connectOptions = ConnectOptions(token: accessToken) { (builder) in
builder.isDominantSpeakerEnabled = true
builder.isNetworkQualityEnabled = true
if let localAudioTrack = self.localAudioTrack {
builder.audioTracks = [localAudioTrack]
}
if let localVideoTrack = self.localVideoTrack {
builder.videoTracks = [localVideoTrack]
}
if let preferredAudioCodec = TwiloVideoSettingsManager.shared.audioCodec {
builder.preferredAudioCodecs = [preferredAudioCodec]
}
if let preferredVideoCodec = TwiloVideoSettingsManager.shared.videoCodec {
builder.preferredVideoCodecs = [preferredVideoCodec]
}
if let encodingParameters = TwiloVideoSettingsManager.shared.getEncodingParameters() {
builder.encodingParameters = encodingParameters
}
builder.region = "gll"
builder.roomName = roomName
}
self.room = TwilioVideoSDK.connect(options: connectOptions, delegate: self)
UIApplication.shared.isIdleTimerDisabled = true
}
Response in not received from Twilio in either of the methods mentioned below
func didConnect(to room: Room) {
NSLog("Room: \(room.name) SID: \(room.sid)")
if (room.remoteParticipants.count > 0) {
self.remoteParticipant = room.remoteParticipants[0]
self.remoteParticipant.delegate = self
}
self.delegate.videoServiceManagerDidConnectToRoom(name:room.name)
}
func roomDidFailToConnect(room: Room, error: Error) {
NSLog("Failed to connect to a Room: \(error).")
self.delegate.videoServiceManagerFailToConnectRoom(error: error.localizedDescription)
self.leaveRoom()
}
I am not able connect to the room every time and sometimes I get the error mentioned below :
Failed to connect to a Room: Error Domain=com.twilio.video Code=53000 "Signaling connection error" UserInfo={NSLocalizedDescription=Signaling connection error, NSLocalizedFailureReason=SIP error 408}.
When I check the Twilio logs in debug mode I am not getting any error.
Please guide me to rectify if there is any mistake in my code
Twilio employee here. Error 53000 is somewhat vague and could occur due to different things: https://www.twilio.com/docs/api/errors/53000
I'd suggest the following next steps:
try reproducing this error using the iOS Quickstart app (https://github.com/twilio/video-quickstart-ios)
try running our Networktest on the problematic device: https://www.networktest.twilio.com

Cannot invoke initializer for type 'AVCaptureDeviceInput' with an argument list of type '(device: AVCaptureDevice!, error: inout NSError?)'

I am following this from code in an old swift tutorial so possibly there was a change I was unaware of in Swift 2 with how to handle errors, but here is my code
backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
var error : NSError?
var input = AVCaptureDeviceInput(device: backCamera, error: &error)
I do not understand as to why the error in the title even occurs, it occurs highlighting the input variable.
That is deprecated. Use this:
var input = AVCaptureDeviceInput()
do {
input = try AVCaptureDeviceInput(backCamera)
} catch {
//error
}
Check some Swift 2 documentation. The constructor is defined with a single device: parameter and a throws annotation instead of the error:.
Update swift3
This is how we can handle AVCaptureDeviceInput error on swift3
var input = AVCaptureDeviceInput()
do {
input = try AVCaptureDeviceInput(device: device)
}
catch {
// error
}

Error while sending data with Game Center

I'm trying to get my application to send data to the other player that is in the match. I keep getting this error:
Error Domain=Foundation._GenericObjCError Code=0 "(null)".
My code for sending data is below. I've tried sending strings, and custom objects as well and get the same error.
var isReady: Int = 1
let data = NSData(bytes: &isReady, length: sizeof(Int))
do {
try match.sendData(data, toPlayers: match.players, dataMode: .Reliable)
} catch let error as NSError {
print("Error trying to send object: \(error)")
}

handling error using xcode 7.0 beta in asynchronous block

I am trying to validate different errors while downloading text files from AWS S3, and with the next piece of code:
... above here function receiving String parameters ruta, archivo, archivoLocal
let directorioURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! as NSURL
let archivoURL = directorioURL.URLByAppendingPathComponent("b\(archivoLocal)")
let downloadRequest = AWSS3TransferManagerDownloadRequest()
downloadRequest.bucket = ruta
downloadRequest.key = archivo
downloadRequest.downloadingFileURL = archivoURL
let transferManager = AWSS3TransferManager.defaultS3TransferManager()
let task = BFTask()
let executor = BFExecutor.mainThreadExecutor()
transferManager.download(downloadRequest).continueWithExecutor(executor, withBlock: { (task) -> AnyObject! in
if task.error != nil {
if task.error.domain == AWSS3TransferManagerErrorDomain {
self.processDomainErrorType(AWSS3TransferManagerErrorType(rawValue: task.error.code))
} else {
self.processError(task.error)
}
} else if task.result != nil {
do {
let mytext = try String(contentsOfURL: archivoURL, encoding: NSUTF8StringEncoding)
self.processResult(mytext)
} catch let urlerror as? NSError {
self.processError(urlerror)
}
}
...
I am getting the error:
Invalid conversion from throwing function of type '(_) throws -> AnyObject!' to non-throwing function type '#convention(block) (BFTask!) -> AnyObject!'
I obtained the "do { try } catch" syntax from https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-ID10
I can remove the error by replacing the catch clause with:
} catch _ {
self.processError(NSError(domain: "String-ContentsOfURL Error", code: 100, userInfo: nil))
}
Of course this way I will never know the real cause why ContentsOfURL could be failing.
All I can figure out why this error happens is because this syntax is valid only for OS X apps and for iOS the error handling guide at
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html#//apple_ref/doc/uid/TP40014097-CH42
allows only the second syntax unless you own the object throwing the errors from an enum structure of ErrorType type, which is not the case since I want to catch the NSError from String object, contentsOfURL function.
I hope someone could guide me through this, maybe being XCode 7 a beta, the catch syntax is still incomplete or maybe I should not matter about the reason why this function fails, but I think it is important to determine what is making this function fail and if it could be traced and fixed before reaching the do-try-catch clause.
Additionally to the above error, I am getting a warning in the task variable assignation line to BFTask() saying that "Initialization of immutable value 'task' was never used". I think this is a bug with this beta version that it doesn't include the pattern to acknowledge that the variable task is being used in the asynchronous block. I'd appreciate a lot some confirmation about this and if I just need to ignore it.
By the way, the only reason I am using XCode 7 beta is because my client wants to evaluate the app before acquiring their apple membership.
Apple replaced NSError with ErrorType in Swift 2.
Replace your own explicit usage of NSError with ErrorType and you don't get this type of compiler errors.

Core Data - Swift - Catch "keypath not found in entity" error

I am trying to catch an error when I execute a FetchRequest with a wrong/inexistent Key/Keypath but the app still crashes.
This is how I created the NSPredicate:
let pred = NSPredicate(format: "(\("WRONGKEY") = %#)", equalTo)
let request = NSFetchRequest()
request.predicate = pred
request.entity = MyEntityDescription
(WRONGKEY is a parameter that could be wrong/nonexistent in the Core Data schema)
And this is the line that cause the error:
var objects = managedContext?.executeFetchRequest(request, error: &error) as? [Model]
This is the error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath keyX not found in entity < NSSQLEntity EN id=2 >'
* First throw call stack: .....
So I have tried to use:
if let objects = managedContext?.executeFetchRequest(request, error: &error) as? [Model] {
println("okkkkkkkk")
} else {
println("error")
}
but doesn't work.
I have tried:
if(error != nil) {
but doesn't work either.
Is there a way to catch the error and avoid that the app crashes?
In Swift, try-catch isn't available. You can switch back to Objective-C, or use a library like this one to add the functionality.
That said, your problem can be solved by keeping track of which keys are valid, instead of implementing a try-and-see approach.

Resources