diff --git a/packages/libpulseaudio/build.sh b/packages/libpulseaudio/build.sh index 3b081389f3..d7f67ba667 100644 --- a/packages/libpulseaudio/build.sh +++ b/packages/libpulseaudio/build.sh @@ -1,7 +1,7 @@ TERMUX_PKG_HOMEPAGE=https://www.freedesktop.org/wiki/Software/PulseAudio TERMUX_PKG_DESCRIPTION="A featureful, general-purpose sound server - shared libraries" TERMUX_PKG_VERSION=11.1 -TERMUX_PKG_REVISION=2 +TERMUX_PKG_REVISION=3 TERMUX_PKG_SHA256=f2521c525a77166189e3cb9169f75c2ee2b82fa3fcf9476024fbc2c3a6c9cd9e TERMUX_PKG_SRCURL=https://www.freedesktop.org/software/pulseaudio/releases/pulseaudio-${TERMUX_PKG_VERSION}.tar.xz TERMUX_PKG_DEPENDS="libltdl, libsndfile, libandroid-glob" diff --git a/packages/libpulseaudio/module-sles-sink.c b/packages/libpulseaudio/module-sles-sink.c index 5e19613169..313a1c42c4 100644 --- a/packages/libpulseaudio/module-sles-sink.c +++ b/packages/libpulseaudio/module-sles-sink.c @@ -46,19 +46,20 @@ #include "module-sles-sink-symdef.h" #ifdef USE_ANDROID_SIMPLE_BUFFER_QUEUE -#define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE -#define IID_BUFFERQUEUE SL_IID_ANDROIDSIMPLEBUFFERQUEUE -#define BufferQueueItf SLAndroidSimpleBufferQueueItf -#define BufferQueueState SLAndroidSimpleBufferQueueState -#define IID_BUFFERQUEUE_USED SL_IID_ANDROIDSIMPLEBUFFERQUEUE -#define INDEX index + #include + #define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE + #define IID_BUFFERQUEUE SL_IID_ANDROIDSIMPLEBUFFERQUEUE + #define BufferQueueItf SLAndroidSimpleBufferQueueItf + #define BufferQueueState SLAndroidSimpleBufferQueueState + #define IID_BUFFERQUEUE_USED SL_IID_ANDROIDSIMPLEBUFFERQUEUE + #define INDEX index #else -#define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_BUFFERQUEUE -#define IID_BUFFERQUEUE SL_IID_BUFFERQUEUE -#define BufferQueueItf SLBufferQueueItf -#define BufferQueueState SLBufferQueueState -#define IID_BUFFERQUEUE_USED IID_BUFFERQUEUE -#define INDEX playIndex + #define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_BUFFERQUEUE + #define IID_BUFFERQUEUE SL_IID_BUFFERQUEUE + #define BufferQueueItf SLBufferQueueItf + #define BufferQueueState SLBufferQueueState + #define IID_BUFFERQUEUE_USED IID_BUFFERQUEUE + #define INDEX playIndex #endif #define checkResult(r) do { \ @@ -79,7 +80,8 @@ PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_LOAD_ONCE(false); PA_MODULE_USAGE( "sink_name= " - "sink_properties= "); + "sink_properties= " + "rate= "); #define DEFAULT_SINK_NAME "OpenSL ES sink" #define BLOCK_USEC (PA_USEC_PER_SEC * 2) @@ -113,6 +115,7 @@ struct userdata { static const char* const valid_modargs[] = { "sink_name", "sink_properties", + "rate", NULL }; @@ -165,9 +168,9 @@ static void sink_update_requested_latency_cb(pa_sink *s) { pa_sink_set_max_request_within_thread(s, nbytes); } -void pa_init_sles_player(struct userdata *s) +static int pa_init_sles_player(struct userdata *s, SLint32 sl_rate) { - if (s == NULL) return; + if (s == NULL) return -1; SLresult result; // create engine @@ -190,10 +193,15 @@ void pa_init_sles_player(struct userdata *s) locator_bufferqueue.locatorType = DATALOCATOR_BUFFERQUEUE; locator_bufferqueue.numBuffers = 50; + if (sl_rate < 0) { + pa_log("Incompatible sample rate"); + return -1; + } + SLDataFormat_PCM pcm; pcm.formatType = SL_DATAFORMAT_PCM; pcm.numChannels = 2; - pcm.samplesPerSec = SL_SAMPLINGRATE_32; + pcm.samplesPerSec = sl_rate; pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; pcm.containerSize = 16; pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; @@ -216,9 +224,10 @@ void pa_init_sles_player(struct userdata *s) result = (*s->bqPlayerObject)->GetInterface(s->bqPlayerObject, IID_BUFFERQUEUE_USED, &s->bqPlayerBufferQueue); checkResult(result); result = (*s->bqPlayerPlay)->SetPlayState(s->bqPlayerPlay, SL_PLAYSTATE_PLAYING); checkResult(result); + return 0; } -void pa_destroy_sles_player(struct userdata *s){ +static void pa_destroy_sles_player(struct userdata *s){ if (s == NULL) return; (*s->bqPlayerPlay)->SetPlayState(s->bqPlayerPlay, SL_PLAYSTATE_STOPPED); (*s->bqPlayerObject)->Destroy(s->bqPlayerObject); @@ -245,16 +254,10 @@ static void process_render(struct userdata *u, pa_usec_t now) { (*u->bqPlayerBufferQueue)->Enqueue(u->bqPlayerBufferQueue, (uint8_t*) p + u->memchunk.index, u->memchunk.length); pa_memblock_release(u->memchunk.memblock); -/* pa_log_debug("Ate %lu bytes.", (unsigned long) chunk.length); */ u->timestamp += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec); - ate += u->memchunk.length; - - if (ate >= u->sink->thread_info.max_request) - break; + if (ate >= u->sink->thread_info.max_request) break; } - -/* pa_log_debug("Ate in sum %lu bytes (of %lu)", (unsigned long) ate, (unsigned long) nbytes); */ } static void thread_func(void *userdata) { @@ -304,6 +307,40 @@ fail: finish: pa_log_debug("Thread shutting down"); } + +static SLint32 PA2SLrate(int32_t rate){ + if (!(rate >= 8000 && rate <= 192000)) return -1; + switch(rate){ + case 8000: + return SL_SAMPLINGRATE_8; + case 11025: + return SL_SAMPLINGRATE_11_025; + case 12000: + return SL_SAMPLINGRATE_12; + case 16000: + return SL_SAMPLINGRATE_16; + case 22050: + return SL_SAMPLINGRATE_22_05; + case 24000: + return SL_SAMPLINGRATE_24; + case 32000: + return SL_SAMPLINGRATE_32; + case 44100: + return SL_SAMPLINGRATE_44_1; + case 48000: + return SL_SAMPLINGRATE_48; + case 64000: + return SL_SAMPLINGRATE_64; + case 88200: + return SL_SAMPLINGRATE_88_2; + case 96000: + return SL_SAMPLINGRATE_96; + case 192000: + return SL_SAMPLINGRATE_192; + default: + return -1; + } +} int pa__init(pa_module*m) { struct userdata *u = NULL; @@ -321,19 +358,33 @@ int pa__init(pa_module*m) { } // High rate causes glitches on some devices, this is needed to prevent it - ss.rate = 32000; - ss.channels = 2; - ss.format = PA_SAMPLE_S16LE; + //ss.rate = 32000; + //ss.channels = 2; + //ss.format = PA_SAMPLE_S16LE; + + //OK. That will allow users to define sampling rate under his responsibility + ss = m->core->default_sample_spec; map = m->core->default_channel_map; + if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { + pa_log("Invalid sample format specification or channel map"); + goto fail; + } - + //Needed. Don't touch + ss.channels = 2; + ss.format = PA_SAMPLE_S16LE; + int forceFormat = atoi(getenv("PROPERTY_OUTPUT_SAMPLE_RATE")); + if (forceFormat >= 8000 && forceFormat <= 192000) + ss.rate = forceFormat; + m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); - pa_init_sles_player(u); + if (pa_init_sles_player(u, PA2SLrate(ss.rate)) < 0) + goto fail; int buff[2] = {0, 0}; (*u->bqPlayerBufferQueue)->Enqueue(u->bqPlayerBufferQueue, buff, 1); @@ -343,7 +394,7 @@ int pa__init(pa_module*m) { pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)); pa_sink_new_data_set_sample_spec(&data, &ss); pa_sink_new_data_set_channel_map(&data, &map); - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, _("Null Output")); + pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, _("OpenSL ES Output")); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract"); if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { @@ -372,7 +423,7 @@ int pa__init(pa_module*m) { pa_sink_set_max_rewind(u->sink, nbytes); pa_sink_set_max_request(u->sink, nbytes); - if (!(u->thread = pa_thread_new("null-sink", thread_func, u))) { + if (!(u->thread = pa_thread_new("sles-sink", thread_func, u))) { pa_log("Failed to create thread."); goto fail; }