Home | History | Annotate | Download | only in audio_loopback
      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 ////////////////////////////////////////////
     19 /// Actual sles functions.
     20 
     21 
     22 // Test program to record from default audio input and playback to default audio output.
     23 // It will generate feedback (Larsen effect) if played through on-device speakers,
     24 // or acts as a delay if played through headset.
     25 
     26 #include "sles.h"
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <stddef.h>
     30 
     31 #include <assert.h>
     32 #include <pthread.h>
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <string.h>
     36 #include <unistd.h>
     37 
     38 int slesInit(sles_data ** ppSles, int samplingRate, int frameCount, int micSource,
     39              int numFramesToIgnore) {
     40     int status = SLES_FAIL;
     41     if (ppSles != NULL) {
     42         sles_data * pSles = (sles_data*) calloc(1, sizeof (sles_data));
     43 
     44         SLES_PRINTF("malloc %zu bytes at %p", sizeof(sles_data), pSles);
     45         *ppSles = pSles;
     46         if (pSles != NULL)
     47         {
     48             SLES_PRINTF("creating server. Sampling rate =%d, frame count = %d",samplingRate,
     49                     frameCount);
     50             status = slesCreateServer(pSles, samplingRate, frameCount, micSource,
     51                                       numFramesToIgnore);
     52             SLES_PRINTF("slesCreateServer =%d", status);
     53         }
     54     }
     55     return status;
     56 }
     57 int slesDestroy(sles_data ** ppSles) {
     58     int status = SLES_FAIL;
     59     if (ppSles != NULL) {
     60         slesDestroyServer(*ppSles);
     61 
     62         if (*ppSles != NULL)
     63         {
     64             free(*ppSles);
     65             *ppSles = 0;
     66         }
     67         status = SLES_SUCCESS;
     68     }
     69     return status;
     70 }
     71 
     72 #define ASSERT_EQ(x, y) do { if ((x) == (y)) ; else { fprintf(stderr, "0x%x != 0x%x\n", \
     73         (unsigned) (x), (unsigned) (y)); assert((x) == (y)); } } while (0)
     74 
     75 
     76 // Called after audio recorder fills a buffer with data
     77 static void recorderCallback(SLAndroidSimpleBufferQueueItf caller __unused, void *context) {
     78     sles_data *pSles = (sles_data*) context;
     79     if (pSles != NULL) {
     80 
     81 
     82 
     83         SLresult result;
     84 
     85         pthread_mutex_lock(&(pSles->mutex));
     86         //ee  SLES_PRINTF("<R");
     87 
     88         // We should only be called when a recording buffer is done
     89         assert(pSles->rxFront <= pSles->rxBufCount);
     90         assert(pSles->rxRear <= pSles->rxBufCount);
     91         assert(pSles->rxFront != pSles->rxRear);
     92         char *buffer = pSles->rxBuffers[pSles->rxFront];
     93 
     94         // Remove buffer from record queue
     95         if (++pSles->rxFront > pSles->rxBufCount) {
     96             pSles->rxFront = 0;
     97         }
     98 
     99         // Throw out first frames
    100         if (pSles->numFramesToIgnore) {
    101             SLuint32 framesToErase = pSles->numFramesToIgnore;
    102             if (framesToErase > pSles->bufSizeInFrames) {
    103                 framesToErase = pSles->bufSizeInFrames;
    104             }
    105             pSles->numFramesToIgnore -= framesToErase;
    106             // FIXME: this assumes each sample is a short
    107             memset(buffer, 0, framesToErase * pSles->channels * sizeof(short));
    108         }
    109 
    110         ssize_t actual = audio_utils_fifo_write(&(pSles->fifo), buffer,
    111                 (size_t) pSles->bufSizeInFrames);
    112         if (actual != (ssize_t) pSles->bufSizeInFrames) {
    113             write(1, "?", 1);
    114         }
    115 
    116         // This is called by a realtime (SCHED_FIFO) thread,
    117         // and it is unsafe to do I/O as it could block for unbounded time.
    118         // Flash filesystem is especially notorious for blocking.
    119         if (pSles->fifo2Buffer != NULL) {
    120             actual = audio_utils_fifo_write(&(pSles->fifo2), buffer,
    121                     (size_t) pSles->bufSizeInFrames);
    122             if (actual != (ssize_t) pSles->bufSizeInFrames) {
    123                 write(1, "?", 1);
    124             }
    125         }
    126 
    127         // Enqueue this same buffer for the recorder to fill again.
    128         result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue, buffer,
    129                 pSles->bufSizeInBytes);
    130         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    131 
    132         // Update our model of the record queue
    133         SLuint32 rxRearNext = pSles->rxRear+1;
    134         if (rxRearNext > pSles->rxBufCount) {
    135             rxRearNext = 0;
    136         }
    137         assert(rxRearNext != pSles->rxFront);
    138         pSles->rxBuffers[pSles->rxRear] = buffer;
    139         pSles->rxRear = rxRearNext;
    140 
    141 
    142 
    143         //ee  SLES_PRINTF("r>");
    144         pthread_mutex_unlock(&(pSles->mutex));
    145 
    146     } //pSles not null
    147 }
    148 
    149 
    150 // Called after audio player empties a buffer of data
    151 static void playerCallback(SLBufferQueueItf caller __unused, void *context) {
    152     sles_data *pSles = (sles_data*) context;
    153     if (pSles != NULL) {
    154 
    155         SLresult result;
    156 
    157         pthread_mutex_lock(&(pSles->mutex));
    158         //ee  SLES_PRINTF("<P");
    159 
    160         // Get the buffer that just finished playing
    161         assert(pSles->txFront <= pSles->txBufCount);
    162         assert(pSles->txRear <= pSles->txBufCount);
    163         assert(pSles->txFront != pSles->txRear);
    164         char *buffer = pSles->txBuffers[pSles->txFront];
    165         if (++pSles->txFront > pSles->txBufCount) {
    166             pSles->txFront = 0;
    167         }
    168 
    169 
    170         ssize_t actual = audio_utils_fifo_read(&(pSles->fifo), buffer, pSles->bufSizeInFrames);
    171         if (actual != (ssize_t) pSles->bufSizeInFrames) {
    172             write(1, "/", 1);
    173             // on underrun from pipe, substitute silence
    174             memset(buffer, 0, pSles->bufSizeInFrames * pSles->channels * sizeof(short));
    175         }
    176 
    177         if (pSles->injectImpulse == -1) {
    178             // Experimentally, a single frame impulse was insufficient to trigger feedback.
    179             // Also a Nyquist frequency signal was also insufficient, probably because
    180             // the response of output and/or input path was not adequate at high frequencies.
    181             // This short burst of a few cycles of square wave at Nyquist/4 was found to work well.
    182             for (unsigned i = 0; i < pSles->bufSizeInFrames / 8; i += 8) {
    183                 for (int j = 0; j < 8; j++) {
    184                     for (unsigned k = 0; k < pSles->channels; k++) {
    185                         ((short *)buffer)[(i+j)*pSles->channels+k] = j < 4 ? 0x7FFF : 0x8000;
    186                     }
    187                 }
    188             }
    189             pSles->injectImpulse = 0;
    190         }
    191 
    192         // Enqueue the filled buffer for playing
    193         result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue, buffer,
    194                 pSles->bufSizeInBytes);
    195         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    196 
    197         // Update our model of the player queue
    198         assert(pSles->txFront <= pSles->txBufCount);
    199         assert(pSles->txRear <= pSles->txBufCount);
    200         SLuint32 txRearNext = pSles->txRear+1;
    201         if (txRearNext > pSles->txBufCount) {
    202             txRearNext = 0;
    203         }
    204         assert(txRearNext != pSles->txFront);
    205         pSles->txBuffers[pSles->txRear] = buffer;
    206         pSles->txRear = txRearNext;
    207 
    208 
    209         //ee    SLES_PRINTF("p>");
    210         pthread_mutex_unlock(&(pSles->mutex));
    211 
    212     } //pSles not null
    213 }
    214 
    215 int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount,
    216                      int micSource, int numFramesToIgnore) {
    217     int status = SLES_FAIL;
    218 
    219     if (pSles == NULL) {
    220         return status;
    221     }
    222 
    223     //        adb shell slesTest_feedback -r1 -t1 -s48000 -f240 -i300 -e3 -o/sdcard/log.wav
    224     //            r1 and t1 are the receive and transmit buffer counts, typically 1
    225     //            s is the sample rate, typically 48000 or 44100
    226     //            f is the frame count per buffer, typically 240 or 256
    227     //            i is the number of milliseconds before impulse.  You may need to adjust this.
    228     //            e is number of seconds to record
    229     //            o is output .wav file name
    230 
    231 
    232     //        // default values
    233     //        SLuint32 rxBufCount = 1;     // -r#
    234     //        SLuint32 txBufCount = 1;     // -t#
    235     //        SLuint32 bufSizeInFrames = 240;  // -f#
    236     //        SLuint32 channels = 1;       // -c#
    237     //        SLuint32 sampleRate = 48000; // -s#
    238     //        SLuint32 exitAfterSeconds = 3; // -e#
    239     //        SLuint32 freeBufCount = 0;   // calculated
    240     //        SLuint32 bufSizeInBytes = 0; // calculated
    241     //        int injectImpulse = 300; // -i#i
    242     //
    243     //        // Storage area for the buffer queues
    244     //        char **rxBuffers;
    245     //        char **txBuffers;
    246     //        char **freeBuffers;
    247     //
    248     //        // Buffer indices
    249     //        SLuint32 rxFront;    // oldest recording
    250     //        SLuint32 rxRear;     // next to be recorded
    251     //        SLuint32 txFront;    // oldest playing
    252     //        SLuint32 txRear;     // next to be played
    253     //        SLuint32 freeFront;  // oldest free
    254     //        SLuint32 freeRear;   // next to be freed
    255     //
    256     //        audio_utils_fifo fifo; //(*)
    257     //        SLAndroidSimpleBufferQueueItf recorderBufferQueue;
    258     //        SLBufferQueueItf playerBufferQueue;
    259 
    260     // default values
    261     pSles->rxBufCount = 1;     // -r#
    262     pSles->txBufCount = 1;     // -t#
    263     pSles->bufSizeInFrames = frameCount;//240;  // -f#
    264     pSles->channels = 1;       // -c#
    265     pSles->sampleRate = samplingRate;//48000; // -s#
    266     pSles->exitAfterSeconds = 3; // -e#
    267     pSles->freeBufCount = 0;   // calculated
    268     pSles->bufSizeInBytes = 0; // calculated
    269     pSles->injectImpulse = 300; // -i#i
    270 
    271     if (numFramesToIgnore > 0) {
    272         pSles->numFramesToIgnore = numFramesToIgnore;
    273     } else {
    274         pSles->numFramesToIgnore = 0;
    275     }
    276 
    277     // Storage area for the buffer queues
    278     //        char **rxBuffers;
    279     //        char **txBuffers;
    280     //        char **freeBuffers;
    281 
    282     // Buffer indices
    283 /*
    284     pSles->rxFront;    // oldest recording
    285     pSles->rxRear;     // next to be recorded
    286     pSles->txFront;    // oldest playing
    287     pSles->txRear;     // next to be played
    288     pSles->freeFront;  // oldest free
    289     pSles->freeRear;   // next to be freed
    290 
    291     pSles->fifo; //(*)
    292 */
    293     pSles->fifo2Buffer = NULL;
    294 
    295     // compute total free buffers as -r plus -t
    296     pSles->freeBufCount = pSles->rxBufCount + pSles->txBufCount;
    297     // compute buffer size
    298     pSles->bufSizeInBytes = pSles->channels * pSles->bufSizeInFrames * sizeof(short);
    299 
    300     // Initialize free buffers
    301     pSles->freeBuffers = (char **) calloc(pSles->freeBufCount+1, sizeof(char *));
    302     unsigned j;
    303     for (j = 0; j < pSles->freeBufCount; ++j) {
    304         pSles->freeBuffers[j] = (char *) malloc(pSles->bufSizeInBytes);
    305     }
    306     pSles->freeFront = 0;
    307     pSles->freeRear = pSles->freeBufCount;
    308     pSles->freeBuffers[j] = NULL;
    309 
    310     // Initialize record queue
    311     pSles->rxBuffers = (char **) calloc(pSles->rxBufCount+1, sizeof(char *));
    312     pSles->rxFront = 0;
    313     pSles->rxRear = 0;
    314 
    315     // Initialize play queue
    316     pSles->txBuffers = (char **) calloc(pSles->txBufCount+1, sizeof(char *));
    317     pSles->txFront = 0;
    318     pSles->txRear = 0;
    319 
    320     size_t frameSize = pSles->channels * sizeof(short);
    321 #define FIFO_FRAMES 1024
    322     pSles->fifoBuffer = new short[FIFO_FRAMES * pSles->channels];
    323     audio_utils_fifo_init(&(pSles->fifo), FIFO_FRAMES, frameSize, pSles->fifoBuffer);
    324 
    325     //        SNDFILE *sndfile;
    326     //        if (outFileName != NULL) {
    327     // create .wav writer
    328     //            SF_INFO info;
    329     //            info.frames = 0;
    330     //            info.samplerate = sampleRate;
    331     //            info.channels = channels;
    332     //            info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
    333     //            sndfile = sf_open(outFileName, SFM_WRITE, &info);
    334     //            if (sndfile != NULL) {
    335 #define FIFO2_FRAMES 65536
    336     pSles->fifo2Buffer = new short[FIFO2_FRAMES * pSles->channels];
    337     audio_utils_fifo_init(&(pSles->fifo2), FIFO2_FRAMES, frameSize, pSles->fifo2Buffer);
    338     //            } else {
    339     //                fprintf(stderr, "sf_open failed\n");
    340     //            }
    341     //        } else {
    342     //            sndfile = NULL;
    343     //        }
    344 
    345     SLresult result;
    346 
    347     // create engine
    348     result = slCreateEngine(&(pSles->engineObject), 0, NULL, 0, NULL, NULL);
    349     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    350     result = (*(pSles->engineObject))->Realize(pSles->engineObject, SL_BOOLEAN_FALSE);
    351     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    352     SLEngineItf engineEngine;
    353     result = (*(pSles->engineObject))->GetInterface(pSles->engineObject, SL_IID_ENGINE,
    354             &engineEngine);
    355     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    356 
    357     // create output mix
    358     result = (*engineEngine)->CreateOutputMix(engineEngine, &(pSles->outputmixObject), 0, NULL,
    359             NULL);
    360     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    361     result = (*(pSles->outputmixObject))->Realize(pSles->outputmixObject, SL_BOOLEAN_FALSE);
    362     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    363 
    364     // create an audio player with buffer queue source and output mix sink
    365     SLDataSource audiosrc;
    366     SLDataSink audiosnk;
    367     SLDataFormat_PCM pcm;
    368     SLDataLocator_OutputMix locator_outputmix;
    369     SLDataLocator_BufferQueue locator_bufferqueue_tx;
    370     locator_bufferqueue_tx.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
    371     locator_bufferqueue_tx.numBuffers = pSles->txBufCount;
    372     locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    373     locator_outputmix.outputMix = pSles->outputmixObject;
    374     pcm.formatType = SL_DATAFORMAT_PCM;
    375     pcm.numChannels = pSles->channels;
    376     pcm.samplesPerSec = pSles->sampleRate * 1000;
    377     pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
    378     pcm.containerSize = 16;
    379     pcm.channelMask = pSles->channels == 1 ? SL_SPEAKER_FRONT_CENTER :
    380             (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
    381     pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
    382     audiosrc.pLocator = &locator_bufferqueue_tx;
    383     audiosrc.pFormat = &pcm;
    384     audiosnk.pLocator = &locator_outputmix;
    385     audiosnk.pFormat = NULL;
    386     pSles->playerObject = NULL;
    387     pSles->recorderObject = NULL;
    388     SLInterfaceID ids_tx[1] = {SL_IID_BUFFERQUEUE};
    389     SLboolean flags_tx[1] = {SL_BOOLEAN_TRUE};
    390     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(pSles->playerObject),
    391             &audiosrc, &audiosnk, 1, ids_tx, flags_tx);
    392     if (SL_RESULT_CONTENT_UNSUPPORTED == result) {
    393         fprintf(stderr, "Could not create audio player (result %x), check sample rate\n",
    394                 result);
    395         SLES_PRINTF("ERROR: Could not create audio player (result %x), check sample rate\n",
    396                 result);
    397         goto cleanup;
    398     }
    399     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    400     result = (*(pSles->playerObject))->Realize(pSles->playerObject, SL_BOOLEAN_FALSE);
    401     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    402     SLPlayItf playerPlay;
    403     result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_PLAY,
    404             &playerPlay);
    405     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    406     result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_BUFFERQUEUE,
    407             &(pSles->playerBufferQueue));
    408     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    409     result = (*(pSles->playerBufferQueue))->RegisterCallback(pSles->playerBufferQueue,
    410             playerCallback, pSles);
    411     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    412 
    413     // Enqueue some zero buffers for the player
    414     for (j = 0; j < pSles->txBufCount; ++j) {
    415 
    416         // allocate a free buffer
    417         assert(pSles->freeFront != pSles->freeRear);
    418         char *buffer = pSles->freeBuffers[pSles->freeFront];
    419         if (++pSles->freeFront > pSles->freeBufCount) {
    420             pSles->freeFront = 0;
    421         }
    422 
    423         // put on play queue
    424         SLuint32 txRearNext = pSles->txRear + 1;
    425         if (txRearNext > pSles->txBufCount) {
    426             txRearNext = 0;
    427         }
    428         assert(txRearNext != pSles->txFront);
    429         pSles->txBuffers[pSles->txRear] = buffer;
    430         pSles->txRear = txRearNext;
    431         result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue,
    432                 buffer, pSles->bufSizeInBytes);
    433         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    434     }
    435 
    436     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
    437     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    438 
    439     // Create an audio recorder with microphone device source and buffer queue sink.
    440     // The buffer queue as sink is an Android-specific extension.
    441 
    442     SLDataLocator_IODevice locator_iodevice;
    443     SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_rx;
    444     locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE;
    445     locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT;
    446     locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
    447     locator_iodevice.device = NULL;
    448     audiosrc.pLocator = &locator_iodevice;
    449     audiosrc.pFormat = NULL;
    450     locator_bufferqueue_rx.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
    451     locator_bufferqueue_rx.numBuffers = pSles->rxBufCount;
    452     audiosnk.pLocator = &locator_bufferqueue_rx;
    453     audiosnk.pFormat = &pcm;
    454     {
    455         SLInterfaceID ids_rx[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
    456                 SL_IID_ANDROIDCONFIGURATION};
    457         SLboolean flags_rx[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    458         result = (*engineEngine)->CreateAudioRecorder(engineEngine, &(pSles->recorderObject),
    459                 &audiosrc, &audiosnk, 2, ids_rx, flags_rx);
    460         if (SL_RESULT_SUCCESS != result) {
    461             fprintf(stderr, "Could not create audio recorder (result %x), "
    462                     "check sample rate and channel count\n", result);
    463             status = SLES_FAIL;
    464 
    465             SLES_PRINTF("ERROR: Could not create audio recorder (result %x), "
    466                     "check sample rate and channel count\n", result);
    467             goto cleanup;
    468         }
    469     }
    470     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    471 
    472     {
    473         /* Get the Android configuration interface which is explicit */
    474         SLAndroidConfigurationItf configItf;
    475         result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
    476                 SL_IID_ANDROIDCONFIGURATION, (void*)&configItf);
    477         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    478         SLuint32 presetValue = micSource;
    479         /* Use the configuration interface to configure the recorder before it's realized */
    480         if (presetValue != SL_ANDROID_RECORDING_PRESET_NONE) {
    481             result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET,
    482                     &presetValue, sizeof(SLuint32));
    483             ASSERT_EQ(SL_RESULT_SUCCESS, result);
    484         }
    485 
    486     }
    487 
    488     result = (*(pSles->recorderObject))->Realize(pSles->recorderObject, SL_BOOLEAN_FALSE);
    489     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    490     SLRecordItf recorderRecord;
    491     result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, SL_IID_RECORD,
    492             &recorderRecord);
    493     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    494     result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
    495             SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(pSles->recorderBufferQueue));
    496     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    497     result = (*(pSles->recorderBufferQueue))->RegisterCallback(pSles->recorderBufferQueue,
    498             recorderCallback, pSles);
    499     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    500 
    501     // Enqueue some empty buffers for the recorder
    502     for (j = 0; j < pSles->rxBufCount; ++j) {
    503 
    504         // allocate a free buffer
    505         assert(pSles->freeFront != pSles->freeRear);
    506         char *buffer = pSles->freeBuffers[pSles->freeFront];
    507         if (++pSles->freeFront > pSles->freeBufCount) {
    508             pSles->freeFront = 0;
    509         }
    510 
    511         // put on record queue
    512         SLuint32 rxRearNext = pSles->rxRear + 1;
    513         if (rxRearNext > pSles->rxBufCount) {
    514             rxRearNext = 0;
    515         }
    516         assert(rxRearNext != pSles->rxFront);
    517         pSles->rxBuffers[pSles->rxRear] = buffer;
    518         pSles->rxRear = rxRearNext;
    519         result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue,
    520                 buffer, pSles->bufSizeInBytes);
    521         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    522     }
    523 
    524     // Kick off the recorder
    525     result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING);
    526     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    527 
    528     // Tear down the objects and exit
    529     status = SLES_SUCCESS;
    530     cleanup:
    531     SLES_PRINTF("Finished initialization with status: %d", status);
    532 
    533     return status;
    534 }
    535 
    536 int slesProcessNext(sles_data *pSles, double *pSamples, long maxSamples) {
    537     //int status = SLES_FAIL;
    538 
    539     SLES_PRINTF("slesProcessNext: pSles = %p, currentSample: %p,  maxSamples = %ld", pSles,
    540             pSamples, maxSamples);
    541 
    542     int samplesRead = 0;
    543 
    544     int currentSample = 0;
    545     double *pCurrentSample = pSamples;
    546     int maxValue = 32768;
    547 
    548     if (pSles == NULL) {
    549         return samplesRead;
    550     }
    551 
    552     SLresult result;
    553     for (int i = 0; i < 10; i++) {
    554         usleep(100000);
    555         if (pSles->fifo2Buffer != NULL) {
    556             for (;;) {
    557                 short buffer[pSles->bufSizeInFrames * pSles->channels];
    558                 ssize_t actual = audio_utils_fifo_read(&(pSles->fifo2), buffer,
    559                         pSles->bufSizeInFrames);
    560                 if (actual <= 0)
    561                     break;
    562                 {
    563                     for (int jj =0; jj<actual && currentSample < maxSamples; jj++) {
    564                         *(pCurrentSample++) = ((double)buffer[jj])/maxValue;
    565                         currentSample++;
    566                     }
    567                 }
    568                 samplesRead +=actual;
    569             }
    570         }
    571         if (pSles->injectImpulse > 0) {
    572             if (pSles->injectImpulse <= 100) {
    573                 pSles->injectImpulse = -1;
    574                 write(1, "I", 1);
    575             } else {
    576                 if ((pSles->injectImpulse % 1000) < 100) {
    577                     write(1, "i", 1);
    578                 }
    579                 pSles->injectImpulse -= 100;
    580             }
    581         } else if (i == 9) {
    582             write(1, ".", 1);
    583         }
    584     }
    585     SLBufferQueueState playerBQState;
    586     result = (*(pSles->playerBufferQueue))->GetState(pSles->playerBufferQueue,
    587             &playerBQState);
    588     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    589     SLAndroidSimpleBufferQueueState recorderBQState;
    590     result = (*(pSles->recorderBufferQueue))->GetState(pSles->recorderBufferQueue,
    591             &recorderBQState);
    592     ASSERT_EQ(SL_RESULT_SUCCESS, result);
    593 
    594     SLES_PRINTF("End of slesProcessNext: pSles = %p, samplesRead = %d, maxSamples= %ld", pSles,
    595             samplesRead, maxSamples);
    596 
    597     return samplesRead;
    598 }
    599 
    600 int slesDestroyServer(sles_data *pSles) {
    601     int status = SLES_FAIL;
    602 
    603     SLES_PRINTF("Start slesDestroyServer: pSles = %p", pSles);
    604     if (pSles == NULL) {
    605         return status;
    606     }
    607 
    608     if (NULL != pSles->playerObject) {
    609 
    610         SLES_PRINTF("stopping player...");
    611         SLPlayItf playerPlay;
    612         SLresult result = (*(pSles->playerObject))->GetInterface(pSles->playerObject,
    613                 SL_IID_PLAY, &playerPlay);
    614 
    615         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    616 
    617         //stop player and recorder if they exist
    618         result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED);
    619         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    620     }
    621 
    622     if (NULL != pSles->recorderObject) {
    623         SLES_PRINTF("stopping recorder...");
    624         SLRecordItf recorderRecord;
    625         SLresult result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
    626                 SL_IID_RECORD, &recorderRecord);
    627         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    628 
    629         result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
    630         ASSERT_EQ(SL_RESULT_SUCCESS, result);
    631     }
    632 
    633     usleep(1000);
    634 
    635     audio_utils_fifo_deinit(&(pSles->fifo));
    636     delete[] pSles->fifoBuffer;
    637 
    638     SLES_PRINTF("slesDestroyServer 2");
    639 
    640     //        if (sndfile != NULL) {
    641     audio_utils_fifo_deinit(&(pSles->fifo2));
    642     delete[] pSles->fifo2Buffer;
    643 
    644     SLES_PRINTF("slesDestroyServer 3");
    645 
    646     //            sf_close(sndfile);
    647     //        }
    648     if (NULL != pSles->playerObject) {
    649         (*(pSles->playerObject))->Destroy(pSles->playerObject);
    650     }
    651 
    652     SLES_PRINTF("slesDestroyServer 4");
    653 
    654     if (NULL != pSles->recorderObject) {
    655         (*(pSles->recorderObject))->Destroy(pSles->recorderObject);
    656     }
    657 
    658     SLES_PRINTF("slesDestroyServer 5");
    659 
    660     (*(pSles->outputmixObject))->Destroy(pSles->outputmixObject);
    661     SLES_PRINTF("slesDestroyServer 6");
    662     (*(pSles->engineObject))->Destroy(pSles->engineObject);
    663     SLES_PRINTF("slesDestroyServer 7");
    664 
    665     //        free(pSles);
    666     //        pSles=NULL;
    667 
    668     status = SLES_SUCCESS;
    669 
    670     SLES_PRINTF("End slesDestroyServer: status = %d", status);
    671     return status;
    672 }
    673 
    674