You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用AudioKit(v5.6.1)测量iOS应用中MIDI音符输入的时长?

AudioKit MIDI时间戳计算音符时长及DispatchTime替代方案

一、AudioKit MIDI时间戳能不能用来计算音符时长?

可以,但需要先理解时间戳的本质并做正确转换。

AudioKit在receivedMIDINoteOn/receivedMIDINoteOff中提供的时间戳,本质是**mach_absolute_time()的原始返回值**——这是CPU的时钟周期计数,并非直接的毫秒/秒单位,需要通过系统API转换为实际时间间隔。

转换步骤:

  1. 通过mach_timebase_info获取系统时间基准系数(numer和denom,用于将时钟周期转换为纳秒)
  2. 计算noteOn和noteOff时间戳的差值
  3. 将差值转换为纳秒,再换算成毫秒

示例代码:

import MachO

func machTimestampToMilliseconds(_ timestamp: UInt64) -> Double {
    var timebaseInfo = mach_timebase_info_data_t()
    guard mach_timebase_info(&timebaseInfo) == KERN_SUCCESS else { return 0 }
    // 转换为纳秒,再转毫秒
    let nanoseconds = timestamp * UInt64(timebaseInfo.numer) / UInt64(timebaseInfo.denom)
    return Double(nanoseconds) / 1_000_000.0
}

// 计算你的实验数据
let noteOnTs: UInt64 = 115071237234
let noteOffTs: UInt64 = 115315013613
let durationMs = machTimestampToMilliseconds(noteOffTs - noteOnTs)
print("实际时长:\(durationMs) ms")

这个方案的优势是:mach_absolute_time()是单调递增的时间源,不受系统时间调整(如手动改时间、NTP同步)影响,计算时间间隔的准确性更高。

二、改用DispatchTime.now()是否合理?

视你的需求场景而定:

适用场景

如果只需要记录回调函数被触发的时间差,且不担心系统时间变动的影响,DispatchTime.now()是更简便的选择:

  • DispatchTime.now().rawValue直接返回纳秒级时间戳,计算差值后转毫秒非常直观
  • 无需额外的系统API转换

示例代码:

var noteOnDispatchTime: DispatchTime?

func receivedMIDINoteOn(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, channel: MIDIChannel, timestamp: MIDITimeStamp) {
    noteOnDispatchTime = .now()
}

func receivedMIDINoteOff(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, channel: MIDIChannel, timestamp: MIDITimeStamp) {
    guard let onTime = noteOnDispatchTime else { return }
    let offTime = DispatchTime.now()
    let durationNs = offTime.rawValue - onTime.rawValue
    let durationMs = Double(durationNs) / 1_000_000.0
    print("音符时长:\(durationMs) ms")
}

局限性

DispatchTime.now()依赖系统墙钟时间,如果用户手动修改系统时间、或系统进行NTP时间同步,会导致时间差计算出现错误,不适合对时间准确性要求高的场景。

总结

  • 优先选择AudioKit提供的MIDI时间戳,配合系统API转换,能保证时间间隔计算的准确性和稳定性
  • 若追求实现简便且能接受系统时间变动的风险,可使用DispatchTime.now()

内容的提问来源于stack exchange,提问作者apps2go

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 14:10:19