summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct5
-rw-r--r--gtk2_ardour/ardour.menus16
-rw-r--r--gtk2_ardour/ardour_ui.h4
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc10
-rw-r--r--gtk2_ardour/ardour_ui_options.cc77
-rw-r--r--gtk2_ardour/mixer_strip.cc3
-rw-r--r--gtk2_ardour/route_ui.cc24
-rw-r--r--gtk2_ardour/route_ui.h4
-rw-r--r--libs/ardour/ardour/ardour.h2
-rw-r--r--libs/ardour/ardour/configuration_vars.h6
-rw-r--r--libs/ardour/ardour/io.h4
-rw-r--r--libs/ardour/ardour/route.h2
-rw-r--r--libs/ardour/ardour/types.h8
-rw-r--r--libs/ardour/enums.cc7
-rw-r--r--libs/ardour/globals.cc60
-rw-r--r--libs/ardour/io.cc12
-rw-r--r--libs/ardour/route.cc31
17 files changed, 260 insertions, 15 deletions
diff --git a/SConstruct b/SConstruct
index 5e37b5bfb4..4a26efb6e4 100644
--- a/SConstruct
+++ b/SConstruct
@@ -36,6 +36,7 @@ opts.AddOptions(
BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic. Might break compilation. For pedants', 0),
BoolOption('FFT_ANALYSIS', 'Include FFT analysis window', 0),
BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1),
+ BoolOption('USE_XMMINTRIN', 'Use gcc XMM intrinsics where possible', 1),
BoolOption('LIBLO', 'Compile with support for liblo library', 1),
BoolOption('NLS', 'Set to turn on i18n support', 1),
PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
@@ -625,8 +626,8 @@ elif ((re.search ("i[0-9]86", config[config_cpu]) != None) or (re.search ("x86_6
opt_flags.append ("-march=i686")
if ((env['DIST_TARGET'] == 'i686') or (env['DIST_TARGET'] == 'x86_64')) and build_host_supports_sse:
- opt_flags.extend (["-msse", "-mfpmath=sse"])
- debug_flags.extend (["-msse", "-mfpmath=sse"])
+ opt_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
+ debug_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
# end of processor-specific section
# optimization section
diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus
index 3f9c900422..0faa3ea60b 100644
--- a/gtk2_ardour/ardour.menus
+++ b/gtk2_ardour/ardour.menus
@@ -340,7 +340,15 @@
<menuitem action='LayerLaterHigher'/>
<menuitem action='LayerMoveAddHigher'/>
<menuitem action='LayerAddHigher'/>
- </menu>
+ </menu>
+ <menu name='Denormals' action='Denormals'>
+ <menuitem action='DenormalProtection'/>
+ <separator/>
+ <menuitem action='DenormalNone'/>
+ <menuitem action='DenormalFTZ'/>
+ <menuitem action='DenormalDAZ'/>
+ <menuitem action='DenormalFTZDAZ'/>
+ </menu>
<separator/>
<menuitem action='SendMTC'/>
<menuitem action='SendMMC'/>
@@ -357,10 +365,8 @@
<menuitem action='StopRecordingOnXrun'/>
<menuitem action='StopTransportAtEndOfSession'/>
<menuitem action='GainReduceFastTransport'/>
- <separator/>
- <menuitem action='PrimaryClockDeltaEditCursor'/>
- <menuitem action='SecondaryClockDeltaEditCursor'/>
- <separator/>
+ <menuitem action='PrimaryClockDeltaEditCursor'/>
+ <menuitem action='SecondaryClockDeltaEditCursor'/>
</menu>
<menu name='Help' action='Help'>
<menuitem action='About'/>
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 5b165589e1..fc4114554c 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -669,11 +669,14 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_use_osc ();
+ void toggle_denormal_protection ();
+
void set_input_auto_connect (ARDOUR::AutoConnectOption);
void set_output_auto_connect (ARDOUR::AutoConnectOption);
void set_solo_model (ARDOUR::SoloModel);
void set_monitor_model (ARDOUR::MonitorModel);
void set_remote_model (ARDOUR::RemoteModel);
+ void set_denormal_model (ARDOUR::DenormalModel);
void toggle_StopPluginsWithTransport();
void toggle_DoNotRunPluginsWhileRecording();
@@ -692,6 +695,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void mtc_port_changed ();
void map_solo_model ();
void map_monitor_model ();
+ void map_denormal_model ();
void map_remote_model ();
void map_file_header_format ();
void map_file_data_format ();
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index 3463c20648..af3032c2b0 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -94,6 +94,7 @@ ARDOUR_UI::install_actions ()
ActionManager::register_action (main_actions, X_("Metering"), _("Metering"));
ActionManager::register_action (main_actions, X_("MeteringFallOffRate"), _("Fall off rate"));
ActionManager::register_action (main_actions, X_("MeteringHoldTime"), _("Hold Time"));
+ ActionManager::register_action (main_actions, X_("Denormals"), _("Denormal Handling"));
/* the real actions */
@@ -416,6 +417,15 @@ ARDOUR_UI::install_actions ()
ActionManager::register_toggle_action (option_actions, X_("PrimaryClockDeltaEditCursor"), _("Primary Clock delta to edit cursor"), mem_fun (*this, &ARDOUR_UI::toggle_PrimaryClockDeltaEditCursor));
ActionManager::register_toggle_action (option_actions, X_("SecondaryClockDeltaEditCursor"), _("Secondary Clock delta to edit cursor"), mem_fun (*this, &ARDOUR_UI::toggle_SecondaryClockDeltaEditCursor));
+ RadioAction::Group denormal_group;
+
+ ActionManager::register_toggle_action (option_actions, X_("DenormalProtection"), _("Use DC bias"), mem_fun (*this, &ARDOUR_UI::toggle_denormal_protection));
+
+ ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalNone"), _("No processor handling"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalNone));
+ ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZ"), _("Use FlushToZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZ));
+ ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalDAZ"), _("Use DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalDAZ));
+ ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZDAZ"), _("Use FlushToZero & DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZDAZ));
+
act = ActionManager::register_toggle_action (option_actions, X_("DoNotRunPluginsWhileRecording"), _("Do not run plugins while recording"), mem_fun (*this, &ARDOUR_UI::toggle_DoNotRunPluginsWhileRecording));
ActionManager::session_sensitive_actions.push_back (act);
diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc
index d456e30146..813c615d39 100644
--- a/gtk2_ardour/ardour_ui_options.cc
+++ b/gtk2_ardour/ardour_ui_options.cc
@@ -76,6 +76,12 @@ ARDOUR_UI::toggle_send_midi_feedback ()
}
void
+ARDOUR_UI::toggle_denormal_protection ()
+{
+ ActionManager::toggle_config_state ("options", "DenormalProtection", &Configuration::set_denormal_protection, &Configuration::get_denormal_protection);
+}
+
+void
ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
{
const char *action = 0;
@@ -293,6 +299,45 @@ ARDOUR_UI::set_monitor_model (MonitorModel model)
}
void
+ARDOUR_UI::set_denormal_model (DenormalModel model)
+{
+ const char* action = 0;
+
+ switch (model) {
+ case DenormalNone:
+ action = X_("DenormalNone");
+ break;
+
+ case DenormalFTZ:
+ action = X_("DenormalFTZ");
+ break;
+
+ case DenormalDAZ:
+ action = X_("DenormalDAZ");
+ break;
+
+ case DenormalFTZDAZ:
+ action = X_("DenormalFTZDAZ");
+ break;
+
+ default:
+ fatal << string_compose (_("programming error: unknown denormal model in ARDOUR_UI::set_denormal_model: %1"), model) << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Glib::RefPtr<Action> act = ActionManager::get_action ("options", action);
+
+ if (act) {
+ Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
+
+ if (ract && ract->get_active() && Config->get_denormal_model() != model) {
+ Config->set_denormal_model (model);
+ }
+ }
+
+}
+
+void
ARDOUR_UI::toggle_auto_input ()
{
ActionManager::toggle_config_state ("Transport", "ToggleAutoInput", &Configuration::set_auto_input, &Configuration::get_auto_input);
@@ -529,6 +574,36 @@ ARDOUR_UI::map_monitor_model ()
}
void
+ARDOUR_UI::map_denormal_model ()
+{
+ const char* on = 0;
+
+ switch (Config->get_denormal_model()) {
+ case DenormalNone:
+ on = X_("DenormalNone");
+ break;
+ case DenormalFTZ:
+ on = X_("DenormalFTZ");
+ break;
+ case DenormalDAZ:
+ on = X_("DenormalDAZ");
+ break;
+ case DenormalFTZDAZ:
+ on = X_("DenormalFTZDAZ");
+ break;
+ }
+
+ Glib::RefPtr<Action> act = ActionManager::get_action ("options", on);
+ if (act) {
+ Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+
+ if (tact && !tact->get_active()) {
+ tact->set_active (true);
+ }
+ }
+}
+
+void
ARDOUR_UI::map_remote_model ()
{
const char* on = 0;
@@ -917,6 +992,8 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
ActionManager::map_some_state ("options", "StopTransportAtEndOfSession", &Configuration::get_stop_at_session_end);
} else if (PARAM_IS ("monitoring-model")) {
map_monitor_model ();
+ } else if (PARAM_IS ("denormal-model")) {
+ map_denormal_model ();
} else if (PARAM_IS ("remote-model")) {
map_remote_model ();
} else if (PARAM_IS ("use-video-sync")) {
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index 9225fa6b12..1e007cac4c 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -984,6 +984,9 @@ MixerStrip::build_route_ops_menu ()
items.push_back (CheckMenuElem (_("Invert Polarity"), mem_fun (*this, &RouteUI::toggle_polarity)));
polarity_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
polarity_menu_item->set_active (_route->phase_invert());
+ items.push_back (CheckMenuElem (_("Protect against denormals"), mem_fun (*this, &RouteUI::toggle_denormal_protection)));
+ denormal_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
+ denormal_menu_item->set_active (_route->denormal_protection());
build_remote_control_menu ();
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc
index 303d05dc86..b33cb13a0d 100644
--- a/gtk2_ardour/route_ui.cc
+++ b/gtk2_ardour/route_ui.cc
@@ -65,6 +65,8 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
wait_for_release = false;
route_active_menu_item = 0;
was_solo_safe = false;
+ polarity_menu_item = 0;
+ denormal_menu_item = 0;
if (set_color_from_route()) {
set_color (unique_random_color());
@@ -879,6 +881,28 @@ RouteUI::polarity_changed ()
}
void
+RouteUI::toggle_denormal_protection ()
+{
+ if (denormal_menu_item) {
+
+ bool x;
+
+ ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
+
+ if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
+ _route->set_denormal_protection (x, this);
+ }
+ }
+}
+
+void
+RouteUI::denormal_protection_changed ()
+{
+ /* no signal for this yet */
+}
+
+
+void
RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
{
bool yn = _route->solo_safe ();
diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h
index 20cd6f1f28..ceb6cf09cc 100644
--- a/gtk2_ardour/route_ui.h
+++ b/gtk2_ardour/route_ui.h
@@ -145,6 +145,10 @@ class RouteUI : public virtual AxisView
void toggle_polarity ();
virtual void polarity_changed ();
+ Gtk::CheckMenuItem *denormal_menu_item;
+ void toggle_denormal_protection();
+ virtual void denormal_protection_changed ();
+
void disconnect_input ();
void disconnect_output ();
diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h
index e1be7ad998..c7bf7edcf8 100644
--- a/libs/ardour/ardour/ardour.h
+++ b/libs/ardour/ardour/ardour.h
@@ -77,6 +77,8 @@ namespace ARDOUR {
};
static const double SHUTTLE_FRACT_SPEED1=0.48412291827; /* derived from A1,A2 */
+
+ void setup_fpu ();
}
/* how do we make these be within the Ardour namespace? */
diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
index 3b72130222..8ba9830841 100644
--- a/libs/ardour/ardour/configuration_vars.h
+++ b/libs/ardour/ardour/configuration_vars.h
@@ -144,8 +144,14 @@ CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-bac
CONFIG_VARIABLE (string, possible_audio_file_regexp, "possible-audio-file-regexp", "\\.(wav|aiff|caf|w64|L|R)$")
/* Theme */
+
CONFIG_VARIABLE (string, ui_rc_file, "ui-rc-file", "ardour2_ui_dark.rc")
+/* denormal management */
+
+CONFIG_VARIABLE (bool, denormal_protection, "denormal-protection", false)
+CONFIG_VARIABLE (DenormalModel, denormal_model, "denormal-model", DenormalNone)
+
/* BWAV */
CONFIG_VARIABLE (string, bwf_country_code, "bwf-country-code", "US")
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 18929ee528..0b86eb4088 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -107,6 +107,9 @@ class IO : public PBD::StatefulDestructible
gain_t gain () const { return _desired_gain; }
virtual gain_t effective_gain () const;
+ void set_denormal_protection (bool yn, void *src);
+ bool denormal_protection() const { return _denormal_protection; }
+
void set_phase_invert (bool yn, void *src);
bool phase_invert() const { return _phase_invert; }
@@ -284,6 +287,7 @@ class IO : public PBD::StatefulDestructible
Bundle* _output_bundle;
bool no_panner_reset;
bool _phase_invert;
+ bool _denormal_protection;
XMLNode* deferred_state;
DataType _default_type;
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 34fa7b5463..ed839f091b 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -124,7 +124,7 @@ class Route : public IO
void set_mute_config (mute_type, bool, void *src);
bool get_mute_config (mute_type);
-
+
void set_edit_group (RouteGroup *, void *);
void drop_edit_group (void *);
RouteGroup *edit_group () { return _edit_group; }
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 813c75f673..ce52252fc4 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -270,6 +270,13 @@ namespace ARDOUR {
ExternalMonitoring,
};
+ enum DenormalModel {
+ DenormalNone,
+ DenormalFTZ,
+ DenormalDAZ,
+ DenormalFTZDAZ
+ };
+
enum RemoteModel {
UserOrdered,
MixerOrdered,
@@ -365,6 +372,7 @@ std::istream& operator>>(std::istream& o, ARDOUR::SlaveSource& sf);
std::istream& operator>>(std::istream& o, ARDOUR::ShuttleBehaviour& sf);
std::istream& operator>>(std::istream& o, ARDOUR::ShuttleUnits& sf);
std::istream& operator>>(std::istream& o, ARDOUR::SmpteFormat& sf);
+std::istream& operator>>(std::istream& o, ARDOUR::DenormalModel& sf);
using ARDOUR::nframes_t;
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 389a88f295..356c0df5c1 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -51,6 +51,7 @@ setup_enum_writer ()
Placement _Placement;
MonitorModel _MonitorModel;
RemoteModel _RemoteModel;
+ DenormalModel _DenormalModel;
CrossfadeModel _CrossfadeModel;
LayerModel _LayerModel;
SoloModel _SoloModel;
@@ -162,6 +163,12 @@ setup_enum_writer ()
REGISTER_ENUM (ExternalMonitoring);
REGISTER (_MonitorModel);
+ REGISTER_ENUM (DenormalNone);
+ REGISTER_ENUM (DenormalFTZ);
+ REGISTER_ENUM (DenormalDAZ);
+ REGISTER_ENUM (DenormalFTZDAZ);
+ REGISTER (_DenormalModel);
+
REGISTER_ENUM (UserOrdered);
REGISTER_ENUM (MixerOrdered);
REGISTER_ENUM (EditorOrdered);
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index fcebe92dce..1224897d6d 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -27,6 +27,10 @@
#include <fst.h>
#endif
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
#include <lrdf.h>
#include <pbd/error.h>
@@ -237,8 +241,9 @@ setup_hardware_optimization (bool try_optimization)
: "%rax", "%rcx", "%rdx", "memory");
#endif /* USE_X86_64_ASM */
+
use_sse &= (1 << 25); // bit 25 = SSE support
-
+
if (use_sse) {
info << "Using SSE optimized routines" << endmsg;
@@ -283,6 +288,9 @@ setup_hardware_optimization (bool try_optimization)
info << "No H/W specific optimizations in use" << endmsg;
}
+
+ setup_fpu ();
+
}
int
@@ -532,6 +540,55 @@ ARDOUR::LocaleGuard::~LocaleGuard ()
free ((char*)old);
}
+void
+ARDOUR::setup_fpu ()
+{
+#ifdef USE_XMMINTRIN
+ int MXCSR;
+
+ /* XXX use real code to determine if the processor supports
+ DenormalsAreZero and FlushToZero
+ */
+
+ bool has_daz = false;
+ bool can_ftz = true;
+
+ if (!can_ftz && !has_daz) {
+ return;
+ }
+
+ MXCSR = _mm_getcsr();
+
+ switch (Config->get_denormal_model()) {
+ case DenormalNone:
+ MXCSR &= ~_MM_FLUSH_ZERO_ON;
+ break;
+
+ case DenormalFTZ:
+ MXCSR |= _MM_FLUSH_ZERO_ON;
+ break;
+
+ case DenormalDAZ:
+ MXCSR &= ~_MM_FLUSH_ZERO_ON;
+ if (has_daz) {
+ MXCSR |= 0x8000;
+ }
+ break;
+
+ case DenormalFTZDAZ:
+ if (has_daz) {
+ MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
+ } else {
+ MXCSR |= _MM_FLUSH_ZERO_ON;
+ }
+ break;
+ }
+
+ _mm_setcsr (MXCSR);
+
+#endif
+}
+
ARDOUR::OverlapType
ARDOUR::coverage (nframes_t sa, nframes_t ea,
nframes_t sb, nframes_t eb)
@@ -634,4 +691,5 @@ std::istream& operator>>(std::istream& o, SlaveSource& var) { return int_to_type
std::istream& operator>>(std::istream& o, ShuttleBehaviour& var) { return int_to_type<ShuttleBehaviour> (o, var); }
std::istream& operator>>(std::istream& o, ShuttleUnits& var) { return int_to_type<ShuttleUnits> (o, var); }
std::istream& operator>>(std::istream& o, SmpteFormat& var) { return int_to_type<SmpteFormat> (o, var); }
+std::istream& operator>>(std::istream& o, DenormalModel& var) { return int_to_type<DenormalModel> (o, var); }
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 49649aac6a..d7ac2b7e74 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -2436,7 +2436,17 @@ IO::set_phase_invert (bool yn, void *src)
{
if (_phase_invert != yn) {
_phase_invert = yn;
+ // phase_invert_changed (src); /* EMIT SIGNAL */
}
- // phase_invert_changed (src); /* EMIT SIGNAL */
}
+void
+IO::set_denormal_protection (bool yn, void *src)
+{
+ if (_denormal_protection != yn) {
+ _denormal_protection = yn;
+ // denormal_protection_changed (src); /* EMIT SIGNAL */
+ }
+}
+
+
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 17322229ed..e431df1ba9 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -79,6 +79,7 @@ Route::init ()
_soloed = false;
_solo_safe = false;
_phase_invert = false;
+ _denormal_protection = false;
order_keys[strdup (N_("signal"))] = order_key_cnt++;
_active = true;
_silent = false;
@@ -234,9 +235,9 @@ Route::set_gain (gain_t val, void *src)
*/
void
Route::process_output_buffers (BufferSet& bufs,
- nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, nframes_t offset, bool with_redirects, int declick,
- bool meter)
+ nframes_t start_frame, nframes_t end_frame,
+ nframes_t nframes, nframes_t offset, bool with_redirects, int declick,
+ bool meter)
{
// This is definitely very audio-only for now
assert(_default_type == DataType::AUDIO);
@@ -351,7 +352,22 @@ Route::process_output_buffers (BufferSet& bufs,
}
}
- /* ---------------------------------------------------------------------------------------------------
+ /* -----------------------------------------------------------------------------------------------------
+ DENORMAL CONTROL
+ -------------------------------------------------------------------------------------------------- */
+
+ if (_denormal_protection || Config->get_denormal_protection()) {
+
+ for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
+ Sample* const sp = i->data();
+
+ for (nframes_t nx = offset; nx < nframes + offset; ++nx) {
+ sp[nx] += 1.0e-27f;
+ }
+ }
+ }
+
+ /* ----------------------------------------------------------------------------------------------------
PRE-FADER REDIRECTS
-------------------------------------------------------------------------------------------------- */
@@ -1466,6 +1482,7 @@ Route::state(bool full_state)
node->add_property("muted", _muted?"yes":"no");
node->add_property("soloed", _soloed?"yes":"no");
node->add_property("phase-invert", _phase_invert?"yes":"no");
+ node->add_property("denormal-protection", _denormal_protection?"yes":"no");
node->add_property("mute-affects-pre-fader", _mute_affects_pre_fader?"yes":"no");
node->add_property("mute-affects-post-fader", _mute_affects_post_fader?"yes":"no");
node->add_property("mute-affects-control-outs", _mute_affects_control_outs?"yes":"no");
@@ -1701,7 +1718,11 @@ Route::_set_state (const XMLNode& node, bool call_base)
}
if ((prop = node.property (X_("phase-invert"))) != 0) {
- set_phase_invert(prop->value()=="yes"?true:false, this);
+ set_phase_invert (prop->value()=="yes"?true:false, this);
+ }
+
+ if ((prop = node.property (X_("denormal-protection"))) != 0) {
+ set_denormal_protection (prop->value()=="yes"?true:false, this);
}
if ((prop = node.property (X_("active"))) != 0) {