Home | History | Annotate | Download | only in jni
      1 /*
      2  *  snd_android.c
      3  *  Android-specific sound interface
      4  *
      5  */
      6 
      7 #include "quakedef.h"
      8 
      9 #include <pthread.h>
     10 #include <time.h>
     11 #include <math.h>
     12 #include <stdlib.h>
     13 #include <unistd.h>
     14 
     15 #include <android/log.h>
     16 #include <SLES/OpenSLES.h>
     17 
     18 #define LOG_TAG "Quake snd_android"
     19 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
     20 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
     21 
     22 const size_t SAMPLE_RATE = 11025;
     23 
     24 
     25 const size_t BYTES_PER_SAMPLE = 2;
     26 const size_t CHANNEL_COUNT = 2;
     27 const size_t BITS_PER_SAMPLE = 8 * BYTES_PER_SAMPLE;
     28 
     29 const size_t TOTAL_BUFFER_SIZE = 4 * 1024;
     30 
     31 #define MAX_NUMBER_INTERFACES 3
     32 
     33 /* Local storage for Audio data in 16 bit words */
     34 #define AUDIO_DATA_STORAGE_SIZE (TOTAL_BUFFER_SIZE / 2)
     35 /* Audio data buffer size in 16 bit words. 8 data segments are used in
     36 this simple example */
     37 #define AUDIO_DATA_BUFFER_SIZE (4096/8)
     38 
     39 const size_t NUMBER_OF_BUFFERS = AUDIO_DATA_STORAGE_SIZE / AUDIO_DATA_BUFFER_SIZE;
     40 
     41 /* Checks for error. If any errors exit the application! */
     42 void CheckErr( SLresult res )
     43 {
     44     if ( res != SL_RESULT_SUCCESS )
     45         {
     46             fprintf(stdout, "%u SL failure, exiting\n", res);
     47             exit(EXIT_FAILURE);
     48         }
     49     else {
     50         //fprintf(stdout, "%d SL success, proceeding...\n", res);
     51     }
     52 }
     53 
     54 /* Structure for passing information to callback function */
     55 typedef struct CallbackCntxt_ {
     56     SLPlayItf  playItf;
     57     SLint16*   pDataBase;    // Base adress of local audio data storage
     58     SLint16*   pData;        // Current adress of local audio data storage
     59     SLuint32   size;
     60 } CallbackCntxt;
     61 
     62 /* Local storage for Audio data */
     63 SLint16 pcmData[AUDIO_DATA_STORAGE_SIZE];
     64 
     65 /* Callback for Buffer Queue events */
     66 void BufferQueueCallback(
     67         SLBufferQueueItf queueItf,
     68         void *pContext)
     69 {
     70     //fprintf(stdout, "BufferQueueCallback called\n");
     71     SLresult res;
     72     //fprintf(stdout, " pContext=%p\n", pContext);
     73     CallbackCntxt *pCntxt = (CallbackCntxt*)pContext;
     74 
     75     if (pCntxt->pData >= (pCntxt->pDataBase + pCntxt->size)) {
     76         pCntxt->pData = pCntxt->pDataBase;
     77     }
     78     {
     79         //fprintf(stdout, "callback: before enqueue\n");
     80         res = (*queueItf)->Enqueue(queueItf, (void*) pCntxt->pData,
     81                 2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
     82         CheckErr(res);
     83         /* Increase data pointer by buffer size */
     84         pCntxt->pData += AUDIO_DATA_BUFFER_SIZE;
     85     }
     86     //fprintf(stdout, "end of BufferQueueCallback()\n");
     87 }
     88 
     89 SLEngineItf                EngineItf;
     90 
     91 SLint32                    numOutputs = 0;
     92 SLuint32                   deviceID = 0;
     93 
     94 
     95 SLDataSource               audioSource;
     96 SLDataLocator_BufferQueue  bufferQueue;
     97 SLDataFormat_PCM           pcm;
     98 
     99 SLDataSink                 audioSink;
    100 SLDataLocator_OutputMix    locator_outputmix;
    101 
    102 
    103 SLVolumeItf                volumeItf;
    104 
    105 
    106 SLboolean required[MAX_NUMBER_INTERFACES];
    107 SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
    108 
    109 /* Callback context for the buffer queue callback function */
    110 CallbackCntxt cntxt;
    111 
    112 static SLObjectItf                OutputMix;
    113 static SLPlayItf                  playItf;
    114 static SLObjectItf                player;
    115 static SLBufferQueueItf           bufferQueueItf;
    116 static SLBufferQueueState         state;
    117 
    118 /* Play some audio from a buffer queue  */
    119 void TestPlaySawtoothBufferQueue( SLObjectItf sl )
    120 {
    121     SLresult                   res;
    122     int                        i;
    123 
    124     /* Get the SL Engine Interface which is implicit */
    125     res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
    126     CheckErr(res);
    127 
    128     /* Initialize arrays required[] and iidArray[] */
    129     for (i=0;i<MAX_NUMBER_INTERFACES;i++)
    130         {
    131             required[i] = SL_BOOLEAN_FALSE;
    132             iidArray[i] = SL_IID_NULL;
    133         }
    134 
    135     // Set arrays required[] and iidArray[] for VOLUME interface
    136     required[0] = SL_BOOLEAN_TRUE;
    137     iidArray[0] = SL_IID_VOLUME;
    138     // Create Output Mix object to be used by player
    139     res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0,
    140             iidArray, required); CheckErr(res);
    141 
    142     // Realizing the Output Mix object in synchronous mode.
    143     res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE);
    144     CheckErr(res);
    145 
    146 #if 0
    147     res = (*OutputMix)->GetInterface(OutputMix, SL_IID_VOLUME,
    148             (void*)&volumeItf); CheckErr(res);
    149 #endif
    150 
    151     /* Setup the data source structure for the buffer queue */
    152     bufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
    153     bufferQueue.numBuffers = 4;  /* Four buffers in our buffer queue */
    154 
    155     /* Setup the format of the content in the buffer queue */
    156     pcm.formatType = SL_DATAFORMAT_PCM;
    157     pcm.numChannels = 2;
    158     pcm.samplesPerSec = SL_SAMPLINGRATE_11_025;
    159     pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
    160     pcm.containerSize = 16;
    161     pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
    162     pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
    163 
    164     audioSource.pFormat      = (void *)&pcm;
    165     audioSource.pLocator     = (void *)&bufferQueue;
    166 
    167     /* Setup the data sink structure */
    168     locator_outputmix.locatorType   = SL_DATALOCATOR_OUTPUTMIX;
    169     locator_outputmix.outputMix    = OutputMix;
    170     audioSink.pLocator           = (void *)&locator_outputmix;
    171     audioSink.pFormat            = NULL;
    172 
    173     /* Initialize the audio data to silence */
    174     memset(pcmData, 0, sizeof(pcmData));
    175 
    176     /* Initialize the context for Buffer queue callbacks */
    177     cntxt.pDataBase = /*(void*)&*/pcmData;
    178     cntxt.pData = cntxt.pDataBase;
    179     cntxt.size = sizeof(pcmData) / 2;
    180 
    181     /* Set arrays required[] and iidArray[] for SEEK interface
    182           (PlayItf is implicit) */
    183     required[0] = SL_BOOLEAN_TRUE;
    184     iidArray[0] = SL_IID_BUFFERQUEUE;
    185 
    186     /* Create the music player */
    187     res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player,
    188             &audioSource, &audioSink, 1, iidArray, required); CheckErr(res);
    189     fprintf(stdout, "bufferQueue example: after CreateAudioPlayer\n");
    190 
    191     /* Realizing the player in synchronous mode. */
    192     res = (*player)->Realize(player, SL_BOOLEAN_FALSE); CheckErr(res);
    193     fprintf(stdout, "bufferQueue example: after Realize\n");
    194 
    195     /* Get seek and play interfaces */
    196     res = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
    197     CheckErr(res);
    198     fprintf(stdout, "bufferQueue example: after GetInterface(PLAY)\n");
    199 
    200     res = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE,
    201             (void*)&bufferQueueItf); CheckErr(res);
    202 
    203     /* Setup to receive buffer queue event callbacks */
    204     res = (*bufferQueueItf)->RegisterCallback(bufferQueueItf,
    205             BufferQueueCallback, &cntxt); CheckErr(res);
    206 
    207 #if 0
    208     /* Before we start set volume to -3dB (-300mB) */
    209     res = (*volumeItf)->SetVolumeLevel(volumeItf, -300); CheckErr(res);
    210 #endif
    211 
    212     /* Enqueue a few buffers to get the ball rolling */
    213     res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData,
    214             2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
    215     CheckErr(res);
    216     cntxt.pData += AUDIO_DATA_BUFFER_SIZE;
    217 
    218     res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData,
    219             2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
    220     CheckErr(res);
    221     cntxt.pData += AUDIO_DATA_BUFFER_SIZE;
    222 
    223     res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData,
    224             2 * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
    225     CheckErr(res);
    226     cntxt.pData += AUDIO_DATA_BUFFER_SIZE;
    227 
    228     /* Play the PCM samples using a buffer queue */
    229     fprintf(stdout, "bufferQueue example: starting to play\n");
    230     res = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PLAYING );
    231     CheckErr(res);
    232 
    233     /* Wait until the PCM data is done playing, the buffer queue callback
    234            will continue to queue buffers until the entire PCM data has been
    235            played. This is indicated by waiting for the count member of the
    236            SLBufferQueueState to go to zero.
    237      */
    238     res = (*bufferQueueItf)->GetState(bufferQueueItf, &state);
    239     CheckErr(res);
    240 
    241 #if 0
    242     // while (state.playIndex < 100) {
    243     while (state.count) {
    244         usleep(10000);
    245         (*bufferQueueItf)->GetState(bufferQueueItf, &state);
    246     }
    247 
    248  #endif
    249 }
    250 
    251 SLObjectItf gSoundEngine;
    252 
    253 int startAndroidSound()
    254 {
    255     SLresult    res;
    256 
    257     SLEngineOption EngineOption[] = {
    258             {(SLuint32) SL_ENGINEOPTION_THREADSAFE,
    259             (SLuint32) SL_BOOLEAN_TRUE}};
    260 
    261     res = slCreateEngine( &gSoundEngine, 1, EngineOption, 0, NULL, NULL);
    262     CheckErr(res);
    263     /* Realizing the SL Engine in synchronous mode. */
    264     res = (*gSoundEngine)->Realize(gSoundEngine, SL_BOOLEAN_FALSE); CheckErr(res);
    265 
    266     /* Run the test */
    267     TestPlaySawtoothBufferQueue(gSoundEngine);
    268     return EXIT_SUCCESS;
    269 }
    270 
    271 void finishAndroidSound()
    272 {
    273     SLresult                   res;
    274 
    275     if (gSoundEngine == NULL) {
    276         return;
    277     }
    278 
    279     /* Make sure player is stopped */
    280     if (playItf != NULL) {
    281          res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
    282          CheckErr(res);
    283          playItf = NULL;
    284     }
    285 
    286     if (player != NULL) {
    287          /* Destroy the player */
    288          (*player)->Destroy(player);
    289          player = NULL;
    290     }
    291 
    292     if (OutputMix != NULL) {
    293         /* Destroy Output Mix object */
    294         (*OutputMix)->Destroy(OutputMix);
    295         OutputMix = NULL;
    296     }
    297 
    298     /* Shutdown OpenSL ES */
    299     (*gSoundEngine)->Destroy(gSoundEngine);
    300     gSoundEngine = NULL;
    301 }
    302 
    303 #if 1
    304 
    305 /*
    306 ==================
    307 SNDDMA_Init
    308 
    309 Try to find a sound device to mix for.
    310 Returns false if nothing is found.
    311 ==================
    312 */
    313 qboolean SNDDMA_Init(void)
    314 {
    315     // Initialize Quake's idea of a DMA buffer.
    316 
    317     shm = &sn;
    318     memset((void*)&sn, 0, sizeof(sn));
    319 
    320     shm->splitbuffer = false;	// Not used.
    321     shm->samplebits = 16;
    322     shm->speed = 11025;
    323     shm->channels = 2;
    324     shm->samples = TOTAL_BUFFER_SIZE / BYTES_PER_SAMPLE;
    325     shm->samplepos = 0; // Not used.
    326     shm->buffer = (unsigned char*) pcmData;
    327     shm->submission_chunk = 1; // Not used.
    328 
    329     shm->soundalive = true;
    330 
    331     if ( (shm->samples & 0x1ff) != 0 ) {
    332       LOGE("SNDDDMA_Init: samples must be power of two.");
    333       return false;
    334     }
    335 
    336     if ( shm->buffer == 0 ) {
    337       LOGE("SNDDDMA_Init: Could not allocate sound buffer.");
    338       return false;
    339     }
    340 
    341     int result = startAndroidSound();
    342     return result == EXIT_SUCCESS;
    343 }
    344 
    345 /*
    346 ==============
    347 SNDDMA_GetDMAPos
    348 
    349 return the current sample position (in mono samples read)
    350 inside the recirculating dma buffer, so the mixing code will know
    351 how many sample are required to fill it up.
    352 ===============
    353 */
    354 int SNDDMA_GetDMAPos(void)
    355 {
    356     SLresult                   res;
    357     if (bufferQueueItf != NULL) {
    358         res = (*bufferQueueItf)->GetState(bufferQueueItf, &state);
    359         CheckErr(res);
    360         // Index of the currently playing or filling buffer.
    361         SLuint32 playIndex = state.playIndex;
    362         int ringIndex = playIndex % NUMBER_OF_BUFFERS;
    363         return ringIndex * AUDIO_DATA_BUFFER_SIZE;
    364     }
    365     return 0;
    366 }
    367 
    368 /*
    369 ===============
    370 SNDDMA_ReportWrite
    371 
    372 Report valid data being written into the DMA buffer by the sound mixing code.
    373 This is an Android specific API.
    374 ================
    375 */
    376 void SNDDMA_ReportWrite(size_t lengthBytes) {
    377     // TODO: keep track of how much of the sound ring buffer has sound in it,
    378     // detect starvation, and mix silence when we are starving.
    379 }
    380 
    381 /*
    382 ==============
    383 SNDDMA_Submit
    384 
    385 Send sound to device if buffer isn't really the dma buffer
    386 ===============
    387 */
    388 void SNDDMA_Submit(void)
    389 {
    390 }
    391 
    392 /*
    393 ==============
    394 SNDDMA_Shutdown
    395 
    396 Reset the sound device for exiting
    397 ===============
    398 */
    399 void SNDDMA_Shutdown(void)
    400 {
    401     finishAndroidSound();
    402 }
    403 
    404 
    405 #else
    406 
    407 // Written by the callback function running in an audio thread.
    408 // index in bytes of where we last read.
    409 
    410 static volatile size_t gDMAByteIndex;
    411 
    412 
    413 // Written by main thread
    414 static size_t gAvailableBytes;
    415 static bool gSoundMixingStarted;
    416 
    417 // The condition is "new data is now available"
    418 
    419 static pthread_mutex_t condition_mutex = PTHREAD_MUTEX_INITIALIZER;
    420 static pthread_cond_t  condition_cond  = PTHREAD_COND_INITIALIZER;
    421 
    422 /*
    423 ==================
    424 SNDDMA_Init
    425 
    426 Try to find a sound device to mix for.
    427 Returns false if nothing is found.
    428 ==================
    429 */
    430 
    431 
    432 const size_t SAMPLE_RATE = 11025;
    433 
    434 
    435 const size_t BYTES_PER_SAMPLE = 2;
    436 const size_t CHANNEL_COUNT = 2;
    437 const size_t BITS_PER_SAMPLE = 8 * BYTES_PER_SAMPLE;
    438 
    439 const size_t TOTAL_BUFFER_SIZE = 16 * 1024;
    440 
    441 static size_t min(size_t a, size_t b) {
    442   return a < b ? a : b;
    443 }
    444 
    445 static size_t mod(size_t value, size_t mod) {
    446   return value % mod;
    447 }
    448 
    449 static size_t next(size_t value, size_t mod) {
    450   value = value + 1;
    451   if ( value >= mod ) {
    452     value = 0;
    453   }
    454   return value;
    455 }
    456 
    457 static size_t prev(size_t value, size_t mod) {
    458   if ( value <= 0 ) {
    459     value = mod;
    460   }
    461   return value - 1;
    462 }
    463 
    464 
    465 static bool enableSound() {
    466 
    467     if (COM_CheckParm("-nosound"))
    468         return false;
    469 
    470   return true;
    471 }
    472 
    473 // Choose one:
    474 
    475 // #define GENERATE_SINE_WAVE
    476 #define NORMAL_SOUND
    477 
    478 #ifdef GENERATE_SINE_WAVE
    479 
    480 static const float p = 2 * M_PI * 440.0f / SAMPLE_RATE;
    481 static float left = 0.0f;
    482 static float right = 0.0f;
    483 
    484 static float sinef(float x)
    485 {
    486     const float A =   1.0f / (2.0f*M_PI);
    487     const float B = -16.0f;
    488     const float C =   8.0f;
    489 
    490     // scale angle for easy argument reduction
    491     x *= A;
    492 
    493     if (fabsf(x) >= 0.5f) {
    494         // Argument reduction
    495         x = x - ceilf(x + 0.5f) + 1.0f;
    496     }
    497 
    498     const float y = B*x*fabsf(x) + C*x;
    499     return 0.2215f * (y*fabsf(y) - y) + y;
    500 }
    501 
    502 static
    503 void AndroidQuakeSoundCallback(int event, void* user, void *info) {
    504 
    505     if (event != AudioTrack::EVENT_MORE_DATA) return;
    506 
    507     const AudioTrack::Buffer *buffer = static_cast<const AudioTrack::Buffer *>(info);
    508     size_t bytesToCopy = buffer->size;
    509     size_t framesToCopy = buffer->size / (BYTES_PER_SAMPLE * CHANNEL_COUNT);
    510     short* pData = buffer->i16;
    511 
    512     for(size_t frame = 0; frame < framesToCopy; frame++) {
    513         short leftSample = (short) (32767.0f * sinef(left));
    514         left += p;
    515         if (left > 2*M_PI) {
    516             left -= 2*M_PI;
    517         }
    518         pData[frame * CHANNEL_COUNT] = leftSample;
    519 
    520         short rightSample = (short) (32767.0f * sinef(right));
    521         right += 2 * p;
    522         if (right > 2*M_PI) {
    523             right -= 2*M_PI;
    524         }
    525         pData[1 + frame * CHANNEL_COUNT] = rightSample;
    526     }
    527 
    528     gDMAByteIndex = mod(gDMAByteIndex + bytesToCopy, TOTAL_BUFFER_SIZE);
    529     asm volatile ("":::"memory");
    530 }
    531 
    532 #endif
    533 
    534 #ifdef NORMAL_SOUND
    535 
    536 static bool gWaitingForMixerToRestart;
    537 
    538 // Assumes the mutex is acquired.
    539 // Waits until audio is available or a time period has elapsed.
    540 static bool shouldMixSilence() {
    541   if (!gSoundMixingStarted) {
    542     return true;
    543   }
    544     while (gAvailableBytes == 0) {
    545       if (gWaitingForMixerToRestart) {
    546         return true;
    547       }
    548         timeval tp;
    549         if (gettimeofday(&tp, NULL)) {
    550           return true;
    551         }
    552      const long WAIT_NS = 40 * 1000 * 1000;
    553      const long NS_PER_SECOND = 1000 * 1000 * 1000;
    554      timespec ts;
    555      ts.tv_sec  = tp.tv_sec;
    556      ts.tv_nsec = tp.tv_usec * 1000 + WAIT_NS;
    557      if (ts.tv_nsec >= NS_PER_SECOND) {
    558        ts.tv_nsec -= NS_PER_SECOND;
    559        ts.tv_sec += 1;
    560      }
    561      if (ETIMEDOUT == pthread_cond_timedwait( &condition_cond,  &condition_mutex, &ts)) {
    562        gWaitingForMixerToRestart = true;
    563        return true;
    564      }
    565     }
    566     gWaitingForMixerToRestart = false;
    567     return false;
    568 }
    569 
    570 static
    571 void AndroidQuakeSoundCallback(int event, void* user, void *info) {
    572 
    573     if (event != AudioTrack::EVENT_MORE_DATA) return;
    574 
    575     const AudioTrack::Buffer *buffer = static_cast<const AudioTrack::Buffer *>(info);
    576     size_t dmaByteIndex = gDMAByteIndex;
    577     size_t size = buffer->size;
    578     unsigned char* pDestBuffer = (unsigned char*) buffer->raw;
    579 
    580     if (size == 0) return;
    581 
    582     if ( ! shm ) {
    583         memset(pDestBuffer, 0, size);
    584         return;
    585     }
    586 
    587     const unsigned char* pSrcBuffer = shm->buffer;
    588 
    589     while(size > 0) {
    590         pthread_mutex_lock( &condition_mutex );
    591 
    592         if (shouldMixSilence()) {
    593           memset(pDestBuffer, 0, size);
    594           pthread_mutex_unlock( &condition_mutex );
    595           return;
    596         }
    597 
    598         size_t chunkSize = min(gAvailableBytes, min(TOTAL_BUFFER_SIZE-dmaByteIndex, size));
    599         gAvailableBytes -= chunkSize;
    600 
    601         pthread_mutex_unlock( &condition_mutex );
    602 
    603     memcpy(pDestBuffer, pSrcBuffer + dmaByteIndex, chunkSize);
    604     size -= chunkSize;
    605     pDestBuffer += chunkSize;
    606     dmaByteIndex += chunkSize;
    607     if (dmaByteIndex >= TOTAL_BUFFER_SIZE) {
    608       dmaByteIndex = 0;
    609     }
    610   }
    611 
    612   gDMAByteIndex = dmaByteIndex;
    613   asm volatile ("":::"memory");
    614 }
    615 
    616 #endif
    617 
    618 qboolean SNDDMA_Init(void)
    619 {
    620   if ( ! enableSound() ) {
    621     return false;
    622   }
    623 
    624   gDMAByteIndex = 0;
    625 
    626   // Initialize the AudioTrack.
    627 
    628   status_t result = gAudioTrack.set(
    629     AUDIO_STREAM_DEFAULT, // stream type
    630     SAMPLE_RATE,   // sample rate
    631     BITS_PER_SAMPLE == 16 ? AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_8_BIT,      // format (8 or 16)
    632     (CHANNEL_COUNT > 1) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO,       // channel mask
    633     0,       // default buffer size
    634     0, // flags
    635     AndroidQuakeSoundCallback, // callback
    636     0,  // user
    637     0); // default notification size
    638 
    639   LOGI("AudioTrack status  = %d (%s)\n", result, result == NO_ERROR ? "success" : "error");
    640 
    641   if ( result == NO_ERROR ) {
    642     LOGI("AudioTrack latency = %u ms\n", gAudioTrack.latency());
    643     LOGI("AudioTrack format = %u bits\n", gAudioTrack.format() == AUDIO_FORMAT_PCM_16_BIT ? 16 : 8);
    644     LOGI("AudioTrack sample rate = %u Hz\n", gAudioTrack.getSampleRate());
    645     LOGI("AudioTrack frame count = %d\n", int(gAudioTrack.frameCount()));
    646     LOGI("AudioTrack channel count = %d\n", gAudioTrack.channelCount());
    647 
    648     // Initialize Quake's idea of a DMA buffer.
    649 
    650     shm = &sn;
    651     memset((void*)&sn, 0, sizeof(sn));
    652 
    653     shm->splitbuffer = false;	// Not used.
    654     shm->samplebits = gAudioTrack.format() == AUDIO_FORMAT_PCM_16_BIT ? 16 : 8;
    655     shm->speed = gAudioTrack.getSampleRate();
    656     shm->channels = gAudioTrack.channelCount();
    657     shm->samples = TOTAL_BUFFER_SIZE / BYTES_PER_SAMPLE;
    658     shm->samplepos = 0; // Not used.
    659     shm->buffer = (unsigned char*) Hunk_AllocName(TOTAL_BUFFER_SIZE, (char*) "shmbuf");
    660     shm->submission_chunk = 1; // Not used.
    661 
    662     shm->soundalive = true;
    663 
    664     if ( (shm->samples & 0x1ff) != 0 ) {
    665       LOGE("SNDDDMA_Init: samples must be power of two.");
    666       return false;
    667     }
    668 
    669     if ( shm->buffer == 0 ) {
    670       LOGE("SNDDDMA_Init: Could not allocate sound buffer.");
    671       return false;
    672     }
    673 
    674     gAudioTrack.setVolume(1.0f, 1.0f);
    675     gAudioTrack.start();
    676   }
    677 
    678   return result == NO_ERROR;
    679 }
    680 
    681 /*
    682 ==============
    683 SNDDMA_GetDMAPos
    684 
    685 return the current sample position (in mono samples read)
    686 inside the recirculating dma buffer, so the mixing code will know
    687 how many sample are required to fill it up.
    688 ===============
    689 */
    690 int SNDDMA_GetDMAPos(void)
    691 {
    692   int dmaPos = gDMAByteIndex / BYTES_PER_SAMPLE;
    693   asm volatile ("":::"memory");
    694   return dmaPos;
    695 }
    696 
    697 /*
    698 ===============
    699 SNDDMA_ReportWrite
    700 
    701 Report valid data being written into the DMA buffer by the sound mixing code.
    702 This is an Android specific API.
    703 ================
    704 */
    705 void SNDDMA_ReportWrite(size_t lengthBytes) {
    706     pthread_mutex_lock( &condition_mutex );
    707     gSoundMixingStarted = true;
    708     if (gAvailableBytes == 0) {
    709         pthread_cond_signal( &condition_cond );
    710     }
    711     gAvailableBytes += lengthBytes;
    712     pthread_mutex_unlock( &condition_mutex );
    713 }
    714 
    715 /*
    716 ==============
    717 SNDDMA_Submit
    718 
    719 Send sound to device if buffer isn't really the dma buffer
    720 ===============
    721 */
    722 void SNDDMA_Submit(void)
    723 {
    724 }
    725 
    726 /*
    727 ==============
    728 SNDDMA_Shutdown
    729 
    730 Reset the sound device for exiting
    731 ===============
    732 */
    733 void SNDDMA_Shutdown(void)
    734 {
    735   gAudioTrack.stop();
    736 }
    737 
    738 #endif
    739