Example #1
0
    HRESULT MyClock::GetAudioClockTime(REFERENCE_TIME* pAudioTime, REFERENCE_TIME* pCounterTime)
    {
        CheckPointer(pAudioTime, E_POINTER);

        CAutoLock lock(this);

        if (m_audioClock)
        {
            uint64_t audioFrequency, audioPosition, audioTime;
            if (SUCCEEDED(m_audioClock->GetFrequency(&audioFrequency)) &&
                SUCCEEDED(m_audioClock->GetPosition(&audioPosition, &audioTime)))
            {
                int64_t counterTime = llMulDiv(GetPerformanceCounter(), OneSecond, m_performanceFrequency, 0);
                int64_t clockTime = llMulDiv(audioPosition, OneSecond, audioFrequency, 0) +
                                    m_audioStart + (audioPosition > 0 ? m_audioOffset + counterTime - audioTime : 0);

                *pAudioTime = clockTime;

                if (pCounterTime)
                    *pCounterTime = counterTime;

                return S_OK;
            }
        }

        return E_FAIL;
    }
Example #2
0
int64_t AudioDevicePush::GetPosition()
{
    UINT64 deviceClockFrequency, deviceClockPosition;
    ThrowIfFailed(m_backend->audioClock->GetFrequency(&deviceClockFrequency));
    ThrowIfFailed(m_backend->audioClock->GetPosition(&deviceClockPosition, nullptr));

    return llMulDiv(deviceClockPosition, OneSecond, deviceClockFrequency, 0);
}
Example #3
0
    void DspRate::Process(DspChunk& chunk)
    {
        soxr_t soxr = GetBackend();

        if (!soxr || chunk.IsEmpty())
            return;

        if (m_state == State::Variable && !m_inStateTransition && m_variableDelay > 0)
        {
            uint64_t inputPosition = llMulDiv(m_variableOutputFrames, m_inputRate, m_outputRate, 0);
            int64_t adjustedFrames = inputPosition + m_variableDelay - m_variableInputFrames;

            REFERENCE_TIME adjustTime = m_adjustTime - FramesToTimeLong(adjustedFrames, m_inputRate);

            double ratio = (double)m_inputRate * 4 / (m_outputRate * (4 + (double)adjustTime / OneSecond));

            // TODO: decrease jitter

            soxr_set_io_ratio(m_soxrv, ratio, m_outputRate / 1000);
        }

        DspChunk output = ProcessChunk(soxr, chunk);

        if (m_state == State::Variable)
        {
            m_variableInputFrames += chunk.GetFrameCount();
            m_variableOutputFrames += output.GetFrameCount();

            // soxr_delay() method is not implemented for variable rate conversion yet,
            // but the delay stays more or less constant and we can calculate it in a roundabout way.
            if (m_variableDelay == 0 && m_variableOutputFrames > 0)
            {
                uint64_t inputPosition = llMulDiv(m_variableOutputFrames, m_inputRate, m_outputRate, 0);
                m_variableDelay = m_variableInputFrames - inputPosition;
            }
        }

        FinishStateTransition(output, chunk, false);

        chunk = std::move(output);
    }
Example #4
0
    REFERENCE_TIME MyClock::GetPrivateTime()
    {
        CAutoLock lock(this);

        REFERENCE_TIME audioClockTime, audioClockCounterTime;
        if (SUCCEEDED(GetAudioClockTime(&audioClockTime, &audioClockCounterTime)))
        {
            m_counterOffset = audioClockTime - audioClockCounterTime;
            return audioClockTime;
        }

        return m_counterOffset + llMulDiv(GetPerformanceCounter(), OneSecond, m_performanceFrequency, 0);
    }
Example #5
0
LONGLONG CRenderersData::GetPerfCounter() const
{
    LARGE_INTEGER i64Ticks100ns;
    LARGE_INTEGER llPerfFrequency;

    QueryPerformanceFrequency(&llPerfFrequency);
    if (llPerfFrequency.QuadPart != 0) {
        QueryPerformanceCounter(&i64Ticks100ns);
        return llMulDiv(i64Ticks100ns.QuadPart, 10000000, llPerfFrequency.QuadPart, 0);
    } else {
        // ms to 100ns units
        return LONGLONG(timeGetTime()) * 10000;
    }
}
Example #6
0
 REFERENCE_TIME MyTestClock::GetPrivateTime()
 {
     return llMulDiv(GetPerformanceCounter(), OneSecond, m_performanceFrequency, 0);
 }
