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 // Play an audio file using buffer queue
     18 
     19 #include <assert.h>
     20 #include <math.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <unistd.h>
     25 
     26 #include <SLES/OpenSLES.h>
     27 #ifdef ANDROID
     28 #include "sndfile.h"
     29 #else
     30 #include <sndfile.h>
     31 #endif
     32 
     33 unsigned numBuffers = 2;
     34 int framesPerBuffer = 512;
     35 SNDFILE *sndfile;
     36 SF_INFO sfinfo;
     37 unsigned which; // which buffer to use next
     38 SLboolean eof;  // whether we have hit EOF on input yet
     39 short *buffers;
     40 SLuint32 byteOrder; // desired to use for PCM buffers
     41 SLuint32 nativeByteOrder;   // of platform
     42 SLuint32 bitsPerSample = 16;
     43 
     44 // swap adjacent bytes; this would normally be in <unistd.h> but is missing here
     45 static void swab(const void *from, void *to, ssize_t n)
     46 {
     47     // from and to as char pointers
     48     const char *from_ch = (const char *) from;
     49     char *to_ch = (char *) to;
     50     // note that we don't swap the last odd byte
     51     while (n >= 2) {
     52         to_ch[0] = from_ch[1];
     53         to_ch[1] = from_ch[0];
     54         to_ch += 2;
     55         from_ch += 2;
     56         n -= 2;
     57     }
     58 }
     59 
     60 // squeeze 16-bit signed PCM samples down to 8-bit unsigned PCM samples by truncation; no dithering
     61 static void squeeze(const short *from, unsigned char *to, ssize_t n)
     62 {
     63     // note that we don't squeeze the last odd byte
     64     while (n >= 2) {
     65         *to++ = (*from++ + 32768) >> 8;
     66         n -= 2;
     67     }
     68 }
     69 
     70 // This callback is called each time a buffer finishes playing
     71 
     72 static void callback(SLBufferQueueItf bufq, void *param)
     73 {
     74     assert(NULL == param);
     75     if (!eof) {
     76         short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
     77         sf_count_t count;
     78         count = sf_readf_short(sndfile, buffer, (sf_count_t) framesPerBuffer);
     79         if (0 >= count) {
     80             eof = SL_BOOLEAN_TRUE;
     81         } else {
     82             SLuint32 nbytes = count * sfinfo.channels * sizeof(short);
     83             if (byteOrder != nativeByteOrder) {
     84                 swab(buffer, buffer, nbytes);
     85             }
     86             if (bitsPerSample == 8) {
     87                 squeeze(buffer, (unsigned char *) buffer, nbytes);
     88                 nbytes /= 2;
     89             }
     90             SLresult result = (*bufq)->Enqueue(bufq, buffer, nbytes);
     91             assert(SL_RESULT_SUCCESS == result);
     92             if (++which >= numBuffers)
     93                 which = 0;
     94         }
     95     }
     96 }
     97 
     98 int main(int argc, char **argv)
     99 {
    100     // Determine the native byte order (SL_BYTEORDER_NATIVE not available until 1.1)
    101     union {
    102         short s;
    103         char c[2];
    104     } u;
    105     u.s = 0x1234;
    106     if (u.c[0] == 0x34) {
    107         nativeByteOrder = SL_BYTEORDER_LITTLEENDIAN;
    108     } else if (u.c[0] == 0x12) {
    109         nativeByteOrder = SL_BYTEORDER_BIGENDIAN;
    110     } else {
    111         fprintf(stderr, "Unable to determine native byte order\n");
    112         return EXIT_FAILURE;
    113     }
    114     byteOrder = nativeByteOrder;
    115 
    116     SLboolean enableReverb = SL_BOOLEAN_FALSE;
    117     SLpermille rate = 1000;
    118 
    119     // process command-line options
    120     int i;
    121     for (i = 1; i < argc; ++i) {
    122         char *arg = argv[i];
    123         if (arg[0] != '-')
    124             break;
    125         if (!strcmp(arg, "-b")) {
    126             byteOrder = SL_BYTEORDER_BIGENDIAN;
    127         } else if (!strcmp(arg, "-l")) {
    128             byteOrder = SL_BYTEORDER_LITTLEENDIAN;
    129         } else if (!strcmp(arg, "-8")) {
    130             bitsPerSample = 8;
    131         } else if (!strncmp(arg, "-f", 2)) {
    132             framesPerBuffer = atoi(&arg[2]);
    133         } else if (!strncmp(arg, "-n", 2)) {
    134             numBuffers = atoi(&arg[2]);
    135         } else if (!strncmp(arg, "-p", 2)) {
    136             rate = atoi(&arg[2]);
    137         } else if (!strcmp(arg, "-r")) {
    138             enableReverb = SL_BOOLEAN_TRUE;
    139         } else {
    140             fprintf(stderr, "option %s ignored\n", arg);
    141         }
    142     }
    143 
    144     if (argc - i != 1) {
    145         fprintf(stderr, "usage: [-b/l] [-8] [-f#] [-n#] [-p#] [-r] %s filename\n", argv[0]);
    146         return EXIT_FAILURE;
    147     }
    148 
    149     const char *filename = argv[i];
    150     //memset(&sfinfo, 0, sizeof(SF_INFO));
    151     sfinfo.format = 0;
    152     sndfile = sf_open(filename, SFM_READ, &sfinfo);
    153     if (NULL == sndfile) {
    154         perror(filename);
    155         return EXIT_FAILURE;
    156     }
    157 
    158     // verify the file format
    159     switch (sfinfo.channels) {
    160     case 1:
    161     case 2:
    162         break;
    163     default:
    164         fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels);
    165         break;
    166     }
    167     switch (sfinfo.samplerate) {
    168     case  8000:
    169     case 11025:
    170     case 12000:
    171     case 16000:
    172     case 22050:
    173     case 24000:
    174     case 32000:
    175     case 44100:
    176     case 48000:
    177         break;
    178     default:
    179         fprintf(stderr, "unsupported sample rate %d\n", sfinfo.samplerate);
    180         break;
    181     }
    182     switch (sfinfo.format & SF_FORMAT_TYPEMASK) {
    183     case SF_FORMAT_WAV:
    184         break;
    185     default:
    186         fprintf(stderr, "unsupported format type 0x%x\n", sfinfo.format & SF_FORMAT_TYPEMASK);
    187         break;
    188     }
    189     switch (sfinfo.format & SF_FORMAT_SUBMASK) {
    190     case SF_FORMAT_PCM_16:
    191     case SF_FORMAT_PCM_U8:
    192     case SF_FORMAT_ULAW:
    193     case SF_FORMAT_ALAW:
    194     case SF_FORMAT_IMA_ADPCM:
    195         break;
    196     default:
    197         fprintf(stderr, "unsupported sub-format 0x%x\n", sfinfo.format & SF_FORMAT_SUBMASK);
    198         break;
    199     }
    200 
    201     buffers = (short *) malloc(framesPerBuffer * sfinfo.channels * sizeof(short) * numBuffers);
    202 
    203     // create engine
    204     SLresult result;
    205     SLObjectItf engineObject;
    206     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
    207     assert(SL_RESULT_SUCCESS == result);
    208     SLEngineItf engineEngine;
    209     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    210     assert(SL_RESULT_SUCCESS == result);
    211     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
    212     assert(SL_RESULT_SUCCESS == result);
    213 
    214     // create output mix
    215     SLObjectItf outputMixObject;
    216     SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
    217     SLboolean req[1] = {SL_BOOLEAN_TRUE};
    218     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, enableReverb ? 1 : 0,
    219             ids, req);
    220     assert(SL_RESULT_SUCCESS == result);
    221     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
    222     assert(SL_RESULT_SUCCESS == result);
    223 
    224     // configure environmental reverb on output mix
    225     SLEnvironmentalReverbItf mixEnvironmentalReverb = NULL;
    226     if (enableReverb) {
    227         result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
    228                 &mixEnvironmentalReverb);
    229         assert(SL_RESULT_SUCCESS == result);
    230         SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
    231         result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb,
    232                 &settings);
    233         assert(SL_RESULT_SUCCESS == result);
    234     }
    235 
    236     // configure audio source
    237     SLDataLocator_BufferQueue loc_bufq;
    238     loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
    239     loc_bufq.numBuffers = numBuffers;
    240     SLDataFormat_PCM format_pcm;
    241     format_pcm.formatType = SL_DATAFORMAT_PCM;
    242     format_pcm.numChannels = sfinfo.channels;
    243     format_pcm.samplesPerSec = sfinfo.samplerate * 1000;
    244     format_pcm.bitsPerSample = bitsPerSample;
    245     format_pcm.containerSize = format_pcm.bitsPerSample;
    246     format_pcm.channelMask = 1 == format_pcm.numChannels ? SL_SPEAKER_FRONT_CENTER :
    247             SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
    248     format_pcm.endianness = byteOrder;
    249     SLDataSource audioSrc;
    250     audioSrc.pLocator = &loc_bufq;
    251     audioSrc.pFormat = &format_pcm;
    252 
    253     // configure audio sink
    254     SLDataLocator_OutputMix loc_outmix;
    255     loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    256     loc_outmix.outputMix = outputMixObject;
    257     SLDataSink audioSnk;
    258     audioSnk.pLocator = &loc_outmix;
    259     audioSnk.pFormat = NULL;
    260 
    261     // create audio player
    262     SLInterfaceID ids2[3] = {SL_IID_BUFFERQUEUE, SL_IID_PLAYBACKRATE, SL_IID_EFFECTSEND};
    263     SLboolean req2[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    264     SLObjectItf playerObject;
    265     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
    266             &audioSnk, enableReverb ? 3 : 2, ids2, req2);
    267     assert(SL_RESULT_SUCCESS == result);
    268 
    269     // realize the player
    270     result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
    271     assert(SL_RESULT_SUCCESS == result);
    272 
    273     // get the effect send interface and enable effect send reverb for this player
    274     if (enableReverb) {
    275         SLEffectSendItf playerEffectSend;
    276         result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
    277         assert(SL_RESULT_SUCCESS == result);
    278         result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb,
    279                 SL_BOOLEAN_TRUE, (SLmillibel) 0);
    280         assert(SL_RESULT_SUCCESS == result);
    281     }
    282 
    283     // get the playback rate interface and configure the rate
    284     SLPlaybackRateItf playerPlaybackRate;
    285     result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAYBACKRATE, &playerPlaybackRate);
    286     assert(SL_RESULT_SUCCESS == result);
    287     SLpermille defaultRate;
    288     result = (*playerPlaybackRate)->GetRate(playerPlaybackRate, &defaultRate);
    289     assert(SL_RESULT_SUCCESS == result);
    290     SLuint32 defaultProperties;
    291     result = (*playerPlaybackRate)->GetProperties(playerPlaybackRate, &defaultProperties);
    292     assert(SL_RESULT_SUCCESS == result);
    293     printf("default playback rate %d per mille, properties 0x%x\n", defaultRate, defaultProperties);
    294     if (rate != defaultRate) {
    295         result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, rate);
    296         if (SL_RESULT_FEATURE_UNSUPPORTED == result) {
    297             fprintf(stderr, "playback rate %d is unsupported\n", rate);
    298         } else if (SL_RESULT_PARAMETER_INVALID == result) {
    299             fprintf(stderr, "playback rate %d is invalid", rate);
    300         } else {
    301             assert(SL_RESULT_SUCCESS == result);
    302         }
    303     }
    304 
    305     // get the play interface
    306     SLPlayItf playerPlay;
    307     result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
    308     assert(SL_RESULT_SUCCESS == result);
    309 
    310     // get the buffer queue interface
    311     SLBufferQueueItf playerBufferQueue;
    312     result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
    313             &playerBufferQueue);
    314     assert(SL_RESULT_SUCCESS == result);
    315 
    316     // loop until EOF or no more buffers
    317     for (which = 0; which < numBuffers; ++which) {
    318         short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
    319         sf_count_t frames = framesPerBuffer;
    320         sf_count_t count;
    321         count = sf_readf_short(sndfile, buffer, frames);
    322         if (0 >= count) {
    323             eof = SL_BOOLEAN_TRUE;
    324             break;
    325         }
    326 
    327         // enqueue a buffer
    328         SLuint32 nbytes = count * sfinfo.channels * sizeof(short);
    329         if (byteOrder != nativeByteOrder) {
    330             swab(buffer, buffer, nbytes);
    331         }
    332         if (bitsPerSample == 8) {
    333             squeeze(buffer, (unsigned char *) buffer, nbytes);
    334             nbytes /= 2;
    335         }
    336         result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, nbytes);
    337         assert(SL_RESULT_SUCCESS == result);
    338     }
    339     if (which >= numBuffers)
    340         which = 0;
    341 
    342     // register a callback on the buffer queue
    343     result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL);
    344     assert(SL_RESULT_SUCCESS == result);
    345 
    346     // set the player's state to playing
    347     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
    348     assert(SL_RESULT_SUCCESS == result);
    349 
    350     // wait until the buffer queue is empty
    351     SLBufferQueueState bufqstate;
    352     for (;;) {
    353         result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate);
    354         assert(SL_RESULT_SUCCESS == result);
    355         if (0 >= bufqstate.count) {
    356             break;
    357         }
    358         sleep(1);
    359     }
    360 
    361     // destroy audio player
    362     (*playerObject)->Destroy(playerObject);
    363 
    364     // destroy output mix
    365     (*outputMixObject)->Destroy(outputMixObject);
    366 
    367     // destroy engine
    368     (*engineObject)->Destroy(engineObject);
    369 
    370     return EXIT_SUCCESS;
    371 }
    372