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