AudioKit exportAsynchronously fails after changing input device - macos

I need to make an ability to change input device for record on the fly while program is running (between recording sessions, not in recording process).
Here is the code that, i suppose, have to do that. But when im trying to change input device, AKNodeRecorder records nothing (duration always 0) and after trying to call exportAsynchronously on recorder.audioFile i always get an following error:
[central] 54: ERROR: >avae> AVAudioFile.mm:37: AVAudioFileImpl: error 2003334207
Tried to change almost all, but nothing has an effect. Here is the code that changes input device.
func setupRecordingChain(_ deviceIndex: Int = 0)
{
AudioKit.stop()
setupInputDevice(for: deviceIndex)
self.micMixer = AKMixer(self.mic)
self.micBooster = AKBooster(self.micMixer)
self.micBooster.gain = 0
do {
self.recorder = try AKNodeRecorder(node: self.micMixer)
}
catch {
//catch error
}
self.mainMixer = AKMixer(self.micBooster)
AudioKit.output = self.mainMixer
AudioKit.start()
}
private func setupInputDevice(for deviceIndex: Int)
{
guard let inputDevices = AudioKit.inputDevices else { return }
let inputDevice = inputDevices[deviceIndex]
do {
try self.mic.setDevice(inputDevice)
} catch {
//catch error
}
}

Related

XCode Unit Test vs app function call performance

I see quite a huge discrepancy between the time it takes to process (read, parse) csv file inside a unit test vs exactly the same code reading and parsing the same file from the same location in either simulator or running on a device.
I see around x8 time difference. Running on the main thread.
Edit: The unit test is much faster. Logging times around method call, in both places
More findings:
what I actually found and perhaps this is important is that the function being called actually creates a number of threads and then waits for all of them to complete It splits an array of 180000 rows into chunks and processes each chunk asynchronously. (Using DispatchQueue.global().async and DispatchGroup).
Depending on the number of threads the performance while calling in the app degrades, while in a unit test is fairly similar.
func processCSV(fileName: String, columnToGet:[String]?, block: (([String:String]) ->())? = nil) throws -> ([[String:String]]) {
var userReport = [[String:String]?]()
var wmsEntries = 0
do {
let data = try String(contentsOfFile: fileName, encoding: .utf8)
var myStrings = data.components(separatedBy: .newlines)
let headerRow = myStrings.first?.components(separatedBy: ",")
let headerCount = headerRow?.count ?? 0
var headerColumnMap = [String:Int]()
try columnToGet?.forEach({ column in
guard let index = headerRow?.firstIndex(where: {$0.compare(column, options: .caseInsensitive) == .orderedSame}) else {
throw NSError(domain: "Unexpected or invalid header in csv file.", code: NSFileReadCorruptFileError, userInfo:nil )
}
headerColumnMap[column] = index
})
myStrings = Array(myStrings.dropFirst()).filter({!$0.isEmpty})
wmsEntries = myStrings.count
userReport = [[String:String]?](repeating: nil, count: wmsEntries)
let dispatchGroup = DispatchGroup()
func insert(_ record:[Substring], at:Int) {
var entry = [String:String]()
headerColumnMap.forEach({ key, value in
entry[key] = record[value].trimmingCharacters(in: .whitespacesAndNewlines)
})
DispatchQueue.global().async {
block?(entry)
}
userReport[at] = entry
}
let chunkSize = max(1000, myStrings.count / 9)
for (chunkIndex, chunk) in myStrings.chunked(into: chunkSize).enumerated() {
dispatchGroup.enter()
DispatchQueue.global().async {
for (counter, str) in chunk.enumerated() {
let data = self.parse(line: str)
let insertIndex = chunkIndex * chunkSize + counter
guard data.count == headerCount, data.count > columnToGet?.count ?? 0 else {
DDLogError("Error in file, mismatched number of values, on line \(myStrings[chunkIndex * chunkSize + counter])")
continue
}
insert(data, at: insertIndex)
}
dispatchGroup.leave()
}
}
dispatchGroup.wait()
} catch {
print(error)
}
let filtered = userReport.filter({$0 != nil}) as! [[String:String]]
self.numberLinesWithError = wmsEntries - filtered.count
return filtered
}

Argument passed to call that takes no arguments.. Firebase

