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:
+59
-46
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user