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