Ableton Link开始停止同步延迟

时间:2019-09-10 12:11:39

标签: c++ signal-processing audiokit ableton-live

我设法在我的C ++ DSP中实现了Ableton Link。它在按下开始键时开始计数,并且几乎没有延迟地同步播放。但是,第一次启动和停止之后的任何时间都不再同步。引入了延迟,有时更多,有时更少。我不明白为什么会这样。

此代码正在启动Ableton Link:

void abletonSetup(){

    struct mach_timebase_info timeInfo = mach_timebase_info_data_t();
    mach_timebase_info(&timeInfo);

    ABLLinkRef linkRef = ABLLinkNew(bpm);
    EngineData sharedEngineData = EngineData();
    EngineData localEngineData = EngineData();

    _linkData = LinkData();
    _linkData.ablLink = linkRef;
    _linkData.sampleRate = sampleRate;
    _linkData.secondsToHostTime = (1.0e9 * Float64(timeInfo.denom)) / Float64(timeInfo.numer);
    _linkData.sharedEngineData = sharedEngineData;
    _linkData.localEngineData = localEngineData;
    _linkData.timeAtLastClick = 0;
    _linkData.isPlaying = false;

    // add listeners
    ABLLinkSetIsEnabledCallback(_linkData.ablLink, &AKClockDSPKernel::abletonEnabledListener, this);
    ABLLinkSetIsConnectedCallback(_linkData.ablLink, &AKClockDSPKernel::abletonConnectedListener, this);
    ABLLinkSetIsStartStopSyncEnabledCallback(_linkData.ablLink, &AKClockDSPKernel::abletonStartStopListener, this);
    ABLLinkSetSessionTempoCallback(_linkData.ablLink, &AKClockDSPKernel::abletonBPMListener, this);

    // manually update vars:
    abletonEnabled = ABLLinkIsEnabled(_linkData.ablLink);
    abletonConnected = ABLLinkIsConnected(_linkData.ablLink);
    abletonStartStop = ABLLinkIsStartStopSyncEnabled(_linkData.ablLink);
    setAbletonActive();

}

此函数计算延迟(从外部C ++调用):

void setAbletonLatency(double value, int bufferSize){

    const Float64 hostTicksPerSample = _linkData.secondsToHostTime / sampleRate;
    const UInt64 deviceLatency = UInt64(_linkData.secondsToHostTime * value);
    const UInt64 bufferInTicks = UInt64( hostTicksPerSample * bufferSize);
    // latency introduced by my app:
    const UInt64 latencyInTicks = UInt64( hostTicksPerSample * getZtxLatency());

    UInt64 outputLatency = deviceLatency + bufferInTicks + latencyInTicks;

    os_unfair_lock_lock(&lock);
    _linkData.sharedEngineData.outputLatency = outputLatency;
    os_unfair_lock_unlock(&lock);

}

在主音频线程的开头调用以下函数:

void abletonUpdate() {

    LinkData linkData = _linkData;

    const ABLLinkSessionStateRef sessionState = ABLLinkCaptureAudioSessionState(linkData.ablLink);

    EngineData engineData;
    pullEngineData(&linkData, &engineData);

    // The mHostTime member of the timestamp represents the time at
    // which the buffer is delivered to the audio hardware. The output
    // latency is the time from when the buffer is delivered to the
    // audio hardware to when the beginning of the buffer starts
    // reaching the output. We add those values to get the host time
    // at which the first sample of this buffer will reach the output.
    //const UInt64 hostTimeAtBufferBegin = inTimeStamp->mHostTime + engineData.outputLatency;

    UInt64 hostTimeAtBufferBegin = mach_absolute_time() + engineData.outputLatency;

    if(abletonStartStop == true){

        if (engineData.requestStart && !ABLLinkIsPlaying(sessionState)) {
            // Request starting playback at the beginning of this buffer.
            ABLLinkSetIsPlaying(sessionState, YES, hostTimeAtBufferBegin);
        }

        if (engineData.requestStop && ABLLinkIsPlaying(sessionState)) {
            // Request stopping playback at the beginning of this buffer.
            ABLLinkSetIsPlaying(sessionState, NO, hostTimeAtBufferBegin);
        }

        if (!linkData.isPlaying && ABLLinkIsPlaying(sessionState)) {
            // Reset the session state's beat timeline so that the requested
            // beat time corresponds to the time the transport will start playing.
            // The returned beat time is the actual beat time mapped to the time
            // playback will start, which therefore may be less than the requested
            // beat time by up to a quantum.

            ABLLinkRequestBeatAtStartPlayingTime(sessionState, 0., engineData.quantum);
            linkData.isPlaying = YES;

            abletonLastCount = 0;
            showAbletonCounting();

        }else if(linkData.isPlaying && !ABLLinkIsPlaying(sessionState)) {
            linkData.isPlaying = NO;
        }

    }

    // Handle a tempo proposal

    if (engineData.proposeBpm != INVALID_BPM) {
        // Propose that the new tempo takes effect at the beginning of this buffer.
        ABLLinkSetTempo(sessionState, engineData.proposeBpm, hostTimeAtBufferBegin);
    }

    ABLLinkCommitAudioSessionState(linkData.ablLink, sessionState);

    _linkData = linkData;


    // If Ableton start / stop sync is activated:
    if(abletonStartStop == true){

        if (linkData.isPlaying) {

            float beatTime = ABLLinkBeatAtTime(ABLLinkCaptureAppSessionState(linkData.ablLink), hostTimeAtBufferBegin, engineData.quantum);
            float beatQuantum = fmod(engineData.quantum + beatTime, engineData.quantum);

            if(started == false && beatQuantum < 0.1){
                started = true;
            }else if(started == false && beatQuantum >= 0.1){

                // code for showing count-in via GUI:
                if(beatQuantum >= abletonLastCount + 1){
                    abletonLastCount = beatQuantum;
                    linkDidChange(floor(beatQuantum));
                }

            }

        }else{

            if(started == true){
                stop();
            }

        }

    }

}

任何帮助都受到赞赏。

  

编辑:

     

我发现问题出在我的应用程序中。我不得不   每次停止触发时复位内部时钟。所以代码   以上应该是正确的。我会保留原样,也许是这样   会帮助别人的。

0 个答案:

没有答案