diff options
-rw-r--r-- | libs/backends/portaudio/portaudio_backend.cc | 8 | ||||
-rw-r--r-- | libs/backends/portaudio/win_utils.cc | 136 | ||||
-rw-r--r-- | libs/backends/portaudio/win_utils.h | 58 | ||||
-rw-r--r-- | libs/backends/portaudio/winmmemidi_input_device.cc | 2 | ||||
-rw-r--r-- | libs/backends/portaudio/winmmemidi_io.cc | 5 | ||||
-rw-r--r-- | libs/backends/portaudio/winmmemidi_output_device.cc | 4 |
6 files changed, 158 insertions, 55 deletions
diff --git a/libs/backends/portaudio/portaudio_backend.cc b/libs/backends/portaudio/portaudio_backend.cc index dcdb0d168d..f4ab827556 100644 --- a/libs/backends/portaudio/portaudio_backend.cc +++ b/libs/backends/portaudio/portaudio_backend.cc @@ -680,7 +680,7 @@ PortAudioBackend::samples_since_cycle_start () return 0; } - return m_cycle_timer.samples_since_cycle_start (utils::get_microseconds()); + return m_cycle_timer.samples_since_cycle_start (PBD::get_microseconds()); } int @@ -1525,7 +1525,7 @@ PortAudioBackend::blocking_process_main(const float* interleaved_input_data, int64_t min_elapsed_us = 1000000; int64_t max_elapsed_us = 0; - m_dsp_calc.set_start_timestamp_us (utils::get_microseconds()); + m_dsp_calc.set_start_timestamp_us (PBD::get_microseconds()); i = 0; /* Copy input audio data into input port buffers */ @@ -1551,7 +1551,7 @@ PortAudioBackend::blocking_process_main(const float* interleaved_input_data, } m_last_cycle_start = m_cycle_timer.get_start(); - m_cycle_timer.reset_start(utils::get_microseconds()); + m_cycle_timer.reset_start(PBD::get_microseconds()); m_cycle_count++; uint64_t cycle_diff_us = (m_cycle_timer.get_start() - m_last_cycle_start); @@ -1599,7 +1599,7 @@ PortAudioBackend::blocking_process_main(const float* interleaved_input_data, _processed_samples += _samples_per_period; /* calculate DSP load */ - m_dsp_calc.set_stop_timestamp_us (utils::get_microseconds()); + m_dsp_calc.set_stop_timestamp_us (PBD::get_microseconds()); _dsp_load = m_dsp_calc.get_dsp_load(); DEBUG_TIMING(string_compose("DSP Load: %1\n", _dsp_load)); diff --git a/libs/backends/portaudio/win_utils.cc b/libs/backends/portaudio/win_utils.cc index dc0f8d5270..6d0e404749 100644 --- a/libs/backends/portaudio/win_utils.cc +++ b/libs/backends/portaudio/win_utils.cc @@ -27,27 +27,6 @@ namespace { -bool& -qpc_frequency_success () -{ - static bool success = false; - return success; -} - -LARGE_INTEGER -qpc_frequency () -{ - LARGE_INTEGER freq; - if (QueryPerformanceFrequency(&freq) == 0) { - DEBUG_TIMING ("Failed to determine frequency of QPC\n"); - qpc_frequency_success() = false; - } else { - qpc_frequency_success() = true; - } - - return freq; -} - UINT& old_timer_resolution () { @@ -57,33 +36,63 @@ old_timer_resolution () } // anon namespace -namespace utils { +namespace PBD { + +namespace MMTIMERS { bool -set_min_timer_resolution () +set_min_resolution () { TIMECAPS caps; if (timeGetDevCaps (&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) { DEBUG_TIMING ("Could not get timer device capabilities.\n"); return false; - } else { - old_timer_resolution () = caps.wPeriodMin; - if (timeBeginPeriod (caps.wPeriodMin) != TIMERR_NOERROR) { - DEBUG_TIMING (string_compose ( - "Could not set minimum timer resolution to %1(ms)\n", caps.wPeriodMin)); - return false; - } + } + return set_resolution(caps.wPeriodMin); +} + +bool +set_resolution (uint32_t timer_resolution_ms) +{ + TIMECAPS caps; + + if (timeGetDevCaps (&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) { + DEBUG_TIMING ("Could not get timer device capabilities.\n"); + return false; + } + + UINT old_timer_res = caps.wPeriodMin; + + if (timeBeginPeriod(timer_resolution_ms) != TIMERR_NOERROR) { + DEBUG_TIMING( + string_compose("Could not set minimum timer resolution to %1(ms)\n", + timer_resolution_ms)); + return false; } + old_timer_resolution () = old_timer_res; + DEBUG_TIMING (string_compose ("Multimedia timer resolution set to %1(ms)\n", caps.wPeriodMin)); + return true; +} +bool +get_resolution (uint32_t& timer_resolution_ms) +{ + TIMECAPS caps; + + if (timeGetDevCaps(&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) { + DEBUG_TIMING ("Could not get timer device capabilities.\n"); + return false; + } + timer_resolution_ms = caps.wPeriodMin; return true; } bool -reset_timer_resolution () +reset_resolution () { if (old_timer_resolution ()) { if (timeEndPeriod (old_timer_resolution ()) != TIMERR_NOERROR) { @@ -98,26 +107,77 @@ reset_timer_resolution () return true; } +} // namespace MMTIMERS + +namespace { + +bool& +qpc_frequency_success () +{ + static bool success = false; + return success; +} + +LARGE_INTEGER +qpc_frequency () +{ + LARGE_INTEGER freq; + if (QueryPerformanceFrequency(&freq) == 0) { + DEBUG_TIMING ("Failed to determine frequency of QPC\n"); + qpc_frequency_success() = false; + } else { + qpc_frequency_success() = true; + } + + return freq; +} + +LARGE_INTEGER +qpc_frequency_cached () +{ + static LARGE_INTEGER frequency = qpc_frequency (); + return frequency; +} + +} // anon namespace + +namespace QPC { + +bool +get_timer_valid () +{ + // setup caching the timer frequency + qpc_frequency_cached (); + return qpc_frequency_success (); +} + int64_t get_microseconds () { - static LARGE_INTEGER frequency = qpc_frequency (); LARGE_INTEGER current_val; if (qpc_frequency_success()) { - // MS docs say this will always succeed for systems >= XP but it may // not return a monotonic value with non-invariant TSC's etc if (QueryPerformanceCounter(¤t_val) != 0) { return (int64_t)(((double)current_val.QuadPart) / - ((double)frequency.QuadPart) * 1000000.0); - } else { - DEBUG_TIMING ("Could not get QPC timer\n"); + ((double)qpc_frequency_cached().QuadPart) * 1000000.0); } - return -1; + } + DEBUG_TIMING ("Could not get QPC timer\n"); + return -1; +} + +} // namespace QPC + +int64_t +get_microseconds () +{ + if (qpc_frequency_success()) { + return QPC::get_microseconds (); } // For XP systems that don't support a high-res performance counter return g_get_monotonic_time (); } -} // namespace utils +} // namespace PBD diff --git a/libs/backends/portaudio/win_utils.h b/libs/backends/portaudio/win_utils.h index 072ce1f0b0..c0c7bbf491 100644 --- a/libs/backends/portaudio/win_utils.h +++ b/libs/backends/portaudio/win_utils.h @@ -21,22 +21,66 @@ #include <stdint.h> -namespace utils { +namespace PBD { -bool set_min_timer_resolution (); +namespace MMTIMERS { -bool reset_timer_resolution (); +/** + * Set the minimum Multimedia Timer resolution as supported by the system + * @return true if min timer resolution was successfully set + * + * Call reset_resolution to restore old timer resolution + */ +bool set_min_resolution (); + +/** + * Get current Multimedia Timer resolution + * @return true if getting the timer value was successful + */ +bool get_resolution(uint32_t& timer_resolution_us); + +/** + * Set current Multimedia Timer resolution + * @return true if setting the timer value was successful + */ +bool set_resolution(uint32_t timer_resolution_us); + +/** + * Reset the Multimedia Timer back to what it was originally before + * setting the timer resolution. + */ +bool reset_resolution (); + +} // namespace MMTIMERS + +namespace QPC { + +/** + * @return true if QueryPerformanceCounter is usable as a timer source + */ +bool get_timer_valid (); + +/** + * @return the value of the performance counter converted to microseconds + * + * If get_counter_valid returns true then get_microseconds will always + * return a positive value. If QPC is not supported(OS < XP) then -1 is + * returned but the MS docs say that this won't occur for systems >= XP. + */ +int64_t get_microseconds (); + +} // namespace QPC -/** The highest resolution timer source provided by the system. On Vista and +/** + * The highest resolution timer source provided by the system. On Vista and * above this is the value returned by QueryPerformanceCounter(QPC). On XP, * this will QPC if supported or otherwise g_get_monotonic_time will be used. * * @return A timer value in microseconds or -1 in the event that the reading - * the timer source fails, but the MS docs say that this won't occur for - * systems >= XP + * the timer source fails. */ int64_t get_microseconds (); -} +} // namespace PBD #endif // WIN_UTILS_H diff --git a/libs/backends/portaudio/winmmemidi_input_device.cc b/libs/backends/portaudio/winmmemidi_input_device.cc index d7a0a6dbaa..95e7faa476 100644 --- a/libs/backends/portaudio/winmmemidi_input_device.cc +++ b/libs/backends/portaudio/winmmemidi_input_device.cc @@ -346,7 +346,7 @@ WinMMEMidiInputDevice::enqueue_midi_msg (const uint8_t* midi_data, } // don't use winmme timestamps for now - uint64_t ts = utils::get_microseconds (); + uint64_t ts = PBD::get_microseconds (); DEBUG_TIMING (string_compose ( "Enqueing MIDI data device: %1 with timestamp: %2 and size %3\n", diff --git a/libs/backends/portaudio/winmmemidi_io.cc b/libs/backends/portaudio/winmmemidi_io.cc index 43c5d36469..4c93799637 100644 --- a/libs/backends/portaudio/winmmemidi_io.cc +++ b/libs/backends/portaudio/winmmemidi_io.cc @@ -31,7 +31,6 @@ #include "i18n.h" using namespace ARDOUR; -using namespace utils; WinMMEMidiIO::WinMMEMidiIO() : m_active (false) @@ -136,7 +135,7 @@ WinMMEMidiIO::start () m_run = true; DEBUG_MIDI ("Starting MIDI driver\n"); - set_min_timer_resolution(); + PBD::MMTIMERS::set_min_resolution(); discover(); start_devices (); } @@ -156,7 +155,7 @@ WinMMEMidiIO::stop () cleanup (); pthread_mutex_unlock (&m_device_lock); - reset_timer_resolution(); + PBD::MMTIMERS::reset_resolution(); } void diff --git a/libs/backends/portaudio/winmmemidi_output_device.cc b/libs/backends/portaudio/winmmemidi_output_device.cc index 84a72a2304..a1d76cd236 100644 --- a/libs/backends/portaudio/winmmemidi_output_device.cc +++ b/libs/backends/portaudio/winmmemidi_output_device.cc @@ -390,7 +390,7 @@ WinMMEMidiOutputDevice::midi_output_thread () DEBUG_MIDI ("WinMMEMidiOut: MIDI buffer underrun, shouldn't occur\n"); continue; } - uint64_t current_time = utils::get_microseconds (); + uint64_t current_time = PBD::get_microseconds (); DEBUG_TIMING (string_compose ( "WinMMEMidiOut: h.time = %1, current_time = %2\n", h.time, current_time)); @@ -408,7 +408,7 @@ WinMMEMidiOutputDevice::midi_output_thread () break; } - uint64_t wakeup_time = utils::get_microseconds (); + uint64_t wakeup_time = PBD::get_microseconds (); DEBUG_TIMING (string_compose ("WinMMEMidiOut: woke up at %1(ms)\n", ((double)wakeup_time) / 1000.0)); if (wakeup_time > h.time) { |