To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Revision:

root / src / may / vamp.yeti @ 594:495cc8973458

History | View | Annotate | Download (10.9 KB)

1
module may.vamp;
2

    
3
import org.vamp_plugins:
4
       Plugin, Plugin$InputDomain,
5
       PluginLoader, PluginLoader$AdapterFlags, PluginLoader$LoadFailedException,
6
       ParameterDescriptor, OutputDescriptor, OutputDescriptor$SampleType,
7
       RealTime, Feature;
8

    
9
import java.lang: UnsatisfiedLinkError;
10

    
11
import java.util: Map, List;
12

    
13
vec = load may.vector;
14
fr = load may.stream.framer;
15
af = load may.stream.audiofile;
16
mat = load may.matrix;
17
vamprdf = load may.vamp.vamprdf;
18
vamppost = load may.vamp.vamppost;
19

    
20
store = load yertle.store;
21

    
22
realTime r is ~RealTime -> number = r#sec() + (r#nsec() / 1000000000);
23

    
24
feature f is ~Feature -> 'a = {
25
    timestamp = if f#hasTimestamp then Time (realTime f#timestamp) else Untimed () fi,
26
    duration = if f#hasDuration then Time (realTime f#duration) else Untimed () fi,
27
    values = vec.fromFloats f#values,
28
    label = f#label,
29
    };
30

    
31
featureList fl is ~Object -> 'a =
32
    if nullptr? fl then []
33
    else
34
        a = fl unsafely_as ~List;
35
        result = array [];
36
        itr = a#iterator();
37
        itr#hasNext() loop (push result (feature (itr#next() unsafely_as ~Feature)));
38
        list result
39
    fi;
40

    
41
featureSet fs is ~Map -> 'a =
42
   (numberOf n is ~Object -> number = (n unsafely_as ~Integer)#intValue();
43
    s = [:];
44
    kk = list fs#keySet()#toArray();
45
    for kk do k: s[numberOf k] := featureList fs#get(k) done;
46
    s);
47

    
48
stores = [:];
49

    
50
getSingletonStoreFor loader =
51
    synchronized stores do:
52
        if loader in stores then
53
            stores[loader]
54
        else
55
            s = store.newRdfStore ();
56
            loader s;
57
            stores[loader] := s;
58
            s;
59
        fi
60
    done;
61

    
62
getSystemStore () =
63
    getSingletonStoreFor vamprdf.loadSystemVampRdf;
64

    
65
getGlobalStore () = 
66
    getSingletonStoreFor vamprdf.loadGlobalVampRdf;
67

    
68
getPluginPath () =
69
   (try
70
        map string PluginLoader#getInstance()#getPluginPath();
71
    catch UnsatisfiedLinkError e:
72
        eprintln "Warning: Unable to obtain plugin path:\n\(e)";
73
        [];
74
    yrt);
75

    
76
listPlugins () =
77
   (try
78
        map string PluginLoader#getInstance()#listPlugins();
79
    catch UnsatisfiedLinkError e:
80
        eprintln "Warning: Unable to obtain plugin list:\n\(e)";
81
        [];
82
    yrt);
83

    
84
getPluginKeysFrom store =
85
   (nodes = vamprdf.allPluginNodes store;
86
    // ordering is random out of the store; might as well sort
87
    sort (concatMap do n:
88
        case vamprdf.pluginKeyByNode store n of Some k: [k]; None (): [] esac 
89
        done nodes));
90

    
91
getKnownPluginKeys () =
92
   (global = getPluginKeysFrom (getGlobalStore ());
93
    system = getPluginKeysFrom (getSystemStore ());
94
    sort (nub (concat [global, system])));
95

    
96
getDataForKnownPlugin key =
97
    case vamprdf.pluginDataByKey (getSystemStore ()) key of
98
    Some d: Some d;
99
    None _: vamprdf.pluginDataByKey (getGlobalStore ()) key;
100
    esac;
101
   
102
categoryOf key =
103
    map string PluginLoader#getInstance()#getPluginCategory(key);
104

    
105
inputDomain d is ~Plugin$InputDomain -> 'a = 
106
    if d == Plugin$InputDomain#FREQUENCY_DOMAIN then
107
        FrequencyDomain ()
108
    else
109
        TimeDomain ()
110
    fi;
111

    
112
parameterDescriptor pd is ~ParameterDescriptor -> 'a = {
113
    identifier = pd#identifier,
114
    name = pd#name,
115
    description = pd#description,
116
    unit = pd#unit,
117
    minValue = pd#minValue,
118
    maxValue = pd#maxValue,
