1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3  *  Copyright (C) 2011-2017 - Daniel De Matteis
4  *
5  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
6  *  of the GNU General Public License as published by the Free Software Found-
7  *  ation, either version 3 of the License, or (at your option) any later version.
8  *
9  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11  *  PURPOSE.  See the GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License along with RetroArch.
14  *  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <SLES/OpenSLES.h>
18 #ifdef ANDROID
19 #include <SLES/OpenSLES_Android.h>
20 #endif
21 
22 #include <rthreads/rthreads.h>
23 
24 #include "../../retroarch.h"
25 
26 /* Helper macros, COM-style. */
27 #define SLObjectItf_Realize(a, ...) ((*(a))->Realize(a, __VA_ARGS__))
28 #define SLObjectItf_GetInterface(a, ...) ((*(a))->GetInterface(a, __VA_ARGS__))
29 #define SLObjectItf_Destroy(a) ((*(a))->Destroy((a)))
30 
31 #define SLEngineItf_CreateOutputMix(a, ...) ((*(a))->CreateOutputMix(a, __VA_ARGS__))
32 #define SLEngineItf_CreateAudioPlayer(a, ...) ((*(a))->CreateAudioPlayer(a, __VA_ARGS__))
33 
34 #define SLPlayItf_SetPlayState(a, ...) ((*(a))->SetPlayState(a, __VA_ARGS__))
35 
36 typedef struct sl
37 {
38    uint8_t **buffer;
39    uint8_t *buffer_chunk;
40 
41    SLObjectItf engine_object;
42    SLEngineItf engine;
43 
44    SLObjectItf output_mix;
45    SLObjectItf buffer_queue_object;
46    SLAndroidSimpleBufferQueueItf buffer_queue;
47    SLPlayItf player;
48 
49    slock_t *lock;
50    scond_t *cond;
51    unsigned buf_size;
52    unsigned buf_count;
53    unsigned buffer_index;
54    unsigned buffer_ptr;
55    volatile unsigned buffered_blocks;
56    bool nonblock;
57    bool is_paused;
58 } sl_t;
59 
opensl_callback(SLAndroidSimpleBufferQueueItf bq,void * ctx)60 static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *ctx)
61 {
62    sl_t *sl = (sl_t*)ctx;
63    __sync_fetch_and_sub(&sl->buffered_blocks, 1);
64    scond_signal(sl->cond);
65 }
66 
67 #define GOTO_IF_FAIL(x) do { \
68    if ((res = (x)) != SL_RESULT_SUCCESS) \
69       goto error; \
70 } while (0)
71 
sl_free(void * data)72 static void sl_free(void *data)
73 {
74    sl_t *sl = (sl_t*)data;
75    if (!sl)
76       return;
77 
78    if (sl->player)
79       SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_STOPPED);
80 
81    if (sl->buffer_queue_object)
82       SLObjectItf_Destroy(sl->buffer_queue_object);
83 
84    if (sl->output_mix)
85       SLObjectItf_Destroy(sl->output_mix);
86 
87    if (sl->engine_object)
88       SLObjectItf_Destroy(sl->engine_object);
89 
90    if (sl->lock)
91       slock_free(sl->lock);
92    if (sl->cond)
93       scond_free(sl->cond);
94 
95    free(sl->buffer);
96    free(sl->buffer_chunk);
97    free(sl);
98 }
99 
sl_init(const char * device,unsigned rate,unsigned latency,unsigned block_frames,unsigned * new_rate)100 static void *sl_init(const char *device, unsigned rate, unsigned latency,
101       unsigned block_frames,
102       unsigned *new_rate)
103 {
104    unsigned i;
105    SLDataFormat_PCM fmt_pcm                        = {0};
106    SLDataSource audio_src                          = {0};
107    SLDataSink audio_sink                           = {0};
108    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {0};
109    SLDataLocator_OutputMix loc_outmix              = {0};
110    SLresult res                                    = 0;
111    SLInterfaceID                                id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
112    SLboolean                                req    = SL_BOOLEAN_TRUE;
113    sl_t                                        *sl = (sl_t*)calloc(1, sizeof(sl_t));
114 
115    (void)device;
116    if (!sl)
117       goto error;
118 
119    RARCH_LOG("[OpenSL]: Requested audio latency: %u ms.", latency);
120 
121    GOTO_IF_FAIL(slCreateEngine(&sl->engine_object, 0, NULL, 0, NULL, NULL));
122    GOTO_IF_FAIL(SLObjectItf_Realize(sl->engine_object, SL_BOOLEAN_FALSE));
123    GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->engine_object, SL_IID_ENGINE, &sl->engine));
124 
125    GOTO_IF_FAIL(SLEngineItf_CreateOutputMix(sl->engine, &sl->output_mix, 0, NULL, NULL));
126    GOTO_IF_FAIL(SLObjectItf_Realize(sl->output_mix, SL_BOOLEAN_FALSE));
127 
128    if (block_frames)
129       sl->buf_size  = block_frames * 4;
130    else
131       sl->buf_size  = next_pow2(32 * latency);
132 
133    sl->buf_count    = (latency * 4 * rate + 500) / 1000;
134    sl->buf_count    = (sl->buf_count + sl->buf_size / 2) / sl->buf_size;
135 
136    if (sl->buf_count < 2)
137       sl->buf_count = 2;
138 
139    sl->buffer       = (uint8_t**)calloc(sizeof(uint8_t*), sl->buf_count);
140    if (!sl->buffer)
141       goto error;
142 
143    sl->buffer_chunk = (uint8_t*)calloc(sl->buf_count, sl->buf_size);
144    if (!sl->buffer_chunk)
145       goto error;
146 
147    for (i = 0; i < sl->buf_count; i++)
148       sl->buffer[i] = sl->buffer_chunk + i * sl->buf_size;
149 
150    RARCH_LOG("[OpenSL]: Setting audio latency: Block size = %u, Blocks = %u, Total = %u ...\n",
151          sl->buf_size, sl->buf_count, sl->buf_size * sl->buf_count);
152 
153    fmt_pcm.formatType     = SL_DATAFORMAT_PCM;
154    fmt_pcm.numChannels    = 2;
155    fmt_pcm.samplesPerSec  = rate * 1000; /* Samplerate is in milli-Hz. */
156    fmt_pcm.bitsPerSample  = 16;
157    fmt_pcm.containerSize  = 16;
158    fmt_pcm.channelMask    = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
159    fmt_pcm.endianness     = SL_BYTEORDER_LITTLEENDIAN; /* Android only. */
160 
161    audio_src.pLocator     = &loc_bufq;
162    audio_src.pFormat      = &fmt_pcm;
163 
164    loc_bufq.locatorType   = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
165    loc_bufq.numBuffers    = sl->buf_count;
166 
167    loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
168    loc_outmix.outputMix   = sl->output_mix;
169 
170    audio_sink.pLocator    = &loc_outmix;
171 
172    GOTO_IF_FAIL(SLEngineItf_CreateAudioPlayer(sl->engine, &sl->buffer_queue_object,
173             &audio_src, &audio_sink,
174             1, &id, &req));
175    GOTO_IF_FAIL(SLObjectItf_Realize(sl->buffer_queue_object, SL_BOOLEAN_FALSE));
176 
177    GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
178             &sl->buffer_queue));
179 
180    sl->cond               = scond_new();
181    sl->lock               = slock_new();
182 
183    (*sl->buffer_queue)->RegisterCallback(sl->buffer_queue, opensl_callback, sl);
184 
185    /* Enqueue a bit to get stuff rolling. */
186    sl->buffered_blocks    = sl->buf_count;
187    sl->buffer_index       = 0;
188 
189    for (i = 0; i < sl->buf_count; i++)
190       (*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[i], sl->buf_size);
191 
192    GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_PLAY, &sl->player));
193    GOTO_IF_FAIL(SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING));
194 
195    return sl;
196 
197 error:
198    RARCH_ERR("[OpenSL]: Couldn't initialize OpenSL ES driver, error code: [%d].\n", (int)res);
199    sl_free(sl);
200    return NULL;
201 }
202 
sl_stop(void * data)203 static bool sl_stop(void *data)
204 {
205    sl_t      *sl = (sl_t*)data;
206    sl->is_paused = (SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_STOPPED)
207          == SL_RESULT_SUCCESS) ? true : false;
208 
209    return sl->is_paused ? true : false;
210 }
211 
sl_alive(void * data)212 static bool sl_alive(void *data)
213 {
214    sl_t *sl = (sl_t*)data;
215    if (!sl)
216       return false;
217    return !sl->is_paused;
218 }
219 
sl_set_nonblock_state(void * data,bool state)220 static void sl_set_nonblock_state(void *data, bool state)
221 {
222    sl_t *sl = (sl_t*)data;
223    if (sl)
224       sl->nonblock = state;
225 }
226 
sl_start(void * data,bool is_shutdown)227 static bool sl_start(void *data, bool is_shutdown)
228 {
229    sl_t      *sl = (sl_t*)data;
230    sl->is_paused = (SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING)
231          == SL_RESULT_SUCCESS) ? false : true;
232    return sl->is_paused ? false : true;
233 }
234 
sl_write(void * data,const void * buf_,size_t size)235 static ssize_t sl_write(void *data, const void *buf_, size_t size)
236 {
237    sl_t           *sl = (sl_t*)data;
238    size_t     written = 0;
239    const uint8_t *buf = (const uint8_t*)buf_;
240 
241    while (size)
242    {
243       size_t avail_write;
244 
245       if (sl->nonblock)
246       {
247          if (sl->buffered_blocks == sl->buf_count)
248             break;
249       }
250       else
251       {
252          slock_lock(sl->lock);
253          while (sl->buffered_blocks == sl->buf_count)
254             scond_wait(sl->cond, sl->lock);
255          slock_unlock(sl->lock);
256       }
257 
258       avail_write = MIN(sl->buf_size - sl->buffer_ptr, size);
259 
260       if (avail_write)
261       {
262          memcpy(sl->buffer[sl->buffer_index] + sl->buffer_ptr, buf, avail_write);
263          sl->buffer_ptr += avail_write;
264          buf            += avail_write;
265          size           -= avail_write;
266          written        += avail_write;
267       }
268 
269       if (sl->buffer_ptr >= sl->buf_size)
270       {
271          SLresult res     = (*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[sl->buffer_index], sl->buf_size);
272          sl->buffer_index = (sl->buffer_index + 1) % sl->buf_count;
273          __sync_fetch_and_add(&sl->buffered_blocks, 1);
274          sl->buffer_ptr   = 0;
275 
276          if (res != SL_RESULT_SUCCESS)
277          {
278             RARCH_ERR("[OpenSL]: Failed to write! (Error: 0x%x)\n", (unsigned)res);
279             return -1;
280          }
281       }
282    }
283 
284    return written;
285 }
286 
sl_write_avail(void * data)287 static size_t sl_write_avail(void *data)
288 {
289    sl_t *sl = (sl_t*)data;
290    size_t avail = (sl->buf_count - (int)sl->buffered_blocks - 1) * sl->buf_size + (sl->buf_size - (int)sl->buffer_ptr);
291    return avail;
292 }
293 
sl_buffer_size(void * data)294 static size_t sl_buffer_size(void *data)
295 {
296    sl_t *sl = (sl_t*)data;
297    return sl->buf_size * sl->buf_count;
298 }
299 
sl_use_float(void * data)300 static bool sl_use_float(void *data)
301 {
302    (void)data;
303    return false;
304 }
305 
306 audio_driver_t audio_opensl = {
307    sl_init,
308    sl_write,
309    sl_stop,
310    sl_start,
311    sl_alive,
312    sl_set_nonblock_state,
313    sl_free,
314    sl_use_float,
315    "opensl",
316    NULL,
317    NULL,
318    sl_write_avail,
319    sl_buffer_size,
320 };
321