chiark / gitweb /
updated sles module
authorits-pointless <bored@goat.si>
Tue, 16 Jan 2018 08:37:19 +0000 (19:37 +1100)
committerFredrik Fornwall <fredrik@fornwall.net>
Tue, 16 Jan 2018 13:15:04 +0000 (14:15 +0100)
packages/libpulseaudio/build.sh
packages/libpulseaudio/module-sles-sink.c

index 3b081389f3aa5457c9a79d2f79ea213c84391071..d7f67ba667e0b9fdd77a09a46d7a263b66818f0c 100644 (file)
@@ -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"
index 5e196131699b9da9930f491ee07cd1daa4089bf4..313a1c42c4515a89d2c4a77fff029e758ca697c4 100644 (file)
 #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 <SLES/OpenSLES_Android.h>
+       #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=<name for the sink> "
-        "sink_properties=<properties for the sink> ");
+        "sink_properties=<properties for the sink> "
+        "rate=<sampling 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;
     }