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     SLpermille initialRate = 0;
    122     SLpermille finalRate = 0;
    123     SLpermille deltaRate = 1;
    124     SLmillisecond deltaRateMs = 0;
    125 
    126     // process command-line options
    127     int i;
    128     for (i = 1; i < argc; ++i) {
    129         char *arg = argv[i];
    130         if (arg[0] != '-') {
    131             break;
    132         }
    133         if (!strcmp(arg, "-b")) {
    134             byteOrder = SL_BYTEORDER_BIGENDIAN;
    135         } else if (!strcmp(arg, "-l")) {
    136             byteOrder = SL_BYTEORDER_LITTLEENDIAN;
    137         } else if (!strcmp(arg, "-8")) {
    138             bitsPerSample = 8;
    139         } else if (!strncmp(arg, "-f", 2)) {
    140             framesPerBuffer = atoi(&arg[2]);
    141         } else if (!strncmp(arg, "-n", 2)) {
    142             numBuffers = atoi(&arg[2]);
    143         } else if (!strncmp(arg, "-p", 2)) {
    144             initialRate = atoi(&arg[2]);
    145         } else if (!strncmp(arg, "-P", 2)) {
    146             finalRate = atoi(&arg[2]);
    147         } else if (!strncmp(arg, "-q", 2)) {
    148             deltaRate = atoi(&arg[2]);
    149             // deltaRate is a magnitude, so take absolute value
    150             if (deltaRate < 0) {
    151                 deltaRate = -deltaRate;
    152             }
    153         } else if (!strncmp(arg, "-Q", 2)) {
    154             deltaRateMs = atoi(&arg[2]);
    155         } else if (!strcmp(arg, "-r")) {
    156             enableReverb = SL_BOOLEAN_TRUE;
    157         } else {
    158             fprintf(stderr, "option %s ignored\n", arg);
    159         }
    160     }
    161 
    162     if (argc - i != 1) {
    163         fprintf(stderr, "usage: [-b/l] [-8] [-f#] [-n#] [-p#] [-r] %s filename\n", argv[0]);
    164         fprintf(stderr, "    -b  force big-endian byte order (default is native byte order)\n");
    165         fprintf(stderr, "    -l  force little-endian byte order (default is native byte order)\n");
    166         fprintf(stderr, "    -8  output 8-bits per sample (default is 16-bits per sample)\n");
    167         fprintf(stderr, "    -f# frames per buffer (default 512)\n");
    168         fprintf(stderr, "    -n# number of buffers (default 2)\n");
    169         fprintf(stderr, "    -p# initial playback rate in per mille (default 1000)\n");
    170         fprintf(stderr, "    -P# final playback rate in per mille (default same as -p#)\n");
    171         fprintf(stderr, "    -q# magnitude of playback rate changes in per mille (default 1)\n");
    172         fprintf(stderr, "    -Q# period between playback rate changes in ms (default 50)\n");
    173         fprintf(stderr, "    -r  enable reverb (default disabled)\n");
    174         return EXIT_FAILURE;
    175     }
    176 
    177     const char *filename = argv[i];
    178     //memset(&sfinfo, 0, sizeof(SF_INFO));
    179     sfinfo.format = 0;
    180     sndfile = sf_open(filename, SFM_READ, &sfinfo);
    181     if (NULL == sndfile) {
    182         perror(filename);
    183         return EXIT_FAILURE;
    184     }
    185 
    186     // verify the file format
    187     switch (sfinfo.channels) {
    188     case 1:
    189     case 2:
    190         break;
    191     default:
    192         fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels);
    193         goto close_sndfile;
    194     }
    195 
    196     switch (sfinfo.samplerate) {
    197     case  8000:
    198     case 11025:
    199     case 12000:
    200     case 16000:
    201     case 22050:
    202     case 24000:
    203     case 32000:
    204     case 44100:
    205     case 48000:
    206         break;
    207     default:
    208         fprintf(stderr, "unsupported sample rate %d\n", sfinfo.samplerate);
    209         goto close_sndfile;
    210     }
    211 
    212     switch (sfinfo.format & SF_FORMAT_TYPEMASK) {
    213     case SF_FORMAT_WAV:
    214         break;
    215     default:
    216         fprintf(stderr, "unsupported format type 0x%x\n", sfinfo.format & SF_FORMAT_TYPEMASK);
    217         goto close_sndfile;
    218     }
    219 
    220     switch (sfinfo.format & SF_FORMAT_SUBMASK) {
    221     case SF_FORMAT_PCM_16:
    222     case SF_FORMAT_PCM_U8:
    223     case SF_FORMAT_ULAW:
    224     case SF_FORMAT_ALAW:
    225     case SF_FORMAT_IMA_ADPCM:
    226         break;
    227     default:
    228         fprintf(stderr, "unsupported sub-format 0x%x\n", sfinfo.format & SF_FORMAT_SUBMASK);
    229         goto close_sndfile;
    230     }
    231 
    232     buffers = (short *) malloc(framesPerBuffer * sfinfo.channels * sizeof(short) * numBuffers);
    233 
    234     // create engine
    235     SLresult result;
    236     SLObjectItf engineObject;
    237     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
    238     assert(SL_RESULT_SUCCESS == result);
    239     SLEngineItf engineEngine;
    240     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    241     assert(SL_RESULT_SUCCESS == result);
    242     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
    243     assert(SL_RESULT_SUCCESS == result);
    244 
    245     // create output mix
    246     SLObjectItf outputMixObject;
    247     SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
    248     SLboolean req[1] = {SL_BOOLEAN_TRUE};
    249     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, enableReverb ? 1 : 0,
    250             ids, req);
    251     assert(SL_RESULT_SUCCESS == result);
    252     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
    253     assert(SL_RESULT_SUCCESS == result);
    254 
    255     // configure environmental reverb on output mix
    256     SLEnvironmentalReverbItf mixEnvironmentalReverb = NULL;
    257     if (enableReverb) {
    258         result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
    259                 &mixEnvironmentalReverb);
    260         assert(SL_RESULT_SUCCESS == result);
    261         SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
    262         result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb,
    263                 &settings);
    264         assert(SL_RESULT_SUCCESS == result);
    265     }
    266 
    267     // configure audio source
    268     SLDataLocator_BufferQueue loc_bufq;
    269     loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
    270     loc_bufq.numBuffers = numBuffers;
    271     SLDataFormat_PCM format_pcm;
    272     format_pcm.formatType = SL_DATAFORMAT_PCM;
    273     format_pcm.numChannels = sfinfo.channels;
    274     format_pcm.samplesPerSec = sfinfo.samplerate * 1000;
    275     format_pcm.bitsPerSample = bitsPerSample;
    276     format_pcm.containerSize = format_pcm.bitsPerSample;
    277     format_pcm.channelMask = 1 == format_pcm.numChannels ? SL_SPEAKER_FRONT_CENTER :
    278             SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
    279     format_pcm.endianness = byteOrder;
    280     SLDataSource audioSrc;
    281     audioSrc.pLocator = &loc_bufq;
    282     audioSrc.pFormat = &format_pcm;
    283 
    284     // configure audio sink
    285     SLDataLocator_OutputMix loc_outmix;
    286     loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    287     loc_outmix.outputMix = outputMixObject;
    288     SLDataSink audioSnk;
    289     audioSnk.pLocator = &loc_outmix;
    290     audioSnk.pFormat = NULL;
    291 
    292     // create audio player
    293     SLInterfaceID ids2[3] = {SL_IID_BUFFERQUEUE, SL_IID_PLAYBACKRATE, SL_IID_EFFECTSEND};
    294     SLboolean req2[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    295     SLObjectItf playerObject;
    296     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
    297             &audioSnk, enableReverb ? 3 : 2, ids2, req2);
    298     if (SL_RESULT_SUCCESS != result) {
    299         fprintf(stderr, "can't create audio player\n");
    300         goto no_player;
    301     }
    302 
    303     // realize the player
    304     result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
    305     assert(SL_RESULT_SUCCESS == result);
    306 
    307     // get the effect send interface and enable effect send reverb for this player
    308     if (enableReverb) {
    309         SLEffectSendItf playerEffectSend;
    310         result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
    311         assert(SL_RESULT_SUCCESS == result);
    312         result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb,
    313                 SL_BOOLEAN_TRUE, (SLmillibel) 0);
    314         assert(SL_RESULT_SUCCESS == result);
    315     }
    316 
    317     // get the playback rate interface and configure the rate
    318     SLPlaybackRateItf playerPlaybackRate;
    319     result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAYBACKRATE, &playerPlaybackRate);
    320     assert(SL_RESULT_SUCCESS == result);
    321     SLpermille defaultRate;
    322     result = (*playerPlaybackRate)->GetRate(playerPlaybackRate, &defaultRate);
    323     assert(SL_RESULT_SUCCESS == result);
    324     SLuint32 defaultProperties;
    325     result = (*playerPlaybackRate)->GetProperties(playerPlaybackRate, &defaultProperties);
    326     assert(SL_RESULT_SUCCESS == result);
    327     printf("default playback rate %d per mille, properties 0x%x\n", defaultRate, defaultProperties);
    328     if (initialRate <= 0) {
    329         initialRate = defaultRate;
    330     }
    331     if (finalRate <= 0) {
    332         finalRate = initialRate;
    333     }
    334     SLpermille currentRate = defaultRate;
    335     if (finalRate == initialRate) {
    336         deltaRate = 0;
    337     } else if (finalRate < initialRate) {
    338         deltaRate = -deltaRate;
    339     }
    340     if (initialRate != defaultRate) {
    341         result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, initialRate);
    342         if (SL_RESULT_FEATURE_UNSUPPORTED == result) {
    343             fprintf(stderr, "initial playback rate %d is unsupported\n", initialRate);
    344             deltaRate = 0;
    345         } else if (SL_RESULT_PARAMETER_INVALID == result) {
    346             fprintf(stderr, "initial playback rate %d is invalid\n", initialRate);
    347             deltaRate = 0;
    348         } else {
    349             assert(SL_RESULT_SUCCESS == result);
    350             currentRate = initialRate;
    351         }
    352     }
    353 
    354     // get the play interface
    355     SLPlayItf playerPlay;
    356     result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
    357     assert(SL_RESULT_SUCCESS == result);
    358 
    359     // get the buffer queue interface
    360     SLBufferQueueItf playerBufferQueue;
    361     result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
    362             &playerBufferQueue);
    363     assert(SL_RESULT_SUCCESS == result);
    364 
    365     // loop until EOF or no more buffers
    366     for (which = 0; which < numBuffers; ++which) {
    367         short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
    368         sf_count_t frames = framesPerBuffer;
    369         sf_count_t count;
    370         count = sf_readf_short(sndfile, buffer, frames);
    371         if (0 >= count) {
    372             eof = SL_BOOLEAN_TRUE;
    373             break;
    374         }
    375 
    376         // enqueue a buffer
    377         SLuint32 nbytes = count * sfinfo.channels * sizeof(short);
    378         if (byteOrder != nativeByteOrder) {
    379             swab(buffer, buffer, nbytes);
    380         }
    381         if (bitsPerSample == 8) {
    382             squeeze(buffer, (unsigned char *) buffer, nbytes);
    383             nbytes /= 2;
    384         }
    385         result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, nbytes);
    386         assert(SL_RESULT_SUCCESS == result);
    387     }
    388     if (which >= numBuffers) {
    389         which = 0;
    390     }
    391 
    392     // register a callback on the buffer queue
    393     result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL);
    394     assert(SL_RESULT_SUCCESS == result);
    395 
    396     // set the player's state to playing
    397     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
    398     assert(SL_RESULT_SUCCESS == result);
    399 
    400     // get the initial time
    401     struct timespec prevTs;
    402     clock_gettime(CLOCK_MONOTONIC, &prevTs);
    403     long elapsedNs = 0;
    404     long deltaRateNs = deltaRateMs * 1000000;
    405 
    406     // wait until the buffer queue is empty
    407     SLBufferQueueState bufqstate;
    408     for (;;) {
    409         result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate);
    410         assert(SL_RESULT_SUCCESS == result);
    411         if (0 >= bufqstate.count) {
    412             break;
    413         }
    414         if (deltaRate == 0) {
    415             sleep(1);
    416         } else {
    417             struct timespec curTs;
    418             clock_gettime(CLOCK_MONOTONIC, &curTs);
    419             elapsedNs += (curTs.tv_sec - prevTs.tv_sec) * 1000000000 +
    420                     // this term can be negative
    421                     (curTs.tv_nsec - prevTs.tv_nsec);
    422             prevTs = curTs;
    423             if (elapsedNs < deltaRateNs) {
    424                 usleep((deltaRateNs - elapsedNs) / 1000);
    425                 continue;
    426             }
    427             elapsedNs -= deltaRateNs;
    428             SLpermille nextRate = currentRate + deltaRate;
    429             result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, nextRate);
    430             if (SL_RESULT_SUCCESS != result) {
    431                 fprintf(stderr, "next playback rate %d is unsupported\n", nextRate);
    432             } else if (SL_RESULT_PARAMETER_INVALID == result) {
    433                 fprintf(stderr, "next playback rate %d is invalid\n", nextRate);
    434             } else {
    435                 assert(SL_RESULT_SUCCESS == result);
    436             }
    437             currentRate = nextRate;
    438             if (currentRate >= max(initialRate, finalRate)) {
    439                 currentRate = max(initialRate, finalRate);
    440                 deltaRate = -abs(deltaRate);
    441             } else if (currentRate <= min(initialRate, finalRate)) {
    442                 currentRate = min(initialRate, finalRate);
    443                 deltaRate = abs(deltaRate);
    444             }
    445         }
    446     }
    447 
    448     // destroy audio player
    449     (*playerObject)->Destroy(playerObject);
    450 
    451 no_player:
    452 
    453     // destroy output mix
    454     (*outputMixObject)->Destroy(outputMixObject);
    455 
    456     // destroy engine
    457     (*engineObject)->Destroy(engineObject);
    458 
    459 close_sndfile:
    460 
    461     (void) sf_close(sndfile);
    462 
    463     return EXIT_SUCCESS;
    464 }
    465