Old 09-05-2019, 11:06 AM   #1
Alkamist
Human being with feelings
 
Join Date: Dec 2011
Posts: 506
Default Convert audio source position to item time?

I am interested in a function where you can pass in a take and the desired source time to convert to real time offset from the item's start position.

This would require taking into account the take's playrate and stretch markers.

I came up with a group of functions to essentially do this, however my results with dealing with sloped stretch markers isn't quite accurate, especially with drastic slopes and slow rates.

Does anyone know of any ways to convert audio source time to real time?

Here's what I've done so far:

Code:
function Reaper.getStretchMarkers(take)
    local stretchMarkers = {}
    local numStretchMarkers = reaper.GetTakeNumStretchMarkers(take)
    for i = 1, numStretchMarkers do
        local _, pos, srcPos = reaper.GetTakeStretchMarker(take, i - 1)

        stretchMarkers[i] = {
            pos = pos,
            srcPos = srcPos,
            slope = reaper.GetTakeStretchMarkerSlope(take, i - 1)
        }
    end

    for index, marker in ipairs(stretchMarkers) do
        local markerRate = 1.0
        local markerLength = 0
        if index < #stretchMarkers then
            local nextMarker = stretchMarkers[index + 1]

            markerLength = nextMarker.pos - marker.pos
            markerSourceLength = nextMarker.srcPos - marker.srcPos
            markerRate = markerSourceLength / markerLength * (1.0 - marker.slope)
        end

        marker.rate = markerRate
        marker.length = markerLength
        marker.srcLength = markerSourceLength
    end

    return stretchMarkers
end

function Reaper.getSourcePosition(take, time)
    if time == nil then return nil end

    local playrate = reaper.GetMediaItemTakeInfo_Value(take, "D_PLAYRATE")

    local tempMarkerIndex = reaper.SetTakeStretchMarker(take, -1, time * playrate)

    local _, pos, srcPos = reaper.GetTakeStretchMarker(take, tempMarkerIndex)

    reaper.DeleteTakeStretchMarkers(take, tempMarkerIndex)

    return srcPos
end

function Reaper.getSourceOffset(take)
    return Reaper.getSourcePosition(take, 0.0)
end

function Reaper.getRealPosition(take, sourceTime)
    if sourceTime == nil then return nil end

    local startOffset = Reaper.getSourceOffset(take)
    local playrate = reaper.GetMediaItemTakeInfo_Value(take, "D_PLAYRATE")

    local stretchMarkers = Reaper.getStretchMarkers(take)

    if #stretchMarkers < 1 then
        return (sourceTime - startOffset) / playrate
    end

    local markerIndex = 0

    for index, marker in ipairs(stretchMarkers) do
        if sourceTime < marker.srcPos then
            markerIndex = index - 1
            break
        end

        if index == #stretchMarkers then
            markerIndex = index
        end
    end

    if markerIndex == 0 then
        return (sourceTime - startOffset) / playrate
    end

    local activeMarker = stretchMarkers[markerIndex]

    local relativeSourcePosition = sourceTime - activeMarker.srcPos

    local actualSlope = 0.0
    if activeMarker.srcLength > 0 and activeMarker.length > 0 then
        actualSlope = (activeMarker.srcLength / activeMarker.length - activeMarker.rate) / (0.5 * activeMarker.srcLength)
    end

    local currentMarkerRate = activeMarker.rate + relativeSourcePosition * actualSlope
    local averageMarkerRate = (activeMarker.rate + currentMarkerRate) * 0.5
    local scaledOffset = relativeSourcePosition / averageMarkerRate

    local realTime = activeMarker.pos + scaledOffset

    return realTime / playrate
end
Alkamist is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 09:58 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.