2 * Copyright (C) 2005-2019 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
4 * Copyright (C) 2006-2008 Doug McLain <doug@nostar.net>
5 * Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
6 * Copyright (C) 2006-2017 Tim Mayberry <mojofunk@gmail.com>
7 * Copyright (C) 2006 Sampo Savolainen <v2@iki.fi>
8 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
9 * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
10 * Copyright (C) 2013-2015 John Emmas <john@creativepost.co.uk>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "libardour-config.h"
35 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
38 #include <sys/types.h>
40 #ifndef PLATFORM_WINDOWS
41 #include <sys/resource.h>
49 #include "pbd/gstdio_compat.h"
51 #ifdef PLATFORM_WINDOWS
52 #include <stdio.h> // for _setmaxstdio
53 #include <windows.h> // for LARGE_INTEGER
60 #ifdef WINDOWS_VST_SUPPORT
65 #include "ardour/linux_vst_support.h"
68 #ifdef AUDIOUNIT_SUPPORT
69 #include "ardour/audio_unit.h"
72 #if defined(__SSE__) || defined(USE_XMMINTRIN)
73 #include <xmmintrin.h>
77 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
80 #include <glibmm/fileutils.h>
81 #include <glibmm/miscutils.h>
88 #include "pbd/error.h"
91 #include "pbd/strsplit.h"
93 #include "pbd/file_utils.h"
94 #include "pbd/enumwriter.h"
96 #include "midi++/port.h"
97 #include "midi++/mmc.h"
99 #include "LuaBridge/LuaBridge.h"
101 #include "ardour/analyser.h"
102 #include "ardour/audio_library.h"
103 #include "ardour/audio_backend.h"
104 #include "ardour/audioengine.h"
105 #include "ardour/audioplaylist.h"
106 #include "ardour/audioregion.h"
107 #include "ardour/buffer_manager.h"
108 #include "ardour/control_protocol_manager.h"
109 #include "ardour/directory_names.h"
110 #include "ardour/event_type_map.h"
111 #include "ardour/filesystem_paths.h"
112 #include "ardour/midi_region.h"
113 #include "ardour/midi_ui.h"
114 #include "ardour/midiport_manager.h"
115 #include "ardour/mix.h"
116 #include "ardour/operations.h"
117 #include "ardour/panner_manager.h"
118 #include "ardour/plugin_manager.h"
119 #include "ardour/presentation_info.h"
120 #include "ardour/process_thread.h"
121 #include "ardour/profile.h"
122 #include "ardour/rc_configuration.h"
123 #include "ardour/region.h"
124 #include "ardour/route_group.h"
125 #include "ardour/runtime_functions.h"
126 #include "ardour/session_event.h"
127 #include "ardour/source_factory.h"
128 #include "ardour/transport_fsm.h"
129 #include "ardour/transport_master_manager.h"
131 #include "ardour/uri_map.h"
133 #include "audiographer/routines.h"
135 #if defined (__APPLE__)
136 #include <CoreFoundation/CoreFoundation.h>
139 #include "pbd/i18n.h"
141 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
142 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
143 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
145 using namespace ARDOUR;
149 bool libardour_initialized = false;
151 compute_peak_t ARDOUR::compute_peak = 0;
152 find_peaks_t ARDOUR::find_peaks = 0;
153 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
154 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
155 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
156 copy_vector_t ARDOUR::copy_vector = 0;
158 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
159 PBD::Signal3<void,std::string,std::string,bool> ARDOUR::PluginScanMessage;
160 PBD::Signal1<void,int> ARDOUR::PluginScanTimeout;
161 PBD::Signal0<void> ARDOUR::GUIIdle;
162 PBD::Signal3<bool,std::string,std::string,int> ARDOUR::CopyConfigurationFiles;
164 std::map<std::string, bool> ARDOUR::reserved_io_names;
166 static bool have_old_configuration_files = false;
169 extern void setup_enum_writer ();
172 /* this is useful for quite a few things that want to check
173 if any bounds-related property has changed
175 PBD::PropertyChange ARDOUR::bounds_change;
177 static PBD::ScopedConnection engine_startup_connection;
180 setup_hardware_optimization (bool try_optimization)
182 bool generic_mix_functions = true;
184 if (try_optimization) {
186 FPU* fpu = FPU::instance();
188 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
190 #ifdef PLATFORM_WINDOWS
191 /* We have AVX-optimized code for Windows */
194 /* AVX code doesn't compile on Linux yet */
198 info << "Using AVX optimized routines" << endmsg;
201 compute_peak = x86_sse_avx_compute_peak;
202 find_peaks = x86_sse_avx_find_peaks;
203 apply_gain_to_buffer = x86_sse_avx_apply_gain_to_buffer;
204 mix_buffers_with_gain = x86_sse_avx_mix_buffers_with_gain;
205 mix_buffers_no_gain = x86_sse_avx_mix_buffers_no_gain;
206 copy_vector = x86_sse_avx_copy_vector;
208 generic_mix_functions = false;
210 } else if (fpu->has_sse()) {
212 info << "Using SSE optimized routines" << endmsg;
215 compute_peak = x86_sse_compute_peak;
216 find_peaks = x86_sse_find_peaks;
217 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
218 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
219 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
220 copy_vector = default_copy_vector;
222 generic_mix_functions = false;
226 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
228 if (floor (kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_4) { /* at least Tiger */
229 compute_peak = veclib_compute_peak;
230 find_peaks = veclib_find_peaks;
231 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
232 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
233 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
234 copy_vector = default_copy_vector;
236 generic_mix_functions = false;
238 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
242 /* consider FPU denormal handling to be "h/w optimization" */
247 if (generic_mix_functions) {
249 compute_peak = default_compute_peak;
250 find_peaks = default_find_peaks;
251 apply_gain_to_buffer = default_apply_gain_to_buffer;
252 mix_buffers_with_gain = default_mix_buffers_with_gain;
253 mix_buffers_no_gain = default_mix_buffers_no_gain;
254 copy_vector = default_copy_vector;
256 info << "No H/W specific optimizations in use" << endmsg;
259 AudioGrapher::Routines::override_compute_peak (compute_peak);
260 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
264 lotsa_files_please ()
266 #ifndef PLATFORM_WINDOWS
269 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
272 /* See the COMPATIBILITY note on the Apple setrlimit() man page */
273 rl.rlim_cur = min ((rlim_t) OPEN_MAX, rl.rlim_max);
275 rl.rlim_cur = rl.rlim_max;
278 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
279 if (rl.rlim_cur == RLIM_INFINITY) {
280 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
282 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
285 if (rl.rlim_cur != RLIM_INFINITY) {
286 info << string_compose (_("Your system is configured to limit %1 to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
290 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
293 /* this only affects stdio. 2048 is the maxium possible (512 the default).
295 * If we want more, we'll have to replaces the POSIX I/O interfaces with
296 * Win32 API calls (CreateFile, WriteFile, etc) which allows for 16K.
298 * see http://stackoverflow.com/questions/870173/is-there-a-limit-on-number-of-open-files-in-windows
299 * and http://bugs.mysql.com/bug.php?id=24509
301 int newmax = _setmaxstdio (2048);
303 info << string_compose (_("Your system is configured to limit %1 to %2 open files"), PROGRAM_NAME, newmax) << endmsg;
305 error << string_compose (_("Could not set system open files limit. Current limit is %1 open files"), _getmaxstdio()) << endmsg;
311 copy_configuration_files (string const & old_dir, string const & new_dir, int old_version)
316 /* ensure target directory exists */
318 if (g_mkdir_with_parents (new_dir.c_str(), 0755)) {
322 if (old_version >= 3) {
324 old_name = Glib::build_filename (old_dir, X_("recent"));
325 new_name = Glib::build_filename (new_dir, X_("recent"));
327 copy_file (old_name, new_name);
329 old_name = Glib::build_filename (old_dir, X_("sfdb"));
330 new_name = Glib::build_filename (new_dir, X_("sfdb"));
332 copy_file (old_name, new_name);
334 /* can only copy ardour.rc/config - UI config is not compatible */
336 /* users who have been using git/nightlies since the last
337 * release of 3.5 will have $CONFIG/config rather than
338 * $CONFIG/ardour.rc. Pick up the newer "old" config file,
339 * to avoid confusion.
342 string old_name = Glib::build_filename (old_dir, X_("config"));
344 if (!Glib::file_test (old_name, Glib::FILE_TEST_EXISTS)) {
345 old_name = Glib::build_filename (old_dir, X_("ardour.rc"));
348 new_name = Glib::build_filename (new_dir, X_("config"));
350 copy_file (old_name, new_name);
352 /* copy templates and route templates */
354 old_name = Glib::build_filename (old_dir, X_("templates"));
355 new_name = Glib::build_filename (new_dir, X_("templates"));
357 copy_recurse (old_name, new_name);
359 old_name = Glib::build_filename (old_dir, X_("route_templates"));
360 new_name = Glib::build_filename (new_dir, X_("route_templates"));
362 copy_recurse (old_name, new_name);
366 old_name = Glib::build_filename (old_dir, X_("presets"));
367 new_name = Glib::build_filename (new_dir, X_("presets"));
369 copy_recurse (old_name, new_name);
372 g_mkdir_with_parents (Glib::build_filename (new_dir, plugin_metadata_dir_name).c_str(), 0755);
374 old_name = Glib::build_filename (old_dir, X_("plugin_statuses")); /* until 6.0 */
375 new_name = Glib::build_filename (new_dir, plugin_metadata_dir_name, X_("plugin_statuses"));
376 copy_file (old_name, new_name); /* can fail silently */
378 old_name = Glib::build_filename (old_dir, plugin_metadata_dir_name, X_("plugin_statuses"));
379 copy_file (old_name, new_name);
383 old_name = Glib::build_filename (old_dir, plugin_metadata_dir_name, X_("plugin_tags"));
384 new_name = Glib::build_filename (new_dir, plugin_metadata_dir_name, X_("plugin_tags"));
386 copy_file (old_name, new_name);
390 old_name = Glib::build_filename (old_dir, export_formats_dir_name);
391 new_name = Glib::build_filename (new_dir, export_formats_dir_name);
393 vector<string> export_formats;
394 g_mkdir_with_parents (Glib::build_filename (new_dir, export_formats_dir_name).c_str(), 0755);
395 find_files_matching_pattern (export_formats, old_name, X_("*.format"));
396 for (vector<string>::iterator i = export_formats.begin(); i != export_formats.end(); ++i) {
397 std::string from = *i;
398 std::string to = Glib::build_filename (new_name, Glib::path_get_basename (*i));
399 copy_file (from, to);
407 ARDOUR::check_for_old_configuration_files ()
409 int current_version = atoi (X_(PROGRAM_VERSION));
411 if (current_version <= 1) {
415 int old_version = current_version - 1;
417 string old_config_dir = user_config_directory (old_version);
418 /* pass in the current version explicitly to avoid creation */
419 string current_config_dir = user_config_directory (current_version);
421 if (!Glib::file_test (current_config_dir, Glib::FILE_TEST_IS_DIR)) {
422 if (Glib::file_test (old_config_dir, Glib::FILE_TEST_IS_DIR)) {
423 have_old_configuration_files = true;
429 ARDOUR::handle_old_configuration_files (boost::function<bool (std::string const&, std::string const&, int)> ui_handler)
431 if (have_old_configuration_files) {
432 int current_version = atoi (X_(PROGRAM_VERSION));
433 assert (current_version > 1); // established in check_for_old_configuration_files ()
434 int old_version = current_version - 1;
435 string old_config_dir = user_config_directory (old_version);
436 string current_config_dir = user_config_directory (current_version);
438 if (ui_handler (old_config_dir, current_config_dir, old_version)) {
439 copy_configuration_files (old_config_dir, current_config_dir, old_version);
447 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
449 if (libardour_initialized) {
454 if (getenv("ARDOUR_LUA_METATABLES")) {
455 luabridge::Security::setHideMetatables (false);
460 fftwf_make_planner_thread_safe ();
463 if (!PBD::init()) return false;
466 (void) bindtextdomain(PACKAGE, localedir);
467 (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
470 SessionEvent::init_event_pool ();
471 TransportFSM::Event::init_pool ();
473 Operations::make_operations_quarks ();
474 SessionObject::make_property_quarks ();
475 Region::make_property_quarks ();
476 MidiRegion::make_property_quarks ();
477 AudioRegion::make_property_quarks ();
478 RouteGroup::make_property_quarks ();
479 Playlist::make_property_quarks ();
480 AudioPlaylist::make_property_quarks ();
481 PresentationInfo::make_property_quarks ();
482 TransportMaster::make_property_quarks ();
484 /* this is a useful ready to use PropertyChange that many
485 things need to check. This avoids having to compose
486 it every time we want to check for any of the relevant
490 bounds_change.add (ARDOUR::Properties::start);
491 bounds_change.add (ARDOUR::Properties::position);
492 bounds_change.add (ARDOUR::Properties::length);
494 /* provide a state version for the few cases that need it and are not
495 driven by reading state from disk (e.g. undo/redo)
498 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
500 ARDOUR::setup_enum_writer ();
502 // allow ardour the absolute maximum number of open files
503 lotsa_files_please ();
508 Library = new AudioLibrary;
510 BootMessage (_("Loading configuration"));
512 Config = new RCConfiguration;
514 if (Config->load_state ()) {
518 Config->set_use_windows_vst (use_windows_vst);
520 Config->set_use_lxvst(true);
523 Profile = new RuntimeProfile;
526 #ifdef WINDOWS_VST_SUPPORT
527 if (Config->get_use_windows_vst() && fst_init (0)) {
533 if (Config->get_use_lxvst() && vstfx_init (0)) {
538 #ifdef AUDIOUNIT_SUPPORT
539 AUPluginInfo::load_cached_info ();
542 setup_hardware_optimization (try_optimization);
544 SourceFactory::init ();
547 /* singletons - first object is "it" */
548 (void) PluginManager::instance();
550 (void) URIMap::instance();
552 (void) EventTypeMap::instance();
554 ControlProtocolManager::instance().discover_control_protocols ();
556 /* for each control protocol, check for a request buffer factory method
557 and if it exists, store it in the EventLoop list of such
558 methods. This allows the relevant threads to register themselves
559 with EventLoops so that signal emission can be RT-safe.
562 ControlProtocolManager::instance().register_request_buffer_factories ();
563 /* it would be nice if this could auto-register itself in the
564 constructor, since MidiControlUI is a singleton, but it can't be
565 created until after the engine is running. Therefore we have to
566 explicitly register it here.
568 EventLoop::register_request_buffer_factory (X_("midiUI"), MidiControlUI::request_factory);
570 /* the + 4 is a bit of a handwave. i don't actually know
571 how many more per-thread buffer sets we need above
572 the h/w concurrency, but its definitely > 1 more.
574 BufferManager::init (hardware_concurrency() + 4);
576 PannerManager::instance().discover_panners();
578 ARDOUR::AudioEngine::create ();
579 TransportMasterManager::create ();
581 /* it is unfortunate that we need to include reserved names here that
582 refer to control surfaces. But there's no way to ensure a complete
583 lack of collisions without doing this, since the control surface
584 support may not even be active. Without adding an API to control
585 surface support that would list their port names, we do have to
588 We also need to know if the given I/O is an actual route.
589 For routes (e.g. "master"), bus creation needs to be allowed the first time,
590 while for pure I/O (e.g. "Click") track/bus creation must always fail.
593 reserved_io_names[_("Monitor")] = true;
594 reserved_io_names[_("Master")] = true;
595 reserved_io_names["auditioner"] = true; // auditioner.cc Track (s, "auditioner",...)
598 reserved_io_names[X_("Click")] = false; // session.cc ClickIO (*this, X_("Click")
599 reserved_io_names[_("Control")] = false;
600 reserved_io_names[_("Mackie")] = false;
601 reserved_io_names[_("FaderPort Recv")] = false;
602 reserved_io_names[_("FaderPort Send")] = false;
603 reserved_io_names[_("FaderPort2 Recv")] = false;
604 reserved_io_names[_("FaderPort2 Send")] = false;
605 reserved_io_names[_("FaderPort8 Recv")] = false;
606 reserved_io_names[_("FaderPort8 Send")] = false;
607 reserved_io_names[_("FaderPort16 Recv")] = false;
608 reserved_io_names[_("FaderPort16 Send")] = false;
610 libardour_initialized = true;
616 ARDOUR::init_post_engine (uint32_t start_cnt)
620 if (start_cnt == 0) {
624 ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
626 if ((node = Config->control_protocol_state()) != 0) {
627 ControlProtocolManager::instance().set_state (*node, 0 /* here: global-config state */);
632 TransportMasterManager::instance().restart ();
639 if (!libardour_initialized) {
643 engine_startup_connection.disconnect ();
645 delete &ControlProtocolManager::instance();
646 ARDOUR::AudioEngine::destroy ();
652 #ifdef WINDOWS_VST_SUPPORT
659 delete &PluginManager::instance();
667 ARDOUR::no_auto_connect()
669 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
675 FPU* fpu = FPU::instance ();
677 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
678 // valgrind doesn't understand this assembler stuff
679 // September 10th, 2007
683 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
684 /* see also https://carlh.net/plugins/denormals.php */
688 if (!fpu->has_flush_to_zero() && !fpu->has_denormals_are_zero()) {
692 MXCSR = _mm_getcsr();
694 #ifdef DEBUG_DENORMAL_EXCEPTION
695 /* This will raise a FP exception if a denormal is detected */
696 MXCSR &= ~_MM_MASK_DENORM;
699 switch (Config->get_denormal_model()) {
701 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
705 if (fpu->has_flush_to_zero()) {
706 MXCSR |= _MM_FLUSH_ZERO_ON;
711 MXCSR &= ~_MM_FLUSH_ZERO_ON;
712 if (fpu->has_denormals_are_zero()) {
718 if (fpu->has_flush_to_zero()) {
719 if (fpu->has_denormals_are_zero()) {
720 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
722 MXCSR |= _MM_FLUSH_ZERO_ON;
730 #elif defined(__aarch64__)
731 /* http://infocenter.arm.com/help/topic/com.arm.doc.ddi0488d/CIHCACFF.html
732 * bit 24: flush-to-zero */
733 if (Config->get_denormal_model() != DenormalNone) {
735 __asm__ __volatile__ (
737 "orr %0, %0, #0x1000000 \n"
740 : "=r"(cw) :: "memory");
743 #elif defined(__arm__)
744 /* http://infocenter.arm.com/help/topic/com.arm.doc.dui0068b/BCFHFBGA.html
745 * bit 24: flush-to-zero */
746 if (Config->get_denormal_model() != DenormalNone) {
748 __asm__ __volatile__ (
750 "orr %0, %0, #0x1000000 \n"
752 : "=r"(cw) :: "memory");
758 /* this can be changed to modify the translation behaviour for
759 cases where the user has never expressed a preference.
761 static const bool translate_by_default = true;
764 ARDOUR::translation_enable_path ()
766 return Glib::build_filename (user_config_directory(), ".translate");
770 ARDOUR::translations_are_enabled ()
772 int fd = g_open (ARDOUR::translation_enable_path().c_str(), O_RDONLY, 0444);
775 return translate_by_default;
781 if (::read (fd, &c, 1) == 1 && c == '1') {
791 ARDOUR::set_translations_enabled (bool yn)
793 string i18n_enabler = ARDOUR::translation_enable_path();
794 int fd = g_open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
808 (void) ::write (fd, &c, 1);
811 Config->ParameterChanged ("enable-translation");
817 ARDOUR::get_available_sync_options ()
819 vector<SyncSource> ret;
821 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
822 if (backend && backend->name() == "JACK") {
823 ret.push_back (Engine);
827 ret.push_back (MIDIClock);
833 /** Return a monotonic value for the number of microseconds that have elapsed
834 * since an arbitrary zero origin.
838 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
840 #include <mach/mach_time.h>
841 #define CLOCK_REALTIME 0
842 #define CLOCK_MONOTONIC 0
844 clock_gettime (int /*clk_id*/, struct timespec *t)
846 static bool initialized = false;
847 static mach_timebase_info_data_t timebase;
849 mach_timebase_info(&timebase);
853 time = mach_absolute_time();
854 double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
855 double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
857 t->tv_nsec = nseconds;
863 ARDOUR::get_microseconds ()
865 #ifdef PLATFORM_WINDOWS
866 microseconds_t ret = 0;
867 LARGE_INTEGER freq, time;
869 if (QueryPerformanceFrequency(&freq))
870 if (QueryPerformanceCounter(&time))
871 ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
876 if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
880 return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
884 /** Return the number of bits per sample for a given sample format.
886 * This is closely related to sndfile_data_width() but does NOT
887 * return a "magic" value to differentiate between 32 bit integer
888 * and 32 bit floating point values.
892 ARDOUR::format_data_width (ARDOUR::SampleFormat format)
898 case ARDOUR::FormatInt16:
900 case ARDOUR::FormatInt24: