1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* interactive buffer queue test program */ 18 19#ifdef ANDROID 20#define USE_ANDROID_SIMPLE_BUFFER_QUEUE // change to #undef for compatibility testing 21#endif 22 23#include <assert.h> 24#include <math.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <unistd.h> 28#include <SLES/OpenSLES.h> 29#ifdef USE_ANDROID_SIMPLE_BUFFER_QUEUE 30#include <SLES/OpenSLES_Android.h> 31#endif 32#include "getch.h" 33 34#ifdef USE_ANDROID_SIMPLE_BUFFER_QUEUE 35#define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE 36#define IID_BUFFERQUEUE SL_IID_ANDROIDSIMPLEBUFFERQUEUE 37#define BufferQueueItf SLAndroidSimpleBufferQueueItf 38#define BufferQueueState SLAndroidSimpleBufferQueueState 39#define INDEX index 40#else 41#define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_BUFFERQUEUE 42#define IID_BUFFERQUEUE SL_IID_BUFFERQUEUE 43#define BufferQueueItf SLBufferQueueItf 44#define BufferQueueState SLBufferQueueState 45#define INDEX playIndex 46#endif 47 48#define checkResult(r) do { if ((r) != SL_RESULT_SUCCESS) fprintf(stderr, "error %d at %s:%d\n", \ 49 (int) r, __FILE__, __LINE__); } while (0) 50 51typedef struct { 52 short left; 53 short right; 54} frame_t; 55 56#define SINE_FRAMES (44100*5) 57frame_t sine[SINE_FRAMES]; 58 59#define SQUARE_FRAMES (44100*5) 60frame_t square[SQUARE_FRAMES]; 61 62#define SAWTOOTH_FRAMES (44100*5) 63frame_t sawtooth[SAWTOOTH_FRAMES]; 64 65#define HALF_FRAMES (44100*5) 66frame_t half[HALF_FRAMES]; 67 68BufferQueueItf expectedCaller = NULL; 69void *expectedContext = NULL; 70 71static void callback(BufferQueueItf caller, void *context) 72{ 73 putchar('.'); 74 if (caller != expectedCaller) 75 printf("caller %p expected %p\r\n", caller, expectedCaller); 76 if (context != expectedContext) 77 printf("context %p expected %p\r\n", context, expectedContext); 78 fflush(stdout); 79} 80 81int main(int argc, char **argv) 82{ 83 SLresult result; 84 85 // create engine 86 SLObjectItf engineObject; 87 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 88 checkResult(result); 89 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 90 checkResult(result); 91 SLEngineItf engineEngine; 92 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 93 checkResult(result); 94 95 // create output mix 96 SLObjectItf outputmixObject; 97 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL); 98 checkResult(result); 99 result = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE); 100 checkResult(result); 101 102 // create audio player 103 SLDataSource audiosrc; 104 SLDataSink audiosnk; 105 SLDataFormat_PCM pcm; 106 SLDataLocator_OutputMix locator_outputmix; 107 SLDataLocator_BufferQueue locator_bufferqueue; 108 locator_bufferqueue.locatorType = DATALOCATOR_BUFFERQUEUE; 109 locator_bufferqueue.numBuffers = 255; 110 locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 111 locator_outputmix.outputMix = outputmixObject; 112 pcm.formatType = SL_DATAFORMAT_PCM; 113 pcm.numChannels = 2; 114 pcm.samplesPerSec = SL_SAMPLINGRATE_44_1; 115 pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 116 pcm.containerSize = 16; 117 pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 118 pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 119 audiosrc.pLocator = &locator_bufferqueue; 120 audiosrc.pFormat = &pcm; 121 audiosnk.pLocator = &locator_outputmix; 122 audiosnk.pFormat = NULL; 123 SLObjectItf playerObject; 124 SLInterfaceID ids[2] = {IID_BUFFERQUEUE, SL_IID_MUTESOLO}; 125 SLboolean flags[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 126 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk, 127 2, ids, flags); 128 checkResult(result); 129 result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 130 checkResult(result); 131 SLPlayItf playerPlay; 132 result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); 133 checkResult(result); 134 BufferQueueItf playerBufferqueue; 135 result = (*playerObject)->GetInterface(playerObject, IID_BUFFERQUEUE, &playerBufferqueue); 136 checkResult(result); 137 SLMuteSoloItf playerMuteSolo; 138 result = (*playerObject)->GetInterface(playerObject, SL_IID_MUTESOLO, &playerMuteSolo); 139 checkResult(result); 140 SLuint8 numChannels = 123; 141 result = (*playerMuteSolo)->GetNumChannels(playerMuteSolo, &numChannels); 142 assert(2 == numChannels); 143 SLuint32 state; 144 state = SL_PLAYSTATE_PLAYING; 145 result = (*playerPlay)->SetPlayState(playerPlay, state); 146 checkResult(result); 147 148 unsigned i; 149 float pi2 = 3.14*2; 150 float hz = 441; 151 float sr = 44100; 152 for (i = 0; i < SINE_FRAMES; ++i) { 153 sine[i].left = sin((float) (i / (sr / hz)) * pi2 ) * 32000.0; 154 sine[i].right = sine[i].left; 155 } 156 for (i = 0; i < SQUARE_FRAMES; ++i) { 157 square[i].left = (i % (unsigned) (sr / hz)) < 50 ? 32767 : -32768; 158 square[i].right = square[i].left; 159 } 160 for (i = 0; i < SAWTOOTH_FRAMES; ++i) { 161 sawtooth[i].left = ((((int) (i % (unsigned) (sr / hz))) - 50) / 100.0) * 60000.0 - 30000.0; 162 sawtooth[i].right = sawtooth[i].left; 163 } 164 for (i = 0; i < HALF_FRAMES; ++i) { 165 half[i].left = sine[i].left; 166 half[i].right = sawtooth[i].right / 2; 167 } 168 169 set_conio_terminal_mode(); 170 int in_count = 0; 171 unsigned count = 0; 172 for (;;) { 173 usleep(10000); 174 if (kbhit()) { 175 frame_t *buffer; 176 unsigned size; 177 BufferQueueState bufqstate; 178 int ch = getch(); 179 switch (ch) { 180 case '0' ... '9': 181 if (in_count) { 182 count = count * 10 + (ch - '0'); 183 } else { 184 count = ch - '0'; 185 in_count = 1; 186 } 187 continue; 188 case 'i': 189 buffer = sine; 190 size = sizeof(sine); 191 goto enqueue; 192 case 'q': 193 buffer = square; 194 size = sizeof(square); 195 goto enqueue; 196 case 'h': 197 buffer = half; 198 size = sizeof(half); 199 goto enqueue; 200 case 'r': 201 if (in_count) { 202 expectedCaller = playerBufferqueue; 203 expectedContext = (void *) count; 204 } else { 205 expectedCaller = NULL; 206 expectedContext = (void *) NULL; 207 } 208 result = (*playerBufferqueue)->RegisterCallback(playerBufferqueue, in_count ? 209 callback : NULL, expectedContext); 210 checkResult(result); 211 break; 212 case 'a': 213 buffer = sawtooth; 214 size = sizeof(sawtooth); 215enqueue: 216 for (i = 0; i < (in_count ? count : 1); ++i) { 217 result = (*playerBufferqueue)->Enqueue(playerBufferqueue, buffer, size); 218 checkResult(result); 219 } 220 break; 221 case 'c': 222 result = (*playerBufferqueue)->Clear(playerBufferqueue); 223 checkResult(result); 224 putchar('\r'); 225 result = (*playerBufferqueue)->GetState(playerBufferqueue, &bufqstate); 226 checkResult(result); 227 if (bufqstate.count != 0) 228 printf("\rcount=%u\r\n", (unsigned) bufqstate.count); 229#if 0 230 putchar('\r'); 231 putchar('\n'); 232#endif 233 fflush(stdout); 234 break; 235 case 'g': 236 result = (*playerBufferqueue)->GetState(playerBufferqueue, &bufqstate); 237 checkResult(result); 238 printf("\rplayIndex=%u\r\n", (unsigned) bufqstate.INDEX); 239 printf("count=%u\r\n", (unsigned) bufqstate.count); 240 break; 241 case 'p': 242 state = SL_PLAYSTATE_PAUSED; 243 goto setplaystate; 244 case 's': 245 state = SL_PLAYSTATE_STOPPED; 246 goto setplaystate; 247 case 'P': 248 state = SL_PLAYSTATE_PLAYING; 249setplaystate: 250 result = (*playerPlay)->SetPlayState(playerPlay, state); 251 checkResult(result); 252 SLuint32 newstate; 253 result = (*playerPlay)->GetPlayState(playerPlay, &newstate); 254 checkResult(result); 255 if (newstate != state) 256 printf("\rSetPlayState(%u) -> GetPlayState(%u)\r\n", (unsigned) state, 257 (unsigned) newstate); 258#if 0 259 putchar('\r'); 260 putchar('\n'); 261 fflush(stdout); 262#endif 263 checkResult(result); 264 break; 265 case 'x': 266 goto out; 267 default: 268 putchar('?'); 269 fflush(stdout); 270 break; 271 } 272 in_count = 0; 273 } 274 } 275 276out: 277 (*playerObject)->Destroy(playerObject); 278 (*outputmixObject)->Destroy(outputmixObject); 279 (*engineObject)->Destroy(engineObject); 280 return EXIT_SUCCESS; 281} 282