Home | History | Annotate | Download | only in cpp
      1 /*
      2  * Copyright (C) 2015 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 // FIXME taken from OpenSLES_AndroidConfiguration.h
     18 #define SL_ANDROID_KEY_PERFORMANCE_MODE  ((const SLchar*) "androidPerformanceMode")
     19 
     20 ////////////////////////////////////////////
     21 /// Actual sles functions.
     22 
     23 
     24 // Test program to record from default audio input and playback to default audio output.
     25 // It will generate feedback (Larsen effect) if played through on-device speakers,
     26 // or acts as a delay if played through headset.
     27 
     28 #define _USE_MATH_DEFINES
     29 #include <cmath>
     30 #include "sles.h"
     31 #include "audio_utils/atomic.h"
     32 #include "byte_buffer.h"
     33 #include <unistd.h>
     34 #include <string.h>
     35 
     36 static int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int micSource,
     37         int performanceMode,
     38         int testType, double frequency1, char* byteBufferPtr, int byteBufferLength,
     39         short* loopbackTone, int maxRecordedLateCallbacks, int ignoreFirstFrames);
     40 static int slesDestroyServer(sles_data *pSles);
     41 
     42 static void initBufferStats(bufferStats *stats);
     43 static void collectBufferPeriod(bufferStats *stats, bufferStats *fdpStats,
     44         callbackTimeStamps *timeStamps, short expectedBufferPeriod);
     45 static bool updateBufferStats(bufferStats *stats, int64_t diff_in_nano, int expectedBufferPeriod);
     46 static void recordTimeStamp(callbackTimeStamps *timeStamps,
     47         int64_t callbackDuration, int64_t timeStamp);
     48 
     49 int slesComputeDefaultSettings(int /*performanceMode*/, int* /*samplingRate*/,
     50             int* /*playerBufferFrameCount*/, int* /*recorderBufferFrameCount*/) {
     51     // For OpenSL ES, these parameters can be determined by NativeAudioThread itself.
     52     return STATUS_FAIL;
     53 }
     54 
     55 int slesInit(void ** ppCtx, int samplingRate, int frameCount, int micSource,
     56              int performanceMode,
     57              int testType, double frequency1, char* byteBufferPtr, int byteBufferLength,
     58              short* loopbackTone, int maxRecordedLateCallbacks, int ignoreFirstFrames) {
     59     sles_data ** ppSles = (sles_data**) ppCtx;
     60     int status = STATUS_FAIL;
     61     if (ppSles != NULL) {
     62         sles_data * pSles = (sles_data*) calloc(1, sizeof(sles_data));
     63 
     64         SLES_PRINTF("pSles malloc %zu bytes at %p", sizeof(sles_data), pSles);
     65         //__android_log_print(ANDROID_LOG_INFO, "sles_jni",
     66         //"malloc %d bytes at %p", sizeof(sles_data), pSles);//Or ANDROID_LOG_INFO, ...
     67         *ppSles = pSles;
     68         if (pSles != NULL)
     69         {
     70             SLES_PRINTF("creating server. Sampling rate =%d, frame count = %d",
     71                         samplingRate, frameCount);
     72             status = slesCreateServer(pSles, samplingRate, frameCount, micSource,
     73                                       performanceMode, testType,
     74                                       frequency1, byteBufferPtr, byteBufferLength, loopbackTone,
     75                                       maxRecordedLateCallbacks, ignoreFirstFrames);
     76             SLES_PRINTF("slesCreateServer =%d", status);
     77         }
     78     }
     79 
     80     return status;
     81 }
     82 int slesDestroy(void ** ppCtx) {
     83     sles_data ** ppSles = (sles_data**)ppCtx;
     84     int status = STATUS_FAIL;
     85     if (ppSles != NULL) {
     86         slesDestroyServer(*ppSles);
     87 
     88         if (*ppSles != NULL)
     89         {
     90             SLES_PRINTF("free memory at %p",*ppSles);
     91             free(*ppSles);
     92             *ppSles = 0;
     93         }
     94         status = STATUS_SUCCESS;
     95     }
     96     return status;
     97 }
     98 
     99 #define ASSERT(x) do { if(!(x)) { __android_log_assert("assert", "sles_jni", \
    100                     "ASSERTION FAILED: " #x); } } while (0)
    101 #define ASSERT_EQ(x, y) do { if ((x) == (y)) ; else __android_log_assert("assert", "sles_jni", \
    102                     "ASSERTION FAILED: 0x%x != 0x%x\n", (unsigned) (x), (unsigned) (y)); } while (0)
    103 
    104 // Called after audio recorder fills a buffer with data, then we can read from this filled buffer
    105 static void recorderCallback(SLAndroidSimpleBufferQueueItf caller __unused, void *context) {
    106     sles_data *pSles = (sles_data*) context;
    107     if (pSles != NULL) {
    108         collectBufferPeriod(&pSles->recorderBufferStats, NULL /*fdpStats*/,
    109                             &pSles->recorderTimeStamps, pSles->expectedBufferPeriod);
    110 
    111         //__android_log_print(ANDROID_LOG_INFO, "sles_jni", "in recorderCallback");
    112         SLresult result;
    113 
    114         //ee  SLES_PRINTF("<R");
    115 
    116         // We should only be called when a recording buffer is done
    117         ASSERT(pSles->rxFront <= pSles->rxBufCount);
    118         ASSERT(pSles->rxRear <= pSles->rxBufCount);
    119         ASSERT(pSles->rxFront != pSles->rxRear);
    120         char *buffer = pSles->rxBuffers[pSles->rxFront]; //pSles->rxBuffers stores the data recorded
    121 
    122 
    123         // Remove buffer from record queue
    124         if (++pSles->rxFront > pSles->rxBufCount) {
    125             pSles->rxFront = 0;
    126         }
    127 
    128         if (pSles->testType == TEST_TYPE_LATENCY) {
    129             // Throw out first frames
    130             if (pSles->ignoreFirstFrames) {
    131                 int framesToErase = pSles->ignoreFirstFrames;
    132                 if (framesToErase > (int) pSles->bufSizeInFrames) {
    133                     framesToErase = pSles->bufSizeInFrames;
    134                 }
    135                 pSles->ignoreFirstFrames -= framesToErase;
    136                 memset(buffer, 0, framesToErase * pSles->channels * sizeof(short));
    137             }
    138 
    139             ssize_t actual = audio_utils_fifo_write(&(pSles->fifo), buffer,
    140                     (size_t) pSles->bufSizeInFrames);
    141 
    142             if (actual != (ssize_t) pSles->bufSizeInFrames) {
    143                 write(1, "?", 1);
    144             }
    145 
    146             // This is called by a realtime (SCHED_FIFO) thread,
    147             // and it is unsafe to do I/O as it could block for unbounded time.
    148             // Flash filesystem is especially notorious for blocking.
    149             if (pSles->fifo2Buffer != NULL) {
    150                 actual = audio_utils_fifo_write(&(pSles->fifo2), buffer,
    151                         (size_t) pSles->bufSizeInFrames);
    152                 if (actual != (ssize_t) pSles->bufSizeInFrames) {
    153                     write(1, "?", 1);
    154                 }
    155             }
    156         } else if (pSles->testType == TEST_TYPE_BUFFER_PERIOD) {
    157             if (pSles->fifo2Buffer != NULL) {
    158                 ssize_t actual = byteBuffer_write(pSles->byteBufferPtr, pSles->byteBufferLength,
    159                         buffer, (size_t) pSles->bufSizeInFrames, pSles->channels);
    160 
    161                 //FIXME should log errors using other methods instead of printing to terminal
    162                 if (actual != (ssize_t) pSles->bufSizeInFrames) {
    163                     write(1, "?", 1);
    164                 }
    165             }
    166         }
    167 
    168 
    169         // Enqueue this same buffer for the recorder to fill again.
    170         result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue, buffer,
    171                                                           pSles->bufSizeInBytes);
    172         //__android_log_print(ANDROID_LOG_INFO, "recorderCallback", "recorder buffer size: %i",
    173         //                    pSles->bufSizeInBytes);
    174         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    175 
    176 
    177         // Update our model of the record queue
    178         SLuint32 rxRearNext = pSles->rxRear + 1;
    179         if (rxRearNext > pSles->rxBufCount) {
    180             rxRearNext = 0;
    181         }
    182         ASSERT(rxRearNext != pSles->rxFront);
    183         pSles->rxBuffers[pSles->rxRear] = buffer;
    184         pSles->rxRear = rxRearNext;
    185 
    186 
    187 
    188       //ee  SLES_PRINTF("r>");
    189 
    190     } //pSles not null
    191 }
    192 
    193 
    194 // Calculate nanosecond difference between two timespec structs from clock_gettime(CLOCK_MONOTONIC)
    195 // tv_sec [0, max time_t] , tv_nsec [0, 999999999]
    196 static int64_t diffInNano(struct timespec previousTime, struct timespec currentTime) {
    197     return (int64_t) (currentTime.tv_sec - previousTime.tv_sec) * (int64_t) NANOS_PER_SECOND +
    198             currentTime.tv_nsec - previousTime.tv_nsec;
    199 }
    200 
    201 // Called after audio player empties a buffer of data
    202 static void playerCallback(SLBufferQueueItf caller __unused, void *context) {
    203     sles_data *pSles = (sles_data*) context;
    204     if (pSles != NULL) {
    205         collectBufferPeriod(&pSles->playerBufferStats, &pSles->recorderBufferStats /*fdpStats*/,
    206                             &pSles->playerTimeStamps, pSles->expectedBufferPeriod);
    207         SLresult result;
    208 
    209         //ee  SLES_PRINTF("<P");
    210 
    211         // Get the buffer that just finished playing
    212         ASSERT(pSles->txFront <= pSles->txBufCount);
    213         ASSERT(pSles->txRear <= pSles->txBufCount);
    214         ASSERT(pSles->txFront != pSles->txRear);
    215         char *buffer = pSles->txBuffers[pSles->txFront];
    216         if (++pSles->txFront > pSles->txBufCount) {
    217             pSles->txFront = 0;
    218         }
    219 
    220         if (pSles->testType == TEST_TYPE_LATENCY) {
    221             // Jitter buffer should have strictly less than 2 buffers worth of data in it.
    222             // This is to prevent the test itself from adding too much latency.
    223             size_t discardedInputFrames = 0;
    224             for (;;) {
    225                 size_t availToRead = audio_utils_fifo_availToRead(&pSles->fifo);
    226                 if (availToRead < pSles->bufSizeInFrames * 2) {
    227                     break;
    228                 }
    229                 ssize_t actual = audio_utils_fifo_read(&pSles->fifo, buffer,
    230                         pSles->bufSizeInFrames);
    231                 if (actual > 0) {
    232                     discardedInputFrames += actual;
    233                 }
    234                 if (actual != (ssize_t) pSles->bufSizeInFrames) {
    235                     break;
    236                 }
    237             }
    238             if (discardedInputFrames > 0) {
    239                 if (pSles->totalDiscardedInputFrames > 0) {
    240                     __android_log_print(ANDROID_LOG_WARN, "sles_jni",
    241                         "Discarded an additional %zu input frames after a total of %zu input frames"
    242                         " had previously been discarded",
    243                         discardedInputFrames, pSles->totalDiscardedInputFrames);
    244                 }
    245                 pSles->totalDiscardedInputFrames += discardedInputFrames;
    246             }
    247 
    248             ssize_t actual = audio_utils_fifo_read(&(pSles->fifo), buffer, pSles->bufSizeInFrames);
    249             if (actual != (ssize_t) pSles->bufSizeInFrames) {
    250                 write(1, "/", 1);
    251                 // on underrun from pipe, substitute silence
    252                 memset(buffer, 0, pSles->bufSizeInFrames * pSles->channels * sizeof(short));
    253             }
    254 
    255             if (pSles->injectImpulse == -1) {   // here we inject pulse
    256 
    257                 /*// Experimentally, a single frame impulse was insufficient to trigger feedback.
    258                 // Also a Nyquist frequency signal was also insufficient, probably because
    259                 // the response of output and/or input path was not adequate at high frequencies.
    260                 // This short burst of a few cycles of square wave at Nyquist/4 found to work well.
    261                 for (unsigned i = 0; i < pSles->bufSizeInFrames / 8; i += 8) {
    262                     for (int j = 0; j < 8; j++) {
    263                         for (unsigned k = 0; k < pSles->channels; k++) {
    264                             ((short *) buffer)[(i + j) * pSles->channels + k] =
    265                                                                             j < 4 ? 0x7FFF : 0x8000;
    266                         }
    267                     }
    268                 }*/
    269 
    270                 //inject java generated tone
    271                 for (unsigned i = 0; i < pSles->bufSizeInFrames; ++i) {
    272                     for (unsigned k = 0; k < pSles->channels; ++k) {
    273                         ((short *) buffer)[i * pSles->channels + k] = pSles->loopbackTone[i];
    274                     }
    275                 }
    276 
    277                 pSles->injectImpulse = 0;
    278                 pSles->totalDiscardedInputFrames = 0;
    279             }
    280         } else if (pSles->testType == TEST_TYPE_BUFFER_PERIOD) {
    281             double twoPi = M_PI * 2;
    282             int maxShort = 32767;
    283             float amplitude = 0.8;
    284             short value;
    285             double phaseIncrement = pSles->frequency1 / pSles->sampleRate;
    286             bool isGlitchEnabled = false;
    287             for (unsigned i = 0; i < pSles->bufSizeInFrames; i++) {
    288                 value = (short) (sin(pSles->bufferTestPhase1) * maxShort * amplitude);
    289                 for (unsigned k = 0; k < pSles->channels; ++k) {
    290                     ((short *) buffer)[i* pSles->channels + k] = value;
    291                 }
    292 
    293                 pSles->bufferTestPhase1 += twoPi * phaseIncrement;
    294                 // insert glitches if isGlitchEnabled == true, and insert it for every second
    295                 if (isGlitchEnabled && (pSles->count % pSles->sampleRate == 0)) {
    296                     pSles->bufferTestPhase1 += twoPi * phaseIncrement;
    297                 }
    298 
    299                 pSles->count++;
    300 
    301                 while (pSles->bufferTestPhase1 > twoPi) {
    302                     pSles->bufferTestPhase1 -= twoPi;
    303                 }
    304             }
    305         }
    306 
    307         // Enqueue the filled buffer for playing
    308         result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue, buffer,
    309                                                         pSles->bufSizeInBytes);
    310         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    311 
    312         // Update our model of the player queue
    313         ASSERT(pSles->txFront <= pSles->txBufCount);
    314         ASSERT(pSles->txRear <= pSles->txBufCount);
    315         SLuint32 txRearNext = pSles->txRear + 1;
    316         if (txRearNext > pSles->txBufCount) {
    317             txRearNext = 0;
    318         }
    319         ASSERT(txRearNext != pSles->txFront);
    320         pSles->txBuffers[pSles->txRear] = buffer;
    321         pSles->txRear = txRearNext;
    322 
    323     } //pSles not null
    324 }
    325 
    326 // Used to set initial values for the bufferStats struct before values can be recorded.
    327 static void initBufferStats(bufferStats *stats) {
    328     stats->buffer_period = new int[RANGE](); // initialized to zeros
    329     stats->previous_time = {0,0};
    330     stats->current_time = {0,0};
    331 
    332     stats->buffer_count = 0;
    333     stats->max_buffer_period = 0;
    334 
    335     stats->measurement_count = 0;
    336     stats->SDM = 0;
    337     stats->var = 0;
    338 }
    339 
    340 // Called in the beginning of playerCallback() to collect the interval between each callback.
    341 // fdpStats is either NULL or a pointer to the buffer statistics for the full-duplex partner.
    342 static void collectBufferPeriod(bufferStats *stats, bufferStats *fdpStats,
    343         callbackTimeStamps *timeStamps, short expectedBufferPeriod) {
    344     clock_gettime(CLOCK_MONOTONIC, &(stats->current_time));
    345 
    346     if (timeStamps->startTime.tv_sec == 0 && timeStamps->startTime.tv_nsec == 0) {
    347         timeStamps->startTime = stats->current_time;
    348     }
    349 
    350     (stats->buffer_count)++;
    351 
    352     if (stats->previous_time.tv_sec != 0 && stats->buffer_count > BUFFER_PERIOD_DISCARD &&
    353          (fdpStats == NULL || fdpStats->buffer_count > BUFFER_PERIOD_DISCARD_FULL_DUPLEX_PARTNER)) {
    354 
    355         int64_t callbackDuration = diffInNano(stats->previous_time, stats->current_time);
    356 
    357         bool outlier = updateBufferStats(stats, callbackDuration, expectedBufferPeriod);
    358 
    359         //recording timestamps of buffer periods not at expected buffer period
    360         if (outlier) {
    361             int64_t timeStamp = diffInNano(timeStamps->startTime, stats->current_time);
    362             recordTimeStamp(timeStamps, callbackDuration, timeStamp);
    363         }
    364     }
    365 
    366     stats->previous_time = stats->current_time;
    367 }
    368 
    369 // Records an outlier given the duration in nanoseconds and the number of nanoseconds
    370 // between it and the start of the test.
    371 static void recordTimeStamp(callbackTimeStamps *timeStamps,
    372         int64_t callbackDuration, int64_t timeStamp) {
    373     if (timeStamps->exceededCapacity) {
    374         return;
    375     }
    376 
    377     //only marked as exceeded if attempting to record a late callback after arrays full
    378     if (timeStamps->index == timeStamps->capacity){
    379         timeStamps->exceededCapacity = true;
    380     } else {
    381         timeStamps->callbackDurations[timeStamps->index] =
    382                 (short) ((callbackDuration + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI);
    383         timeStamps->timeStampsMs[timeStamps->index] =
    384                 (int) ((timeStamp + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI);
    385         timeStamps->index++;
    386     }
    387 }
    388 
    389 static void atomicSetIfGreater(volatile int32_t *addr, int32_t val) {
    390     // TODO: rewrite this to avoid the need for unbounded spinning
    391     int32_t old;
    392     do {
    393         old = *addr;
    394         if (val < old) return;
    395     } while(!android_atomic_compare_exchange(&old, val, addr));
    396 }
    397 
    398 // Updates the stats being collected about buffer periods. Returns true if this is an outlier.
    399 static bool updateBufferStats(bufferStats *stats, int64_t diff_in_nano, int expectedBufferPeriod) {
    400     stats->measurement_count++;
    401 
    402     // round up to nearest millisecond
    403     int diff_in_milli = (int) ((diff_in_nano + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI);
    404 
    405     if (diff_in_milli > stats->max_buffer_period) {
    406         stats->max_buffer_period = diff_in_milli;
    407     }
    408 
    409     // from 0 ms to 1000 ms, plus a sum of all instances > 1000ms
    410     if (diff_in_milli >= (RANGE - 1)) {
    411         (stats->buffer_period)[RANGE-1]++;
    412     } else if (diff_in_milli >= 0) {
    413         (stats->buffer_period)[diff_in_milli]++;
    414     } else { // for diff_in_milli < 0
    415         __android_log_print(ANDROID_LOG_INFO, "sles_player", "Having negative BufferPeriod.");
    416     }
    417 
    418     int64_t delta = diff_in_nano - (int64_t) expectedBufferPeriod * NANOS_PER_MILLI;
    419     stats->SDM += delta * delta;
    420     if (stats->measurement_count > 1) {
    421         stats->var = stats->SDM / stats->measurement_count;
    422     }
    423 
    424     // check if the lateness is so bad that a systrace should be captured
    425     // TODO: replace static threshold of lateness with a dynamic determination
    426     if (diff_in_milli > expectedBufferPeriod + LATE_CALLBACK_CAPTURE_THRESHOLD) {
    427         // TODO: log in a non-blocking way
    428         //__android_log_print(ANDROID_LOG_INFO, "buffer_stats", "Callback late by %d ms",
    429         //                    diff_in_milli - expectedBufferPeriod);
    430         atomicSetIfGreater(&(stats->captureRank), diff_in_milli - expectedBufferPeriod);
    431     }
    432     return diff_in_milli > expectedBufferPeriod + LATE_CALLBACK_OUTLIER_THRESHOLD;
    433 }
    434 
    435 static int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int micSource,
    436         int performanceMode,
    437         int testType, double frequency1, char *byteBufferPtr, int byteBufferLength,
    438         short *loopbackTone, int maxRecordedLateCallbacks, int ignoreFirstFrames) {
    439     int status = STATUS_FAIL;
    440 
    441     if (pSles != NULL) {
    442 
    443         //        adb shell slesTest_feedback -r1 -t1 -s48000 -f240 -i300 -e3 -o/sdcard/log.wav
    444         //            r1 and t1 are the receive and transmit buffer counts, typically 1
    445         //            s is the sample rate, typically 48000 or 44100
    446         //            f is the frame count per buffer, typically 240 or 256
    447         //            i is the number of milliseconds before impulse.  You may need to adjust this.
    448         //            e is number of seconds to record
    449         //            o is output .wav file name
    450 
    451 
    452         //        // default values
    453         //        SLuint32 rxBufCount = 1;     // -r#
    454         //        SLuint32 txBufCount = 1;     // -t#
    455         //        SLuint32 bufSizeInFrames = 240;  // -f#
    456         //        SLuint32 channels = 1;       // -c#
    457         //        SLuint32 sampleRate = 48000; // -s#
    458         //        SLuint32 exitAfterSeconds = 3; // -e#
    459         //        SLuint32 freeBufCount = 0;   // calculated
    460         //        SLuint32 bufSizeInBytes = 0; // calculated
    461         //        int injectImpulse = 300; // -i#i
    462         //
    463         //        // Storage area for the buffer queues
    464         //        char **rxBuffers;
    465         //        char **txBuffers;
    466         //        char **freeBuffers;
    467         //
    468         //        // Buffer indices
    469         //        SLuint32 rxFront;    // oldest recording
    470         //        SLuint32 rxRear;     // next to be recorded
    471         //        SLuint32 txFront;    // oldest playing
    472         //        SLuint32 txRear;     // next to be played
    473         //        SLuint32 freeFront;  // oldest free
    474         //        SLuint32 freeRear;   // next to be freed
    475         //
    476         //        audio_utils_fifo fifo; //(*)
    477         //        SLAndroidSimpleBufferQueueItf recorderBufferQueue;
    478         //        SLBufferQueueItf playerBufferQueue;
    479 
    480         // default values
    481         pSles->rxBufCount = 1;     // -r#
    482         pSles->txBufCount = 1;     // -t#
    483         pSles->bufSizeInFrames = frameCount;//240;  // -f#
    484         pSles->channels = 1;       // -c#
    485         pSles->sampleRate = samplingRate;//48000; // -s#
    486         pSles->exitAfterSeconds = 3; // -e#
    487         pSles->freeBufCount = 0;   // calculated
    488         pSles->bufSizeInBytes = 0; // calculated
    489         pSles->injectImpulse = 300; // -i#i
    490         pSles->totalDiscardedInputFrames = 0;
    491         pSles->ignoreFirstFrames = ignoreFirstFrames;
    492 
    493         // Storage area for the buffer queues
    494         //        char **rxBuffers;
    495         //        char **txBuffers;
    496         //        char **freeBuffers;
    497 
    498         // Buffer indices
    499 #if 0
    500         pSles->rxFront;    // oldest recording
    501         pSles->rxRear;     // next to be recorded
    502         pSles->txFront;    // oldest playing
    503         pSles->txRear;     // next to be played
    504         pSles->freeFront;  // oldest free
    505         pSles->freeRear;   // next to be freed
    506 
    507         pSles->fifo; //(*)
    508 #endif
    509         pSles->fifo2Buffer = NULL;  //this fifo is for sending data to java code (to plot it)
    510 #if 0
    511         pSles->recorderBufferQueue;
    512         pSles->playerBufferQueue;
    513 #endif
    514 
    515 
    516 
    517         // compute total free buffers as -r plus -t
    518         pSles->freeBufCount = pSles->rxBufCount + pSles->txBufCount;
    519         // compute buffer size
    520         pSles->bufSizeInBytes = pSles->channels * pSles->bufSizeInFrames * sizeof(short);
    521 
    522         // Initialize free buffers
    523         pSles->freeBuffers = (char **) calloc(pSles->freeBufCount + 1, sizeof(char *));
    524         SLES_PRINTF("  calloc freeBuffers %llu bytes at %p", (long long)pSles->freeBufCount + 1,
    525                     pSles->freeBuffers);
    526         unsigned j;
    527         for (j = 0; j < pSles->freeBufCount; ++j) {
    528             pSles->freeBuffers[j] = (char *) malloc(pSles->bufSizeInBytes);
    529             SLES_PRINTF(" buff%d malloc %llu bytes at %p",j, (long long)pSles->bufSizeInBytes,
    530                         pSles->freeBuffers[j]);
    531         }
    532         pSles->freeFront = 0;
    533         pSles->freeRear = pSles->freeBufCount;
    534         pSles->freeBuffers[j] = NULL;
    535 
    536         // Initialize record queue
    537         pSles->rxBuffers = (char **) calloc(pSles->rxBufCount + 1, sizeof(char *));
    538         SLES_PRINTF("  calloc rxBuffers %llu bytes at %p", (long long)pSles->rxBufCount + 1,
    539                 pSles->rxBuffers);
    540         pSles->rxFront = 0;
    541         pSles->rxRear = 0;
    542 
    543         // Initialize play queue
    544         pSles->txBuffers = (char **) calloc(pSles->txBufCount + 1, sizeof(char *));
    545         SLES_PRINTF("  calloc txBuffers %llu bytes at %p", (long long)pSles->txBufCount + 1,
    546                 pSles->txBuffers);
    547         pSles->txFront = 0;
    548         pSles->txRear = 0;
    549 
    550         size_t frameSize = pSles->channels * sizeof(short);
    551 #define FIFO_FRAMES 1024
    552         pSles->fifoBuffer = new short[FIFO_FRAMES * pSles->channels];
    553         audio_utils_fifo_init(&(pSles->fifo), FIFO_FRAMES, frameSize, pSles->fifoBuffer);
    554 
    555         //        SNDFILE *sndfile;
    556         //        if (outFileName != NULL) {
    557         // create .wav writer
    558         //            SF_INFO info;
    559         //            info.frames = 0;
    560         //            info.samplerate = sampleRate;
    561         //            info.channels = channels;
    562         //            info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
    563         //            sndfile = sf_open(outFileName, SFM_WRITE, &info);
    564         //            if (sndfile != NULL) {
    565 #define FIFO2_FRAMES 65536
    566         pSles->fifo2Buffer = new short[FIFO2_FRAMES * pSles->channels];
    567         audio_utils_fifo_init(&(pSles->fifo2), FIFO2_FRAMES, frameSize, pSles->fifo2Buffer);
    568         //            } else {
    569         //                fprintf(stderr, "sf_open failed\n");
    570         //            }
    571         //        } else {
    572         //            sndfile = NULL;
    573         //        }
    574 
    575         initBufferStats(&pSles->recorderBufferStats);
    576         initBufferStats(&pSles->playerBufferStats);
    577 
    578         // init other variables needed for buffer test
    579         pSles->testType = testType;
    580         pSles->frequency1 = frequency1;
    581         pSles->bufferTestPhase1 = 0;
    582         pSles->count = 0;
    583         pSles->byteBufferPtr = byteBufferPtr;
    584         pSles->byteBufferLength = byteBufferLength;
    585 
    586         //init loopback tone
    587         pSles->loopbackTone = loopbackTone;
    588 
    589         pSles->recorderTimeStamps = {
    590             new int[maxRecordedLateCallbacks],      //int* timeStampsMs
    591             new short[maxRecordedLateCallbacks],    //short* callbackDurations
    592             0,                                      //short index
    593             {0,0},                                  //struct timespec startTime;
    594             maxRecordedLateCallbacks,               //int capacity
    595             false                                   //bool exceededCapacity
    596         };
    597 
    598         pSles->playerTimeStamps = {
    599             new int[maxRecordedLateCallbacks],      //int* timeStampsMs
    600             new short[maxRecordedLateCallbacks],    //short* callbackDurations;
    601             0,                                      //short index
    602             {0,0},                                  //struct timespec startTime;
    603             maxRecordedLateCallbacks,               //int capacity
    604             false                                   //bool exceededCapacity
    605         };
    606 
    607         pSles->expectedBufferPeriod = (short) (
    608                 round(pSles->bufSizeInFrames * MILLIS_PER_SECOND / (float) pSles->sampleRate));
    609 
    610         SLresult result;
    611 
    612         // create engine
    613 #if 0
    614         pSles->engineObject;
    615 #endif
    616         result = slCreateEngine(&(pSles->engineObject), 0, NULL, 0, NULL, NULL);
    617         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    618         result = (*(pSles->engineObject))->Realize(pSles->engineObject, SL_BOOLEAN_FALSE);
    619         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    620         SLEngineItf engineEngine;
    621         result = (*(pSles->engineObject))->GetInterface(pSles->engineObject, SL_IID_ENGINE,
    622                 &engineEngine);
    623         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    624 
    625         // create output mix
    626 #if 0
    627         pSles->outputmixObject;
    628 #endif
    629         result = (*engineEngine)->CreateOutputMix(engineEngine, &(pSles->outputmixObject), 0, NULL,
    630                 NULL);
    631         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    632         result = (*(pSles->outputmixObject))->Realize(pSles->outputmixObject, SL_BOOLEAN_FALSE);
    633         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    634 
    635         // create an audio player with buffer queue source and output mix sink
    636         SLDataSource audiosrc;
    637         SLDataSink audiosnk;
    638         SLDataFormat_PCM pcm;
    639         SLDataLocator_OutputMix locator_outputmix;
    640         SLDataLocator_BufferQueue locator_bufferqueue_tx;
    641         locator_bufferqueue_tx.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
    642         locator_bufferqueue_tx.numBuffers = pSles->txBufCount;
    643         locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    644         locator_outputmix.outputMix = pSles->outputmixObject;
    645         pcm.formatType = SL_DATAFORMAT_PCM;
    646         pcm.numChannels = pSles->channels;
    647         pcm.samplesPerSec = pSles->sampleRate * 1000;
    648         pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
    649         pcm.containerSize = 16;
    650         pcm.channelMask = pSles->channels == 1 ? SL_SPEAKER_FRONT_CENTER :
    651                 (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
    652         pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
    653         audiosrc.pLocator = &locator_bufferqueue_tx;
    654         audiosrc.pFormat = &pcm;
    655         audiosnk.pLocator = &locator_outputmix;
    656         audiosnk.pFormat = NULL;
    657         pSles->playerObject = NULL;
    658         pSles->recorderObject = NULL;
    659         SLInterfaceID ids_tx[2] = {SL_IID_BUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
    660         SLboolean flags_tx[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    661         result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(pSles->playerObject),
    662                 &audiosrc, &audiosnk, 2, ids_tx, flags_tx);
    663         if (SL_RESULT_CONTENT_UNSUPPORTED == result) {
    664             SLES_PRINTF("ERROR: Could not create audio player (result %x), check sample rate\n",
    665                                                      result);
    666             goto cleanup;
    667         }
    668         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    669 
    670         {
    671            /* Get the Android configuration interface which is explicit */
    672             SLAndroidConfigurationItf configItf;
    673             result = (*(pSles->playerObject))->GetInterface(pSles->playerObject,
    674                                                  SL_IID_ANDROIDCONFIGURATION, (void*)&configItf);
    675             ASSERT_EQ(SL_RESULT_SUCCESS, result);
    676 
    677             /* Use the configuration interface to configure the player before it's realized */
    678             if (performanceMode != -1) {
    679                 SLuint32 performanceMode32 = performanceMode;
    680                 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE,
    681                         &performanceMode32, sizeof(SLuint32));
    682                 ASSERT_EQ(SL_RESULT_SUCCESS, result);
    683             }
    684 
    685         }
    686 
    687         result = (*(pSles->playerObject))->Realize(pSles->playerObject, SL_BOOLEAN_FALSE);
    688         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    689         SLPlayItf playerPlay;
    690         result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_PLAY,
    691                 &playerPlay);
    692         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    693         result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_BUFFERQUEUE,
    694                 &(pSles->playerBufferQueue));
    695         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    696         result = (*(pSles->playerBufferQueue))->RegisterCallback(pSles->playerBufferQueue,
    697                 playerCallback, pSles); //playerCallback is the name of callback function
    698         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    699 
    700         // Enqueue some zero buffers for the player
    701         for (j = 0; j < pSles->txBufCount; ++j) {
    702 
    703             // allocate a free buffer
    704             ASSERT(pSles->freeFront != pSles->freeRear);
    705             char *buffer = pSles->freeBuffers[pSles->freeFront];
    706             if (++pSles->freeFront > pSles->freeBufCount) {
    707                 pSles->freeFront = 0;
    708             }
    709 
    710             // put on play queue
    711             SLuint32 txRearNext = pSles->txRear + 1;
    712             if (txRearNext > pSles->txBufCount) {
    713                 txRearNext = 0;
    714             }
    715             ASSERT(txRearNext != pSles->txFront);
    716             pSles->txBuffers[pSles->txRear] = buffer;
    717             pSles->txRear = txRearNext;
    718             result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue,
    719                     buffer, pSles->bufSizeInBytes);
    720             ASSERT_EQ(SL_RESULT_SUCCESS, result);
    721         }
    722 
    723         result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
    724         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    725 
    726         // Create an audio recorder with microphone device source and buffer queue sink.
    727         // The buffer queue as sink is an Android-specific extension.
    728         SLDataLocator_IODevice locator_iodevice;
    729         SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_rx;
    730 
    731         locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE;
    732         locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT;
    733         locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
    734         locator_iodevice.device = NULL;
    735 
    736         audiosrc.pLocator = &locator_iodevice;
    737         audiosrc.pFormat = NULL;
    738 
    739         locator_bufferqueue_rx.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
    740         locator_bufferqueue_rx.numBuffers = pSles->rxBufCount;
    741 
    742         audiosnk.pLocator = &locator_bufferqueue_rx;
    743         audiosnk.pFormat = &pcm;
    744 
    745         {   //why brackets here?
    746             SLInterfaceID ids_rx[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
    747                                        SL_IID_ANDROIDCONFIGURATION};
    748             SLboolean flags_rx[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    749             result = (*engineEngine)->CreateAudioRecorder(engineEngine, &(pSles->recorderObject),
    750                     &audiosrc, &audiosnk, 2, ids_rx, flags_rx);
    751             if (SL_RESULT_SUCCESS != result) {
    752                 status = STATUS_FAIL;
    753 
    754                 SLES_PRINTF("ERROR: Could not create audio recorder (result %x), "
    755                              "check sample rate and channel count\n", result);
    756                 goto cleanup;
    757             }
    758         }
    759         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    760 
    761         {
    762            /* Get the Android configuration interface which is explicit */
    763             SLAndroidConfigurationItf configItf;
    764             result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
    765                                                  SL_IID_ANDROIDCONFIGURATION, (void*)&configItf);
    766             ASSERT_EQ(SL_RESULT_SUCCESS, result);
    767 
    768             SLuint32 presetValue = micSource;
    769             //SL_ANDROID_RECORDING_PRESET_CAMCORDER;//SL_ANDROID_RECORDING_PRESET_NONE;
    770 
    771             /* Use the configuration interface to configure the recorder before it's realized */
    772             if (presetValue != SL_ANDROID_RECORDING_PRESET_NONE) {
    773                 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET,
    774                         &presetValue, sizeof(SLuint32));
    775                 ASSERT_EQ(SL_RESULT_SUCCESS, result);
    776             }
    777             if (performanceMode != -1) {
    778                 SLuint32 performanceMode32 = performanceMode;
    779                 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE,
    780                         &performanceMode32, sizeof(SLuint32));
    781                 ASSERT_EQ(SL_RESULT_SUCCESS, result);
    782             }
    783 
    784         }
    785 
    786         result = (*(pSles->recorderObject))->Realize(pSles->recorderObject, SL_BOOLEAN_FALSE);
    787         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    788 
    789         SLRecordItf recorderRecord;
    790         result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, SL_IID_RECORD,
    791                 &recorderRecord);
    792         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    793 
    794         result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
    795                 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(pSles->recorderBufferQueue));
    796         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    797 
    798         result = (*(pSles->recorderBufferQueue))->RegisterCallback(pSles->recorderBufferQueue,
    799                 recorderCallback, pSles);
    800         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    801 
    802         // Enqueue some empty buffers for the recorder
    803         for (j = 0; j < pSles->rxBufCount; ++j) {
    804 
    805             // allocate a free buffer
    806             ASSERT(pSles->freeFront != pSles->freeRear);
    807             char *buffer = pSles->freeBuffers[pSles->freeFront];
    808             if (++pSles->freeFront > pSles->freeBufCount) {
    809                 pSles->freeFront = 0;
    810             }
    811 
    812             // put on record queue
    813             SLuint32 rxRearNext = pSles->rxRear + 1;
    814             if (rxRearNext > pSles->rxBufCount) {
    815                 rxRearNext = 0;
    816             }
    817             ASSERT(rxRearNext != pSles->rxFront);
    818             pSles->rxBuffers[pSles->rxRear] = buffer;
    819             pSles->rxRear = rxRearNext;
    820             result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue,
    821                     buffer, pSles->bufSizeInBytes);
    822             ASSERT_EQ(SL_RESULT_SUCCESS, result);
    823         }
    824 
    825         // Kick off the recorder
    826         result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING);
    827         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    828 
    829 
    830 
    831         // Tear down the objects and exit
    832         status = STATUS_SUCCESS;
    833         cleanup:
    834 
    835         SLES_PRINTF("Finished initialization with status: %d", status);
    836 
    837     }
    838     return status;
    839 }
    840 
    841 // Read data from fifo2Buffer and store into pSamples.
    842 int slesProcessNext(void *pCtx, double *pSamples, long maxSamples) {
    843     //int status = STATUS_FAIL;
    844     sles_data *pSles = (sles_data*)pCtx;
    845 
    846     SLES_PRINTF("slesProcessNext: pSles = %p, currentSample: %p,  maxSamples = %ld",
    847                 pSles, pSamples, maxSamples);
    848 
    849     int samplesRead = 0;
    850 
    851     int currentSample = 0;
    852     double *pCurrentSample = pSamples;
    853     int maxValue = 32768;
    854 
    855     if (pSles != NULL) {
    856 
    857         SLresult result;
    858         for (int i = 0; i < 10; i++) {
    859             usleep(100000);         // sleep for 0.1s
    860             if (pSles->fifo2Buffer != NULL) {
    861                 for (;;) {
    862                     short buffer[pSles->bufSizeInFrames * pSles->channels];
    863                     ssize_t actual = audio_utils_fifo_read(&(pSles->fifo2), buffer,
    864                             pSles->bufSizeInFrames);
    865                     if (actual <= 0)
    866                         break;
    867                     {
    868                         for (int jj = 0; jj < actual && currentSample < maxSamples; jj++) {
    869                             *(pCurrentSample++) = ((double) buffer[jj]) / maxValue;
    870                             currentSample++;
    871                         }
    872                     }
    873                     samplesRead += actual;
    874                 }
    875             }
    876             if (pSles->injectImpulse > 0) {
    877                 if (pSles->injectImpulse <= 100) {
    878                     pSles->injectImpulse = -1;
    879                     write(1, "I", 1);
    880                 } else {
    881                     if ((pSles->injectImpulse % 1000) < 100) {
    882                         write(1, "i", 1);
    883                     }
    884                     pSles->injectImpulse -= 100;
    885                 }
    886             } else if (i == 9) {
    887                 write(1, ".", 1);
    888             }
    889         }
    890         SLBufferQueueState playerBQState;
    891         result = (*(pSles->playerBufferQueue))->GetState(pSles->playerBufferQueue,
    892                   &playerBQState);
    893         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    894         SLAndroidSimpleBufferQueueState recorderBQState;
    895         result = (*(pSles->recorderBufferQueue))->GetState(pSles->recorderBufferQueue,
    896                   &recorderBQState);
    897         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    898 
    899         SLES_PRINTF("End of slesProcessNext: pSles = %p, samplesRead = %d, maxSamples = %ld",
    900                     pSles, samplesRead, maxSamples);
    901     }
    902     return samplesRead;
    903 }
    904 
    905 
    906 static int slesDestroyServer(sles_data *pSles) {
    907     int status = STATUS_FAIL;
    908 
    909      SLES_PRINTF("Start slesDestroyServer: pSles = %p", pSles);
    910 
    911     if (pSles != NULL) {
    912         if (NULL != pSles->playerObject) {
    913             SLES_PRINTF("stopping player...");
    914             SLPlayItf playerPlay;
    915             SLresult result = (*(pSles->playerObject))->GetInterface(pSles->playerObject,
    916                                                         SL_IID_PLAY, &playerPlay);
    917 
    918             ASSERT_EQ(SL_RESULT_SUCCESS, result);
    919 
    920             //stop player and recorder if they exist
    921              result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED);
    922             ASSERT_EQ(SL_RESULT_SUCCESS, result);
    923         }
    924 
    925         if (NULL != pSles->recorderObject) {
    926             SLES_PRINTF("stopping recorder...");
    927             SLRecordItf recorderRecord;
    928             SLresult result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
    929                                                           SL_IID_RECORD, &recorderRecord);
    930             ASSERT_EQ(SL_RESULT_SUCCESS, result);
    931 
    932             result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
    933             ASSERT_EQ(SL_RESULT_SUCCESS, result);
    934         }
    935 
    936         usleep(1000);
    937 
    938         audio_utils_fifo_deinit(&(pSles->fifo));
    939         delete[] pSles->fifoBuffer;
    940 
    941         SLES_PRINTF("slesDestroyServer 2");
    942 
    943         //        if (sndfile != NULL) {
    944         audio_utils_fifo_deinit(&(pSles->fifo2));
    945         delete[] pSles->fifo2Buffer;
    946 
    947         SLES_PRINTF("slesDestroyServer 3");
    948 
    949         //            sf_close(sndfile);
    950         //        }
    951         if (NULL != pSles->playerObject) {
    952             (*(pSles->playerObject))->Destroy(pSles->playerObject);
    953         }
    954 
    955         SLES_PRINTF("slesDestroyServer 4");
    956 
    957         if (NULL != pSles->recorderObject) {
    958             (*(pSles->recorderObject))->Destroy(pSles->recorderObject);
    959         }
    960 
    961         SLES_PRINTF("slesDestroyServer 5");
    962 
    963         (*(pSles->outputmixObject))->Destroy(pSles->outputmixObject);
    964         SLES_PRINTF("slesDestroyServer 6");
    965         (*(pSles->engineObject))->Destroy(pSles->engineObject);
    966         SLES_PRINTF("slesDestroyServer 7");
    967 
    968         //free buffers
    969         if (NULL != pSles->freeBuffers) {
    970             for (unsigned j = 0; j < pSles->freeBufCount; ++j) {
    971                 if (NULL != pSles->freeBuffers[j]) {
    972                     SLES_PRINTF(" free buff%d at %p",j, pSles->freeBuffers[j]);
    973                     free (pSles->freeBuffers[j]);
    974                 }
    975             }
    976             SLES_PRINTF("  free freeBuffers at %p", pSles->freeBuffers);
    977             free(pSles->freeBuffers);
    978         } else {
    979             SLES_PRINTF("  freeBuffers NULL, no need to free");
    980         }
    981 
    982 
    983         if (NULL != pSles->rxBuffers) {
    984             SLES_PRINTF("  free rxBuffers at %p", pSles->rxBuffers);
    985             free(pSles->rxBuffers);
    986         } else {
    987             SLES_PRINTF("  rxBuffers NULL, no need to free");
    988         }
    989 
    990         if (NULL != pSles->txBuffers) {
    991             SLES_PRINTF("  free txBuffers at %p", pSles->txBuffers);
    992             free(pSles->txBuffers);
    993         } else {
    994             SLES_PRINTF("  txBuffers NULL, no need to free");
    995         }
    996 
    997 
    998         status = STATUS_SUCCESS;
    999     }
   1000     SLES_PRINTF("End slesDestroyServer: status = %d", status);
   1001     return status;
   1002 }
   1003 
   1004 
   1005 int* slesGetRecorderBufferPeriod(void *pCtx) {
   1006     sles_data *pSles = (sles_data*)pCtx;
   1007     return pSles->recorderBufferStats.buffer_period;
   1008 }
   1009 
   1010 int slesGetRecorderMaxBufferPeriod(void *pCtx) {
   1011     sles_data *pSles = (sles_data*)pCtx;
   1012     return pSles->recorderBufferStats.max_buffer_period;
   1013 }
   1014 
   1015 int64_t slesGetRecorderVarianceBufferPeriod(void *pCtx) {
   1016     sles_data *pSles = (sles_data*)pCtx;
   1017     return pSles->recorderBufferStats.var;
   1018 }
   1019 
   1020 int* slesGetPlayerBufferPeriod(void *pCtx) {
   1021     sles_data *pSles = (sles_data*)pCtx;
   1022     return pSles->playerBufferStats.buffer_period;
   1023 }
   1024 
   1025 int slesGetPlayerMaxBufferPeriod(void *pCtx) {
   1026     sles_data *pSles = (sles_data*)pCtx;
   1027     return pSles->playerBufferStats.max_buffer_period;
   1028 }
   1029 
   1030 int64_t slesGetPlayerVarianceBufferPeriod(void *pCtx) {
   1031     sles_data *pSles = (sles_data*)pCtx;
   1032     return pSles->playerBufferStats.var;
   1033 }
   1034 
   1035 int slesGetCaptureRank(void *pCtx) {
   1036     sles_data *pSles = (sles_data*)pCtx;
   1037     // clear the capture flags since they're being handled now
   1038     int recorderRank = android_atomic_exchange(0, &pSles->recorderBufferStats.captureRank);
   1039     int playerRank = android_atomic_exchange(0, &pSles->playerBufferStats.captureRank);
   1040 
   1041     if (recorderRank > playerRank) {
   1042         return recorderRank;
   1043     } else {
   1044         return playerRank;
   1045     }
   1046 }
   1047 
   1048 int slesGetPlayerTimeStampsAndExpectedBufferPeriod(void *pCtx, callbackTimeStamps **ppTSs) {
   1049     sles_data *pSles = (sles_data*)pCtx;
   1050     *ppTSs = &pSles->playerTimeStamps;
   1051     return pSles->expectedBufferPeriod;
   1052 }
   1053 
   1054 int slesGetRecorderTimeStampsAndExpectedBufferPeriod(void *pCtx, callbackTimeStamps **ppTSs) {
   1055     sles_data *pSles = (sles_data*)pCtx;
   1056     *ppTSs = &pSles->recorderTimeStamps;
   1057     return pSles->expectedBufferPeriod;
   1058 }
   1059