diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 4459546ff4..10697ec762 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -499,6 +499,110 @@ time warp info and AudioIOListener and whether the playback is looped. #define UPPER_BOUND 1.0 #endif +/* + Adapt and rename the implementation of PaUtil_GetTime from commit + c5d2c51bd6fe354d0ee1119ba932bfebd3ebfacc of portaudio + This code is by @Paul-Licameli . Please refer to: https://github.com/audacity/audacity/pull/946 for further credit. + */ +#if defined( __APPLE__ ) + +#include + +/* Scaler to convert the result of mach_absolute_time to seconds */ +static double machSecondsConversionScaler_ = 0.0; + +/* Initialize it */ +static struct InitializeTime { InitializeTime() { + mach_timebase_info_data_t info; + kern_return_t err = mach_timebase_info( &info ); + if( err == 0 ) + machSecondsConversionScaler_ = 1e-9 * (double) info.numer / (double) info.denom; +} } initializeTime; + +static PaTime util_GetTime( void ) +{ + return mach_absolute_time() * machSecondsConversionScaler_; +} + +#elif defined( __WXMSW__ ) + +#include "profileapi.h" +#include "sysinfoapi.h" +#include "timeapi.h" + +static int usePerformanceCounter_; +static double secondsPerTick_; + +static struct InitializeTime { InitializeTime() { + LARGE_INTEGER ticksPerSecond; + + if( QueryPerformanceFrequency( &ticksPerSecond ) != 0 ) + { + usePerformanceCounter_ = 1; + secondsPerTick_ = 1.0 / (double)ticksPerSecond.QuadPart; + } + else + { + usePerformanceCounter_ = 0; + } +} } initializeTime; + +static double util_GetTime( void ) +{ + LARGE_INTEGER time; + + if( usePerformanceCounter_ ) + { + /* + Note: QueryPerformanceCounter has a known issue where it can skip forward + by a few seconds (!) due to a hardware bug on some PCI-ISA bridge hardware. + This is documented here: + http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q274323& + + The work-arounds are not very paletable and involve querying GetTickCount + at every time step. + + Using rdtsc is not a good option on multi-core systems. + + For now we just use QueryPerformanceCounter(). It's good, most of the time. + */ + QueryPerformanceCounter( &time ); + return time.QuadPart * secondsPerTick_; + } + else + { + #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) + return GetTickCount64() * .001; + #else + return timeGetTime() * .001; + #endif + } +} + +#elif defined(HAVE_CLOCK_GETTIME) + +#include + +static PaTime util_GetTime( void ) +{ + struct timespec tp; + clock_gettime(CLOCK_REALTIME, &tp); + return (PaTime)(tp.tv_sec + tp.tv_nsec * 1e-9); +} + +#else + +#include + +static PaTime util_GetTime( void ) +{ + struct timeval tv; + gettimeofday( &tv, NULL ); + return (PaTime) tv.tv_usec * 1e-6 + tv.tv_sec; +} + +#endif + using std::max; using std::min; @@ -828,7 +932,7 @@ static double SystemTime(bool usingAlsa) static_cast(usingAlsa);//compiler food. #endif - return PaUtil_GetTime() - streamStartTime; + return util_GetTime() - streamStartTime; } #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 27a13fc528..877c3895f4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,8 @@ set( TARGET Sneedacity ) set( TARGET_ROOT ${topdir}/src ) +include (CheckFunctionExists) + message( STATUS "========== Configuring ${TARGET} ==========" ) # Allow modules to link against the Sneedacity executable @@ -1332,6 +1334,12 @@ import_symbol_define( import_symbol SNEEDACITY_DLL ) export_symbol_define( export_symbol SNEEDACITY_DLL ) list( APPEND DEFINES PRIVATE "${export_symbol}" INTERFACE "${import_symbol}" ) +# see AudioIO.cpp +check_function_exists(clock_gettime HAVE_CLOCK_GETTIME) +if(HAVE_CLOCK_GETTIME) + list( APPEND DEFINES HAVE_CLOCK_GETTIME ) +endif() + target_sources( ${TARGET} PRIVATE ${HEADERS} ${SOURCES} ${RESOURCES} ${MAC_RESOURCES} ${WIN_RESOURCES} ) target_compile_definitions( ${TARGET} PRIVATE ${DEFINES} ) target_compile_options( ${TARGET} PRIVATE ${OPTIONS} )