119
    defaultValue = pd#defaultValue,
120
    get quantize () = if pd#isQuantized then QuantizeStep pd#quantizeStep else Unquantized () fi,
121
    valueNames = map string pd#valueNames
122
    };
123

    
124
sampleType t rate is ~OutputDescriptor$SampleType -> number -> 'a =
125
    if t == OutputDescriptor$SampleType#OneSamplePerStep then
126
        OneSamplePerStep ()
127
    elif t == OutputDescriptor$SampleType#FixedSampleRate then
128
        FixedSampleRate rate
129
    else
130
        VariableSampleRate rate
131
    fi;
132

    
133
structureOf rdfOutputData od is 'a -> ~OutputDescriptor -> 'b = 
134
   (computes = case rdfOutputData of Some d: d.computes; None (): Unknown () esac;
135
    s = getSystemStore ();
136
    noteIRI = case s.expand "af:Note" of IRI iri: iri; _: "" esac;
137
    if od#hasFixedBinCount and od#binCount == 0 then
138
        Instants ();
139
    elif od#hasDuration then
140
        if computes != Unknown () then
141
            if computes == Event noteIRI then Notes ();
142
            else Regions ();
143
            fi
144
        elif od#hasFixedBinCount then
145
            if od#binCount > 1 then Notes ();
146
            elif od#unit == "Hz" or strIndexOf (strLower od#unit) "midi" 0 >= 0 then Notes ();
147
            else Regions ();
148
            fi
149
        else
150
            Unknown ();
151
        fi
152
    elif od#hasFixedBinCount and od#binCount == 1 then
153
        case computes of
154
        Event e:
155
            if strEnds? e "Segment" 
156
            then Segmentation ()
157
            else Curve ()
158
            fi;
159
        _:
160
            if od#sampleType == OutputDescriptor$SampleType#OneSamplePerStep
161
            then Series ()
162
            else Curve ()
163
            fi;
164
        esac;
165
    elif od#hasFixedBinCount and
166
         od#sampleType != OutputDescriptor$SampleType#VariableSampleRate then
167
        Grid ();
168
    else
169
        Unknown ();
170
    fi);
