Home | History | Annotate | Download | only in utility
      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 <errno.h>
     21 #include <stdint.h>
     22 #include <time.h>
     23 
     24 #include <aaudio/AAudio.h>
     25 
     26 // Time conversion constants.
     27 #define AAUDIO_NANOS_PER_MICROSECOND ((int64_t)1000)
     28 #define AAUDIO_NANOS_PER_MILLISECOND (AAUDIO_NANOS_PER_MICROSECOND * 1000)
     29 #define AAUDIO_MILLIS_PER_SECOND     1000
     30 #define AAUDIO_NANOS_PER_SECOND      (AAUDIO_NANOS_PER_MILLISECOND * AAUDIO_MILLIS_PER_SECOND)
     31 
     32 class AudioClock {
     33 public:
     34     static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
     35         struct timespec time;
     36         int result = clock_gettime(clockId, &time);
     37         if (result < 0) {
     38             return -errno;
     39         }
     40         return (time.tv_sec * AAUDIO_NANOS_PER_SECOND) + time.tv_nsec;
     41     }
     42 
     43     /**
     44      * Sleep until the specified absolute time.
     45      * Return immediately with AAUDIO_ERROR_ILLEGAL_ARGUMENT if a negative
     46      * nanoTime is specified.
     47      *
     48      * @param nanoTime time to wake up
     49      * @param clockId CLOCK_MONOTONIC is default
     50      * @return 0, a negative error, or 1 if the call is interrupted by a signal handler (EINTR)
     51      */
     52     static int sleepUntilNanoTime(int64_t nanoTime,
     53                                   clockid_t clockId = CLOCK_MONOTONIC) {
     54         if (nanoTime > 0) {
     55             struct timespec time;
     56             time.tv_sec = nanoTime / AAUDIO_NANOS_PER_SECOND;
     57             // Calculate the fractional nanoseconds. Avoids expensive % operation.
     58             time.tv_nsec = nanoTime - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
     59             int err = clock_nanosleep(clockId, TIMER_ABSTIME, &time, nullptr);
     60             switch (err) {
     61             case EINTR:
     62                 return 1;
     63             case 0:
     64                 return 0;
     65             default:
     66                 // Subtract because clock_nanosleep() returns a positive error number!
     67                 return 0 - err;
     68             }
     69         } else {
     70             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
     71         }
     72     }
     73 
     74     /**
     75      * Sleep for the specified number of relative nanoseconds in real-time.
     76      * Return immediately with 0 if a negative nanoseconds is specified.
     77      *
     78      * @param nanoseconds time to sleep
     79      * @param clockId CLOCK_MONOTONIC is default
     80      * @return 0, a negative error, or 1 if the call is interrupted by a signal handler (EINTR)
     81      */
     82     static int sleepForNanos(int64_t nanoseconds, clockid_t clockId = CLOCK_MONOTONIC) {
     83         if (nanoseconds > 0) {
     84             struct timespec time;
     85             time.tv_sec = nanoseconds / AAUDIO_NANOS_PER_SECOND;
     86             // Calculate the fractional nanoseconds. Avoids expensive % operation.
     87             time.tv_nsec = nanoseconds - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
     88             const int flags = 0; // documented as relative sleep
     89             int err = clock_nanosleep(clockId, flags, &time, nullptr);
     90             switch (err) {
     91             case EINTR:
     92                 return 1;
     93             case 0:
     94                 return 0;
     95             default:
     96                 // Subtract because clock_nanosleep() returns a positive error number!
     97                 return 0 - err;
     98             }
     99         }
    100         return 0;
    101     }
    102 };
    103 
    104 
    105 #endif // UTILITY_AUDIO_CLOCK_H
    106