# keyframe/profile.ttl
#
# GENERATED by bin/write-profile.js. Do not edit: the digests are of the
# files on disk, and editing them by hand is how a profile comes to describe
# artefacts that no longer exist. Edit profile.json and run ./build.sh.

@base <https://strandz.it/jigdaw/plugins/keyframe/> .

@prefix jig:   <http://purl.org/stuff/jigdaw/> .
@prefix trn:   <http://purl.org/stuff/transmissions/> .
@prefix pu:    <http://purl.org/stuff/plugin-universe/> .
@prefix lv2:   <http://lv2plug.in/ns/lv2core#> .
@prefix midi:  <http://lv2plug.in/ns/ext/midi#> .
@prefix units: <http://lv2plug.in/ns/extensions/units#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix doap:  <http://usefulinc.com/ns/doap#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
@prefix foaf:  <http://xmlns.com/foaf/0.1/> .

<>
    a jig:WebPlugin , trn:PluginProfile ;
    rdfs:label "Keyframe" ;
    rdfs:comment "Stretches audio in time and shifts its pitch, independently, by reducing the signal to its local extrema and crossfading between playheads over a span the extrema's own density chooses." ;
    trn:vendor "danja" ;
    doap:revision "0.1.0" ;
    doap:developer <http://danny.ayers.name> ;
    foaf:homepage <> ;
    trn:role trn:AudioEffect ;
    trn:accepts trn:Audio ;
    trn:produces trn:Audio ;
    trn:genre "Electronic" , "Experimental" ;
    trn:caution "The algorithm is Matthew Nielsen's, Keyframe Time Stretching via Extrema Sampling, DAFx26, CC BY 4.0. This implementation is written from the paper." ;
    trn:caution "It colours the sound: added saturation and some blurring of spectral detail. It is at its best on dense, layered material and percussion, and at its weakest on solo voice and bells." ;
    trn:caution "A live input cannot be played faster than it arrives, so a time rate above 100 percent plays at the input's own rate, and with a pitch shift it splices back repeatedly. Below 100 percent the output falls behind the input by up to eight seconds and then skips forward. Both skips are splices, and both are audible." ;
    trn:caution "Economy quality joins the extrema with straight lines, which is the roughest reconstruction. Balanced and Full use a smooth curve between them. Full also places each extremum between samples." ;
    trn:caution "Changing Quality or Stereo empties the capture and restarts it, so it is heard as a short gap." ;
    trn:caution "Latency is a fixed 512 frames, which is two forced keyframe hops." ;
    trn:format trn:Jig , trn:WebAudio ;
    pu:licenceId "Apache-2.0" ;

    jig:audioInputs 1 ;
    jig:inputChannels 2 ;
    jig:audioOutputs 1 ;
    jig:outputChannels 2 ;
    jig:renderQuantum 128 ;
    jig:latencyFrames 512 ;
    jig:stateless true ;

    jig:module <#module> ;
    jig:processor <#processor> ;

    lv2:port <#time_rate> , <#pitch_shift> , <#splice_keyframes> , <#max_splice> , <#threshold> , <#mix> , <#output> , <#quality> , <#stereo> .

<#module>
    a jig:Module ;
    jig:location <keyframe.wasm> ;
    jig:mediaType "application/wasm" ;
    jig:abi jig:Abi1 ;
    jig:integrity "sha384-gVx2Jl6SVXeh7JLdaO4mzPLuFRynhIQUhh+tvenYwiXTDBMS9E49hE+zBddAZVO/" .

<#processor>
    a jig:Processor ;
    jig:location <keyframe-processor.js> ;
    jig:mediaType "text/javascript" ;
    jig:registeredName "keyframe" ;
    jig:integrity "sha384-IfZxWbZbRFFhC2Yc8fat5lWmcQHYFhA/Knt5ufh3qrRu+hiBuas1YDUEpxP8+2w7" .

<#time_rate>
    a lv2:InputPort , lv2:ControlPort ;
    lv2:symbol "time_rate" ; lv2:name "Time rate" ;
    lv2:default 100 ; lv2:minimum 25 ; lv2:maximum 400 ;
    jig:paramIndex 0 ;
    units:unit units:pc .

<#pitch_shift>
    a lv2:InputPort , lv2:ControlPort ;
    lv2:symbol "pitch_shift" ; lv2:name "Pitch shift" ;
    lv2:default 0 ; lv2:minimum -24 ; lv2:maximum 24 ;
    jig:paramIndex 1 ;
    units:unit units:semitone12TET .

<#splice_keyframes>
    a lv2:InputPort , lv2:ControlPort ;
    lv2:symbol "splice_keyframes" ; lv2:name "Splice leash" ;
    lv2:default 16 ; lv2:minimum 4 ; lv2:maximum 256 ;
    jig:paramIndex 2 .

<#max_splice>
    a lv2:InputPort , lv2:ControlPort ;
    lv2:symbol "max_splice" ; lv2:name "Maximum splice" ;
    lv2:default 200 ; lv2:minimum 5 ; lv2:maximum 500 ;
    jig:paramIndex 3 ;
    units:unit units:ms .

<#threshold>
    a lv2:InputPort , lv2:ControlPort ;
    lv2:symbol "threshold" ; lv2:name "Analysis threshold" ;
    lv2:default -60 ; lv2:minimum -90 ; lv2:maximum -30 ;
    jig:paramIndex 4 ;
    units:unit units:db .

<#mix>
    a lv2:InputPort , lv2:ControlPort ;
    lv2:symbol "mix" ; lv2:name "Mix" ;
    lv2:default 1 ; lv2:minimum 0 ; lv2:maximum 1 ;
    jig:paramIndex 5 .

<#output>
    a lv2:InputPort , lv2:ControlPort ;
    lv2:symbol "output" ; lv2:name "Output" ;
    lv2:default 0 ; lv2:minimum -24 ; lv2:maximum 12 ;
    jig:paramIndex 6 ;
    units:unit units:db .

<#quality>
    a lv2:InputPort , lv2:ControlPort ;
    lv2:symbol "quality" ; lv2:name "Quality" ;
    lv2:default 0 ; lv2:minimum 0 ; lv2:maximum 2 ;
    jig:paramIndex 7 ;
    lv2:portProperty lv2:enumeration ;
    lv2:scalePoint
        <#quality-0> ,
        <#quality-1> ,
        <#quality-2> .

<#quality-0> rdfs:label "Economy" ; rdf:value 0 .

<#quality-1> rdfs:label "Balanced" ; rdf:value 1 .

<#quality-2> rdfs:label "Full" ; rdf:value 2 .

<#stereo>
    a lv2:InputPort , lv2:ControlPort ;
    lv2:symbol "stereo" ; lv2:name "Stereo" ;
    lv2:default 0 ; lv2:minimum 0 ; lv2:maximum 1 ;
    jig:paramIndex 8 ;
    lv2:portProperty lv2:enumeration ;
    lv2:scalePoint
        <#stereo-0> ,
        <#stereo-1> .

<#stereo-0> rdfs:label "Linked" ; rdf:value 0 .

<#stereo-1> rdfs:label "Independent" ; rdf:value 1 .
