static void sl_free(void *data) { sl_t *sl = (sl_t*)data; if (!sl) return; if (sl->player) SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_STOPPED); if (sl->buffer_queue_object) SLObjectItf_Destroy(sl->buffer_queue_object); if (sl->output_mix) SLObjectItf_Destroy(sl->output_mix); if (sl->engine_object) SLObjectItf_Destroy(sl->engine_object); if (sl->lock) slock_free(sl->lock); if (sl->cond) scond_free(sl->cond); free(sl->buffer); free(sl->buffer_chunk); free(sl); }
static ALCboolean opensl_start_playback(ALCdevice *Device) { osl_data *data = Device->ExtraData; SLAndroidSimpleBufferQueueItf bufferQueue; SLPlayItf player; SLresult result; ALuint i; result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue); PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device); PRINTERR(result, "bufferQueue->RegisterCallback"); } if(SL_RESULT_SUCCESS == result) { data->frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); data->bufferSize = Device->UpdateSize * data->frameSize; data->buffer = calloc(1, data->bufferSize); if(!data->buffer) { result = SL_RESULT_MEMORY_FAILURE; PRINTERR(result, "calloc"); } } /* enqueue the first buffer to kick off the callbacks */ for(i = 0;i < Device->NumUpdates;i++) { if(SL_RESULT_SUCCESS == result) { result = (*bufferQueue)->Enqueue(bufferQueue, data->buffer, data->bufferSize); PRINTERR(result, "bufferQueue->Enqueue"); } } if(SL_RESULT_SUCCESS == result) { result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_PLAY, &player); PRINTERR(result, "bufferQueue->GetInterface"); } if(SL_RESULT_SUCCESS == result) { result = SLPlayItf_SetPlayState(player, SL_PLAYSTATE_PLAYING); PRINTERR(result, "player->SetPlayState"); } if(SL_RESULT_SUCCESS != result) { if(data->bufferQueueObject != NULL) SLObjectItf_Destroy(data->bufferQueueObject); data->bufferQueueObject = NULL; free(data->buffer); data->buffer = NULL; data->bufferSize = 0; return ALC_FALSE; } return ALC_TRUE; }
static bool sl_start(void *data) { sl_t *sl = (sl_t*)data; sl->is_paused = (SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING) == SL_RESULT_SUCCESS) ? false : true; return sl->is_paused ? false : true; }
static bool sl_stop(void *data) { sl_t *sl = (sl_t*)data; sl->is_paused = (SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_STOPPED) == SL_RESULT_SUCCESS) ? true : false; return sl->is_paused ? true : false; }
static void *sl_init(const char *device, unsigned rate, unsigned latency) { unsigned i; SLInterfaceID id; SLboolean req; SLresult res; sl_t *sl; SLDataFormat_PCM fmt_pcm = {0}; SLDataSource audio_src = {0}; SLDataSink audio_sink = {0}; SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {0}; SLDataLocator_OutputMix loc_outmix = {0}; settings_t *settings = config_get_ptr(); (void)device; id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; req = SL_BOOLEAN_TRUE; res = 0; sl = (sl_t*)calloc(1, sizeof(sl_t)); if (!sl) goto error; RARCH_LOG("[SLES]: Requested audio latency: %u ms.", latency); GOTO_IF_FAIL(slCreateEngine(&sl->engine_object, 0, NULL, 0, NULL, NULL)); GOTO_IF_FAIL(SLObjectItf_Realize(sl->engine_object, SL_BOOLEAN_FALSE)); GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->engine_object, SL_IID_ENGINE, &sl->engine)); GOTO_IF_FAIL(SLEngineItf_CreateOutputMix(sl->engine, &sl->output_mix, 0, NULL, NULL)); GOTO_IF_FAIL(SLObjectItf_Realize(sl->output_mix, SL_BOOLEAN_FALSE)); if (settings->audio.block_frames) sl->buf_size = settings->audio.block_frames * 4; else sl->buf_size = next_pow2(32 * latency); sl->buf_count = (latency * 4 * rate + 500) / 1000; sl->buf_count = (sl->buf_count + sl->buf_size / 2) / sl->buf_size; sl->buffer = (uint8_t**)calloc(sizeof(uint8_t*), sl->buf_count); if (!sl->buffer) goto error; sl->buffer_chunk = (uint8_t*)calloc(sl->buf_count, sl->buf_size); if (!sl->buffer_chunk) goto error; for (i = 0; i < sl->buf_count; i++) sl->buffer[i] = sl->buffer_chunk + i * sl->buf_size; RARCH_LOG("[SLES]: Setting audio latency: Block size = %u, Blocks = %u, Total = %u ...\n", sl->buf_size, sl->buf_count, sl->buf_size * sl->buf_count); fmt_pcm.formatType = SL_DATAFORMAT_PCM; fmt_pcm.numChannels = 2; fmt_pcm.samplesPerSec = rate * 1000; // Samplerate is in milli-Hz. fmt_pcm.bitsPerSample = 16; fmt_pcm.containerSize = 16; fmt_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; fmt_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; /* Android only. */ audio_src.pLocator = &loc_bufq; audio_src.pFormat = &fmt_pcm; loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; loc_bufq.numBuffers = sl->buf_count; loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; loc_outmix.outputMix = sl->output_mix; audio_sink.pLocator = &loc_outmix; GOTO_IF_FAIL(SLEngineItf_CreateAudioPlayer(sl->engine, &sl->buffer_queue_object, &audio_src, &audio_sink, 1, &id, &req)); GOTO_IF_FAIL(SLObjectItf_Realize(sl->buffer_queue_object, SL_BOOLEAN_FALSE)); GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &sl->buffer_queue)); sl->cond = scond_new(); sl->lock = slock_new(); (*sl->buffer_queue)->RegisterCallback(sl->buffer_queue, opensl_callback, sl); /* Enqueue a bit to get stuff rolling. */ sl->buffered_blocks = sl->buf_count; sl->buffer_index = 0; for (i = 0; i < sl->buf_count; i++) (*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[i], sl->buf_size); GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_PLAY, &sl->player)); GOTO_IF_FAIL(SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING)); return sl; error: RARCH_ERR("Couldn't initialize OpenSL ES driver, error code: [%d].\n", (int)res); sl_free(sl); return NULL; }
static bool sl_start(void *data) { sl_t *sl = (sl_t*)data; return SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING) == SL_RESULT_SUCCESS; }
static ALCboolean opensl_reset_playback(ALCdevice *Device) { osl_data *data = Device->ExtraData; SLDataLocator_AndroidSimpleBufferQueue loc_bufq; SLAndroidSimpleBufferQueueItf bufferQueue; SLDataLocator_OutputMix loc_outmix; SLDataFormat_PCM format_pcm; SLDataSource audioSrc; SLDataSink audioSnk; SLPlayItf player; SLInterfaceID id; SLboolean req; SLresult result; ALuint i; Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency; Device->UpdateSize = Device->UpdateSize * Device->NumUpdates / 2; Device->NumUpdates = 2; Device->Frequency = 44100; Device->FmtChans = DevFmtStereo; Device->FmtType = DevFmtShort; SetDefaultWFXChannelOrder(Device); id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; req = SL_BOOLEAN_TRUE; loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; loc_bufq.numBuffers = Device->NumUpdates; format_pcm.formatType = SL_DATAFORMAT_PCM; format_pcm.numChannels = ChannelsFromDevFmt(Device->FmtChans); format_pcm.samplesPerSec = Device->Frequency * 1000; format_pcm.bitsPerSample = BytesFromDevFmt(Device->FmtType) * 8; format_pcm.containerSize = format_pcm.bitsPerSample; format_pcm.channelMask = GetChannelMask(Device->FmtChans); format_pcm.endianness = SL_BYTEORDER_NATIVE; audioSrc.pLocator = &loc_bufq; audioSrc.pFormat = &format_pcm; loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; loc_outmix.outputMix = data->outputMix; audioSnk.pLocator = &loc_outmix; audioSnk.pFormat = NULL; result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req); PRINTERR(result, "engine->CreateAudioPlayer"); if(SL_RESULT_SUCCESS == result) { result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE); PRINTERR(result, "bufferQueue->Realize"); } if(SL_RESULT_SUCCESS == result) { result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue); PRINTERR(result, "bufferQueue->GetInterface"); } if(SL_RESULT_SUCCESS == result) { result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device); PRINTERR(result, "bufferQueue->RegisterCallback"); } if(SL_RESULT_SUCCESS == result) { data->frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); data->bufferSize = Device->UpdateSize * data->frameSize; data->buffer = calloc(1, data->bufferSize); if(!data->buffer) { result = SL_RESULT_MEMORY_FAILURE; PRINTERR(result, "calloc"); } } /* enqueue the first buffer to kick off the callbacks */ for(i = 0;i < Device->NumUpdates;i++) { if(SL_RESULT_SUCCESS == result) { result = (*bufferQueue)->Enqueue(bufferQueue, data->buffer, data->bufferSize); PRINTERR(result, "bufferQueue->Enqueue"); } } if(SL_RESULT_SUCCESS == result) { result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_PLAY, &player); PRINTERR(result, "bufferQueue->GetInterface"); } if(SL_RESULT_SUCCESS == result) { result = SLPlayItf_SetPlayState(player, SL_PLAYSTATE_PLAYING); PRINTERR(result, "player->SetPlayState"); } if(SL_RESULT_SUCCESS != result) { if(data->bufferQueueObject != NULL) SLObjectItf_Destroy(data->bufferQueueObject); data->bufferQueueObject = NULL; free(data->buffer); data->buffer = NULL; data->bufferSize = 0; return ALC_FALSE; } return ALC_TRUE; }