playbq.c revision ebca1a420c4ada9eff2e82f0100abaea95b48f24
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
33unsigned numBuffers = 2;
34int framesPerBuffer = 512;
35SNDFILE *sndfile;
36SF_INFO sfinfo;
37unsigned which; // which buffer to use next
38SLboolean eof;  // whether we have hit EOF on input yet
39short *buffers;
40SLuint32 byteOrder; // desired to use for PCM buffers
41SLuint32 nativeByteOrder;   // of platform
42SLuint32 bitsPerSample = 16;
43
44// swap adjacent bytes; this would normally be in <unistd.h> but is missing here
45static 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
61static 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
72static 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
98int 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