use new FPU singleton pattern in libs/ardour
[ardour.git] / libs / ardour / globals.cc
1 /*
2     Copyright (C) 2000 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #ifdef WAF_BUILD
20 #include "libardour-config.h"
21 #endif
22
23 #ifdef interface
24 #undef interface
25 #endif
26
27 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
28 #include <cstdlib>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <sys/time.h>
32 #ifndef PLATFORM_WINDOWS
33 #include <sys/resource.h>
34 #endif
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <time.h>
39
40 #include <glib.h>
41 #include <glib/gstdio.h>
42
43 #ifdef PLATFORM_WINDOWS
44 #include <windows.h> // for LARGE_INTEGER
45 #endif
46
47 #ifdef WINDOWS_VST_SUPPORT
48 #include <fst.h>
49 #endif
50
51 #ifdef LXVST_SUPPORT
52 #include "ardour/linux_vst_support.h"
53 #endif
54
55 #ifdef AUDIOUNIT_SUPPORT
56 #include "ardour/audio_unit.h"
57 #endif
58
59 #if defined(__SSE__) || defined(USE_XMMINTRIN)
60 #include <xmmintrin.h>
61 #endif
62
63 #ifdef check
64 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
65 #endif 
66
67 #include <glibmm/fileutils.h>
68 #include <glibmm/miscutils.h>
69
70 #ifdef HAVE_LRDF
71 #include <lrdf.h>
72 #endif
73
74 #include "pbd/cpus.h"
75 #include "pbd/error.h"
76 #include "pbd/id.h"
77 #include "pbd/pbd.h"
78 #include "pbd/strsplit.h"
79 #include "pbd/fpu.h"
80 #include "pbd/file_utils.h"
81 #include "pbd/enumwriter.h"
82 #include "pbd/basename.h"
83
84 #include "midi++/port.h"
85 #include "midi++/mmc.h"
86
87 #include "ardour/analyser.h"
88 #include "ardour/audio_library.h"
89 #include "ardour/audio_backend.h"
90 #include "ardour/audioengine.h"
91 #include "ardour/audioplaylist.h"
92 #include "ardour/audioregion.h"
93 #include "ardour/buffer_manager.h"
94 #include "ardour/control_protocol_manager.h"
95 #include "ardour/directory_names.h"
96 #include "ardour/event_type_map.h"
97 #include "ardour/filesystem_paths.h"
98 #include "ardour/midi_region.h"
99 #include "ardour/midiport_manager.h"
100 #include "ardour/mix.h"
101 #include "ardour/operations.h"
102 #include "ardour/panner_manager.h"
103 #include "ardour/plugin_manager.h"
104 #include "ardour/process_thread.h"
105 #include "ardour/profile.h"
106 #include "ardour/rc_configuration.h"
107 #include "ardour/region.h"
108 #include "ardour/route_group.h"
109 #include "ardour/runtime_functions.h"
110 #include "ardour/session_event.h"
111 #include "ardour/source_factory.h"
112 #include "ardour/uri_map.h"
113
114 #include "audiographer/routines.h"
115
116 #if defined (__APPLE__)
117        #include <Carbon/Carbon.h> // For Gestalt
118 #endif
119
120 #include "i18n.h"
121
122 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
123 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
124 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
125
126 using namespace ARDOUR;
127 using namespace std;
128 using namespace PBD;
129
130 bool libardour_initialized = false;
131
132 compute_peak_t          ARDOUR::compute_peak = 0;
133 find_peaks_t            ARDOUR::find_peaks = 0;
134 apply_gain_to_buffer_t  ARDOUR::apply_gain_to_buffer = 0;
135 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
136 mix_buffers_no_gain_t   ARDOUR::mix_buffers_no_gain = 0;
137 copy_vector_t                   ARDOUR::copy_vector = 0;
138
139 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
140 PBD::Signal3<void,std::string,std::string,bool> ARDOUR::PluginScanMessage;
141 PBD::Signal1<void,int> ARDOUR::PluginScanTimeout;
142 PBD::Signal0<void> ARDOUR::GUIIdle;
143 PBD::Signal3<bool,std::string,std::string,int> ARDOUR::CopyConfigurationFiles;
144
145 static bool have_old_configuration_files = false;
146
147 namespace ARDOUR {
148 extern void setup_enum_writer ();
149 }
150
151 /* this is useful for quite a few things that want to check
152    if any bounds-related property has changed
153 */
154 PBD::PropertyChange ARDOUR::bounds_change;
155
156 void
157 setup_hardware_optimization (bool try_optimization)
158 {
159         bool generic_mix_functions = true;
160
161         if (try_optimization) {
162
163                 FPU* fpu = FPU::instance();
164
165 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
166
167 #if 0 /* AVX code doesn't compile on Linux yet, don't use generic code instead */
168                 
169                 if (fpu->has_avx()) {
170                         
171                         info << "Using AVX optimized routines" << endmsg;
172
173                         // AVX SET
174                         compute_peak          = x86_sse_avx_compute_peak;
175                         find_peaks            = x86_sse_avx_find_peaks;
176                         apply_gain_to_buffer  = x86_sse_avx_apply_gain_to_buffer;
177                         mix_buffers_with_gain = x86_sse_avx_mix_buffers_with_gain;
178                         mix_buffers_no_gain   = x86_sse_avx_mix_buffers_no_gain;
179                         copy_vector           = x86_sse_avx_copy_vector;
180
181                         generic_mix_functions = false;
182
183                 } else
184 #endif
185                         if (fpu->has_sse()) {
186
187                         info << "Using SSE optimized routines" << endmsg;
188
189                         // SSE SET
190                         compute_peak          = x86_sse_compute_peak;
191                         find_peaks            = x86_sse_find_peaks;
192                         apply_gain_to_buffer  = x86_sse_apply_gain_to_buffer;
193                         mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
194                         mix_buffers_no_gain   = x86_sse_mix_buffers_no_gain;
195                         copy_vector           = default_copy_vector;
196
197                         generic_mix_functions = false;
198
199                 }
200
201 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
202                 SInt32 sysVersion = 0;
203
204                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
205                         sysVersion = 0;
206
207                 if (sysVersion >= 0x00001040) { // Tiger at least
208                         compute_peak           = veclib_compute_peak;
209                         find_peaks             = veclib_find_peaks;
210                         apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
211                         mix_buffers_with_gain  = veclib_mix_buffers_with_gain;
212                         mix_buffers_no_gain    = veclib_mix_buffers_no_gain;
213                         copy_vector            = default_copy_vector;
214
215                         generic_mix_functions = false;
216
217                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
218                 }
219 #endif
220
221                 /* consider FPU denormal handling to be "h/w optimization" */
222
223                 setup_fpu ();
224         }
225
226         if (generic_mix_functions) {
227
228                 compute_peak          = default_compute_peak;
229                 find_peaks            = default_find_peaks;
230                 apply_gain_to_buffer  = default_apply_gain_to_buffer;
231                 mix_buffers_with_gain = default_mix_buffers_with_gain;
232                 mix_buffers_no_gain   = default_mix_buffers_no_gain;
233                 copy_vector           = default_copy_vector;
234
235                 info << "No H/W specific optimizations in use" << endmsg;
236         }
237
238         AudioGrapher::Routines::override_compute_peak (compute_peak);
239         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
240 }
241
242 static void
243 lotsa_files_please ()
244 {
245 #ifndef PLATFORM_WINDOWS
246         struct rlimit rl;
247
248         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
249
250 #ifdef __APPLE__
251                 /* See the COMPATIBILITY note on the Apple setrlimit() man page */
252                 rl.rlim_cur = min ((rlim_t) OPEN_MAX, rl.rlim_max);
253 #else
254                 rl.rlim_cur = rl.rlim_max;
255 #endif
256
257                 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
258                         if (rl.rlim_cur == RLIM_INFINITY) {
259                                 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
260                         } else {
261                                 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
262                         }
263                 } else {
264                         if (rl.rlim_cur != RLIM_INFINITY) {
265                                 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
266                         }
267                 }
268         } else {
269                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
270         }
271 #endif
272 }
273
274 static int
275 copy_configuration_files (string const & old_dir, string const & new_dir, int old_version)
276 {
277         string old_name;
278         string new_name;
279
280         /* ensure target directory exists */
281
282         if (g_mkdir_with_parents (new_dir.c_str(), 0755)) {
283                 return -1;
284         }
285         
286         if (old_version == 3) {
287         
288                 old_name = Glib::build_filename (old_dir, X_("recent"));
289                 new_name = Glib::build_filename (new_dir, X_("recent"));
290
291                 copy_file (old_name, new_name);
292
293                 old_name = Glib::build_filename (old_dir, X_("sfdb"));
294                 new_name = Glib::build_filename (new_dir, X_("sfdb"));
295
296                 copy_file (old_name, new_name);
297
298                 /* can only copy ardour.rc/config - UI config is not compatible */
299
300                 /* users who have been using git/nightlies since the last
301                  * release of 3.5 will have $CONFIG/config rather than
302                  * $CONFIG/ardour.rc. Pick up the newer "old" config file,
303                  * to avoid confusion.
304                  */
305                 
306                 string old_name = Glib::build_filename (old_dir, X_("config"));
307
308                 if (!Glib::file_test (old_name, Glib::FILE_TEST_EXISTS)) {
309                         old_name = Glib::build_filename (old_dir, X_("ardour.rc"));
310                 }
311
312                 new_name = Glib::build_filename (new_dir, X_("config"));
313
314                 copy_file (old_name, new_name);
315
316                 /* copy templates and route templates */
317
318                 old_name = Glib::build_filename (old_dir, X_("templates"));
319                 new_name = Glib::build_filename (new_dir, X_("templates"));
320
321                 copy_recurse (old_name, new_name);
322
323                 old_name = Glib::build_filename (old_dir, X_("route_templates"));
324                 new_name = Glib::build_filename (new_dir, X_("route_templates"));
325
326                 copy_recurse (old_name, new_name);
327
328                 /* presets */
329
330                 old_name = Glib::build_filename (old_dir, X_("presets"));
331                 new_name = Glib::build_filename (new_dir, X_("presets"));
332                 
333                 copy_recurse (old_name, new_name);
334
335                 /* presets */
336
337                 old_name = Glib::build_filename (old_dir, X_("plugin_statuses"));
338                 new_name = Glib::build_filename (new_dir, X_("plugin_statuses"));
339
340                 copy_file (old_name, new_name);
341                 
342                 /* export formats */
343
344                 old_name = Glib::build_filename (old_dir, export_formats_dir_name);
345                 new_name = Glib::build_filename (new_dir, export_formats_dir_name);
346                 
347                 vector<string> export_formats;
348                 g_mkdir_with_parents (Glib::build_filename (new_dir, export_formats_dir_name).c_str(), 0755);
349                 find_files_matching_pattern (export_formats, old_name, X_("*.format"));
350                 for (vector<string>::iterator i = export_formats.begin(); i != export_formats.end(); ++i) {
351                         std::string from = *i;
352                         std::string to = Glib::build_filename (new_name, Glib::path_get_basename (*i));
353                         copy_file (from, to);
354                 }
355         }
356
357         return 0;
358 }
359
360 void
361 ARDOUR::check_for_old_configuration_files ()
362 {
363         int current_version = atoi (X_(PROGRAM_VERSION));
364         
365         if (current_version <= 1) {
366                 return;
367         }
368
369         int old_version = current_version - 1;
370
371         string old_config_dir = user_config_directory (old_version);
372         /* pass in the current version explicitly to avoid creation */
373         string current_config_dir = user_config_directory (current_version);
374
375         if (!Glib::file_test (current_config_dir, Glib::FILE_TEST_IS_DIR)) {
376                 if (Glib::file_test (old_config_dir, Glib::FILE_TEST_IS_DIR)) {
377                         have_old_configuration_files = true;
378                 }
379         }
380 }
381
382 int
383 ARDOUR::handle_old_configuration_files (boost::function<bool (std::string const&, std::string const&, int)> ui_handler)
384 {
385         if (have_old_configuration_files) {
386                 int current_version = atoi (X_(PROGRAM_VERSION));
387                 assert (current_version > 1); // established in check_for_old_configuration_files ()
388                 int old_version = current_version - 1;
389                 string old_config_dir = user_config_directory (old_version);
390                 string current_config_dir = user_config_directory (current_version);
391
392                 if (ui_handler (old_config_dir, current_config_dir, old_version)) {
393                         copy_configuration_files (old_config_dir, current_config_dir, old_version);
394                         return 1;
395                 }
396         }
397         return 0;
398 }
399
400 bool
401 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
402 {
403         if (libardour_initialized) {
404                 return true;
405         }
406
407         if (!PBD::init()) return false;
408
409 #ifdef ENABLE_NLS
410         (void) bindtextdomain(PACKAGE, localedir);
411         (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
412 #endif
413
414         SessionEvent::init_event_pool ();
415
416         Operations::make_operations_quarks ();
417         SessionObject::make_property_quarks ();
418         Region::make_property_quarks ();
419         MidiRegion::make_property_quarks ();
420         AudioRegion::make_property_quarks ();
421         RouteGroup::make_property_quarks ();
422         Playlist::make_property_quarks ();
423         AudioPlaylist::make_property_quarks ();
424
425         /* this is a useful ready to use PropertyChange that many
426            things need to check. This avoids having to compose
427            it every time we want to check for any of the relevant
428            property changes.
429         */
430
431         bounds_change.add (ARDOUR::Properties::start);
432         bounds_change.add (ARDOUR::Properties::position);
433         bounds_change.add (ARDOUR::Properties::length);
434
435         /* provide a state version for the few cases that need it and are not
436            driven by reading state from disk (e.g. undo/redo)
437         */
438
439         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
440
441         ARDOUR::setup_enum_writer ();
442
443         // allow ardour the absolute maximum number of open files
444         lotsa_files_please ();
445
446 #ifdef HAVE_LRDF
447         lrdf_init();
448 #endif
449         Library = new AudioLibrary;
450
451         BootMessage (_("Loading configuration"));
452
453         Config = new RCConfiguration;
454
455         if (Config->load_state ()) {
456                 return false;
457         }
458
459         Config->set_use_windows_vst (use_windows_vst);
460 #ifdef LXVST_SUPPORT
461         Config->set_use_lxvst(true);
462 #endif
463
464         Profile = new RuntimeProfile;
465
466
467 #ifdef WINDOWS_VST_SUPPORT
468         if (Config->get_use_windows_vst() && fst_init (0)) {
469                 return false;
470         }
471 #endif
472
473 #ifdef LXVST_SUPPORT
474         if (Config->get_use_lxvst() && vstfx_init (0)) {
475                 return false;
476         }
477 #endif
478
479 #ifdef AUDIOUNIT_SUPPORT
480         AUPluginInfo::load_cached_info ();
481 #endif
482
483         setup_hardware_optimization (try_optimization);
484
485         SourceFactory::init ();
486         Analyser::init ();
487
488         /* singletons - first object is "it" */
489         (void) PluginManager::instance();
490 #ifdef LV2_SUPPORT
491         (void) URIMap::instance();
492 #endif
493         (void) EventTypeMap::instance();
494
495         ProcessThread::init ();
496         /* the + 4 is a bit of a handwave. i don't actually know
497            how many more per-thread buffer sets we need above
498            the h/w concurrency, but its definitely > 1 more.
499         */
500         BufferManager::init (hardware_concurrency() + 4); 
501
502         PannerManager::instance().discover_panners();
503
504         ARDOUR::AudioEngine::create ();
505
506         libardour_initialized = true;
507
508         return true;
509 }
510
511 void
512 ARDOUR::init_post_engine ()
513 {
514         ControlProtocolManager::instance().discover_control_protocols ();
515
516         XMLNode* node;
517         if ((node = Config->control_protocol_state()) != 0) {
518                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
519         }
520
521         /* find plugins */
522
523         ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
524 }
525
526 void
527 ARDOUR::cleanup () 
528 {
529         if (!libardour_initialized) {
530                 return;
531         }
532
533         ARDOUR::AudioEngine::destroy ();
534
535         delete Library;
536 #ifdef HAVE_LRDF
537         lrdf_cleanup ();
538 #endif
539         delete &ControlProtocolManager::instance();
540 #ifdef WINDOWS_VST_SUPPORT
541         fst_exit ();
542 #endif
543
544 #ifdef LXVST_SUPPORT
545         vstfx_exit();
546 #endif
547         delete &PluginManager::instance();
548         delete Config;
549         PBD::cleanup ();
550
551         return;
552 }
553
554 void
555 ARDOUR::find_bindings_files (map<string,string>& files)
556 {
557         vector<std::string> found;
558         Searchpath spath = ardour_config_search_path();
559
560         if (getenv ("ARDOUR_SAE")) {
561                 find_files_matching_pattern (found, spath, "*SAE-*.bindings");
562         } else {
563                 find_files_matching_pattern (found, spath, "*.bindings");
564         }
565
566         if (found.empty()) {
567                 return;
568         }
569
570         for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
571                 std::string path(*x);
572                 pair<string,string> namepath;
573                 namepath.second = path;
574                 namepath.first = PBD::basename_nosuffix (path);
575                 files.insert (namepath);
576         }
577 }
578
579 bool
580 ARDOUR::no_auto_connect()
581 {
582         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
583 }
584
585 void
586 ARDOUR::setup_fpu ()
587 {
588         FPU* fpu = FPU::instance ();
589         
590         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
591                 // valgrind doesn't understand this assembler stuff
592                 // September 10th, 2007
593                 return;
594         }
595
596 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
597
598         int MXCSR;
599
600         if (!fpu->has_flush_to_zero() && !fpu->has_denormals_are_zero()) {
601                 return;
602         }
603
604         MXCSR  = _mm_getcsr();
605
606 #ifdef DEBUG_DENORMAL_EXCEPTION
607         /* This will raise a FP exception if a denormal is detected */
608         MXCSR &= ~_MM_MASK_DENORM;
609 #endif  
610
611         switch (Config->get_denormal_model()) {
612         case DenormalNone:
613                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
614                 break;
615
616         case DenormalFTZ:
617                 if (fpu->has_flush_to_zero()) {
618                         MXCSR |= _MM_FLUSH_ZERO_ON;
619                 }
620                 break;
621
622         case DenormalDAZ:
623                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
624                 if (fpu->has_denormals_are_zero()) {
625                         MXCSR |= 0x40;
626                 }
627                 break;
628
629         case DenormalFTZDAZ:
630                 if (fpu->has_flush_to_zero()) {
631                         if (fpu->has_denormals_are_zero()) {
632                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
633                         } else {
634                                 MXCSR |= _MM_FLUSH_ZERO_ON;
635                         }
636                 }
637                 break;
638         }
639
640         _mm_setcsr (MXCSR);
641
642 #endif
643 }
644
645 /* this can be changed to modify the translation behaviour for
646    cases where the user has never expressed a preference.
647 */
648 static const bool translate_by_default = true;
649
650 string
651 ARDOUR::translation_enable_path ()
652 {
653         return Glib::build_filename (user_config_directory(), ".translate");
654 }
655
656 bool
657 ARDOUR::translations_are_enabled ()
658 {
659         int fd = g_open (ARDOUR::translation_enable_path().c_str(), O_RDONLY, 0444);
660
661         if (fd < 0) {
662                 return translate_by_default;
663         }
664
665         char c;
666         bool ret = false;
667
668         if (::read (fd, &c, 1) == 1 && c == '1') {
669                 ret = true;
670         }
671
672         ::close (fd);
673
674         return ret;
675 }
676
677 bool
678 ARDOUR::set_translations_enabled (bool yn)
679 {
680         string i18n_enabler = ARDOUR::translation_enable_path();
681         int fd = g_open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
682
683         if (fd < 0) {
684                 return false;
685         }
686         
687         char c;
688         
689         if (yn) {
690                 c = '1';
691         } else {
692                 c = '0';
693         }
694         
695         (void) ::write (fd, &c, 1);
696         (void) ::close (fd);
697
698         return true;
699 }
700
701
702 vector<SyncSource>
703 ARDOUR::get_available_sync_options ()
704 {
705         vector<SyncSource> ret;
706
707         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
708         if (backend && backend->name() == "JACK") {
709                 ret.push_back (Engine);
710         }
711
712         ret.push_back (MTC);
713         ret.push_back (MIDIClock);
714         ret.push_back (LTC);
715
716         return ret;
717 }
718
719 /** Return a monotonic value for the number of microseconds that have elapsed
720  * since an arbitrary zero origin.
721  */
722
723 #ifdef __MACH__
724 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
725  */
726 #include <mach/mach_time.h>
727 #define CLOCK_REALTIME 0
728 #define CLOCK_MONOTONIC 0
729 int 
730 clock_gettime (int /*clk_id*/, struct timespec *t)
731 {
732         static bool initialized = false;
733         static mach_timebase_info_data_t timebase;
734         if (!initialized) {
735                 mach_timebase_info(&timebase);
736                 initialized = true;
737         }
738         uint64_t time;
739         time = mach_absolute_time();
740         double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
741         double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
742         t->tv_sec = seconds;
743         t->tv_nsec = nseconds;
744         return 0;
745 }
746 #endif
747  
748 microseconds_t
749 ARDOUR::get_microseconds ()
750 {
751 #ifdef PLATFORM_WINDOWS
752         microseconds_t ret = 0;
753         LARGE_INTEGER freq, time;
754
755         if (QueryPerformanceFrequency(&freq))
756                 if (QueryPerformanceCounter(&time))
757                         ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
758
759         return ret;
760 #else
761         struct timespec ts;
762         if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
763                 /* EEEK! */
764                 return 0;
765         }
766         return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
767 #endif
768 }
769
770 /** Return the number of bits per sample for a given sample format.
771  *
772  * This is closely related to sndfile_data_width() but does NOT
773  * return a "magic" value to differentiate between 32 bit integer
774  * and 32 bit floating point values.
775  */
776
777 int
778 ARDOUR::format_data_width (ARDOUR::SampleFormat format)
779 {
780
781
782
783         switch (format) {
784         case ARDOUR::FormatInt16:
785                 return 16;
786         case ARDOUR::FormatInt24:
787                 return 24;
788         default:
789                 return 32;
790         }
791 }