]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Add D-Bus convolution filter controls; enable convolution filters to be turned on...
authorMike Brady <mikebrady@eircom.net>
Mon, 11 Nov 2019 21:45:29 +0000 (21:45 +0000)
committerMike Brady <mikebrady@eircom.net>
Mon, 11 Nov 2019 21:45:29 +0000 (21:45 +0000)
FFTConvolver/convolver.cpp
FFTConvolver/convolver.h
common.h
dbus-service.c
documents/sample dbus commands
player.c
shairport.c

index f8f6017937f4a7630d0fa2bc3667bfdf3eb37846..a282482917f439b23803514dce6577a6d9cc4710 100644 (file)
@@ -1,72 +1,85 @@
 
 
-#include "convolver.h"
+#include <pthread.h>
 #include <sndfile.h>
+#include "convolver.h"
 #include "FFTConvolver.h"
 #include "Utilities.h"
 
-extern "C" void _die(const char *filename, const int linenumber, const char *format, ...);
+extern "C" void _warn(const char *filename, const int linenumber, const char *format, ...);
 extern "C" void _debug(const char *filename, const int linenumber, int level, const char *format, ...);
 
-#define die(...) _die(__FILE__, __LINE__, __VA_ARGS__)
+#define warn(...) _warn(__FILE__, __LINE__, __VA_ARGS__)
 #define debug(...) _debug(__FILE__, __LINE__, __VA_ARGS__)
 
