Тактовая частота CoreAudio AudioTimeStamp.mHostTime?

Visual Studio не требует или не требует, чтобы вы явно запрашивали связывание математической библиотеки. Вы должны избегать добавления его в качестве библиотеки ссылок при сборке для Windows. Вместо того чтобы безоговорочно выполнять target_link_libraries(MY_EXECUTABLE m), вы можете использовать:

IF (NOT WIN32)
  target_link_libraries(MY_EXECUTABLE m)
ENDIF()
19
задан qrunchmonkey 23 March 2009 в 23:32
поделиться

2 ответа

Существует следующий файл:

<mach/mach_time.h>

В этом файле вы найду функцию с именем mach_absolute_time () . mach_absolute_time () возвращает число uint64, не имеющее определенного значения. Представьте, что это тиков , но нигде не определено, какова длина одного тика. Определены только четыре вещи:

  1. mach_absolute_time () возвращает количество «тиков» с момента последней загрузки.
  2. При каждой загрузке счетчик тиков начинается с нуля.
  3. Счетчик тиков ведет счет строго вверх (никогда не идет назад).
  4. Счетчик тиков считает тики только во время работы системы.

Как видите, счетчик тиков несколько отличается от обычных системных часов. Во-первых, системные часы запускаются не с нуля при загрузке системы, а с наилучшим приближением системы к текущему «времени настенных часов». Нормальные системные часы также не идут строго вверх, например системные часы могут опережать время, и система регулярно синхронизирует системное время с помощью NTP (Network Time Protocol). Если система замечает, что при следующей синхронизации 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>

. Однако очень маловероятно, что эта функция вернет ошибку, а KERN_SUCCESS равно нулю, поэтому вы также можете непосредственно проверьте, что kerror не равно нулю.

Получив информацию в tinfo , вы можете использовать ее для расчета «коэффициента преобразования», если вы хотите преобразовать это число в единицы реального времени:

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

Приведением первого number в double , GCC автоматически преобразует второе число в double , и результат также будет double . Зная этот коэффициент, который кажется равным 1.0 на машинах Intel, но он может сильно отличаться на машинах PPC (и, возможно, он другой и на ARM), довольно легко преобразовать время хоста в наносекунды и наносекунды во время хоста.

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

systemUptimeNS содержит количество наносекунд, в течение которого система работала (не спала) между последней загрузкой и текущим моментом. Если вы разделите любое время в наносекундах на этот коэффициент, вы получите количество тактов.Это может быть очень полезно для функции mach_wait_until () . Предположим, вы хотите, чтобы текущий поток спал на 800 наносекунд. Вот как вы это сделаете:

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

Небольшой совет: Если вам регулярно нужно преобразовывать значения времени в тики, обычно (в зависимости от ЦП) умножать быстрее, чем делить:

double ns2HTimeFactor = 1.0 / hTime2nsFactor;

Теперь вы можете умножьте на ns2HTimeFactor вместо деления на hTime2nsFactor .

Конечно, пересчитывать коэффициенты каждый раз, когда они вам нужны, - пустая трата времени. Эти факторы постоянны, они никогда не изменятся во время работы системы. Таким образом, вы можете вычислить их где-то рядом с началом приложения и держать их до тех пор, пока приложение не завершится снова.

В Cocoa я бы рекомендовал написать себе статический класс для всего, что указано выше. Коэффициенты преобразования для любого преобразования можно вычислить в методе + (void) initialize класса. Какао гарантирует, что этот метод обязательно автоматически выполняется до того, как какое-либо сообщение когда-либо будет отправлено этому классу, он наверняка выполняется только один раз во время выполнения приложения и наверняка выполняется потокобезопасным способом, поэтому у вас нет беспокоиться о блокировке / синхронизации или атомарных операциях.

47
ответ дан 30 November 2019 в 02:29
поделиться

Вам необходимо использовать структуру 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 /

Самое простое, что можно сделать, это просто использовать вспомогательный класс CAHostTimeBase, предоставленный вам Apple - Developer / examples / CoreAudio / PublicUtility.

CAHostTimeBase.cpp и CAHostTimeBase.h - делает все, что вам нужно для этого.

6
ответ дан 30 November 2019 в 02:29
поделиться