什么是从核心音频回调UI更新的最佳做法? [英] What is the best practice for updating UI from Core Audio Callback?

查看:240
本文介绍了什么是从核心音频回调UI更新的最佳做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前我的包裹围绕核心音频的头,我用的如何更新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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