Chris@56
|
1 '''A high-level interface to the vampyhost extension module, for quickly and easily running Vamp audio analysis plugins on audio files and buffers.'''
|
Chris@56
|
2
|
Chris@56
|
3 import vampyhost
|
Chris@75
|
4 import frames
|
Chris@75
|
5 import load
|
Chris@68
|
6
|
Chris@89
|
7 def process_frames_with_plugin(ff, sample_rate, step_size, plugin, outputs):
|
Chris@89
|
8
|
Chris@98
|
9 out_indices = dict([(id, plugin.get_output(id)["output_index"])
|
Chris@98
|
10 for id in outputs])
|
Chris@89
|
11 plugin.reset()
|
Chris@89
|
12 fi = 0
|
Chris@89
|
13
|
Chris@89
|
14 for f in ff:
|
Chris@89
|
15 timestamp = vampyhost.frame_to_realtime(fi, sample_rate)
|
Chris@89
|
16 results = plugin.process_block(f, timestamp)
|
Chris@89
|
17 # results is a dict mapping output number -> list of feature dicts
|
Chris@89
|
18 for o in outputs:
|
Chris@89
|
19 ix = out_indices[o]
|
Chris@89
|
20 if ix in results:
|
Chris@89
|
21 for r in results[ix]:
|
Chris@89
|
22 yield { o: r }
|
Chris@89
|
23 fi = fi + step_size
|
Chris@89
|
24
|
Chris@89
|
25 results = plugin.get_remaining_features()
|
Chris@89
|
26 for o in outputs:
|
Chris@89
|
27 ix = out_indices[o]
|
Chris@89
|
28 if ix in results:
|
Chris@89
|
29 for r in results[ix]:
|
Chris@89
|
30 yield { o: r }
|
Chris@89
|
31
|
Chris@89
|
32
|
Chris@89
|
33 def process(data, sample_rate, key, output = "", parameters = {}):
|
Chris@98
|
34 """Process audio data with a Vamp plugin, and make the results from a
|
Chris@98
|
35 single plugin output available as a generator.
|
Chris@98
|
36
|
Chris@98
|
37 The provided data should be a 1- or 2-dimensional list or NumPy
|
Chris@98
|
38 array of floats. If it is 2-dimensional, the first dimension is
|
Chris@98
|
39 taken to be the channel count.
|
Chris@98
|
40
|
Chris@98
|
41 The returned results will be those calculated by the plugin with
|
Chris@98
|
42 the given key and returned through its output with the given
|
Chris@98
|
43 output identifier. If the requested output is the empty string,
|
Chris@98
|
44 the first output provided by the plugin will be used.
|
Chris@98
|
45
|
Chris@98
|
46 If the parameters dict is non-empty, the plugin will be configured
|
Chris@98
|
47 by setting its parameters according to the (string) key and
|
Chris@98
|
48 (float) value data found in the dict.
|
Chris@98
|
49
|
Chris@98
|
50 This function acts as a generator, yielding a sequence of result
|
Chris@98
|
51 features as it obtains them. Each feature is represented as a
|
Chris@98
|
52 dictionary containing, optionally, timestamp and duration
|
Chris@98
|
53 (RealTime objects), label (string), and a 1-dimensional array of
|
Chris@98
|
54 float values.
|
Chris@98
|
55 """
|
Chris@89
|
56
|
Chris@89
|
57 plugin, step_size, block_size = load.load_and_configure(data, sample_rate, key, parameters)
|
Chris@89
|
58
|
Chris@89
|
59 if output == "":
|
Chris@89
|
60 output = plugin.get_output(0)["identifier"]
|
Chris@89
|
61
|
Chris@89
|
62 ff = frames.frames_from_array(data, step_size, block_size)
|
Chris@89
|
63
|
Chris@89
|
64 for r in process_frames_with_plugin(ff, sample_rate, step_size, plugin, [output]):
|
Chris@89
|
65 yield r[output]
|
Chris@76
|
66
|
Chris@89
|
67 plugin.unload()
|
Chris@89
|
68
|
Chris@76
|
69
|
Chris@98
|
70 def process_frames(ff, sample_rate, step_size, key, output = "", parameters = {}):
|
Chris@98
|
71 """Process audio data with a Vamp plugin, and make the results from a
|
Chris@98
|
72 single plugin output available as a generator.
|
Chris@95
|
73
|
Chris@98
|
74 The provided data should be an enumerable sequence of time-domain
|
Chris@98
|
75 audio frames, of which each frame is 2-dimensional list or NumPy
|
Chris@98
|
76 array of floats. The first dimension is taken to be the channel
|
Chris@98
|
77 count, and the second dimension the frame or block size. The
|
Chris@98
|
78 step_size argument gives the increment in audio samples from one
|
Chris@98
|
79 frame to the next. Each frame must have the same size.
|
Chris@95
|
80
|
Chris@98
|
81 The returned results will be those calculated by the plugin with
|
Chris@98
|
82 the given key and returned through its output with the given
|
Chris@98
|
83 output identifier. If the requested output is the empty string,
|
Chris@98
|
84 the first output provided by the plugin will be used.
|
Chris@95
|
85
|
Chris@98
|
86 If the parameters dict is non-empty, the plugin will be configured
|
Chris@98
|
87 by setting its parameters according to the (string) key and
|
Chris@98
|
88 (float) value data found in the dict.
|
Chris@98
|
89
|
Chris@98
|
90 This function acts as a generator, yielding a sequence of result
|
Chris@98
|
91 features as it obtains them. Each feature is represented as a
|
Chris@98
|
92 dictionary containing, optionally, timestamp and duration
|
Chris@98
|
93 (RealTime objects), label (string), and a 1-dimensional array of
|
Chris@98
|
94 float values.
|
Chris@98
|
95 """
|
Chris@98
|
96
|
Chris@98
|
97 plugin = vampyhost.load_plugin(key, sample_rate,
|
Chris@98
|
98 vampyhost.ADAPT_INPUT_DOMAIN +
|
Chris@98
|
99 vampyhost.ADAPT_BUFFER_SIZE +
|
Chris@98
|
100 vampyhost.ADAPT_CHANNEL_COUNT)
|
Chris@98
|
101
|
Chris@98
|
102 fi = 0
|
Chris@98
|
103 channels = 0
|
Chris@98
|
104 block_size = 0
|
Chris@98
|
105
|
Chris@98
|
106 if output == "":
|
Chris@98
|
107 out_index = 0
|
Chris@98
|
108 else:
|
Chris@98
|
109 out_index = plugin.get_output(output)["output_index"]
|
Chris@95
|
110
|
Chris@98
|
111 for f in ff:
|
Chris@95
|
112
|
Chris@98
|
113 if fi == 0:
|
Chris@98
|
114 channels = f.shape[0]
|
Chris@98
|
115 block_size = f.shape[1]
|
Chris@98
|
116 plugin.set_parameter_values(parameters)
|
Chris@98
|
117 if not plugin.initialise(channels, step_size, block_size):
|
Chris@98
|
118 raise "Failed to initialise plugin"
|
Chris@98
|
119
|
Chris@98
|
120 timestamp = vampyhost.frame_to_realtime(fi, sample_rate)
|
Chris@98
|
121 results = plugin.process_block(f, timestamp)
|
Chris@98
|
122 # results is a dict mapping output number -> list of feature dicts
|
Chris@98
|
123 if out_index in results:
|
Chris@98
|
124 for r in results[out_index]:
|
Chris@98
|
125 yield r
|
Chris@98
|
126
|
Chris@98
|
127 fi = fi + step_size
|
Chris@98
|
128
|
Chris@98
|
129 if fi > 0:
|
Chris@98
|
130 results = plugin.get_remaining_features()
|
Chris@98
|
131 if out_index in results:
|
Chris@98
|
132 for r in results[out_index]:
|
Chris@98
|
133 yield r
|
Chris@98
|
134
|
Chris@95
|
135 plugin.unload()
|
Chris@95
|
136
|
Chris@95
|
137
|
Chris@84
|
138 def process_multiple_outputs(data, sample_rate, key, outputs, parameters = {}):
|
Chris@68
|
139 #!!! docstring
|
Chris@68
|
140
|
Chris@89
|
141 plugin, step_size, block_size = load.load_and_configure(data, sample_rate, key, parameters)
|
Chris@64
|
142
|
Chris@84
|
143 ff = frames.frames_from_array(data, step_size, block_size)
|
Chris@64
|
144
|
Chris@89
|
145 for r in process_frames_with_plugin(ff, sample_rate, step_size, plugin, outputs):
|
Chris@89
|
146 yield r
|
Chris@61
|
147
|
Chris@89
|
148 plugin.unload()
|