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