add new denormal handling capabilities (95% finished)

git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@1935 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2007-05-31 21:44:18 +00:00
parent c967b91ddf
commit 2291d59bc8
15 changed files with 251 additions and 7 deletions

View file

@ -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'),
@ -624,8 +625,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

View file

@ -353,7 +353,13 @@
<menuitem action='StopRecordingOnXrun'/>
<menuitem action='StopTransportAtEndOfSession'/>
<menuitem action='GainReduceFastTransport'/>
<separator/>
<menu name='Denormals' action='Denormals'>
<menuitem action='DenormalProtection'/>
<menuitem action='DenormalNone'/>
<menuitem action='DenormalFTZ'/>
<menuitem action='DenormalDAZ'/>
<menuitem action='DenormalFTZDAZ'/>
</menu>
</menu>
<menu name='Help' action='Help'>
<menuitem action='About'/>

View file

@ -666,11 +666,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();
@ -687,6 +690,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 ();

View file

@ -93,6 +93,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 */
@ -409,6 +410,15 @@ ARDOUR_UI::install_actions ()
ActionManager::register_toggle_action (option_actions, X_("LatchedRecordEnable"), _("Rec-enable stays engaged at stop"), mem_fun (*this, &ARDOUR_UI::toggle_LatchedRecordEnable));
ActionManager::register_toggle_action (option_actions, X_("RegionEquivalentsOverlap"), _("Region equivalents overlap"), mem_fun (*this, &ARDOUR_UI::toggle_RegionEquivalentsOverlap));
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);

View file

@ -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<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 ()
{
@ -516,6 +561,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 ()
{
@ -905,6 +980,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")) {

View file

@ -985,6 +985,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 ();

View file

@ -63,6 +63,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());
@ -876,6 +878,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)
{

View file

@ -142,6 +142,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 ();

View file

@ -75,6 +75,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? */

View file

@ -140,6 +140,11 @@ CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", false
CONFIG_VARIABLE (bool, periodic_safety_backups, "periodic-safety-backups", true)
CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-backup-interval", 120)
/* 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")

View file

@ -127,6 +127,10 @@ class Route : public IO
void set_phase_invert (bool yn, void *src);
bool phase_invert() const { return _phase_invert; }
void set_denormal_protection (bool yn, void *src);
bool denormal_protection() const { return _denormal_protection; }
void set_edit_group (RouteGroup *, void *);
void drop_edit_group (void *);
@ -258,6 +262,7 @@ class Route : public IO
bool _soloed : 1;
bool _solo_safe : 1;
bool _phase_invert : 1;
bool _denormal_protection : 1;
bool _recordable : 1;
bool _active : 1;
bool _mute_affects_pre_fader : 1;

View file

@ -272,6 +272,13 @@ namespace ARDOUR {
ExternalMonitoring,
};
enum DenormalModel {
DenormalNone,
DenormalFTZ,
DenormalDAZ,
DenormalFTZDAZ
};
enum RemoteModel {
UserOrdered,
MixerOrdered,
@ -368,6 +375,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);
static inline nframes_t
session_frame_to_track_frame (nframes_t session_frame, double speed)

View file

@ -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);

View file

@ -28,6 +28,10 @@
#include <fst.h>
#endif
#ifdef __SSE__
#include <xmmintrin.h>
#endif
#include <lrdf.h>
#include <pbd/error.h>
@ -228,8 +232,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;
@ -274,6 +279,9 @@ setup_hardware_optimization (bool try_optimization)
info << "No H/W specific optimizations in use" << endmsg;
}
setup_fpu ();
}
int
@ -527,6 +535,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)
@ -629,4 +686,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); }

View file

@ -48,7 +48,6 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
uint32_t Route::order_key_cnt = 0;
@ -78,6 +77,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;
@ -341,6 +341,22 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
}
}
/* -----------------------------------------------------------------------------------------------------
DENORMAL CONTROL
-------------------------------------------------------------------------------------------------- */
if (_denormal_protection || Config->get_denormal_protection()) {
for (n = 0; n < nbufs; ++n) {
Sample *sp = bufs[n];
for (nframes_t nx = offset; nx < nframes + offset; ++nx) {
sp[nx] += 1.0e-27f;
}
}
}
/* ----------------------------------------------------------------------------------------------------
PRE-FADER REDIRECTS
-------------------------------------------------------------------------------------------------- */
@ -724,8 +740,17 @@ Route::set_phase_invert (bool yn, void *src)
{
if (_phase_invert != yn) {
_phase_invert = yn;
// phase_invert_changed (src); /* EMIT SIGNAL */
}
}
void
Route::set_denormal_protection (bool yn, void *src)
{
if (_denormal_protection != yn) {
_denormal_protection = yn;
// denormal_protection_changed (src); /* EMIT SIGNAL */
}
// phase_invert_changed (src); /* EMIT SIGNAL */
}
void
@ -1404,6 +1429,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");
@ -1571,7 +1597,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) {