Not sure why i'm getting this.. any suggestions would be grateful!
I ran into issues with my original coding where I had Firebase pod and Firebase Package.. so I started from scratch since that wasnt fixing itself.. now I get this.. and I am at a loss for how to resolve it.
static func fetchUsers() -> AnyPublisher<[UserProfile], Error> {
Future< [UserProfile], Error > { promise in
self.db.collection("Users")
.getDocuments { (snapshot, error) in
if let error = error {
promise(.failure(error))
return
}
guard let snapshot = snapshot else {
promise(.failure(FirebaseError.badSnapshot))
return
}
var users = [UserProfile]()
snapshot.documents.forEach { document in
print(users.count)
if let user = try? document.data(as: UserProfile.self){
if users.contains(where: { $0.id == user.id}) {return}
users.append(user)
} else {
print("Not working")
}
}
promise(.success(users))
}
}
.eraseToAnyPublisher()
}
I believe this is the syntax you're after:
var users = [UserProfile]()
users = snapshot.documents.compactMap { (document) -> UserProfile? in
if users.contains(where: { $0.id == user.id}) {
return nil
} else {
return try? document.data(as: UserProfile.self)
}
}
Also be aware that when you iterate something in Swift and encounter a false condition on an iteration, return will return out of the greater scope, not just that iteration. Therefore, use continue.
for x in y {
guard x > 0 else {
continue // continues loop
}
// ...
}

I wish to grab the AVCaptureConnection audio and enable / disable it when i need too without having to add / remove the input without lag

The title says it all. Not sure what to do about the lag. When I say lag, it seems that when you try to change the state of a connection (the connection.enabled state), it will freeze the avcapturesession to make the changes. Anyway around this? Here is the code I am currently using to grab my audio connection and to change the state. If I run this function before I start recording, it will freeze for a second, I then turn it off after it is done recording but that adds another second of freezing. This is not a great user experience.
func EnableDisableAudioDevice(enableAudio :Bool)
{
var audioInput :AVCaptureDeviceInput?
if (enableAudio) {
for input in appDel.captureSession.inputs as! [AVCaptureDeviceInput]
{
if input.device.hasMediaType(AVMediaTypeAudio)
{
audioInput = input
break
}
}
if (audioInput != nil) {
for conn in audioInput!.ports as! [AVCaptureInputPort]
{
if conn.mediaType == AVMediaTypeAudio
{
conn.enabled = true
break
}
}
}
}
else {
for input in appDel.captureSession.inputs as! [AVCaptureDeviceInput]
{
if input.device.hasMediaType(AVMediaTypeAudio)
{
audioInput = input
break
}
}
if (audioInput != nil) {
for conn in audioInput!.ports as! [AVCaptureInputPort]
{
if conn.mediaType == AVMediaTypeAudio
{
conn.enabled = false
break
}
}
}
}
}
UPDATE:
I was able to figure out that adding audio input does not seem to be the reason the recording is showing, it is because of my AVCaptureMovieFileOuput. If you add that output to your capture session before recording & then add the audio input, it will say you are recording. Not sure if intended or a bug though. Still having issues trying to find a solution to why it locks up the app when adding the output.
Thanks

How to print out value from coredata dictionary in swift 'AnyObject' does not have a member named 'username?

