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 <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