从playfield开源代码复制的opensl es初始化代码
/* -*- coding: utf-8; tab-width: 8; indent-tabs-mode: t; -*- *//** Copyright (c) 2025, Awe Morris. All rights reserved.*//** HAL for OpenSL ES on Android*//* Base */ #include "stratohal/platform.h"/* OpenSLES */ #include <SLES/OpenSLES.h> #include <SLES/OpenSLES_Android.h>/* POSIX */ #include <pthread.h> #include <sys/types.h>/* C */ #include <stdlib.h> #include <string.h> #include <math.h>/** sound Buffer Parameters*/ #define SAMPLING_RATE (44100) #define CHANNELS (2) #define FRAME_SIZE (4) #define BUF_FRAMES (SAMPLING_RATE / 4)/** OpenSL ES Objects*/ static SLObjectItf engine_object; static SLEngineItf engine_engine; static SLObjectItf output_mix_object; static SLObjectItf bq_player_object[SOUND_TRACKS]; static SLPlayItf bq_player_play[SOUND_TRACKS]; static SLAndroidSimpleBufferQueueItf bq_player_buffer_queue[SOUND_TRACKS];/* Buffers */ static uint32_t sample_buf[SOUND_TRACKS][BUF_FRAMES];/* Mutex objects to synchronize accesses to sample_buf */ static pthread_mutex_t sound_mutex[SOUND_TRACKS];/* Input Streams */ static struct wave *wave[SOUND_TRACKS];/* Volume Values */ static float volume[SOUND_TRACKS];/* Finish Flags */ static bool pre_finish[SOUND_TRACKS]; /* Shows if we reached an end-of-stream. */ static bool post_finish[SOUND_TRACKS]; /* Shows if we finished a playback of a final buffer. *//** Forward Declarations*/ static void play_callback(SLAndroidSimpleBufferQueueItf bq, void *context); static void enqueue(int stream); static void scale_samples(uint32_t *buf, int frames, float vol);/** Initialize OpenSL ES.*/ void init_opensl_es(void) {for (int i = 0; i < SOUND_TRACKS; i++)pthread_mutex_init(&sound_mutex[i], NULL);slCreateEngine(&engine_object, 0, NULL, 0, NULL, NULL);(*engine_object)->Realize(engine_object, SL_BOOLEAN_FALSE);(*engine_object)->GetInterface(engine_object, SL_IID_ENGINE, &engine_engine);const SLInterfaceID outids[1] = {SL_IID_PLAYBACKRATE};const SLboolean outreq[1] = {SL_BOOLEAN_FALSE};(*engine_engine)->CreateOutputMix(engine_engine, &output_mix_object, 1, outids, outreq);(*output_mix_object)->Realize(output_mix_object, SL_BOOLEAN_FALSE);SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,2,SL_SAMPLINGRATE_44_1,SL_PCMSAMPLEFORMAT_FIXED_16,SL_PCMSAMPLEFORMAT_FIXED_16,SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,SL_BYTEORDER_LITTLEENDIAN};SLDataSource audio_src = {&loc_bufq, &format_pcm};SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, output_mix_object};SLDataSink audioSnk = {&loc_outmix, NULL};const SLInterfaceID bqids[1] = {SL_IID_BUFFERQUEUE};const SLboolean bqreq[1] = {SL_BOOLEAN_TRUE};for (int i = 0; i < SOUND_TRACKS; i++) {(*engine_engine)->CreateAudioPlayer(engine_engine, &bq_player_object[i], &audio_src, &audioSnk, 1, bqids, bqreq);(*bq_player_object[i])->Realize(bq_player_object[i], SL_BOOLEAN_FALSE);(*bq_player_object[i])->GetInterface(bq_player_object[i], SL_IID_PLAY, &bq_player_play[i]);(*bq_player_object[i])->GetInterface(bq_player_object[i], SL_IID_BUFFERQUEUE, &bq_player_buffer_queue[i]);(*bq_player_buffer_queue[i])->RegisterCallback(bq_player_buffer_queue[i], play_callback, (void *)(intptr_t)i);(*bq_player_play[i])->SetCallbackEventsMask(bq_player_play[i], SL_PLAYEVENT_HEADATEND);(*bq_player_play[i])->SetPlayState(bq_player_play[i], SL_PLAYSTATE_PLAYING);} }void sl_pause_sound(void) {for (int i = 0; i < SOUND_TRACKS; i++) {if (bq_player_play[i] != NULL)(*bq_player_play[i])->SetPlayState(bq_player_play[i], SL_PLAYSTATE_STOPPED);} }void sl_resume_sound(void) {for (int i = 0; i < SOUND_TRACKS; i++) {if (bq_player_play[i] != NULL)(*bq_player_play[i])->SetPlayState(bq_player_play[i], SL_PLAYSTATE_PLAYING);} }static void play_callback(SLAndroidSimpleBufferQueueItf bq, void *context) {int stream = (intptr_t)context;pthread_mutex_lock(&sound_mutex[stream]);enqueue(stream);pthread_mutex_unlock(&sound_mutex[stream]); }static void enqueue(int stream) {if (wave[stream] == NULL)return;/* Set a post-finish flag if an end-of-stream was detected in a previous filling. */if (pre_finish[stream]) {wave[stream] = NULL;post_finish[stream] = true;return;}/* Get PCM samples. */int read_samples = get_wave_samples(wave[stream], sample_buf[stream], BUF_FRAMES);/* Fill the remaining samples by zeros for a case where we have reached an end-of-stream. */if (read_samples < BUF_FRAMES)memset(sample_buf[stream] + read_samples, 0, (size_t)(BUF_FRAMES - read_samples) * FRAME_SIZE);/* Scale samples by a volume value. */scale_samples(sample_buf[stream], BUF_FRAMES, volume[stream]);/* Write the buffer. */(*bq_player_buffer_queue[stream])->Enqueue(bq_player_buffer_queue[stream], sample_buf[stream], read_samples * FRAME_SIZE);/* Set a pre-finish flag if we reached an end-of-stream. */if (is_wave_eos(wave[stream]))pre_finish[stream] = true; }static void scale_samples(uint32_t *buf, int frames, float vol) {float scale;uint32_t frame;int32_t il, ir; /* intermediate L/R */int16_t sl, sr; /* source L/R*/int16_t dl, dr; /* destination L/R */int i;__sync_synchronize();/* Convert a scale factor to an exponential value. */scale = (powf(10.0f, vol) - 1.0f) / (10.0f - 1.0f);/* Scale samples. */for (i = 0; i < frames; i++) {frame = buf[i];sl = (int16_t)(uint16_t)frame;sr = (int16_t)(uint16_t)(frame >> 16);il = (int)(sl * scale);ir = (int)(sr * scale);il = il > 32767 ? 32767 : il;il = il < -32768 ? -32768 : il;ir = ir > 32767 ? 32767 : ir;ir = ir < -32768 ? -32768 : ir;dl = (int16_t)il;dr = (int16_t)ir;buf[i] = ((uint32_t)(uint16_t)dl) | (((uint32_t)(uint16_t)dr) << 16);} }/** HAL*/bool play_sound(int stream, struct wave *w) {if (bq_player_play[stream] == NULL)return true;pthread_mutex_lock(&sound_mutex[stream]);{wave[stream] = w;pre_finish[stream] = false;post_finish[stream] = false;enqueue(stream);}pthread_mutex_unlock(&sound_mutex[stream]);return true; }bool stop_sound(int stream) {if (bq_player_play[stream] == NULL)return true;pthread_mutex_lock(&sound_mutex[stream]);{wave[stream] = NULL;pre_finish[stream] = false;post_finish[stream] = false;}pthread_mutex_unlock(&sound_mutex[stream]);return true; }bool set_sound_volume(int stream, float vol) {volume[stream] = vol;__sync_synchronize();return true; }bool is_sound_finished(int stream) {__sync_synchronize();if (!post_finish[stream])return false;return true; }