From 38ed75ff979e72e73a759c350cd8b1e64e2ed18c Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 1 Jun 2007 02:27:21 +0000 Subject: [PATCH] merge denormal handling work from 2.0-ongoing git-svn-id: svn://localhost/ardour2/trunk@1937 d708f5d6-7413-0410-9779-e7cbd77b26cf --- SConstruct | 5 +- gtk2_ardour/ardour.menus | 16 +++-- gtk2_ardour/ardour_ui.h | 4 ++ gtk2_ardour/ardour_ui_ed.cc | 10 ++++ gtk2_ardour/ardour_ui_options.cc | 77 +++++++++++++++++++++++++ gtk2_ardour/mixer_strip.cc | 3 + gtk2_ardour/route_ui.cc | 24 ++++++++ gtk2_ardour/route_ui.h | 4 ++ libs/ardour/ardour/ardour.h | 2 + libs/ardour/ardour/configuration_vars.h | 6 ++ libs/ardour/ardour/io.h | 4 ++ libs/ardour/ardour/route.h | 2 +- libs/ardour/ardour/types.h | 8 +++ libs/ardour/enums.cc | 7 +++ libs/ardour/globals.cc | 60 ++++++++++++++++++- libs/ardour/io.cc | 12 +++- libs/ardour/route.cc | 31 ++++++++-- 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 @@ - + + + + + + + + + @@ -357,10 +365,8 @@ - - - - + + 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 @@ -75,6 +75,12 @@ ARDOUR_UI::toggle_send_midi_feedback () ActionManager::toggle_config_state ("options", "SendMIDIfeedback", &Configuration::set_midi_feedback, &Configuration::get_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) { @@ -292,6 +298,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 act = ActionManager::get_action ("options", action); + + if (act) { + Glib::RefPtr ract = Glib::RefPtr::cast_dynamic(act); + + if (ract && ract->get_active() && Config->get_denormal_model() != model) { + Config->set_denormal_model (model); + } + } + +} + void ARDOUR_UI::toggle_auto_input () { @@ -528,6 +573,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 act = ActionManager::get_action ("options", on); + if (act) { + Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); + + if (tact && !tact->get_active()) { + tact->set_active (true); + } + } +} + void ARDOUR_UI::map_remote_model () { @@ -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 (&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 (&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 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()); @@ -878,6 +880,28 @@ RouteUI::polarity_changed () /* no signal for this yet */ } +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) { 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 #endif +#ifdef __SSE__ +#include +#endif + #include #include @@ -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 (o, var); } std::istream& operator>>(std::istream& o, ShuttleUnits& var) { return int_to_type (o, var); } std::istream& operator>>(std::istream& o, SmpteFormat& var) { return int_to_type (o, var); } +std::istream& operator>>(std::istream& o, DenormalModel& var) { return int_to_type (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) {