Add D-Bus convolution filter controls; enable convolution filters to be turned on and off or changed; enable convolution gain to be checked and changed.

This commit is contained in:
Mike Brady
2019-11-11 21:45:29 +00:00
parent 6635bb5d0b
commit f2930387b3
7 changed files with 98 additions and 56 deletions
+59 -46
View 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 (filename) {
SNDFILE* file = sf_open(filename, SFM_READ, &info);
if (file) {
if (info.samplerate != 44100)
die("Impulse file \"%s\" sample rate is %d Hz. Only 44100 Hz is supported", filename, info.samplerate);
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];
if (info.channels != 1 && info.channels != 2)
die("Impulse file \"%s\" contains %d channels. Only 1 or 2 is supported.", filename, info.channels);
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
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
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);
}
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);
}
convolver_l.init(352, buffer_l, size);
convolver_r.init(352, buffer_r, size);
}
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);
}
+1 -1
View 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);
+1
View File
@@ -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;
+4 -3
View 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);
+11
View 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"
+21 -5
View File
@@ -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
+1 -1
View 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) {