• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #ifndef UTILITY_AUDIO_CLOCK_H
18 #define UTILITY_AUDIO_CLOCK_H
19 
20 #include <stdint.h>
21 #include <time.h>
22 
23 #include <aaudio/AAudio.h>
24 
25 // 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 
31 class AudioClock {
32 public:
33     static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
34         struct timespec time;
35         int result = clock_gettime(clockId, &time);
36         if (result < 0) {
37             return -errno;
38         }
39         return (time.tv_sec * AAUDIO_NANOS_PER_SECOND) + time.tv_nsec;
40     }
41 
42     /**
43      * Sleep until the specified absolute time.
44      * Return immediately with AAUDIO_ERROR_ILLEGAL_ARGUMENT if a negative
45      * 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      */
51     static int sleepUntilNanoTime(int64_t nanoTime,
52                                   clockid_t clockId = CLOCK_MONOTONIC) {
53         if (nanoTime > 0) {
54             struct timespec time;
55             time.tv_sec = nanoTime / AAUDIO_NANOS_PER_SECOND;
56             // Calculate the fractional nanoseconds. Avoids expensive % operation.
57             time.tv_nsec = nanoTime - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
58             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 {
69             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
70         }
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      */
81     static int sleepForNanos(int64_t nanoseconds, clockid_t clockId = CLOCK_MONOTONIC) {
82         if (nanoseconds > 0) {
83             struct timespec time;
84             time.tv_sec = nanoseconds / AAUDIO_NANOS_PER_SECOND;
85             // Calculate the fractional nanoseconds. Avoids expensive % operation.
86             time.tv_nsec = nanoseconds - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
87             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 
104 #endif // UTILITY_AUDIO_CLOCK_H
105