HISE Logo Forum
    • Categories
    • Register
    • Login

    Midi Player Clock Sync (problem)

    Scheduled Pinned Locked Moved General Questions
    4 Posts 1 Posters 104 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • deniskorgD
      deniskorg
      last edited by deniskorg

      Hello guys,

      I have a problem,

      If I have a MIDI player and try to press play using startInternalClock(0), even though I have checked the "Prefer External" synchronization option, when I change the tempo from that DAW simulator in HISE, a desynchronization occurs. On the other hand, if I press play from that DAW simulator, even if I aggressively change the tempo, everything works perfectly, and there are no desynchronizations of that grid changer.

      HiseSnippet 2170.3oc6YstaaibElzNLaj1Kc2hEE8WECB1enzXvnKN9xFzFc2R1x1xlJ9RP.1NhbnzrlZF5gijsxh.z929P0Gf9q9HzGg7Fr8LjTVTNLYy5lTrMaBPh8blyYNemybtMLcEbaRP.Wnoms2Tehl9mYXMkIGVaHlxzZWWS+KLjj.4tTGJrgsV0o93f.hilt9xao3QOyszB+yKebUrGlYSlSRS6HN0lzgNhJmSsa4cnddMwNjdzQI3d0xss4rZbO9X.OKajWyGaeFd.YOrhskLzZgCFpo+GMHtkbWesM2frZd7ltatpylE2rjyZXmhX6h4Ia55rd+hXrql9sa3PkbgkDCVgl9spxclZMjeAKRAGQCn88HpEEzr.MGQtI2yQYhJpZ0FR8b5NyQEnooazctaa4H21Wan7PWQet66KC2.MWhjNP8kVDdKu.7JjDd4S.uTfjdBHcqHH8UFV1Bpub9NJ77oFsYRhvEC2SIgRDuZK8OtsQMNvASZNBeFoo.VbkD4VKe9UPv+buGkM6Cd.xhHQ8DXVfOWHQsvLGOhHKbIFHQxYziIi9SnFrATFwzVP.ys201OGblWWFy.hrACCtfsDTmbRwXxJnh26QfpMMQQmCZDN.fGx1iaelh7Cd..szNIU76tbGRtWYytBhKQDZlLr2qAH+Th23xqDW4a5QF4yQ.GHkfYisc3bZwCjU8Gkai7l4SUURt+LnTSYT4x+ZPTGJ6L3j5wS.swjX8uEb2n7ZHHVjMfj5ArOSwQDC4JrBhmXMbLTlGfYj6XlsjxYKrcNJygboZ8JHIjFGHwi7WA4REARE01rtd3o2K6OjIS1LPDU.2iX5KnL4bIAUjAPJ0E0FAxCgPWPkCQ8GKkf1xER55dh6EJRakH1g.AIGB+MzYeAjVPP9fdorAqfvHGR.3YFBwvzmiiLAa6whfUPpSAX2dHhFfHSnNP.ObRB93ACgeBDEgxdkwalMSJdPlixNTt+8Y6QtTVC640GJZkKxzZwufLgHVIxD8giLHDdWoILCQhCaP0qbLJfNZrGFpHDgPPXVjruhs5J3iTKEPFgRGSAPyFftfKNCzAjtRrkdSMy9h4YpgUn5fmdUJ5tsq2VcKQDEfryv59lCHg05iHm6tJVPw7bWvnRHhJ.5IAg0vCu7ay5QsOKHNFLJEU4YPRNZ2nbzZIxQu1Io3rGOhun65jmy0TR7QnLrpRVjKM1lhpiUMLDRYUyJlA1UMN33Xvhb2cAttapg5Kvh5TDbub1yNhUPSvd.9x9CYyLLLbvREsZA4t4h14QJW+ak1UlerBtJ9Ic8qRseEnlt5U.K72dLJkJLojXg91zhvSsVzKdTB+zdbIYeVtPEl8EYQWeKW2T2K1hBK7mx1pKbwaRvbrwi5qRslatJFgteK1R0302RMYGe6nKpDLxYsYT499D1qaN.s3aW32dR65XIV0GNlFvGjDJoJHnWGJvXSh5JmwnNI3LvsFxabHgl9cjg694y5YiYDOMpiZ7qDTJnc47wk9lxSmunc4KnNxgWQH+eq7PBcvv4ic8uGWlBkNlMdUlaCz9Q0FyoVLI4EfWlH3MCLQQkg362r.oE.X8j.7zqAv+J95.T6OW1GK.0kPuWy5CvSHPiEnNJQpFZQBEOgY7LT0Qf4JekQffgu3NQETSNQlZt03MfXpEFCREryBnxoImq8c1XZusP7qL5Rk1CSGiKkBFgqq2GXLd31O2ngqpexb.dKilm79YR1jp+Nulmj7YginBqfdGuKdPh+a8CRzW98w6It8ureOwmL6ZX9fAwuLL4zAK.jZiEpLYKx4iIKbA7xGGuEL9u8YIo2gy8il02IIY0oq5HZ4SVbiqeUr7aWg9Th3TlUSXxwP6d1BfakMBO5Lrx9RGoaT7gEMY8VamMp0z0r2pULa4PCVupK+4sL6Loe8KqNoA2zcqglts1dsKK8zFxMVaKygGtUgpGLnWqBObfzx6zNC59zc52535G046C1uuUyc3l0cqcLib.uXq8c8YxKcjUNv7xBSBd5jNri2yau6+z81d0cqTZSwVmy5ZwOuJuRoBaVc5pEqMlcH+7ss6SnEcN54a6Wqzgm9jK58Pobx5a3h2tywGPKI1Amu4zgkNq18eZgCF4c7IGePvyexokZUYZwJRfxAioC2Aac5t8O+9M1+6CV+n5SFNxc0QrStrVsZdm1zkzts250wtUEhth8bqrwgVdEl1aS7ocElSKLYed6RaHFbp8fB6P886z19jSt3nsak24h8DAk1YZ+ROu6EG2nP8SJ1rPiMNoolxWG899UMp8sOCFnTD7r1Mq+r31jOKLbuwkpoRdVGtfhVM9GliT8ezUorVzALrbr.Nkau23QUwv857b9x6wGQYpJryI9kkqSXoQVEFFNKUxhFQwlKD9E97NEg+Y2+veeo+hc4O194WgseJ9gP6ma8Kt1OeLW5ChboC4ikT1fcwRAEdWfATZ1BhksIpOgDLPu54Y5KodHUz57p0JOfEg4Dt3Gg+DuYA0Z83MKLayjl3WDYhepgEjZFlyFZf+tv0nig2Nf1h.IspKn2zbi+q28It6aKA0G+IOCV3fsHin8fm6jrikFzFrofb9gpHljzqwgVaos0KebSvHSUFKUmwvPuJi3iYKzX6MWPovGKn7+tBJKLxclYXzhNx2izfMg3wAJJL9aMpSbwi8jyntXSnc4Lt+PNiZm7h9PBjCNX.QjD6oZPUjxElL+qKeHwifSFz9Mk6.AaXg5SNeC8EE9Y+emQp2W+diH3F9ABQ++aifk+Xif+aaD7ghNFgsE7uyN5qbpxEtSHEv2xBelTFicUqQEzB+xmIiWfGDQ+Na6EOpWQvh2TAKcSEb0apfO7lJ3Z2TAW+lJ3F+zBpZzUYrjOJJ8WSa2tMB+3B55W8gOzWV6+.oSU.r.
      
      deniskorgD 1 Reply Last reply Reply Quote 0
      • deniskorgD
        deniskorg @deniskorg
        last edited by deniskorg

        think there's a problem with these functions...

        Hise Demo.png

        void MainController::handleTransportCallbacks(const AudioPlayHead::CurrentPositionInfo& newInfo, const MasterClock::GridInfo& gi)
        {
            if(gi.resync)
            {   DBG("test1");
                // t reacts only when I press play from the DAW simulator...
                // when tempo is changed
                for(auto tl: tempoListeners)
                    if(tl != nullptr)
                        tl->onResync(newInfo.ppqPosition);
            }
        }
        
        deniskorgD 1 Reply Last reply Reply Quote 0
        • deniskorgD
          deniskorg @deniskorg
          last edited by

          I didn't find any solution for this...

          deniskorgD 1 Reply Last reply Reply Quote 0
          • deniskorgD
            deniskorg @deniskorg
            last edited by

            I finally managed to reach a solution.

            For me, at least, it works fine for now. I don’t know if there was an easier solution, but for me, being able to sync that grid when I modify the tempo (for the internal clock), this change worked. I’ll leave below the function I modified in the source code.

            MasterClock::GridInfo MasterClock::processAndCheckGrid(int numSamples,
            	const AudioPlayHead::CurrentPositionInfo& externalInfo)
            {	
            	GridInfo gi;
            
                auto shouldUseExternalBpm = !linkBpmToSync || !shouldPreferInternal();
            	
                if (bpm != externalInfo.bpm && shouldUseExternalBpm)
                    setBpm(externalInfo.bpm);
            
                if (currentSyncMode == SyncModes::Inactive)
                    return gi;
                
                // .. ADDED .. //
            
                // Store last tempo for detection
                static double lastBpm = -1.0;
                static double bpmSmooth = bpm; // Smoothed BPM
                static double lastPpqPosition = 0.0; // Store last PPQ position
            	
                bool tempoChanged = (bpm != lastBpm); // Detect tempo change
                 
                if (tempoChanged)
                    lastBpm = bpm;
            
                // Interpolate BPM smoothly over time
                double smoothingFactor = 0.1; // Lower = smoother, Higher = faster response
                bpmSmooth += (bpm - bpmSmooth) * smoothingFactor;
            
                // Convert BPM to quarter notes in samples (using smoothed BPM)
                const auto quarterInSamples = (double)TempoSyncer::getTempoInSamples(bpmSmooth, sampleRate, 1.0f);
            
                // Instead of relying on uptime, calculate PPQ dynamically (like in updateFromExternalPlayHead)
                double ppqTime = lastPpqPosition + ((double)numSamples / quarterInSamples);
                lastPpqPosition = ppqTime;
            
                // Calculate grid alignment based on PPQ (like in updateFromExternalPlayHead)
                double multiplier = (double)TempoSyncer::getTempoFactor(clockGrid);
                double nextGridPPQ = std::ceil(ppqTime / multiplier) * multiplier;
                double nextGridSamples = nextGridPPQ * quarterInSamples;
                samplesToNextGrid = nextGridSamples - (ppqTime * quarterInSamples);
            
                if (currentSyncMode == SyncModes::SyncInternal && externalInfo.isPlaying)
                {
                    uptime = ppqTime * quarterInSamples;
                    samplesToNextGrid = gridDelta - (uptime % gridDelta);
                }
            
                // ... added up to here
            
                if (currentState != nextState)
                {
                    currentState = nextState;
                    uptime = numSamples - nextTimestamp;
                    currentGridIndex = 0;
            
                    if (currentState != State::Idle && gridEnabled)
                    {
                        gi.change = true;
                        gi.timestamp = nextTimestamp;
                        gi.gridIndex = currentGridIndex;
                        gi.firstGridInPlayback = true;
                        samplesToNextGrid = gridDelta - nextTimestamp;
                    }
            
                    nextTimestamp = 0;
                }
                else
                {
                    if (currentState == State::Idle)
                    {   
            			uptime = 0;
            			lastPpqPosition = 0.0; // Added ... to reset PpqPosition
            		}
                    else
                    {	
                        jassert(nextTimestamp == 0);
                        uptime += numSamples;
                        samplesToNextGrid -= numSamples;
            
                        if (samplesToNextGrid < 0 && gridEnabled)
                        {
                            currentGridIndex++;
                            gi.change = true;
                            gi.firstGridInPlayback = waitForFirstGrid;
                            waitForFirstGrid = false;
                            gi.gridIndex = currentGridIndex;
                            gi.timestamp = numSamples + samplesToNextGrid;
                            samplesToNextGrid += gridDelta;
                        }
                    }
                }
            
                return gi;
            }
            
            1 Reply Last reply Reply Quote 0
            • First post
              Last post

            22

            Online

            1.7k

            Users

            11.8k

            Topics

            102.5k

            Posts