• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
41 unsigned numBuffers = 2;
42 int framesPerBuffer = 512;
43 SNDFILE *sndfile;
44 SF_INFO sfinfo;
45 unsigned which; // which buffer to use next
46 SLboolean eof;  // whether we have hit EOF on input yet
47 short *buffers;
48 SLuint32 byteOrder; // desired to use for PCM buffers
49 SLuint32 nativeByteOrder;   // of platform
50 SLuint32 bitsPerSample = 16;
51 
52 // swap adjacent bytes; this would normally be in <unistd.h> but is missing here
swab(const void * from,void * to,ssize_t n)53 static 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
squeeze(const short * from,unsigned char * to,ssize_t n)69 static 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 
78 static android::MonoPipeReader *pipeReader;
79 static android::MonoPipe *pipeWriter;
80 static unsigned underruns = 0;
81 
82 // This callback is called each time a buffer finishes playing
83 
callback(SLBufferQueueItf bufq,void * param)84 static 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 
file_reader_loop(void * arg)115 static 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 
main(int argc,char ** argv)150 int 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 
242     // verify the file format
243     switch (sfinfo.channels) {
244     case 1:
245     case 2:
246         break;
247     default:
248         fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels);
249         goto close_sndfile;
250     }
251 
252     switch (sfinfo.samplerate) {
253     case  8000:
254     case 11025:
255     case 12000:
256     case 16000:
257     case 22050:
258     case 24000:
259     case 32000:
260     case 44100:
261     case 48000:
262         break;
263     default:
264         fprintf(stderr, "unsupported sample rate %d\n", sfinfo.samplerate);
265         goto close_sndfile;
266     }
267 
268     switch (sfinfo.format & SF_FORMAT_TYPEMASK) {
269     case SF_FORMAT_WAV:
270         break;
271     default:
272         fprintf(stderr, "unsupported format type 0x%x\n", sfinfo.format & SF_FORMAT_TYPEMASK);
273         goto close_sndfile;
274     }
275 
276     switch (sfinfo.format & SF_FORMAT_SUBMASK) {
277     case SF_FORMAT_PCM_16:
278     case SF_FORMAT_PCM_U8:
279         break;
280     default:
281         fprintf(stderr, "unsupported sub-format 0x%x\n", sfinfo.format & SF_FORMAT_SUBMASK);
282         goto close_sndfile;
283     }
284 
285     {
286 
287     buffers = (short *) malloc(framesPerBuffer * sfinfo.channels * sizeof(short) * numBuffers);
288 
289     // create engine
290     SLresult result;
291     SLObjectItf engineObject;
292     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
293     assert(SL_RESULT_SUCCESS == result);
294     SLEngineItf engineEngine;
295     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
296     assert(SL_RESULT_SUCCESS == result);
297     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
298     assert(SL_RESULT_SUCCESS == result);
299 
300     // create output mix
301     SLObjectItf outputMixObject;
302     SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
303     SLboolean req[1] = {SL_BOOLEAN_TRUE};
304     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, enableReverb ? 1 : 0,
305             ids, req);
306     assert(SL_RESULT_SUCCESS == result);
307     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
308     assert(SL_RESULT_SUCCESS == result);
309 
310     // configure environmental reverb on output mix
311     SLEnvironmentalReverbItf mixEnvironmentalReverb = NULL;
312     if (enableReverb) {
313         result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
314                 &mixEnvironmentalReverb);
315         assert(SL_RESULT_SUCCESS == result);
316         SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
317         result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb,
318                 &settings);
319         assert(SL_RESULT_SUCCESS == result);
320     }
321 
322     // configure audio source
323     SLDataLocator_BufferQueue loc_bufq;
324     loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
325     loc_bufq.numBuffers = numBuffers;
326     SLDataFormat_PCM format_pcm;
327     format_pcm.formatType = SL_DATAFORMAT_PCM;
328     format_pcm.numChannels = sfinfo.channels;
329     format_pcm.samplesPerSec = sfinfo.samplerate * 1000;
330     format_pcm.bitsPerSample = bitsPerSample;
331     format_pcm.containerSize = format_pcm.bitsPerSample;
332     format_pcm.channelMask = 1 == format_pcm.numChannels ? SL_SPEAKER_FRONT_CENTER :
333             SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
334     format_pcm.endianness = byteOrder;
335     SLDataSource audioSrc;
336     audioSrc.pLocator = &loc_bufq;
337     audioSrc.pFormat = &format_pcm;
338 
339     // configure audio sink
340     SLDataLocator_OutputMix loc_outmix;
341     loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
342     loc_outmix.outputMix = outputMixObject;
343     SLDataSink audioSnk;
344     audioSnk.pLocator = &loc_outmix;
345     audioSnk.pFormat = NULL;
346 
347     // create audio player
348     SLInterfaceID ids2[3] = {SL_IID_BUFFERQUEUE, SL_IID_PLAYBACKRATE, SL_IID_EFFECTSEND};
349     SLboolean req2[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
350     SLObjectItf playerObject;
351     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
352             &audioSnk, enableReverb ? 3 : (enablePlaybackRate ? 2 : 1), ids2, req2);
353     if (SL_RESULT_SUCCESS != result) {
354         fprintf(stderr, "can't create audio player\n");
355         goto no_player;
356     }
357 
358     {
359 
360     // realize the player
361     result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
362     assert(SL_RESULT_SUCCESS == result);
363 
364     // get the effect send interface and enable effect send reverb for this player
365     if (enableReverb) {
366         SLEffectSendItf playerEffectSend;
367         result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
368         assert(SL_RESULT_SUCCESS == result);
369         result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb,
370                 SL_BOOLEAN_TRUE, (SLmillibel) 0);
371         assert(SL_RESULT_SUCCESS == result);
372     }
373 
374     // get the playback rate interface and configure the rate
375     SLPlaybackRateItf playerPlaybackRate;
376     SLpermille currentRate = 0;
377     if (enablePlaybackRate) {
378         result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAYBACKRATE,
379                 &playerPlaybackRate);
380         assert(SL_RESULT_SUCCESS == result);
381         SLpermille defaultRate;
382         result = (*playerPlaybackRate)->GetRate(playerPlaybackRate, &defaultRate);
383         assert(SL_RESULT_SUCCESS == result);
384         SLuint32 defaultProperties;
385         result = (*playerPlaybackRate)->GetProperties(playerPlaybackRate, &defaultProperties);
386         assert(SL_RESULT_SUCCESS == result);
387         printf("default playback rate %d per mille, properties 0x%x\n", defaultRate,
388                 defaultProperties);
389         if (initialRate <= 0) {
390             initialRate = defaultRate;
391         }
392         if (finalRate <= 0) {
393             finalRate = initialRate;
394         }
395         currentRate = defaultRate;
396         if (finalRate == initialRate) {
397             deltaRate = 0;
398         } else if (finalRate < initialRate) {
399             deltaRate = -deltaRate;
400         }
401         if (initialRate != defaultRate) {
402             result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, initialRate);
403             if (SL_RESULT_FEATURE_UNSUPPORTED == result) {
404                 fprintf(stderr, "initial playback rate %d is unsupported\n", initialRate);
405                 deltaRate = 0;
406             } else if (SL_RESULT_PARAMETER_INVALID == result) {
407                 fprintf(stderr, "initial playback rate %d is invalid\n", initialRate);
408                 deltaRate = 0;
409             } else {
410                 assert(SL_RESULT_SUCCESS == result);
411                 currentRate = initialRate;
412             }
413         }
414     }
415 
416     // get the play interface
417     SLPlayItf playerPlay;
418     result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
419     assert(SL_RESULT_SUCCESS == result);
420 
421     // get the buffer queue interface
422     SLBufferQueueItf playerBufferQueue;
423     result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
424             &playerBufferQueue);
425     assert(SL_RESULT_SUCCESS == result);
426 
427     // loop until EOF or no more buffers
428     for (which = 0; which < numBuffers; ++which) {
429         short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
430         sf_count_t frames = framesPerBuffer;
431         sf_count_t count;
432         count = sf_readf_short(sndfile, buffer, frames);
433         if (0 >= count) {
434             eof = SL_BOOLEAN_TRUE;
435             break;
436         }
437 
438         // enqueue a buffer
439         SLuint32 nbytes = count * sfinfo.channels * sizeof(short);
440         if (byteOrder != nativeByteOrder) {
441             swab(buffer, buffer, nbytes);
442         }
443         if (bitsPerSample == 8) {
444             squeeze(buffer, (unsigned char *) buffer, nbytes);
445             nbytes /= 2;
446         }
447         result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, nbytes);
448         assert(SL_RESULT_SUCCESS == result);
449     }
450     if (which >= numBuffers) {
451         which = 0;
452     }
453 
454     // register a callback on the buffer queue
455     result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL);
456     assert(SL_RESULT_SUCCESS == result);
457 
458     pipeWriter = new android::MonoPipe(16384, nbaio_format, false /*writeCanBlock*/);
459     android::NBAIO_Format offer = nbaio_format;
460     size_t numCounterOffers = 0;
461     ssize_t neg = pipeWriter->negotiate(&offer, 1, NULL, numCounterOffers);
462     assert(0 == neg);
463     pipeReader = new android::MonoPipeReader(pipeWriter);
464     numCounterOffers = 0;
465     neg = pipeReader->negotiate(&offer, 1, NULL, numCounterOffers);
466     assert(0 == neg);
467 
468     // create thread to read from file
469     pthread_t thread;
470     int ok = pthread_create(&thread, (const pthread_attr_t *) NULL, file_reader_loop, NULL);
471     assert(0 == ok);
472 
473     // give thread a head start so that the pipe is initially filled
474     sleep(1);
475 
476     // set the player's state to playing
477     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
478     assert(SL_RESULT_SUCCESS == result);
479 
480     // get the initial time
481     struct timespec prevTs;
482     clock_gettime(CLOCK_MONOTONIC, &prevTs);
483     long elapsedNs = 0;
484     long deltaRateNs = deltaRateMs * 1000000;
485 
486     // wait until the buffer queue is empty
487     SLBufferQueueState bufqstate;
488     for (;;) {
489         result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate);
490         assert(SL_RESULT_SUCCESS == result);
491         if (0 >= bufqstate.count) {
492             break;
493         }
494         if (!enablePlaybackRate || deltaRate == 0) {
495             sleep(1);
496         } else {
497             struct timespec curTs;
498             clock_gettime(CLOCK_MONOTONIC, &curTs);
499             elapsedNs += (curTs.tv_sec - prevTs.tv_sec) * 1000000000 +
500                     // this term can be negative
501                     (curTs.tv_nsec - prevTs.tv_nsec);
502             prevTs = curTs;
503             if (elapsedNs < deltaRateNs) {
504                 usleep((deltaRateNs - elapsedNs) / 1000);
505                 continue;
506             }
507             elapsedNs -= deltaRateNs;
508             SLpermille nextRate = currentRate + deltaRate;
509             result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, nextRate);
510             if (SL_RESULT_SUCCESS != result) {
511                 fprintf(stderr, "next playback rate %d is unsupported\n", nextRate);
512             } else if (SL_RESULT_PARAMETER_INVALID == result) {
513                 fprintf(stderr, "next playback rate %d is invalid\n", nextRate);
514             } else {
515                 assert(SL_RESULT_SUCCESS == result);
516             }
517             currentRate = nextRate;
518             if (currentRate >= max(initialRate, finalRate)) {
519                 currentRate = max(initialRate, finalRate);
520                 deltaRate = -abs(deltaRate);
521             } else if (currentRate <= min(initialRate, finalRate)) {
522                 currentRate = min(initialRate, finalRate);
523                 deltaRate = abs(deltaRate);
524             }
525         }
526     }
527 
528     // destroy audio player
529     (*playerObject)->Destroy(playerObject);
530 
531     }
532 
533 no_player:
534 
535     // destroy output mix
536     (*outputMixObject)->Destroy(outputMixObject);
537 
538     // destroy engine
539     (*engineObject)->Destroy(engineObject);
540 
541     }
542 
543 close_sndfile:
544 
545     (void) sf_close(sndfile);
546 
547     return EXIT_SUCCESS;
548 }
549