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