changeset 100:72be91c3cb3d

Add & test process_frames_multiple_outputs
author Chris Cannam
date Tue, 10 Feb 2015 10:56:44 +0000
parents 7764eb74a3c6
children 0c5a4dc04ed9
files test/test_process.py vamp/__init__.py vamp/collect.py vamp/process.py
diffstat 4 files changed, 90 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/test/test_process.py	Tue Feb 03 16:24:37 2015 +0000
+++ b/test/test_process.py	Tue Feb 10 10:56:44 2015 +0000
@@ -103,6 +103,21 @@
         actual = results[i]["input-summary"]["values"][0]
         assert actual == expected
 
+def test_process_multi_summary_frames():
+    buf = input_data(blocksize * 10)
+    ff = fr.frames_from_array(buf, blocksize, blocksize)
+    results = list(vamp.process_frames_multiple_outputs(ff, rate, blocksize, plugin_key, [ "input-summary" ], {}))
+    assert len(results) == 10
+    for i in range(len(results)):
+        #
+        # each feature has a single value, equal to the number of non-zero elts
+        # in the input block (which is all of them, i.e. the blocksize) plus
+        # the first elt (which is i * blockSize + 1)
+        #
+        expected = blocksize + i * blocksize + 1
+        actual = results[i]["input-summary"]["values"][0]
+        assert actual == expected
+
 def test_process_freq_summary():
     buf = input_data(blocksize * 10)
     results = list(vamp.process(buf, rate, plugin_key_freq, "input-summary", {}))
--- a/vamp/__init__.py	Tue Feb 03 16:24:37 2015 +0000
+++ b/vamp/__init__.py	Tue Feb 10 10:56:44 2015 +0000
@@ -3,6 +3,6 @@
 import vampyhost
 
 from load import list_plugins, get_outputs_of, get_category_of
-from process import process, process_frames, process_multiple_outputs
+from process import process, process_frames, process_multiple_outputs, process_frames_multiple_outputs
 from collect import collect
 
--- a/vamp/collect.py	Tue Feb 03 16:24:37 2015 +0000
+++ b/vamp/collect.py	Tue Feb 10 10:56:44 2015 +0000
@@ -123,7 +123,7 @@
     plugin returns them, via an asynchronous generator function, use
     vamp.process() instead.
     """
-    
+
     plugin, step_size, block_size = load.load_and_configure(data, sample_rate, key, parameters)
 
     if output == "":
@@ -134,7 +134,7 @@
 
     ff = frames.frames_from_array(data, step_size, block_size)
 
-    results = process.process_frames_with_plugin(ff, sample_rate, step_size, plugin, [output])
+    results = process.process_with_initialised_plugin(ff, sample_rate, step_size, plugin, [output])
 
     rv = reshape(results, sample_rate, step_size, output_desc)
 
--- a/vamp/process.py	Tue Feb 03 16:24:37 2015 +0000
+++ b/vamp/process.py	Tue Feb 10 10:56:44 2015 +0000
@@ -4,7 +4,7 @@
 import frames
 import load
 
-def process_frames_with_plugin(ff, sample_rate, step_size, plugin, outputs):
+def process_with_initialised_plugin(ff, sample_rate, step_size, plugin, outputs):
 
     out_indices = dict([(id, plugin.get_output(id)["output_index"])
                         for id in outputs])
@@ -64,7 +64,7 @@
 
     ff = frames.frames_from_array(data, step_size, block_size)
 
-    for r in process_frames_with_plugin(ff, sample_rate, step_size, plugin, [output]):
+    for r in process_with_initialised_plugin(ff, sample_rate, step_size, plugin, [output]):
         yield r[output]
     
     plugin.unload()
@@ -168,11 +168,77 @@
 
     ff = frames.frames_from_array(data, step_size, block_size)
 
-    for r in process_frames_with_plugin(ff, sample_rate, step_size, plugin, outputs):
+    for r in process_with_initialised_plugin(ff, sample_rate, step_size, plugin, outputs):
         yield r
 
     plugin.unload()
 
-#!!!
-# + process_frames_multiple_outputs
-# + refactor common material
+
+def process_frames_multiple_outputs(ff, sample_rate, step_size, key, outputs, parameters = {}):
+    """Process audio data with a Vamp plugin, and make the results from a
+    set of plugin outputs available as a generator.
+
+    The provided data should be an enumerable sequence of time-domain
+    audio frames, of which each frame is 2-dimensional list or NumPy
+    array of floats. The first dimension is taken to be the channel
+    count, and the second dimension the frame or block size. The
+    step_size argument gives the increment in audio samples from one
+    frame to the next. Each frame must have the same size.
+
+    The returned results will be those calculated by the plugin with
+    the given key and returned through its outputs whose identifiers
+    are given in the outputs argument.
+
+    If the parameters dict is non-empty, the plugin will be configured
+    by setting its parameters according to the (string) key and
+    (float) value data found in the dict.
+
+    This function acts as a generator, yielding a sequence of result
+    feature sets as it obtains them. Each feature set is a dictionary
+    mapping from output identifier to a list of features, each
+    represented as a dictionary containing, optionally, timestamp and
+    duration (RealTime objects), label (string), and a 1-dimensional
+    array of float values.
+    """
+    plugin = vampyhost.load_plugin(key, sample_rate,
+                                   vampyhost.ADAPT_INPUT_DOMAIN +
+                                   vampyhost.ADAPT_BUFFER_SIZE +
+                                   vampyhost.ADAPT_CHANNEL_COUNT)
+
+    out_indices = dict([(id, plugin.get_output(id)["output_index"])
+                        for id in outputs])
+    
+    fi = 0
+    channels = 0
+    block_size = 0
+
+    for f in ff:
+
+        if fi == 0:
+            channels = f.shape[0]
+            block_size = f.shape[1]
+            plugin.set_parameter_values(parameters)
+            if not plugin.initialise(channels, step_size, block_size):
+                raise "Failed to initialise plugin"
+
+        timestamp = vampyhost.frame_to_realtime(fi, sample_rate)
+        results = plugin.process_block(f, timestamp)
+        # results is a dict mapping output number -> list of feature dicts
+        for o in outputs:
+            ix = out_indices[o]
+            if ix in results:
+                for r in results[ix]:
+                    yield { o: r }
+        fi = fi + step_size
+
+    if fi > 0:
+        results = plugin.get_remaining_features()
+        for o in outputs:
+            ix = out_indices[o]
+            if ix in results:
+                for r in results[ix]:
+                    yield { o: r }
+        
+    plugin.unload()
+
+