Mercurial > hg > dml-open-backendtools
comparison pyspark/vamp_plugin_dml.py @ 0:e34cf1b6fe09 tip
commit
author | Daniel Wolff |
---|---|
date | Sat, 20 Feb 2016 18:14:24 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e34cf1b6fe09 |
---|---|
1 # -*- coding: utf-8 -*- | |
2 # | |
3 # Copyright (c) 2013 Paul Brossier <piem@piem.org> | |
4 | |
5 # This file is part of TimeSide. | |
6 | |
7 # TimeSide is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU General Public License as published by | |
9 # the Free Software Foundation, either version 2 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # TimeSide is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU General Public License | |
18 # along with TimeSide. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 # Author: Paul Brossier <piem@piem.org> | |
21 | |
22 from timeside.core import implements, interfacedoc | |
23 from timeside.analyzer.core import Analyzer | |
24 from timeside.api import IAnalyzer | |
25 import re | |
26 import subprocess | |
27 import numpy as np | |
28 | |
29 | |
30 def simple_host_process(argslist): | |
31 """Call vamp-simple-host""" | |
32 | |
33 vamp_host = 'vamp-simple-host' | |
34 command = [vamp_host] | |
35 command.extend(argslist) | |
36 # try ? | |
37 stdout = subprocess.check_output( | |
38 command, stderr=subprocess.STDOUT).splitlines() | |
39 | |
40 return stdout | |
41 | |
42 | |
43 # Raise an exception if Vamp Host is missing | |
44 from timeside.exceptions import VampImportError | |
45 try: | |
46 simple_host_process(['-v']) | |
47 WITH_VAMP = True | |
48 except OSError: | |
49 WITH_VAMP = False | |
50 raise VampImportError | |
51 | |
52 | |
53 class VampSimpleHostDML(Analyzer): | |
54 | |
55 """Vamp plugins library interface analyzer""" | |
56 | |
57 implements(IAnalyzer) | |
58 | |
59 def __init__(self, plugin_list=None): | |
60 super(VampSimpleHostDML, self).__init__() | |
61 if plugin_list is None: | |
62 plugin_list = self.get_plugins_list() | |
63 #plugin_list = [['vamp-example-plugins', 'percussiononsets', 'detectionfunction']] | |
64 | |
65 self.plugin_list = plugin_list | |
66 | |
67 @interfacedoc | |
68 def setup(self, channels=None, samplerate=None, | |
69 blocksize=None, totalframes=None): | |
70 super(VampSimpleHostDML, self).setup( | |
71 channels, samplerate, blocksize, totalframes) | |
72 | |
73 @staticmethod | |
74 @interfacedoc | |
75 def id(): | |
76 return "vamp_simple_host_dml" | |
77 | |
78 @staticmethod | |
79 @interfacedoc | |
80 def name(): | |
81 return "Vamp Plugins Host for DML" | |
82 | |
83 @staticmethod | |
84 @interfacedoc | |
85 def unit(): | |
86 return "" | |
87 | |
88 def process(self, frames, eod=False): | |
89 pass | |
90 return frames, eod | |
91 | |
92 def post_process(self): | |
93 #plugin = 'vamp-example-plugins:amplitudefollower:amplitude' | |
94 | |
95 wavfile = self.mediainfo()['uri'].split('file://')[-1] | |
96 | |
97 for plugin_line in self.plugin_list: | |
98 | |
99 plugin = ':'.join(plugin_line) | |
100 (time, duration, value) = self.vamp_plugin(plugin, wavfile) | |
101 if value is None: | |
102 return | |
103 | |
104 if duration is not None: | |
105 plugin_res = self.new_result( | |
106 data_mode='value', time_mode='segment') | |
107 plugin_res.data_object.duration = duration | |
108 else: | |
109 plugin_res = self.new_result( | |
110 data_mode='value', time_mode='event') | |
111 | |
112 plugin_res.data_object.time = time | |
113 plugin_res.data_object.value = value | |
114 | |
115 # Fix strat, duration issues if audio is a segment | |
116 # if self.mediainfo()['is_segment']: | |
117 # start_index = np.floor(self.mediainfo()['start'] * | |
118 # self.result_samplerate / | |
119 # self.result_stepsize) | |
120 # | |
121 # stop_index = np.ceil((self.mediainfo()['start'] + | |
122 # self.mediainfo()['duration']) * | |
123 # self.result_samplerate / | |
124 # self.result_stepsize) | |
125 # | |
126 # fixed_start = (start_index * self.result_stepsize / | |
127 # self.result_samplerate) | |
128 # fixed_duration = ((stop_index - start_index) * self.result_stepsize / | |
129 # self.result_samplerate) | |
130 # | |
131 # plugin_res.audio_metadata.start = fixed_start | |
132 # plugin_res.audio_metadata.duration = fixed_duration | |
133 # | |
134 # value = value[start_index:stop_index + 1] | |
135 plugin_res.id_metadata.id += '.' + '.'.join(plugin_line[1:]) | |
136 plugin_res.id_metadata.name += ' ' + \ | |
137 ' '.join(plugin_line[1:]) | |
138 | |
139 self.process_pipe.results.add(plugin_res) | |
140 | |
141 @staticmethod | |
142 def vamp_plugin(plugin, wavfile): | |
143 | |
144 args = [plugin, wavfile] | |
145 | |
146 stdout = simple_host_process(args) # run vamp-simple-host | |
147 | |
148 stderr = stdout[0:8] # stderr containing file and process information | |
149 res = stdout[8:] # stdout containg the feature data | |
150 | |
151 if len(res) == 0: | |
152 return ([], [], []) | |
153 | |
154 # Parse stderr to get blocksize and stepsize | |
155 blocksize_info = stderr[4] | |
156 | |
157 import re | |
158 # Match agianst pattern 'Using block size = %d, step size = %d' | |
159 m = re.match( | |
160 'Using block size = (\d+), step size = (\d+)', blocksize_info) | |
161 | |
162 blocksize = int(m.groups()[0]) | |
163 stepsize = int(m.groups()[1]) | |
164 # Get the results | |
165 | |
166 # how are types defined in this? what types can timeside use? | |
167 # value = np.asfarray([line.split(': ')[1] for line in res if (len(line.split(': ')) > 1)]) | |
168 value = [line.split(': ')[1] for line in res if (len(line.split(': ')) > 1)] | |
169 value = [re.sub("[^0-9\.\s]","",x) for x in value] | |
170 value = np.asfarray([[x.split(' ')[0] for x in value], [x.split(' ')[1] for x in value]]) # only get the first thing in the string | |
171 time = np.asfarray([r.split(':')[0].split(',')[0] for r in res]) | |
172 | |
173 time_len = len(res[0].split(':')[0].split(',')) | |
174 if time_len == 1: | |
175 # event | |
176 duration = None | |
177 elif time_len == 2: | |
178 # segment | |
179 duration = np.asfarray( | |
180 [r.split(':')[0].split(',')[1] for r in res]) | |
181 | |
182 return (time, duration, value) | |
183 | |
184 @staticmethod | |
185 def get_plugins_list(): | |
186 arg = ['--list-outputs'] | |
187 stdout = simple_host_process(arg) | |
188 | |
189 return [line.split(':')[1:] for line in stdout] |