什么是从核心音频回调UI更新的最佳做法? [英] What is the best practice for updating UI from Core Audio Callback?
问题描述
我目前我的包裹围绕核心音频的头,我用的如何更新GUI的AudioQueueInputCallback问题的打击。首先我想和电平表从麦克风读取更新标签。
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.
在我的code,我在存储上的每个回调结构中的电流电平表值。
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
}
从这里meterLevel变量是在主线程中使用的NSTimer查询。
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)
}
这code工作得很好,但我觉得好像使用的NSTimer可能不会去它的最好方式。有没有我的回调直接更新标签的方法是什么?
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?
推荐答案
回调幅度可能过于快,所以考虑创建一个平均滤波器(或箱平均值)。
让声音回调更新简单的原始在你的控制器(整型,浮点等)。如果你想你可以做一个委托。它们存储在一个队列,并保持只能说过去的20个项目。摆脱历史最悠久并保持最新。
The callback rate might be too fast so consider creating an average filter ( or box average). Let the audio callback update a simple primitive (int, float, etc.) in your controller. You can make a delegate if you want. Store them in a queue and keep only say the last 20 items. Get rid of the oldest and keep the newest.
让你的UI以定期利率计算出你选择的是最新的N项的平均值,并显示在用户界面上。
Let your UI calculate the average of the latest n items you chose and show it on the ui at a periodic rate.
这篇关于什么是从核心音频回调UI更新的最佳做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!