Example #7
0
    void AudioRenderer::ApplyRateCorrection(DspChunk& chunk)
    {
        CAutoLock objectLock(this);
        assert(m_device);
        assert(!m_device->IsBitstream());
        assert(m_state == State_Running);

        if (chunk.IsEmpty())
            return;

        const REFERENCE_TIME latency = llMulDiv(chunk.GetFrameCount(), OneSecond, chunk.GetRate(), 0) +
                                       m_device->GetStreamLatency() + OneMillisecond * 10;

        const REFERENCE_TIME remaining = m_device->GetEnd() - m_device->GetPosition();

        REFERENCE_TIME deltaTime = 0;

        if (m_live)
        {
            // Rate matching.
            if (remaining > latency)
            {
                size_t dropFrames = (size_t)llMulDiv(m_device->GetWaveFormat()->nSamplesPerSec,
                                                     remaining - latency, OneSecond, 0);

                dropFrames = std::min(dropFrames, chunk.GetFrameCount());

                chunk.ShrinkHead(chunk.GetFrameCount() - dropFrames);

                DebugOut("AudioRenderer drop", dropFrames, "frames for rate matching");
            }
        }
        else
        {
            // Clock matching.
            assert(m_externalClock);

            REFERENCE_TIME graphTime, myTime, myStartTime;
            if (SUCCEEDED(m_myClock.GetAudioClockStartTime(&myStartTime)) &&
                SUCCEEDED(m_myClock.GetAudioClockTime(&myTime, nullptr)) &&
                SUCCEEDED(m_graphClock->GetTime(&graphTime)) &&
                myTime > myStartTime)
            {
                myTime -= m_device->GetSilence();

                if (myTime > graphTime)
                {
                    // Pad and adjust backwards.
                    REFERENCE_TIME padTime = myTime - graphTime;
                    assert(padTime >= 0);

                    size_t padFrames = (size_t)llMulDiv(m_device->GetWaveFormat()->nSamplesPerSec,
                                                        padTime, OneSecond, 0);

                    if (padFrames > m_device->GetWaveFormat()->nSamplesPerSec / 33) // ~30ms threshold
                    {
                        DspChunk tempChunk(chunk.GetFormat(), chunk.GetChannelCount(),
                                           chunk.GetFrameCount() + padFrames, chunk.GetRate());

                        size_t padBytes = tempChunk.GetFrameSize() * padFrames;
                        ZeroMemory(tempChunk.GetData(), padBytes);
                        memcpy(tempChunk.GetData() + padBytes, chunk.GetData(), chunk.GetSize());

                        chunk = std::move(tempChunk);

                        REFERENCE_TIME paddedTime = llMulDiv(padFrames, OneSecond,
                                                             m_device->GetWaveFormat()->nSamplesPerSec, 0);

                        m_myClock.OffsetSlavedClock(-paddedTime);
                        padTime -= paddedTime;
                        assert(padTime >= 0);

                        DebugOut("AudioRenderer pad", paddedTime / 10000., "ms for clock matching at",
                                 m_sampleCorrection.GetLastFrameEnd() / 10000., "frame position");
                    }

                    // Correct the rest with variable rate.
                    m_dspRealtimeRate.Adjust(padTime);
                    m_myClock.OffsetSlavedClock(-padTime);
                }
                else if (remaining > latency)
                {
                    // Crop and adjust forwards.
                    assert(myTime <= graphTime);
                    REFERENCE_TIME dropTime = std::min(graphTime - myTime, remaining - latency);
                    assert(dropTime >= 0);

                    size_t dropFrames = (size_t)llMulDiv(m_device->GetWaveFormat()->nSamplesPerSec,
                                                         dropTime, OneSecond, 0);

                    dropFrames = std::min(dropFrames, chunk.GetFrameCount());

                    if (dropFrames > m_device->GetWaveFormat()->nSamplesPerSec / 33) // ~30ms threshold
                    {
                        chunk.ShrinkHead(chunk.GetFrameCount() - dropFrames);

                        REFERENCE_TIME droppedTime = llMulDiv(dropFrames, OneSecond,
                                                              m_device->GetWaveFormat()->nSamplesPerSec, 0);

                        m_myClock.OffsetSlavedClock(droppedTime);
                        dropTime -= droppedTime;
                        assert(dropTime >= 0);

                        DebugOut("AudioRenderer drop", droppedTime / 10000., "ms for clock matching at",
                                 m_sampleCorrection.GetLastFrameEnd() / 10000., "frame position");
                    }

                    // Correct the rest with variable rate.
                    m_dspRealtimeRate.Adjust(-dropTime);
                    m_myClock.OffsetSlavedClock(dropTime);
                }
            }
        }
    }