blob: 43b71b0766ddf93ef336bbdcfc8e581f5b5faaa9 [file] [log] [blame]
Phil Burke1ce4912016-11-21 10:40:25 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Phil Burkdec33ab2017-01-17 14:48:16 -080017#ifndef UTILITY_AUDIO_CLOCK_H
18#define UTILITY_AUDIO_CLOCK_H
Phil Burke1ce4912016-11-21 10:40:25 -080019
Phil Burkd8bdcab2017-01-03 17:20:30 -080020#include <stdint.h>
Phil Burke1ce4912016-11-21 10:40:25 -080021#include <time.h>
Phil Burkd8bdcab2017-01-03 17:20:30 -080022
Phil Burka4eb0d82017-04-12 15:44:06 -070023#include <aaudio/AAudio.h>
Phil Burke1ce4912016-11-21 10:40:25 -080024
Phil Burk3316d5e2017-02-15 11:23:01 -080025// Time conversion constants.
26#define AAUDIO_NANOS_PER_MICROSECOND ((int64_t)1000)
27#define AAUDIO_NANOS_PER_MILLISECOND (AAUDIO_NANOS_PER_MICROSECOND * 1000)
28#define AAUDIO_MILLIS_PER_SECOND 1000
29#define AAUDIO_NANOS_PER_SECOND (AAUDIO_NANOS_PER_MILLISECOND * AAUDIO_MILLIS_PER_SECOND)
30
Phil Burke1ce4912016-11-21 10:40:25 -080031class AudioClock {
32public:
Phil Burk3316d5e2017-02-15 11:23:01 -080033 static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
Phil Burke1ce4912016-11-21 10:40:25 -080034 struct timespec time;
35 int result = clock_gettime(clockId, &time);
36 if (result < 0) {
37 return -errno;
38 }
Phil Burk5ed503c2017-02-01 09:38:15 -080039 return (time.tv_sec * AAUDIO_NANOS_PER_SECOND) + time.tv_nsec;
Phil Burke1ce4912016-11-21 10:40:25 -080040 }
41
42 /**
43 * Sleep until the specified absolute time.
Phil Burk5ed503c2017-02-01 09:38:15 -080044 * Return immediately with AAUDIO_ERROR_ILLEGAL_ARGUMENT if a negative
Phil Burke1ce4912016-11-21 10:40:25 -080045 * nanoTime is specified.
46 *
47 * @param nanoTime time to wake up
48 * @param clockId CLOCK_MONOTONIC is default
49 * @return 0, a negative error, or 1 if the call is interrupted by a signal handler (EINTR)
50 */
Phil Burk3316d5e2017-02-15 11:23:01 -080051 static int sleepUntilNanoTime(int64_t nanoTime,
Phil Burke1ce4912016-11-21 10:40:25 -080052 clockid_t clockId = CLOCK_MONOTONIC) {
53 if (nanoTime > 0) {
54 struct timespec time;
Phil Burk5ed503c2017-02-01 09:38:15 -080055 time.tv_sec = nanoTime / AAUDIO_NANOS_PER_SECOND;
Phil Burke1ce4912016-11-21 10:40:25 -080056 // Calculate the fractional nanoseconds. Avoids expensive % operation.
Phil Burk5ed503c2017-02-01 09:38:15 -080057 time.tv_nsec = nanoTime - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
Phil Burke1ce4912016-11-21 10:40:25 -080058 int err = clock_nanosleep(clockId, TIMER_ABSTIME, &time, nullptr);
59 switch (err) {
60 case EINTR:
61 return 1;
62 case 0:
63 return 0;
64 default:
65 // Subtract because clock_nanosleep() returns a positive error number!
66 return 0 - err;
67 }
68 } else {
Phil Burk5ed503c2017-02-01 09:38:15 -080069 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
Phil Burke1ce4912016-11-21 10:40:25 -080070 }
71 }
72
73 /**
74 * Sleep for the specified number of relative nanoseconds in real-time.
75 * Return immediately with 0 if a negative nanoseconds is specified.
76 *
77 * @param nanoseconds time to sleep
78 * @param clockId CLOCK_MONOTONIC is default
79 * @return 0, a negative error, or 1 if the call is interrupted by a signal handler (EINTR)
80 */
Phil Burk3316d5e2017-02-15 11:23:01 -080081 static int sleepForNanos(int64_t nanoseconds, clockid_t clockId = CLOCK_MONOTONIC) {
Phil Burke1ce4912016-11-21 10:40:25 -080082 if (nanoseconds > 0) {
83 struct timespec time;
Phil Burk5ed503c2017-02-01 09:38:15 -080084 time.tv_sec = nanoseconds / AAUDIO_NANOS_PER_SECOND;
Phil Burke1ce4912016-11-21 10:40:25 -080085 // Calculate the fractional nanoseconds. Avoids expensive % operation.
Phil Burk5ed503c2017-02-01 09:38:15 -080086 time.tv_nsec = nanoseconds - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
Phil Burke1ce4912016-11-21 10:40:25 -080087 const int flags = 0; // documented as relative sleep
88 int err = clock_nanosleep(clockId, flags, &time, nullptr);
89 switch (err) {
90 case EINTR:
91 return 1;
92 case 0:
93 return 0;
94 default:
95 // Subtract because clock_nanosleep() returns a positive error number!
96 return 0 - err;
97 }
98 }
99 return 0;
100 }
101};
102
103
Phil Burkdec33ab2017-01-17 14:48:16 -0800104#endif // UTILITY_AUDIO_CLOCK_H