slesTestBassBoostPath.cpp revision 91bfd060b992810ca092f640f77f795bc3d008be
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#ifdef ANDROID
18#define LOG_NDEBUG 0
19#define LOG_TAG "slesTest_bassboost"
20
21#include <utils/Log.h>
22#else
23#define LOGV printf
24#endif
25
26#include <getopt.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30#include <unistd.h>
31#include <sys/time.h>
32#include <fcntl.h>
33
34#include "SLES/OpenSLES.h"
35#ifdef ANDROID
36#include "SLES/OpenSLES_Android.h"
37#endif
38
39
40#define MAX_NUMBER_INTERFACES 3
41#define MAX_NUMBER_OUTPUT_DEVICES 6
42
43#define TIME_S_BETWEEN_BB_ON_OFF 3
44
45//-----------------------------------------------------------------
46/* Exits the application if an error is encountered */
47#define ExitOnError(x) ExitOnErrorFunc(x,__LINE__)
48
49void ExitOnErrorFunc( SLresult result , int line)
50{
51    if (SL_RESULT_SUCCESS != result) {
52        fprintf(stderr, "%lu error code encountered at line %d, exiting\n", result, line);
53        exit(1);
54    }
55}
56
57
58//-----------------------------------------------------------------
59
60/* Play an audio path by opening a file descriptor on that path  */
61void TestBassBoostPathFromFD( SLObjectItf sl, const char* path, int16_t boostStrength)
62{
63    SLresult  result;
64    SLEngineItf EngineItf;
65
66    /* Objects this application uses: one player and an ouput mix */
67    SLObjectItf  player, outputMix;
68
69    /* Source of audio data to play */
70    SLDataSource            audioSource;
71#ifdef ANDROID
72    SLDataLocator_AndroidFD locatorFd;
73#else
74    SLDataLocator_URI       locatorUri;
75#endif
76    SLDataFormat_MIME       mime;
77
78    /* Data sinks for the audio player */
79    SLDataSink               audioSink;
80    SLDataLocator_OutputMix  locator_outputmix;
81
82    /* Play and PrefetchStatus interfaces for the audio player */
83    SLPlayItf              playItf;
84    SLPrefetchStatusItf    prefetchItf;
85    SLBassBoostItf         bbItf;
86
87    SLboolean required[MAX_NUMBER_INTERFACES];
88    SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
89
90    /* Get the SL Engine Interface which is implicit */
91    result = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void*)&EngineItf);
92    ExitOnError(result);
93
94    /* Initialize arrays required[] and iidArray[] */
95    for (int i=0 ; i < MAX_NUMBER_INTERFACES ; i++) {
96        required[i] = SL_BOOLEAN_FALSE;
97        iidArray[i] = SL_IID_NULL;
98    }
99
100    /* ------------------------------------------------------ */
101    /* Configuration of the output mix  */
102
103    /* Create Output Mix object to be used by the player */
104     result = (*EngineItf)->CreateOutputMix(EngineItf, &outputMix, 1, iidArray, required);
105     ExitOnError(result);
106
107    /* Realize the Output Mix object in synchronous mode */
108    result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE);
109    ExitOnError(result);
110
111    /* Setup the data sink structure */
112    locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
113    locator_outputmix.outputMix   = outputMix;
114    audioSink.pLocator            = (void*)&locator_outputmix;
115    audioSink.pFormat             = NULL;
116
117    /* ------------------------------------------------------ */
118    /* Configuration of the player  */
119
120    /* Set arrays required[] and iidArray[] for SLPrefetchStatusItf interfaces */
121    /*  (SLPlayItf is implicit) */
122    required[0] = SL_BOOLEAN_TRUE;
123    iidArray[0] = SL_IID_PREFETCHSTATUS;
124    required[1] = SL_BOOLEAN_TRUE;
125    iidArray[1] = SL_IID_BASSBOOST;
126
127#ifdef ANDROID
128    /* Setup the data source structure for the URI */
129    locatorFd.locatorType = SL_DATALOCATOR_ANDROIDFD;
130    int fd = open(path, O_RDONLY);
131    if (fd == -1) {
132        ExitOnError(SL_RESULT_RESOURCE_ERROR);
133    }
134    locatorFd.fd = (SLint32) fd;
135    locatorFd.length = SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE;
136    locatorFd.offset = 0;
137#else
138    locatorUri.locatorType = SL_DATALOCATOR_URI;
139    locatorUri.URI = (SLchar *) path;
140#endif
141
142    mime.formatType = SL_DATAFORMAT_MIME;
143    /*     this is how ignored mime information is specified, according to OpenSL ES spec
144     *     in 9.1.6 SLDataFormat_MIME and 8.23 SLMetadataTraversalItf GetChildInfo */
145    mime.mimeType      = (SLchar*)NULL;
146    mime.containerType = SL_CONTAINERTYPE_UNSPECIFIED;
147
148    audioSource.pFormat  = (void*)&mime;
149#ifdef ANDROID
150    audioSource.pLocator = (void*)&locatorFd;
151#else
152    audioSource.pLocator = (void*)&locatorUri;
153#endif
154
155    /* Create the audio player */
156    result = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 2,
157            iidArray, required);
158    ExitOnError(result);
159
160    /* Realize the player in synchronous mode. */
161    result = (*player)->Realize(player, SL_BOOLEAN_FALSE); ExitOnError(result);
162    fprintf(stdout, "URI example: after Realize\n");
163
164    /* Get the SLPlayItf, SLPrefetchStatusItf and SLAndroidStreamTypeItf interfaces for the player*/
165    result = (*player)->GetInterface(player, SL_IID_PLAY, (void*)&playItf);
166    ExitOnError(result);
167
168    result = (*player)->GetInterface(player, SL_IID_PREFETCHSTATUS, (void*)&prefetchItf);
169    ExitOnError(result);
170
171    result = (*player)->GetInterface(player, SL_IID_BASSBOOST, (void*)&bbItf);
172    ExitOnError(result);
173
174    fprintf(stdout, "Player configured\n");
175
176    /* ------------------------------------------------------ */
177    /* Playback and test */
178
179    /* Start the data prefetching by setting the player to the paused state */
180    result = (*playItf)->SetPlayState( playItf, SL_PLAYSTATE_PAUSED );
181    ExitOnError(result);
182
183    /* Wait until there's data to play */
184    SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;
185    while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA) {
186        usleep(100 * 1000);
187        (*prefetchItf)->GetPrefetchStatus(prefetchItf, &prefetchStatus);
188        ExitOnError(result);
189    }
190
191    /* Get duration */
192    SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
193    result = (*playItf)->GetDuration(playItf, &durationInMsec);
194    ExitOnError(result);
195    if (durationInMsec == SL_TIME_UNKNOWN) {
196        durationInMsec = 5000;
197    }
198
199    /* Start playback */
200    fprintf(stdout, "Starting to play\n");
201    result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING );
202    ExitOnError(result);
203
204    /* Configure BassBoost */
205    SLboolean strengthSupported = SL_BOOLEAN_FALSE;
206    result = (*bbItf)->IsStrengthSupported(bbItf, &strengthSupported);
207    ExitOnError(result);
208    if (SL_BOOLEAN_FALSE == strengthSupported) {
209        fprintf(stdout, "BassBoost strength is not supported on this platform. Too bad!\n");
210    } else {
211        fprintf(stdout, "BassBoost strength is supported, setting strength to %d\n", boostStrength);
212        result = (*bbItf)->SetStrength(bbItf, boostStrength);
213        ExitOnError(result);
214    }
215
216    SLpermille strength = 0;
217    result = (*bbItf)->GetRoundedStrength(bbItf, &strength);
218    ExitOnError(result);
219    fprintf(stdout, "Rounded strength of boost = %d\n", strength);
220
221
222    /* Switch BassBoost on/off every TIME_S_BETWEEN_BB_ON_OFF seconds */
223    SLboolean enabled = SL_BOOLEAN_TRUE;
224    result = (*bbItf)->SetEnabled(bbItf, enabled);
225    ExitOnError(result);
226    for(unsigned int j=0 ; j<(durationInMsec/1000*TIME_S_BETWEEN_BB_ON_OFF) ; j++) {
227        usleep(TIME_S_BETWEEN_BB_ON_OFF * 1000 * 1000);
228        result = (*bbItf)->IsEnabled(bbItf, &enabled);
229        ExitOnError(result);
230        enabled = enabled == SL_BOOLEAN_TRUE ? SL_BOOLEAN_FALSE : SL_BOOLEAN_TRUE;
231        result = (*bbItf)->SetEnabled(bbItf, enabled);
232        if (SL_BOOLEAN_TRUE == enabled) {
233            fprintf(stdout, "BassBoost on\n");
234        } else {
235            fprintf(stdout, "BassBoost off\n");
236        }
237        ExitOnError(result);
238    }
239
240    /* Make sure player is stopped */
241    fprintf(stdout, "Stopping playback\n");
242    result = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
243    ExitOnError(result);
244
245    /* Destroy the player */
246    (*player)->Destroy(player);
247
248    /* Destroy Output Mix object */
249    (*outputMix)->Destroy(outputMix);
250
251#ifdef ANDROID
252    close(fd);
253#endif
254}
255
256//-----------------------------------------------------------------
257int main(int argc, char* const argv[])
258{
259    LOGV("Starting %s\n", argv[0]);
260
261    SLresult    result;
262    SLObjectItf sl;
263
264    fprintf(stdout, "OpenSL ES test %s: exercises SLBassBoostItf ", argv[0]);
265    fprintf(stdout, "and AudioPlayer with SLDataLocator_AndroidFD source / OutputMix sink\n");
266    fprintf(stdout, "Plays the sound file designated by the given path, ");
267    fprintf(stdout, "and applies a bass boost effect of the specified strength,\n");
268    fprintf(stdout, "where strength is a integer value between 0 and 1000.\n");
269    fprintf(stdout, "Every %d seconds, the BassBoost will be turned on and off.\n",
270            TIME_S_BETWEEN_BB_ON_OFF);
271
272    if (argc < 3) {
273        fprintf(stdout, "Usage: \t%s path bass_boost_strength\n", argv[0]);
274        fprintf(stdout, "Example: \"%s /sdcard/my.mp3 1000\" \n", argv[0]);
275        exit(1);
276    }
277
278    SLEngineOption EngineOption[] = {
279            {(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
280    };
281
282    result = slCreateEngine( &sl, 1, EngineOption, 0, NULL, NULL);
283    ExitOnError(result);
284
285    /* Realizing the SL Engine in synchronous mode. */
286    result = (*sl)->Realize(sl, SL_BOOLEAN_FALSE);
287    ExitOnError(result);
288
289    // intentionally not checking that argv[2], the bassboost strength, is between 0 and 1000
290    TestBassBoostPathFromFD(sl, argv[1], (int16_t)atoi(argv[2]));
291
292    /* Shutdown OpenSL ES */
293    (*sl)->Destroy(sl);
294    exit(0);
295
296    return 0;
297}
298