I am currently wrapping my head around Core Audio and I was hit with the question of how to update the GUI the AudioQueueInputCallback. To begin with I want to update a label with the Level Meter reading from the mic.
In my code I am storing the current level meter value in a struct on each callback.
func MyAudioQueueInputCallback(inUserData: UnsafeMutablePointer<Void>, inAQ: AudioQueueRef, inBuffer: AudioQueueBufferRef, inStartTime: UnsafePointer<AudioTimeStamp>, var inNumberPacketDesc: UInt32, inPacketDesc: UnsafePointer<AudioStreamPacketDescription>){
var error: OSStatus
if (inNumberPacketDesc > 0){
error = AudioFileWritePackets(MyRecorder.recordFile, false, inBuffer.memory.mAudioDataByteSize, inPacketDesc, MyRecorder.recordPacket, &inNumberPacketDesc, inBuffer.memory.mAudioData)
checkError(error, operation: "AudioFileWritePackets Failed ")
// Increment the packet index
MyRecorder.recordPacket += Int64(inNumberPacketDesc)
if (MyRecorder.running){
error = AudioQueueEnqueueBuffer(inAQ, inBuffer, inNumberPacketDesc, inPacketDesc)
checkError(error, operation: "AudioQueueEnqueueBuffer Failed BAHHHH")
var level: Float32 = 0
var levelSize = UInt32(sizeof(level.dynamicType))
error = AudioQueueGetProperty(inAQ, kAudioQueueProperty_CurrentLevelMeter, &level, &levelSize)
checkError(error, operation: "AudioQueueGetProperty Failed... Get help!")
MyRecorder.meterLevel = level // meter level stored in public struct
}
}
}
//MARK: User Data Struct / Class
struct MyRecorder {
static var recordFile: AudioFileID = nil
static var recordPacket: Int64 = 0
static var running: Bool = false
static var queue: AudioQueueRef = nil
static var meterLevel: Float32 = 0.00
}
From here the meterLevel variable is polled using an NSTimer on the Main thread.
func setMeterLabel() -> Void{
meter.text = String(MyRecorder.meterLevel)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
main()
var timer = NSTimer.scheduledTimerWithTimeInterval(0.05, target: self, selector: "setMeterLabel", userInfo: nil, repeats: true)
}
This code works just fine but I feel as though using the NSTimer may not be the best way to go about it. Is there a way for my callback to directly update the label?