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
37unsigned numBuffers = 2;
38int framesPerBuffer = 512;
39SNDFILE *sndfile;
40SF_INFO sfinfo;
41unsigned which; // which buffer to use next
42SLboolean eof;  // whether we have hit EOF on input yet
43short *buffers;
44SLuint32 byteOrder; // desired to use for PCM buffers
45SLuint32 nativeByteOrder;   // of platform
46SLuint32 bitsPerSample = 16;
47
48// swap adjacent bytes; this would normally be in <unistd.h> but is missing here
49static 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
65static 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
76static 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
102int 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
461no_player:
462
463    // destroy output mix
464    (*outputMixObject)->Destroy(outputMixObject);
465
466    // destroy engine
467    (*engineObject)->Destroy(engineObject);
468
469close_sndfile:
470
471    (void) sf_close(sndfile);
472
473    return EXIT_SUCCESS;
474}
475