diff --git a/cmake/windows.cmake b/cmake/windows.cmake index a86bf714..ba91a93f 100644 --- a/cmake/windows.cmake +++ b/cmake/windows.cmake @@ -107,6 +107,9 @@ set(JVX_CMAKE_LINKER_FLAGS_EXEC "${JVX_LINKER_DISABLE_WARNING}") set(JVX_SYSTEM_LIBRARIES "") set(JVX_SOCKET_LIBRARIES "ws2_32;wsock32") +# Add OS specific category libraries +set(JVX_SYSTEM_LIBRARIES_WIN_MM "Winmm") + if(NOT JVX_USE_CONSOLE_APPS) set(JVX_APP_TYPE_TOKEN "WIN32") endif() diff --git a/sources/jvxComponents/jvxAudioTechnologies/jvxAuTSyncClock/CMakeLists.txt b/sources/jvxComponents/jvxAudioTechnologies/jvxAuTSyncClock/CMakeLists.txt index 526c6691..4d8c0c8e 100644 --- a/sources/jvxComponents/jvxAudioTechnologies/jvxAuTSyncClock/CMakeLists.txt +++ b/sources/jvxComponents/jvxAudioTechnologies/jvxAuTSyncClock/CMakeLists.txt @@ -34,8 +34,20 @@ set(LOCAL_LIBS jvx-helpers-product_static jvx-audiocodec-helpers_static + ) +# Special rule for Windows here - the thread timer accuracy is a problem. +# However, we have an alternative approach to define timers with timerSetEvent +# For more info, comments are provided at the beginng of ~15 msecs. And this lets the + * timeout return after 20 + 15 = 35 msecs in the worst case. And this destroys the processing in the sense + * of a simulated realtime process. + * + * A user then mentioned the timeSetEvent function + * + * https://learn.microsoft.com/en-us/previous-versions/dd757634(v=vs.85) + * + * which is obsolete. However, only this function seems to work properly. Even the proposed function + * CreateTimerQueueTimer which is proposed seems to be broken due to the above mentioned article: + * + * "I am writing a streaming application, that used one shot CreateTimerQueueTimer timers to trigger + * the sending of UDP packets every few milliseconds. Since Win 10 2004 this is broken, my timers + * only fire after 15ms despite calling timeBeginPeriod(1). I changed it to use timeSetEvent, now + * it works again, including on Windows 10 2004 and 20H2. + * + * So since the 2004 update CreateTimerQueueTimer() ignores the resolution defined by timeBeginPeriod. + * + * Unfortunately timeSetEvent is desclared obsolete, with a recommendation to use the (now broken) + * CreateTimerQueueTimer. On the other hand timeSetEvent has been declared obsolete since at least + * 2008 (earliest mention of the obsolence found in a quick Google search) and it is still around. + * Hopefully it will stay oder Microsoft fixes CreateTimerQueueTimer." + * + * + */ + + // ============================================================= + // ============================================================= + +// Buffering debugging here!! + +// #define MEASURE_TIMING + +#ifdef MEASURE_TIMING +#define JVX_NUM_EVENTS_OBSERVE 1000 +struct oneEntryTimer +{ + jvxData desiredTimeout = 0; + jvxData measuredTimeout = 0; + + jvxData progressTimerFrames = 0; + jvxData progressTimerMeasured = 0; + jvxData progressTimerNext = 0; + jvxData progressTimerDirect = 0; + jvxBool runBuffer = false; +} +static oneEntryTimer[JVX_NUM_EVENTS_OBSERVE]; +static int Cbs = 0; +static int cnt = 0; + +#endif + +// ============================================================= +// ============================================================= + CjvxAudioSyncClockDevice::CjvxAudioSyncClockDevice(JVX_CONSTRUCTOR_ARGUMENTS_MACRO_DECLARE) : CjvxAudioDevice(JVX_CONSTRUCTOR_ARGUMENTS_MACRO_CALL) @@ -61,9 +125,11 @@ CjvxAudioSyncClockDevice::activate() CjvxAudioDevice::properties_active.samplerate.value = 48000; CjvxAudioDevice::properties_active.buffersize.value = 1024; +#ifndef JVX_SYNCED_CLOCK_WINDOWS threads = reqInstTool(_common_set.theToolsHost, JVX_COMPONENT_THREADS); assert(threads.cpPtr); - + threads.cpPtr->initialize(this); +#endif return JVX_NO_ERROR; } return res; @@ -75,10 +141,12 @@ CjvxAudioSyncClockDevice::deactivate() jvxErrorType res = CjvxAudioDevice::_pre_check_deactivate(); if (res == JVX_NO_ERROR) { +#ifndef JVX_SYNCED_CLOCK_WINDOWS + threads.cpPtr->terminate(); retInstTool(_common_set.theToolsHost, JVX_COMPONENT_THREADS, threads); threads.cpPtr = nullptr; threads.objPtr = nullptr; - +#endif CjvxAudioDevice::properties_active.buffersize.value = 1024; CjvxAudioDevice::properties_active.samplerate.value = 48000; CjvxAudioDevice::properties_active.inputchannelselection.value.entries.clear(); @@ -106,76 +174,14 @@ CjvxAudioSyncClockDevice::test_chain_master(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) return res; } -jvxErrorType -CjvxAudioSyncClockDevice::prepare_chain_master(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) +#ifdef JVX_SYNCED_CLOCK_WINDOWS +void myCallback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1,DWORD_PTR dw2) { - jvxErrorType res = CjvxAudioDevice::prepare_chain_master(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - if (res == JVX_NO_ERROR) - { - threads.cpPtr->initialize(this); - } - -#if 0 - // Auto-run the prepare function - res = prepare_chain_master_autostate(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - assert(res == JVX_NO_ERROR); - - // Prepare processing parameters - _common_set_ocon.theData_out.con_data.number_buffers = 1; - jvx_bitZSet(_common_set_ocon.theData_out.con_data.alloc_flags, - (int)jvxDataLinkDescriptorAllocFlags::JVX_LINKDATA_ALLOCATION_FLAGS_IS_ZEROCOPY_CHAIN_SHIFT); - - jvx_bitSet(_common_set_ocon.theData_out.con_data.alloc_flags, - (int)jvxDataLinkDescriptorAllocFlags::JVX_LINKDATA_ALLOCATION_FLAGS_EXPECT_FHEIGHT_INFO_SHIFT); - - // New type of connection by propagating through linked elements - res = _prepare_chain_master(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - if (res == JVX_NO_ERROR) - { - - // All parameters were set before, only very few need update - _common_set_ocon.theData_out.con_data.number_buffers = 1; - - // START HERE!! - } - else - { - _postprocess_chain_master(NULL); - goto leave_error; - } - - return(res); -leave_error: -#endif - return res; + CjvxAudioSyncClockDevice* this_pointer = (CjvxAudioSyncClockDevice*)dwUser; + assert(this_pointer); + this_pointer->timerCallback(); } - -jvxErrorType -CjvxAudioSyncClockDevice::postprocess_chain_master(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) -{ - jvxErrorType res = CjvxAudioDevice::postprocess_chain_master(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - if (res == JVX_NO_ERROR) - { - threads.cpPtr->terminate(); - } - -#if 0 - jvxErrorType res = JVX_NO_ERROR; - jvxErrorType resL; - - - // STOP HERE - - _postprocess_chain_master(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - assert(res == JVX_NO_ERROR); - - // If the chain is postprocessed, the object itself should also be postprocessed if not done so before - resL = postprocess_chain_master_autostate(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - assert(resL == JVX_NO_ERROR); #endif - return res; - -} jvxErrorType CjvxAudioSyncClockDevice::start_chain_master(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) @@ -185,37 +191,32 @@ CjvxAudioSyncClockDevice::start_chain_master(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) { jvxData timeOutBuffer_secs = (jvxData)_common_set_ocon.theData_out.con_params.buffersize / (jvxData)_common_set_ocon.theData_out.con_params.rate; timeOutBuffer_msecs_exact = timeOutBuffer_secs * 1e3; - progress_msecs_accumulated_exact = 0; + + progress_msecs_frames = -1; + progress_msecs_next_call = -1; progress_msecs_measured = -1; + + // Preset the timestamp to measure delta time tStampLastFrame = -1; - jvxSize timeOutBuffer_msecs_floor = floor(timeOutBuffer_msecs_exact); - JVX_GET_TICKCOUNT_US_SETREF(&tStamp); - threads.cpPtr->start(timeOutBuffer_msecs_floor, true, true); - } -#if 0 - jvxErrorType res = JVX_NO_ERROR; - - // If the chain is started, the object itself should also be started if not done so before - jvxErrorType resL = start_chain_master_autostate(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - assert(resL == JVX_NO_ERROR); - res = _start_chain_master(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - if(res != JVX_NO_ERROR) - { - goto leave_error; - } + // Involve a higher rate compared to approx buffersize to take core of the round problem + timeOutBuffer_msecs_exact_n = timeOutBuffer_msecs_exact / 4; - // Start core function - - if (res != JVX_NO_ERROR) - { - _stop_chain_master(NULL); - goto leave_error; - } - - return res; -leave_error: + // Here, we round downwards + timeOutBuffer_msecs_floor = floor(timeOutBuffer_msecs_exact_n); + + // Init the time measurement + JVX_GET_TICKCOUNT_US_SETREF(&tStamp); + +#ifdef JVX_SYNCED_CLOCK_WINDOWS + // Start the time - note that we are allowed to use a maximum of 16 timers according to + // https://stackoverflow.com/questions/18637470/how-to-replace-timesetevent-function-without-losing-functionality + // in windows! + timerId = timeSetEvent(timeOutBuffer_msecs_floor, 0, myCallback, (DWORD_PTR)this, TIME_PERIODIC); +#else + threads.cpPtr->start(timeOutBuffer_msecs_floor, true, true); #endif + } return res; } @@ -226,70 +227,22 @@ CjvxAudioSyncClockDevice::stop_chain_master(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) jvxErrorType res = CjvxAudioDevice::stop_chain_master(JVX_CONNECTION_FEEDBACK_CALL(fdb)); if (res == JVX_NO_ERROR) { - threads.cpPtr->stop(); } -#if 0 - jvxErrorType res = JVX_NO_ERROR; - jvxErrorType resL; - - res = _stop_chain_master(NULL); - assert(res == JVX_NO_ERROR); - - // If the chain is stopped, the object itself should also be stopped if not done so before - resL = stop_chain_master_autostate(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - assert(resL == JVX_NO_ERROR); +#ifdef JVX_SYNCED_CLOCK_WINDOWS + timeKillEvent(timerId); + timerId = 0; +#else + threads.cpPtr->stop(); #endif - return res; -} -jvxErrorType -CjvxAudioSyncClockDevice::prepare_connect_icon(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) -{ - return CjvxAudioDevice::prepare_connect_icon(JVX_CONNECTION_FEEDBACK_CALL(fdb)); - #if 0 - jvxErrorType res = JVX_NO_ERROR; - // This is the return from the link list - - _common_set_icon.theData_in->con_params.buffersize = _inproc.buffersize; - _common_set_icon.theData_in->con_params.format = _inproc.format; - _common_set_icon.theData_in->con_data.buffers = NULL; - _common_set_icon.theData_in->con_data.number_buffers = JVX_MAX(_common_set_icon.theData_in->con_data.number_buffers, 1); - _common_set_icon.theData_in->con_params.number_channels = _inproc.numOutputs; - _common_set_icon.theData_in->con_params.rate = _inproc.samplerate; - - // Connect the output side and start this link - res = allocate_pipeline_and_buffers_prepare_to(); - - // Do not attach any user hint into backward direction - _common_set_icon.theData_in->con_compat.user_hints = NULL; - // _common_set_icon.theData_in->pipeline.idx_stage = 0; return res; -#endif -} - -jvxErrorType -CjvxAudioSyncClockDevice::postprocess_connect_icon(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) -{ - return CjvxAudioDevice::postprocess_connect_icon(JVX_CONNECTION_FEEDBACK_CALL(fdb)); -#if 0 - jvxErrorType res = JVX_NO_ERROR; - - res = deallocate_pipeline_and_buffers_postprocess_to(); - - return res; -#endif } jvxErrorType CjvxAudioSyncClockDevice::process_buffers_icon(jvxSize mt_mask, jvxSize idx_stage) { return CjvxAudioDevice::process_buffers_icon(mt_mask, idx_stage); -#if 0 - jvxErrorType res = JVX_NO_ERROR; - // This is the return from the link list - return res; -#endif } jvxErrorType @@ -301,14 +254,6 @@ CjvxAudioSyncClockDevice::process_start_icon(jvxSize pipeline_offset, jvxSize* i return CjvxAudioDevice::process_start_icon( pipeline_offset, idx_stage, tobeAccessedByStage, clbk, priv_ptr); - -#if 0 - jvxErrorType res = JVX_NO_ERROR; - res = shift_buffer_pipeline_idx_on_start( pipeline_offset, idx_stage, - tobeAccessedByStage, - clbk, priv_ptr); - return res; -#endif } jvxErrorType @@ -320,29 +265,214 @@ CjvxAudioSyncClockDevice::process_stop_icon(jvxSize idx_stage, jvxBool shift_fwd return CjvxAudioDevice::process_stop_icon( idx_stage, shift_fwd, tobeAccessedByStage, clbk, priv_ptr); -#if 0 - jvxErrorType res = JVX_NO_ERROR; +} - // Unlock the buffer for this pipeline - res = shift_buffer_pipeline_idx_on_stop( idx_stage, shift_fwd, - tobeAccessedByStage, clbk, priv_ptr); +void +CjvxAudioSyncClockDevice::core_buffer_run() +{ + // Run one buffer! + // ================================================================================================= + jvxErrorType res = _common_set_ocon.theData_out.con_link.connect_to->process_start_icon(); + assert(res == JVX_NO_ERROR); - return res; + res = _common_set_ocon.theData_out.con_link.connect_to->process_buffers_icon(); + assert(res == JVX_NO_ERROR); + + res = _common_set_ocon.theData_out.con_link.connect_to->process_stop_icon(); + assert(res == JVX_NO_ERROR); +} + + + +void +CjvxAudioSyncClockDevice::timerCallback() +{ + jvxTick tickEnter = JVX_GET_TICKCOUNT_US_GET_CURRENT(&tStamp); + +#ifdef MEASURE_TIMING + // Entry to callback by switching to next element + cnt = (cnt + 1) % JVX_NUM_EVENTS_OBSERVE; + oneEntryTimer[cnt].measuredTimeout = (tickEnter - tickLeave) * 1e-3; + // oneEntryTimer[cnt].progressTimerDirect = (tickEnter - tStampAbsolute) * 1e-3; +#endif + + if (progress_msecs_frames < 0) + { + // First frame, reset everything + progress_msecs_frames = 0; + progress_msecs_next_call = 0; + progress_msecs_measured = 0; + // tStampAbsolute = JVX_GET_TICKCOUNT_US_GET_CURRENT(&tStamp); + } + else + { + progress_msecs_measured += (tickEnter - tStampLastFrame) * 1e-3; + + // We use the timerperiod from the count of timer callback to derive progress + progress_msecs_frames += timeOutBuffer_msecs_floor; + +#ifdef MEASURE_TIMING + oneEntryTimer[cnt].progressTimerMeasured = progress_msecs_measured; + oneEntryTimer[cnt].progressTimerFrames = progress_msecs_frames; + oneEntryTimer[cnt].progressTimerNext = progress_msecs_next_call; + oneEntryTimer[cnt].runBuffer = 0; #endif + + jvxData valueInFocus = progress_msecs_frames; + // jvxData valueInFocus = progress_msecs_measured; + + if (valueInFocus > progress_msecs_next_call) + { + //Cbs++; + core_buffer_run(); +#ifdef MEASURE_TIMING + oneEntryTimer[cnt].runBuffer = 1; +#endif + progress_msecs_next_call += timeOutBuffer_msecs_exact; + } + } + tStampLastFrame = tickEnter; } -jvxErrorType +#ifndef JVX_SYNCED_CLOCK_WINDOWS + + +jvxErrorType CjvxAudioSyncClockDevice::startup(jvxInt64 timestamp_us) { return JVX_NO_ERROR; } +jvxErrorType +CjvxAudioSyncClockDevice::expired(jvxInt64 timestamp_us, jvxSize* delta_ms) +{ + jvxErrorType res = JVX_NO_ERROR; + jvxTick tickLeave = 0; + + this->timerCallback(); + + // Compute the time between enter and "processing done". + // We will consider this when computing the next time period to wait for!! + tickLeave = JVX_GET_TICKCOUNT_US_GET_CURRENT(&tStamp); + + // Compute deviation between corrent timer and measured timer + jvxData deltaT = (progress_msecs_measured - progress_msecs_frames); // These values in msecs + jvxData deltaMsec = timeOutBuffer_msecs_exact_n - deltaT; + + // Consider the time it took to run up to here! + deltaT = (tickLeave - tStampLastFrame) * 1e-3; + deltaMsec -= deltaT; + + if (deltaMsec < 0) + { + res = JVX_ERROR_THREAD_ONCE_MORE; + deltaMsec = 0; + } + + *delta_ms = floor(deltaMsec); + +#ifdef MEASURE_TIMING + oneEntryTimer[cnt].desiredTimeout = deltaMsec;// *delta_ms; +#endif + +#ifdef MEASURE_TIMING + if (cnt == 0) + { + // std::cout << "Hallo" << std::endl; + } +#endif + +/* + jvxErrorType res = JVX_NO_ERROR; + jvxTick tickEnter = JVX_GET_TICKCOUNT_US_GET_CURRENT(&tStamp); + +#ifdef MEASURE_TIMING + oneEntryTimer[cnt].measuredTimeout = (tickEnter - tickLeave) * 1e-3; +#endif + + if (progress_msecs_measured < 0) + { + // First frame + progress_msecs_measured = 0; + progress_msecs_next_call = 0; + } + else + { + // Start time this frame + progress_msecs_measured += (tickEnter - tStampLastFrame) * 1e-3; + + if (progress_msecs_measured > progress_msecs_next_call) + { + core_buffer_run(); + progress_msecs_next_call += timeOutBuffer_msecs_exact; + } + } + tStampLastFrame = tickEnter; + + // ================================================================================================= + + + // ================================================================================================= + + jvxTick tickNow = JVX_GET_TICKCOUNT_US_GET_CURRENT(&tStamp); + progress_msecs_measured += (tickNow - tickEnter) * 1e-3; + + jvxData deltaMsec = progress_msecs_next_call - progress_msecs_measured; + if (deltaMsec < 0) + { + jvxSize numFramesToCompensate = -deltaMsec / timeOutBuffer_msecs_exact; + if (numFramesToCompensate > 5) + { + // If we are here, we have lost too many buffers!! + numFramesToCompensate -= 5; + progress_msecs_measured = -1; + progress_msecs_next_call = 0; + deltaMsec = timeOutBuffer_msecs_exact; + } + } + + deltaMsec = JVX_MAX(deltaMsec, 0); + + *delta_ms = floor(deltaMsec); + +#ifdef MEASURE_TIMING + cnt = (cnt + 1) % JVX_NUM_EVENTS_OBSERVE; + if (cnt == 0) + { + std::cout << "Hallo" << std::endl; + } + oneEntryTimer[cnt].desiredTimeout = *delta_ms; +#endif + + tickLeave = JVX_GET_TICKCOUNT_US_GET_CURRENT(&tStamp); + + */ + return res; +} + +jvxErrorType +CjvxAudioSyncClockDevice::wokeup(jvxInt64 timestamp_us, jvxSize* delta_ms) +{ + return JVX_NO_ERROR; +} + +jvxErrorType +CjvxAudioSyncClockDevice::stopped(jvxInt64 timestamp_us) +{ + return JVX_NO_ERROR; +} +#endif + +#if 0 jvxErrorType CjvxAudioSyncClockDevice::expired(jvxInt64 timestamp_us, jvxSize* delta_ms) { jvxErrorType res = JVX_NO_ERROR; jvxTick tickEnter = JVX_GET_TICKCOUNT_US_GET_CURRENT(&tStamp); + + oneEntryTimer[cnt].measuredTimeout = (tickEnter - tickLeave) * 1e-3; + if (progress_msecs_measured < 0) { // First frame @@ -353,6 +483,11 @@ CjvxAudioSyncClockDevice::expired(jvxInt64 timestamp_us, jvxSize* delta_ms) { // Start time this frame progress_msecs_measured += (tickEnter - tStampLastFrame) * 1e-3; + jvxData targetTimer = (progress_msecs_accumulated_exact + timeOutBuffer_msecs_exact * 0.8); + if (progress_msecs_measured < targetTimer) + { + return JVX_NO_ERROR; + } progress_msecs_accumulated_exact += timeOutBuffer_msecs_exact; } tStampLastFrame = tickEnter; @@ -390,17 +525,15 @@ CjvxAudioSyncClockDevice::expired(jvxInt64 timestamp_us, jvxSize* delta_ms) deltaMsec = JVX_MAX(deltaMsec, 0); *delta_ms = floor(deltaMsec); - return JVX_NO_ERROR; -} -jvxErrorType -CjvxAudioSyncClockDevice::wokeup(jvxInt64 timestamp_us, jvxSize* delta_ms) -{ + cnt = (cnt + 1) % JVX_NUM_EVENTS_OBSERVE; + if (cnt == 0) + { + std::cout << "Hallo" << std::endl; + } + oneEntryTimer[cnt].desiredTimeout = *delta_ms; + tickLeave = JVX_GET_TICKCOUNT_US_GET_CURRENT(&tStamp); return JVX_NO_ERROR; } +#endif -jvxErrorType -CjvxAudioSyncClockDevice::stopped(jvxInt64 timestamp_us) -{ - return JVX_NO_ERROR; -} diff --git a/sources/jvxComponents/jvxAudioTechnologies/jvxAuTSyncClock/src/CjvxAudioSyncClockDevice.h b/sources/jvxComponents/jvxAudioTechnologies/jvxAuTSyncClock/src/CjvxAudioSyncClockDevice.h index 81be1891..0b4a3bcf 100644 --- a/sources/jvxComponents/jvxAudioTechnologies/jvxAuTSyncClock/src/CjvxAudioSyncClockDevice.h +++ b/sources/jvxComponents/jvxAudioTechnologies/jvxAuTSyncClock/src/CjvxAudioSyncClockDevice.h @@ -6,8 +6,10 @@ class CjvxAudioSyncClockTechnology; -class CjvxAudioSyncClockDevice : public CjvxAudioDevice, +class CjvxAudioSyncClockDevice : public CjvxAudioDevice, +#ifndef JVX_SYNCED_CLOCK_WINDOWS public IjvxThreads_report, +#endif public genSyncClock_device { friend class CjvxAudioSyncClockTechnology; @@ -18,12 +20,36 @@ class CjvxAudioSyncClockDevice : public CjvxAudioDevice, jvxSize numInChannelsMax = 2; jvxSize numOutChannelsMax = 2; - refComp threads; - jvxData timeOutBuffer_msecs_exact = 0.0; - jvxData progress_msecs_accumulated_exact = 0.0; + // Progress as indicated by reported frames + jvxData progress_msecs_frames = 0; + + // Progress as measured from high perfomance conuter jvxData progress_msecs_measured = 0; + + // Progress at which to involve the next bufferswitch + jvxData progress_msecs_next_call = 0; + + // Framesize in msecs - exact value due to float variable + jvxData timeOutBuffer_msecs_exact = 0.0; + + // Framesize in msecs - scaled down by period factor + jvxData timeOutBuffer_msecs_exact_n = 0; + + // Framesize in msecs when rounding towards next small integer + jvxSize timeOutBuffer_msecs_floor = 0; + + // Preserve tstamp from last frame jvxInt64 tStampLastFrame = 0; + // jvxInt64 tStampFirst = 0; jvxTimeStampData tStamp; + // jvxTick tStampAbsolute; + +#ifndef JVX_SYNCED_CLOCK_WINDOWS + refComp threads; +#else + MMRESULT timerId = 0; +#endif + public: JVX_CALLINGCONVENTION CjvxAudioSyncClockDevice(JVX_CONSTRUCTOR_ARGUMENTS_MACRO_DECLARE); @@ -41,9 +67,6 @@ class CjvxAudioSyncClockDevice : public CjvxAudioDevice, // =================================================================================== virtual jvxErrorType test_chain_master(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) override; - virtual jvxErrorType JVX_CALLINGCONVENTION prepare_chain_master(JVX_CONNECTION_FEEDBACK_TYPE(fdb)) override; - virtual jvxErrorType JVX_CALLINGCONVENTION postprocess_chain_master( - JVX_CONNECTION_FEEDBACK_TYPE(fdb)) override; virtual jvxErrorType JVX_CALLINGCONVENTION start_chain_master( JVX_CONNECTION_FEEDBACK_TYPE(fdb)) override; virtual jvxErrorType JVX_CALLINGCONVENTION stop_chain_master( @@ -51,10 +74,6 @@ class CjvxAudioSyncClockDevice : public CjvxAudioDevice, // =================================================================================== - virtual jvxErrorType JVX_CALLINGCONVENTION prepare_connect_icon( - JVX_CONNECTION_FEEDBACK_TYPE(fdb))override; - virtual jvxErrorType JVX_CALLINGCONVENTION postprocess_connect_icon( - JVX_CONNECTION_FEEDBACK_TYPE(fdb))override; virtual jvxErrorType JVX_CALLINGCONVENTION process_start_icon( jvxSize pipeline_offset , jvxSize* idx_stage, jvxSize tobeAccessedByStage, @@ -68,10 +87,17 @@ class CjvxAudioSyncClockDevice : public CjvxAudioDevice, callback_process_stop_in_lock clbk, jvxHandle* priv_ptr)override; + void core_buffer_run(); + + void timerCallback(); + +#ifndef JVX_SYNCED_CLOCK_WINDOWS + jvxErrorType startup(jvxInt64 timestamp_us) override; jvxErrorType expired(jvxInt64 timestamp_us, jvxSize* delta_ms) override; jvxErrorType wokeup(jvxInt64 timestamp_us, jvxSize* delta_ms) override; jvxErrorType stopped(jvxInt64 timestamp_us) override; +#endif }; #endif