-static fftconvolver::FFTConvolver convolver_l;
-static fftconvolver::FFTConvolver convolver_r;
+fftconvolver::FFTConvolver convolver_l;
+fftconvolver::FFTConvolver convolver_r;
+
+// always lock use this when accessing the playing conn value
+pthread_mutex_t convolver_lock = PTHREAD_MUTEX_INITIALIZER;
 
 
-void convolver_init(const char* filename, int max_length)
-{
+int convolver_init(const char* filename, int max_length) {
+  int success = 0;
   SF_INFO info;
-  assert(filename);
-  SNDFILE* file = sf_open(filename, SFM_READ, &info);
-  assert(file);
-  
-  if (info.samplerate != 44100)
-    die("Impulse file \"%s\" sample rate is %d Hz. Only 44100 Hz is supported", filename, info.samplerate);
-  
-  if (info.channels != 1 && info.channels != 2)
-    die("Impulse file \"%s\" contains %d channels. Only 1 or 2 is supported.", filename, info.channels);
+  if (filename) {
+    SNDFILE* file = sf_open(filename, SFM_READ, &info);
+    if (file) {
   
-  const size_t size = info.frames > max_length ? max_length : info.frames;
-  float buffer[size*info.channels];
+      if (info.samplerate == 44100)  {  
+        if ((info.channels == 1) || (info.channels == 2)) {
+          const size_t size = info.frames > max_length ? max_length : info.frames;
+          float buffer[size*info.channels];
   
-  size_t l = sf_readf_float(file, buffer, size);
-  assert(l == size);
-
-  convolver_l.reset(); // it is possible that init could be called more than once
-  convolver_r.reset(); // so it could be necessary to remove all previous settings
+          size_t l = sf_readf_float(file, buffer, size);
+          if (l != 0) {
+            pthread_mutex_lock(&convolver_lock);
+            convolver_l.reset(); // it is possible that init could be called more than once
+            convolver_r.reset(); // so it could be necessary to remove all previous settings
   
-  if (info.channels == 1) {
-    convolver_l.init(352, buffer, size);
-    convolver_r.init(352, buffer, size);
-  } else {
-    // deinterleave
-    float buffer_l[size];
-    float buffer_r[size];
+            if (info.channels == 1) {
+              convolver_l.init(352, buffer, size);
+              convolver_r.init(352, buffer, size);
+            } else {
+              // deinterleave
+              float buffer_l[size];
+              float buffer_r[size];
     
-    unsigned int i;
-    for (i=0; i<size; ++i)
-    {
-      buffer_l[i] = buffer[2*i+0];
-      buffer_r[i] = buffer[2*i+1];
-    }
+              unsigned int i;
+              for (i=0; i<size; ++i)
+              {
+                buffer_l[i] = buffer[2*i+0];
+                buffer_r[i] = buffer[2*i+1];
+              }
     
-    convolver_l.init(352, buffer_l, size);
-    convolver_r.init(352, buffer_r, size);
+              convolver_l.init(352, buffer_l, size);
+              convolver_r.init(352, buffer_r, size);
+              
+            }
+            pthread_mutex_unlock(&convolver_lock);
+            success = 1;
+          }
+          debug(1, "IR initialized from \"%s\" with %d channels and %d samples", filename, info.channels, size);
+        } else {
+          warn("Impulse file \"%s\" contains %d channels. Only 1 or 2 is supported.", filename, info.channels);
+        }
+      } else {
+        warn("Impulse file \"%s\" sample rate is %d Hz. Only 44100 Hz is supported", filename, info.samplerate);
+      }
+      sf_close(file);
+    }
   }
-  
-  debug(1, "IR initialized from \"%s\" with %d channels and %d samples", filename, info.channels, size);
-  
-  sf_close(file);
+  return success;
 }
 
-void convolver_process_l(float* data, int length)
-{
+void convolver_process_l(float* data, int length) {
+  pthread_mutex_lock(&convolver_lock);
   convolver_l.process(data, data, length);
+  pthread_mutex_unlock(&convolver_lock);
 }
 
-void convolver_process_r(float* data, int length)
-{
+void convolver_process_r(float* data, int length) {
+  pthread_mutex_lock(&convolver_lock);
   convolver_r.process(data, data, length);
+  pthread_mutex_unlock(&convolver_lock);
 }
index 1b5a98ae50eccadf115ee5d466ca8e1282fdcce3..56f7bc22915ded06b17940cec366c57fc4679900 100644 (file)
@@ -5,7 +5,7 @@
 extern "C" {
 #endif
   
-void convolver_init(const char* file, int max_length);
+int convolver_init(const char* file, int max_length);
 void convolver_process_l(float* data, int length);
 void convolver_process_r(float* data, int length);
   
index d3966a562a84c6ff2952121448342841d703e315..34cd10bae9224e71d1883043227bba93c3f88f32 100644 (file)
--- a/common.h
+++ b/common.h
@@ -230,6 +230,7 @@ typedef struct {
 
 #ifdef CONFIG_CONVOLUTION
   int convolution;
+  int convolver_valid;
   char *convolution_ir_file;
   float convolution_gain;
   int convolution_max_length;
index 7e9d3586e989b1091fa426b6bd078e2abd9bf896..0c85a98171a3f909bc60a3efd147cab835beaba9 100644 (file)
@@ -424,6 +424,7 @@ gboolean notify_convolution_callback(ShairportSync *skeleton,
   if (shairport_sync_get_convolution(skeleton)) {
     debug(1, ">> activating convolution");
     config.convolution = 1;
+    config.convolver_valid = convolver_init(config.convolution_ir_file, config.convolution_max_length);
   } else {
     debug(1, ">> deactivating convolution");
     config.convolution = 0;
@@ -467,7 +468,7 @@ gboolean notify_convolution_impulse_response_file_callback(ShairportSync *skelet
     free(config.convolution_ir_file);
   config.convolution_ir_file = strdup(th);
   debug(1, ">> setting configuration impulse response filter file to \"%s\".", config.convolution_ir_file);
-  convolver_init(config.convolution_ir_file, config.convolution_max_length);
+  config.convolver_valid = convolver_init(config.convolution_ir_file, config.convolution_max_length);
   return TRUE;
 }
 #else
@@ -910,8 +911,8 @@ static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name
   }
   if (config.convolution_ir_file)
     shairport_sync_set_convolution_impulse_response_file(SHAIRPORT_SYNC(shairportSyncSkeleton), config.convolution_ir_file);
-  else
-    shairport_sync_set_convolution_impulse_response_file(SHAIRPORT_SYNC(shairportSyncSkeleton), NULL);
+//  else
+//    shairport_sync_set_convolution_impulse_response_file(SHAIRPORT_SYNC(shairportSyncSkeleton), NULL);
 #endif
   
   shairport_sync_set_version(SHAIRPORT_SYNC(shairportSyncSkeleton), PACKAGE_VERSION);
index e6251929ceb8417947178c13c7d715b0b6d7e443..72581f50a22944162893cd44a36f34a569494ab6 100644 (file)
@@ -32,9 +32,17 @@ dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/Shair
 # Set Drift Tolerance to 1 millisecond
 dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Set string:org.gnome.ShairportSync string:DriftTolerance variant:double:0.001
 
+# Is Loudness Enabled:
+dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Get string:org.gnome.ShairportSync string:LoudnessThreshold
 
 # Enable Loudness Filter
+dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Set string:org.gnome.ShairportSync string:Loudness variant:boolean:true
 
+# Get Loudness Threshold
+dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Get string:org.gnome.ShairportSync string:LoudnessThreshold
+
+# Set Loudness Threshold
+dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Set string:org.gnome.ShairportSync string:LoudnessThreshold variant:double:-15.0
 
 # Is Convolution enabled:
 dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Get string:org.gnome.ShairportSync string:Convolution
@@ -50,3 +58,6 @@ dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/Shair
 
 # Get Convolution Impulse Response File:
 dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Get string:org.gnome.ShairportSync string:ConvolutionImpulseResponseFile
+
+# Set Convolution Impulse Response File:
+dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Set string:org.gnome.ShairportSync string:ConvolutionImpulseResponseFile variant:string:"/etc/shairport-sync/boom.wav"
\ No newline at end of file
index 6f7f64151e8c8151a8ab0d92dc86153157b7f0e5..94fe3802ef64cd4b07ff1a4c1e54c9d9a1b14dff 100644 (file)
--- a/player.c
+++ b/player.c
@@ -2365,9 +2365,24 @@ void *player_thread_func(void *arg) {
                 amount_to_stuff = 0; // no stuffing if it's been disabled
 
               // Apply DSP here
-              if (config.loudness
+              
+              // check the state of loudness and convolution flags here and don't change them for the frame
+              
+              int do_loudness = config.loudness;
+    
+              int do_convolution = 0;
+              if ((config.convolution) && (config.convolver_valid))
+                do_convolution = 1;
+                
+              // we will apply the convolution gain if convolution is enabled, even if there is no valid convolution happening
+              
+              int convolution_is_enabled = 0;
+              if (config.convolution)
+                convolution_is_enabled = 1;
+                
+              if (do_loudness
 #ifdef CONFIG_CONVOLUTION
-                  || config.convolution
+                  || convolution_is_enabled
 #endif
                   ) {
                 int32_t *tbuf32 = (int32_t *)conn->tbuf;
@@ -2383,10 +2398,11 @@ void *player_thread_func(void *arg) {
 
 #ifdef CONFIG_CONVOLUTION
                 // Apply convolution
-                if (config.convolution) {
+                if (do_convolution) {
                   convolver_process_l(fbuf_l, inbuflength);
                   convolver_process_r(fbuf_r, inbuflength);
-
+                }
+                if (convolution_is_enabled) {
                   float gain = pow(10.0, config.convolution_gain / 20.0);
                   for (i = 0; i < inbuflength; ++i) {
                     fbuf_l[i] *= gain;
@@ -2395,7 +2411,7 @@ void *player_thread_func(void *arg) {
                 }
 #endif
 
-                if (config.loudness) {
+                if (do_loudness) {
                   // Apply volume and loudness
                   // Volume must be applied here because the loudness filter will increase the
                   // signal level and it would saturate the int32_t otherwise
index 9c519122585697cb7689a97c817c4ed6abc8504e..c9b5ba1c04e27abc065b7e9f2e4a45a20319949b 100644 (file)
@@ -963,7 +963,7 @@ int parse_options(int argc, char **argv) {
 
       if (config_lookup_string(config.cfg, "dsp.convolution_ir_file", &str)) {
         config.convolution_ir_file = strdup(str);
-        convolver_init(config.convolution_ir_file, config.convolution_max_length);
+        config.convolver_valid = convolver_init(config.convolution_ir_file, config.convolution_max_length);
       }
 
       if (config.convolution && config.convolution_ir_file == NULL) {