代码之家  ›  专栏  ›  技术社区  ›  qrunchmonkey

CoreAudio AudioTimeStamp.mHostTime时钟频率?

  •  19
  • qrunchmonkey  · 技术社区  · 17 年前

    iPhone上的音频时间戳有点问题。当我在模拟器中运行我的应用程序时,AudioTimeStamp.mHostTime的单位似乎是纳秒(100000000秒),而在我的设备(iPod Touch 2G)上运行时,频率似乎约为6000000秒。

    有没有办法找出运行时mHostTime的速率?或者转换成秒、纳秒或任何其他单位?该值在软件或硬件版本之间会发生变化吗?(就像在模拟器和我的设备之间)

    2 回复  |  直到 17 年前
        1
  •  50
  •   Mecki    8 年前

    存在以下文件:

    <mach/mach_time.h>
    

    在这个文件中,您将找到一个名为 mach_absolute_time() . 马赫绝对时间() 返回没有定义含义的uint64数字。想象一下那些是 滴答声

    1. 马赫绝对时间() 返回自上次引导以来的“滴答声”数。
    2. 每次开机时,滴答声计数器从零开始。
    3. 滴答计数器严格地向上计数(从不倒计时)。

    正如您所看到的,滴答声计数器与正常的系统时钟有些不同。首先,系统启动时,系统时钟不是从零开始,而是在系统当前“挂钟时间”的最佳近似值。正常系统时钟也没有严格向上运行,例如,系统时钟可能提前,系统使用NTP(网络时间协议)定期同步系统时间。如果系统在下一次NTP同步时注意到它比时间提前了两秒,则会将系统时钟向后拨两秒以进行校正。这经常会破坏软件,因为许多程序员依赖于这样一个事实:系统时间从不倒退;但它确实如此,而且是被允许这样做的。最后一个区别是,正常的系统时间不会在系统睡眠时停止,但滴答计数器不会在系统睡眠时增加。当系统再次唤醒时,它只比进入睡眠时间提前几点。

    那么,如何将这些滴答声转换为真正的“时间值”?

    mach_timebase_info :

    struct mach_timebase_info {
            uint32_t        numer;
            uint32_t        denom;
    };
    

    可以使用函数获取此结构的正确值 mach_timebase_info()

    kern_return_t kerror;
    mach_timebase_info_data_t tinfo;
    
    kerror = mach_timebase_info(&tinfo);
    if (kerror != KERN_SUCCESS) {
        // TODO: handle error
    }
    

    KERN_SUCCESS (和可能的错误代码)在中定义

    <mach/kern_return.h>
    

    但是,此函数不太可能返回错误,并且 等于零,因此您也可以直接检查 kerror 不是零。

    tinfo

    double hTime2nsFactor = (double)tinfo.numer / tinfo.denom;
    

    通过将第一个数字转换为 double ,GCC自动将第二个数字转换为 双重的 而且结果也将是 双重的

    uint64_t systemUptimeNS = (uint64_t)(mach_absolute_time() * hTime2nsFactor);
    

    mach_wait_until() . 假设您希望当前线程睡眠800纳秒。以下是您的做法:

    uint64_t sleepTimeInTicks = (uint64_t)(800 / hTime2nsFactor);
    mach_wait_until(mach_absolute_time() + sleepTimeInTicks);
    

    小贴士: 如果您经常需要将时间值转换为滴答声,通常(取决于CPU)乘法比除法更快:

    double ns2HTimeFactor = 1.0 / hTime2nsFactor;
    

    现在你可以乘 ns2HTimeFactor 而不是除以 hTime2nsFactor

    当然,每次需要时重新计算这些因素是浪费时间的。这些因素是恒定的,在系统运行时它们永远不会改变。因此,您可以在应用程序开始时的某个位置计算它们,并将它们保留到应用程序再次退出为止。

    +(void)initialize

        2
  •  8
  •   Roger The Engineer    17 年前

    你需要使用 mach_timebase_info

    struct mach_timebase_info {
        uint32_t    numer;
        uint32_t    denom;
    };
    

    见: http://shiftedbits.org/2008/10/01/mach_absolute_time-on-the-iphone/

    推荐文章