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