I am trying to print out the value "username" from my coredata entity.
var request = NSFetchRequest(entityName: "Users")
request.returnsObjectsAsFaults = false
var results = context.executeFetchRequest(request, error: nil)
if (results?.count > 0) {
for result: AnyObject in results! {
println(result.username)
}
}
The line println(result.username) is giving me a compile error of 'AnyObject' does not have a member named 'username'.
You have to cast the array of managed object to the correct type:
for result in results! as [Users] {
println(result.username)
}
This assumes that you have created a managed object subclass for the "Users" entity.
You should also distinguish whether executeFetchRequest() returned nil
(i.e. the fetch request failed), or 0 (i.e. no objects found),
and use the error parameter:
var error : NSError?
if let results = context.executeFetchRequest(request, error: &error) {
if (results.count > 0) {
for result in results as [Users] {
println(result.username)
}
} else {
println("No Users")
}
} else {
println("Fetch failed: \(error)")
// Handle error ...
}
Update for Swift 2/Xcode 7 with try/catch error handling:
do {
let results = try context.executeFetchRequest(request) as! [Users]
if (results.count > 0) {
for result in results {
print(result.username)
}
} else {
print("No Users")
}
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
Note that the forced cast as! [Users] is acceptable here.
The returned objects are always instances of the corresponding class as configured in the Core Data model inspector, otherwise you have
a programming error which should be detected early.
Martin's answer definitely lets you access the properties of your object, but the cast is forced. Like it or not, Swift's strong type system is the future. When returning results from a fetch request, you might consider testing for the type.
func executeFetchRequestT<T:AnyObject>(request:NSFetchRequest, managedObjectContext:NSManagedObjectContext, error: NSErrorPointer = nil) -> [T]? {
var localError: NSError? = nil
if let results:[AnyObject] = managedObjectContext.executeFetchRequest(request, error: &localError) {
if results.count > 0 {
if results[0] is T {
let casted:[T] = results as [T]
return .Some(casted)
}
if error != nil {
error.memory = NSError(domain: "error_domain", code: 0, userInfo: [NSLocalizedDescriptionKey: "Object in fetched results is not the expected type."])
}
} else if 0 == results.count {
return [T]() // just return an empty array
}
}
if error != nil && localError != nil {
error.memory = localError!
}
return .None
}
Using this approach you can type your results and get an error if the type is incorrect.
var fetchError:NSError? = nil
if let results:[Users] = executeFetchRequestT(fetchRequest, managedObjectContext: managedObjectContext, error: &fetchError) {
for user in results {
// access the results with confidence of the correct type
}
} else {
// should have an error condition, handle it appropriately
assertFailure("something bad happened")
}
Change your for loop to this
for result: AnyObject in results! {
if let user: AnyObject = result.valueForKey("username") {
println(user)
}
}
The fix is using valueForKey("String")

Code that has run smoothly for days suddenly not working. Not sure how to fix the exception that is being thrown

I have a piece of code that has been running smoothly since I created it, that has suddenly begun to crash every time I run my app. I keep getting EXC_BREAKPOINT that highlights a line in my Thread 1 that states: Swift._getImplicitlyUnwrappedOptionalValue. I've tried adding breakpoints to catch the suspect code within my method, but nothing turns up and I just keep getting this error. I've been at this for a while now, and I'm pretty stumped as to what is going on and how I'm supposed to fix it. Any help is appreciated! Below I've included a screenshot of the error as well as the method I'm trying to call that produces the error. Thanks!
#IBAction func nextPhoto(sender: UISwipeGestureRecognizer)
{
self.deleteResponseMessage(self)
if photoObjects.count == 0
{
var image:UIImage = UIImage(contentsOfFile: "launchImageTall")
feedView.image = image
}
else
{
userInfo.hidden = false
var content:PFObject = photoObjects[0] as PFObject
var recipients = content["recipients"] as NSMutableArray
var userImageFile = content["imageFile"] as PFFile
userImageFile.getDataInBackgroundWithBlock { (imageData:NSData!, error:NSError!) -> Void in
if error == nil
{
var contentImage = UIImage(data: imageData)
self.feedView.image = contentImage
}
}
var profilePicImageFile = content["senderProfilePic"] as PFFile
profilePicImageFile.getDataInBackgroundWithBlock({ (imageData:NSData!, error:NSError!) -> Void in
if error == nil
{
var picture = UIImage(data: imageData)
self.senderProfilePic.image = picture
}
})
var username = content["senderUsername"] as NSString
senderUsername.text = username
var photoCaption = content["photoCaption"] as NSString
senderMessage.text = photoCaption
senderObjectId = content["senderObjectId"] as NSString
for var i=0;i<photoObjects.count-1;i++
{
photoObjects[i] = photoObjects[i+1]
}
if recipients.count == 1
{
content.deleteInBackground()
}
else
{
recipients.removeObject(currentUserObjectId!)
content.setObject(recipients, forKey: "recipients")
content.saveInBackground()
}
}
}
Did you update Xcode recently. Apple is busy updating their cocoa libraries. Every return value was explicitly being unwrapped (like return String!). Now they are going through every function and evaluating whether it should return an instance (return String) or an optional (String?).
So check your code for optionals and remove those ! or ?.
At least that was the case for me with every Xcode update.

Resources