Mercurial > hg > may
changeset 85:718e0e6a9ca3
Move Vamp structured feature post-processing out into its own module, add tests for it
author | Chris Cannam |
---|---|
date | Mon, 18 Mar 2013 09:48:34 +0000 |
parents | c1c99f26d1fc |
children | 4e93d8ea1e70 |
files | test/all.yeti test/test_vamppost.yeti vamp.yeti vamppost.yeti |
diffstat | 4 files changed, 146 insertions(+), 77 deletions(-) [+] |
line wrap: on
line diff
--- a/test/all.yeti Sun Mar 17 22:29:19 2013 +0000 +++ b/test/all.yeti Mon Mar 18 09:48:34 2013 +0000 @@ -9,6 +9,7 @@ "blockfuncs" : load test.test_blockfuncs, "complex" : load test.test_complex, "fft" : load test.test_fft, +"vamppost" : load test.test_vamppost, ]; bad = sum (mapHash do name testHash: runTests name testHash done tests);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test_vamppost.yeti Mon Mar 18 09:48:34 2013 +0000 @@ -0,0 +1,79 @@ +module test.test_vamppost; + +vp = load vamppost; + +{ compare } = load test.test; + +untimed n = { timestamp = Untimed (), values = [n] }; +timed t n = { timestamp = Time t, values = [n] }; + +[ + +"fillOneSamplePerStep": \( + filled = vp.fillTimestamps { + output = { sampleType = OneSamplePerStep () }, + config = { sampleRate = 1000, stepSize = 100 }, + features = [ + [], + [ untimed 1 ], + [ untimed 1, untimed 2 ], + [], + [ timed 1 1, untimed 2, timed 4 3 ] + ] + }; + compare filled [ + timed 0.1 1 , + timed 0.2 1, timed 0.2 2 , + timed 0.4 1, timed 0.4 2, timed 0.4 3 + ]; +), + +"fillFixedSampleRate": \( + // "If the output feature's hasTimestamp field is true, the host + // should read and use the output feature's timestamp [...] If + // [hasTimestamp] is false, its time will be implicitly calculated + // by incrementing the time of the previous feature according to + // the [output descriptor's] sample rate" + filled = vp.fillTimestamps { + output = { sampleType = FixedSampleRate 500 }, + config = { sampleRate = 1000, stepSize = 100 }, + features = [ + [], + [ untimed 1 ], + [ untimed 1, untimed 2 ], + [], + [ timed 1 1, untimed 2, timed 4 3 ] + ] + }; + compare filled [ + timed 0 1 , + timed 0.2 1, timed 0.4 2 , + timed 1.0 1, timed 1.2 2, timed 4.0 3 + ]; +), + +"fillVariableSampleRate": \( + // For VariableSampleRate outputs, the timestamps should always + // be left entirely alone by fillTimestamps -- it's an error for + // the plugin to return any features without valid timestamps, + // but it isn't the job of fillTimestamps to handle that error + filled = vp.fillTimestamps { + output = { sampleType = VariableSampleRate 500 }, + config = { sampleRate = 1000, stepSize = 100 }, + features = [ + [], + [ untimed 1 ], + [ untimed 1, untimed 2 ], + [], + [ timed 1 1, untimed 2, timed 4 3 ] + ] + }; + compare filled [ + untimed 1 , + untimed 1, untimed 2 , + timed 1.0 1, untimed 2, timed 4.0 3 + ]; +), + +] is hash<string, () -> boolean>; +
--- a/vamp.yeti Sun Mar 17 22:29:19 2013 +0000 +++ b/vamp.yeti Mon Mar 18 09:48:34 2013 +0000 @@ -250,8 +250,6 @@ returnErrorFrom p stream "Failed to initialise plugin \(key) with channels = \(channels), blockSize = \(blockSize), stepSize = \(stepSize)"; fi); -outputsOf p = strJoin ", " (map (.identifier) p.outputs); - process key output stream = case loadPlugin stream.sampleRate key of OK p: @@ -259,73 +257,8 @@ if outputNo >= 0 then processWith key p outputNo stream else - returnErrorFrom p stream "Plugin \(key) has no output named \(output) (outputs are \(outputsOf p))" - fi; - Error e: Error e; - esac; - -flattenTimestamps { output, config, features } = - (stepTime n = - case output.sampleType of - OneSamplePerStep (): - (n * config.stepSize) / config.sampleRate; - //!!! Not right: this will advance the FixedSampleRate counter for each input step (not each feature actually found) -- unit tests would help here - FixedSampleRate rate: - (n * config.stepSize) / rate; - VariableSampleRate rate: - 0; //!!! - esac; - flattenTimestamps' n pending features = - case pending of - feature::rest: - case feature.timestamp of - Time t: - feature; - Untimed (): - (feature with { timestamp = Time (stepTime n) }); - esac :. \(flattenTimestamps' n rest features); - _: - case features of - here::rest: - flattenTimestamps' (n+1) here rest; - _: - []; - esac; - esac; - flattenTimestamps' (-1) [] features); - -structure results = - case results of - OK data: - (flattened = flattenTimestamps data; - case data.output.inferredStructure of - Curve (): // No duration, one value - Curve flattened; - Grid (): // No duration, >1 value, not variable rate - Grid flattened; - Instants (): // Zero-valued features - Instants flattened; - Notes (): // Duration, at least one value (pitch or freq) - Notes flattened; - Regions (): // Duration, zero or more values - Regions flattened; - Segmentation (): // No duration, one value, segment type in RDF - Segmentation flattened; - Unknown (): // Other - Unknown flattened; - esac); - Error e: - Error e; - esac; - -processStructured key output stream = - case loadPlugin stream.sampleRate key of - OK p: - outputNo = outputNumberByName p output; - if outputNo >= 0 then - structure (processWith key p outputNo stream); - else - returnErrorFrom p stream "Plugin \(key) has no output named \(output) (outputs are \(outputsOf p))" + outputs = strJoin ", " (map (.identifier) p.outputs); + returnErrorFrom p stream "Plugin \(key) has no output named \(output) (outputs are \(outputs))" fi; Error e: Error e; esac; @@ -336,12 +269,6 @@ Error e: Error e; esac; -processFileStructured key output filename = - case af.open filename of - Stream s: processStructured key output s; - Error e: Error e; - esac; - { get pluginPath = getPluginPath, get pluginKeys = listPlugins, @@ -349,7 +276,5 @@ categoryOf, process, processFile, -processStructured, -processFileStructured, }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamppost.yeti Mon Mar 18 09:48:34 2013 +0000 @@ -0,0 +1,64 @@ +module vamppost; + +fillOneSamplePerStep config features = + (stepTime n = (n * config.stepSize) / config.sampleRate; + fillTimestamps' n pending features = + case pending of + feature::rest: + (feature with { timestamp = Time (stepTime n) }) + :. \(fillTimestamps' n rest features); + _: + case features of + here::rest: + fillTimestamps' (n+1) here rest; + _: + []; + esac; + esac; + fillTimestamps' (-1) [] features); + +fillFixedSampleRate config rate features = concat features; + +fillTimestamps { output, config, features } = + case output.sampleType of + OneSamplePerStep (): + fillOneSamplePerStep config features; + FixedSampleRate rate: + fillFixedSampleRate config rate features; + VariableSampleRate _: + concat features; + esac; + +structure type features = + case type of + Curve (): // No duration, one value + Curve features; + Grid (): // No duration, >1 value, not variable rate + Grid features; + Instants (): // Zero-valued features + Instants features; + Notes (): // Duration, at least one value (pitch or freq) + Notes features; + Regions (): // Duration, zero or more values + Regions features; + Segmentation (): // No duration, one value, segment type in RDF + Segmentation features; + Unknown (): // Other + Unknown features; + esac; + +postprocess data = + case data of + OK data: + filled = fillTimestamps data; + structure data.output.inferredStructure filled; + Error e: + Error e; + esac; + +{ +fillTimestamps, +postprocess +} + +