171

    
172
outputDescriptor rdfOutputData od is 'a -> ~OutputDescriptor -> 'b = {
173
    identifier = od#identifier,
174
    name = od#name,
175
    description = od#description,
176
    get binCount () = if od#hasFixedBinCount then Fixed od#binCount else Variable () fi,
177
    get valueExtents () = if od#hasKnownExtents then Known { min = od#minValue, max = od#maxValue } else Unknown () fi,
178
    get valueQuantize () = if od#isQuantized then QuantizeStep od#quantizeStep else Unquantized () fi,
179
    valueUnit = od#unit,
180
    binNames = array (map string od#binNames),
181
    sampleType = sampleType od#sampleType od#sampleRate,
182
    hasDuration = od#hasDuration,
183
    computes is Event string | Feature string | Signal string | Unknown () = case rdfOutputData of Some data: data.computes; None (): Unknown () esac,
184
    get inferredStructure () = structureOf rdfOutputData od,
185
    };
186

    
187
plugin key p is string -> ~Plugin -> 'a =
188
   (rdfData = vamprdf.pluginDataByKey (getSystemStore ()) key;
189
    {
190
    plugin = p,
191
    key,
192
    get apiVersion () = p#getVampApiVersion(),
193
    get identifier () = p#getIdentifier(),
194
    get name () = p#getName(),
195
    get description () = p#getDescription(),
196
    get maker () = p#getMaker(),
197
    get copyright () = p#getCopyright(),
198
    get version () = p#getPluginVersion(),
199
    get category () = PluginLoader#getInstance()#getPluginCategory(key),
200
    get hasRdfDescription () = (rdfData != None ()),
201
    get infoURL () = case rdfData of Some data: data.infoURL; None (): "" esac,
202
    get parameters () = array (map parameterDescriptor p#getParameterDescriptors()),
203
    parameterValue identifier = p#getParameter(identifier),
204
    setParameterValue identifier value = p#setParameter(identifier, value),
205
    get programs () = array (map string p#getPrograms()),
206
    get currentProgram () = p#getCurrentProgram(),
207
    selectProgram pr = p#selectProgram(pr),
208
    get inputDomain () = inputDomain p#getInputDomain(),
209
    get preferredBlockSize () = p#getPreferredBlockSize(),
210
    get preferredStepSize () = p#getPreferredStepSize(),
211
    get minChannelCount () = p#getMinChannelCount(),
212
    get maxChannelCount () = p#getMaxChannelCount(),
213
    initialise { channels, hop, blockSize } = p#initialise(channels, hop, blockSize),
214
    reset () = p#reset(),
215
    get outputs () =
216
        array case rdfData of
217
        Some data: map2 outputDescriptor (map Some data.outputs) p#getOutputDescriptors();
218
        None (): map (outputDescriptor (None ())) p#getOutputDescriptors();
219
        esac,
220
    process frame time is 'a -> ~RealTime -> 'b = 
221
        featureSet p#process((map vec.floats (mat.asRows frame)) as ~float[][], 0, time),
222
    getRemainingFeatures () = featureSet p#getRemainingFeatures(),
223
    dispose () = p#dispose(),
224
    });
225

    
226
featuresFromSet outputNo f = if outputNo in f then f[outputNo] else [] fi;
227

    
228
outputNumberByName p name =
229
   (outputs = p.outputs;
230
    case find ((== name) . (.identifier)) outputs of
231
    first::rest: index first outputs;
232
    _: -1;
233
    esac);
234

    
235
loadPlugin rate key =
236
    try
237
        OK (plugin key 
238
            PluginLoader#getInstance()#loadPlugin(key, rate,
239
                PluginLoader$AdapterFlags#ADAPT_INPUT_DOMAIN +
240
                PluginLoader$AdapterFlags#ADAPT_CHANNEL_COUNT))
241
    catch PluginLoader$LoadFailedException _:
242
        Error "Failed to load Vamp plugin with key \(key)"
243
    yrt;
244

    
245
processed params frames count =
246
   (p = params.p;
247
    case frames of
248
    frame::rest:
249
        p.process frame RealTime#frame2RealTime(count, params.sampleRate)
250
        :.
251
        \(processed params rest (count + params.hop));
252
    _: 
253
       (rf = p.getRemainingFeatures ();
254
        p.dispose ();
255
        [rf]);
256
    esac);
257

    
258
converted { p, sampleRate, hop } outputNo fl =
259
    map (featuresFromSet outputNo) fl;
260

    
261
returnErrorFrom p stream text = (p.dispose (); stream.close (); failWith text);
262

    
263
processWith key p outputNo stream =
264
   (blockSize =
265
        if p.preferredBlockSize == 0 then 2048
266
        else p.preferredBlockSize fi;
267
    stepSize =
268
        if p.preferredStepSize == 0 then
269
            if p.inputDomain == FrequencyDomain () then blockSize / 2
270
            else blockSize fi;
271
        else p.preferredStepSize fi;
272
    channels = 1;
273
    params = {
274
        p,
275
        sampleRate = stream.sampleRate, 
276
        channels = 1,
277
        blockSize,
278
        hop = stepSize
279
    };
280
    if p.initialise params then
281
        {
282
            key,
283
            output = p.outputs[outputNo],
284
            parameters = mapIntoHash id p.parameterValue
285
               (map (.identifier) p.parameters),
286
            config = {
287
                channels, blockSize, stepSize,
288
                sampleRate = stream.sampleRate
289
            },
290
            features = converted params outputNo
291
               (processed params (fr.frames blockSize [ Hop stepSize ] stream) 0)
292
        };
293
        // If processing completed successfully, then p is
294
        // disposed by processed and stream is closed by the
295
        // framer
296
    else
297
        returnErrorFrom p stream "Failed to initialise plugin \(key) with channels = \(channels), blockSize = \(blockSize), stepSize = \(stepSize)";
298
    fi);
299

    
300
processStream key output stream =
301
    case loadPlugin stream.sampleRate key of
302
    OK p:
303
        outputNo = outputNumberByName p output;
304
        if outputNo >= 0 then
305
            processWith key p outputNo stream
306
        else
307
            outputs = strJoin ", " (map (.identifier) p.outputs);
308
            returnErrorFrom p stream "Plugin \(key) has no output named \(output) (outputs are: \(outputs))"
309
        fi;
310
    Error e: failWith e;
311
    esac;
312

    
313
processFile key output filename = 
314
    processStream key output (af.open filename);
315

    
316
processStreamStructured key output stream =
317
    vamppost.postprocess (processStream key output stream);
318

    
319
processFileStructured key output filename =
320
    vamppost.postprocess (processFile key output filename);
321

    
322
{
323
get pluginPath = getPluginPath,
324
get pluginKeys = listPlugins,
325
loadPlugin,
326
categoryOf,
327
processStream,
328
processFile,
329
processStreamStructured,
330
processFileStructured,
331
getKnownPluginKeys,
332
getDataForKnownPlugin,
333
}
334