OSDN Git Service

Bug 5135150 Fix ifdef C++
[android-x86/system-media.git] / wilhelm / tests / sandbox / playbq.c
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
33 unsigned numBuffers = 2;
34 int framesPerBuffer = 512;
35 SNDFILE *sndfile;
36 SF_INFO sfinfo;
37 unsigned which; // which buffer to use next
38 SLboolean eof;  // whether we have hit EOF on input yet
39 short *buffers;
40
41 // This callback is called each time a buffer finishes playing
42
43 static void callback(SLBufferQueueItf bufq, void *param)
44 {
45     if (!eof) {
46         short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
47         sf_count_t count;
48         count = sf_readf_short(sndfile, buffer, (sf_count_t) framesPerBuffer);
49         if (0 >= count) {
50             eof = SL_BOOLEAN_TRUE;
51         } else {
52             SLresult result = (*bufq)->Enqueue(bufq, buffer, count * sfinfo.channels *
53                     sizeof(short));
54             assert(SL_RESULT_SUCCESS == result);
55             if (++which >= numBuffers)
56                 which = 0;
57         }
58     }
59 }
60
61 int main(int argc, char **argv)
62 {
63     SLboolean enableReverb = SL_BOOLEAN_FALSE;
64
65     // process command-line options
66     int i;
67     for (i = 1; i < argc; ++i) {
68         char *arg = argv[i];
69         if (arg[0] != '-')
70             break;
71         if (!strncmp(arg, "-f", 2)) {
72             framesPerBuffer = atoi(&arg[2]);
73         } else if (!strncmp(arg, "-n", 2)) {
74             numBuffers = atoi(&arg[2]);
75         } else if (!strcmp(arg, "-r")) {
76             enableReverb = SL_BOOLEAN_TRUE;
77         } else {
78             fprintf(stderr, "option %s ignored\n", arg);
79         }
80     }
81
82     if (argc - i != 1) {
83         fprintf(stderr, "usage: [-r] %s filename\n", argv[0]);
84         return EXIT_FAILURE;
85     }
86
87     const char *filename = argv[i];
88     //memset(&sfinfo, 0, sizeof(SF_INFO));
89     sfinfo.format = 0;
90     sndfile = sf_open(filename, SFM_READ, &sfinfo);
91     if (NULL == sndfile) {
92         perror(filename);
93         return EXIT_FAILURE;
94     }
95
96     // verify the file format
97     switch (sfinfo.channels) {
98     case 1:
99     case 2:
100         break;
101     default:
102         fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels);
103         break;
104     }
105     switch (sfinfo.samplerate) {
106     case  8000:
107     case 11025:
108     case 12000:
109     case 16000:
110     case 22050:
111     case 24000:
112     case 32000:
113     case 44100:
114     case 48000:
115         break;
116     default:
117         fprintf(stderr, "unsupported sample rate %d\n", sfinfo.samplerate);
118         break;
119     }
120     switch (sfinfo.format & SF_FORMAT_TYPEMASK) {
121     case SF_FORMAT_WAV:
122         break;
123     default:
124         fprintf(stderr, "unsupported format type 0x%x\n", sfinfo.format & SF_FORMAT_TYPEMASK);
125         break;
126     }
127     switch (sfinfo.format & SF_FORMAT_SUBMASK) {
128     case SF_FORMAT_PCM_16:
129     case SF_FORMAT_PCM_U8:
130     case SF_FORMAT_ULAW:
131     case SF_FORMAT_ALAW:
132     case SF_FORMAT_IMA_ADPCM:
133         break;
134     default:
135         fprintf(stderr, "unsupported sub-format 0x%x\n", sfinfo.format & SF_FORMAT_SUBMASK);
136         break;
137     }
138
139     buffers = (short *) malloc(framesPerBuffer * sfinfo.channels * sizeof(short) * numBuffers);
140
141     // create engine
142     SLresult result;
143     SLObjectItf engineObject;
144     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
145     assert(SL_RESULT_SUCCESS == result);
146     SLEngineItf engineEngine;
147     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
148     assert(SL_RESULT_SUCCESS == result);
149     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
150     assert(SL_RESULT_SUCCESS == result);
151
152     // create output mix
153     SLObjectItf outputMixObject;
154     SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
155     SLboolean req[1] = {SL_BOOLEAN_TRUE};
156     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, enableReverb ? 1 : 0,
157             ids, req);
158     assert(SL_RESULT_SUCCESS == result);
159     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
160     assert(SL_RESULT_SUCCESS == result);
161
162     // configure environmental reverb on output mix
163     SLEnvironmentalReverbItf mixEnvironmentalReverb = NULL;
164     if (enableReverb) {
165         result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
166                 &mixEnvironmentalReverb);
167         assert(SL_RESULT_SUCCESS == result);
168         SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
169         result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb,
170                 &settings);
171         assert(SL_RESULT_SUCCESS == result);
172     }
173
174     // configure audio source
175     SLDataLocator_BufferQueue loc_bufq;
176     loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
177     loc_bufq.numBuffers = numBuffers;
178     SLDataFormat_PCM format_pcm;
179     format_pcm.formatType = SL_DATAFORMAT_PCM;
180     format_pcm.numChannels = sfinfo.channels;
181     format_pcm.samplesPerSec = sfinfo.samplerate * 1000;
182     format_pcm.bitsPerSample = 16;
183     format_pcm.containerSize = format_pcm.bitsPerSample;
184     format_pcm.channelMask = 1 == format_pcm.numChannels ? SL_SPEAKER_FRONT_CENTER :
185             SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
186     format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
187     SLDataSource audioSrc;
188     audioSrc.pLocator = &loc_bufq;
189     audioSrc.pFormat = &format_pcm;
190
191     // configure audio sink
192     SLDataLocator_OutputMix loc_outmix;
193     loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
194     loc_outmix.outputMix = outputMixObject;
195     SLDataSink audioSnk;
196     audioSnk.pLocator = &loc_outmix;
197     audioSnk.pFormat = NULL;
198
199     // create audio player
200     SLInterfaceID ids2[2] = {SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND};
201     SLboolean req2[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
202     SLObjectItf playerObject;
203     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
204             &audioSnk, enableReverb ? 2 : 1, ids2, req2);
205     assert(SL_RESULT_SUCCESS == result);
206
207     // realize the player
208     result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
209     assert(SL_RESULT_SUCCESS == result);
210
211     // get the effect send interface and enable effect send reverb for this player
212     if (enableReverb) {
213         SLEffectSendItf playerEffectSend;
214         result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
215         assert(SL_RESULT_SUCCESS == result);
216         result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb,
217                 SL_BOOLEAN_TRUE, (SLmillibel) 0);
218         assert(SL_RESULT_SUCCESS == result);
219     }
220
221     // get the play interface
222     SLPlayItf playerPlay;
223     result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
224     assert(SL_RESULT_SUCCESS == result);
225
226     // get the buffer queue interface
227     SLBufferQueueItf playerBufferQueue;
228     result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
229             &playerBufferQueue);
230     assert(SL_RESULT_SUCCESS == result);
231
232     // loop until EOF or no more buffers
233     for (which = 0; which < numBuffers; ++which) {
234         short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
235         sf_count_t frames = framesPerBuffer;
236         sf_count_t count;
237         count = sf_readf_short(sndfile, buffer, frames);
238         if (0 >= count) {
239             eof = SL_BOOLEAN_TRUE;
240             break;
241         }
242
243         // enqueue a buffer
244         result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, count * sfinfo.channels *
245                 sizeof(short));
246         assert(SL_RESULT_SUCCESS == result);
247     }
248     if (which >= numBuffers)
249         which = 0;
250
251     // register a callback on the buffer queue
252     result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL);
253     assert(SL_RESULT_SUCCESS == result);
254
255     // set the player's state to playing
256     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
257     assert(SL_RESULT_SUCCESS == result);
258
259     // wait until the buffer queue is empty
260     SLBufferQueueState bufqstate;
261     for (;;) {
262         result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate);
263         assert(SL_RESULT_SUCCESS == result);
264         if (0 >= bufqstate.count) {
265             break;
266         }
267         sleep(1);
268     }
269
270     // destroy audio player
271     (*playerObject)->Destroy(playerObject);
272
273     // destroy output mix
274     (*outputMixObject)->Destroy(outputMixObject);
275
276     // destroy engine
277     (*engineObject)->Destroy(engineObject);
278
279     return EXIT_SUCCESS;
280 }