Home | History | Annotate | Download | only in sandbox
      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 
     51 typedef struct {
     52     short left;
     53     short right;
     54 } frame_t;
     55 
     56 #define SINE_FRAMES (44100*5)
     57 frame_t sine[SINE_FRAMES];
     58 
     59 #define SQUARE_FRAMES (44100*5)
     60 frame_t square[SQUARE_FRAMES];
     61 
     62 #define SAWTOOTH_FRAMES (44100*5)
     63 frame_t sawtooth[SAWTOOTH_FRAMES];
     64 
     65 #define HALF_FRAMES (44100*5)
     66 frame_t half[HALF_FRAMES];
     67 
     68 BufferQueueItf expectedCaller = NULL;
     69 void *expectedContext = NULL;
     70 
     71 static 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 
     81 int 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     uintptr_t 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);
    215 enqueue:
    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;
    249 setplaystate:
    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 
    276 out:
    277     (*playerObject)->Destroy(playerObject);
    278     (*outputmixObject)->Destroy(outputmixObject);
    279     (*engineObject)->Destroy(engineObject);
    280     return EXIT_SUCCESS;
    281 }
    282