1 | from aubio.bench.node import * |
---|
2 | |
---|
3 | def parse_args(req): |
---|
4 | req.basehref = BASEHREF |
---|
5 | req.datadir = DATADIR |
---|
6 | if req.path_info: path_info = req.path_info |
---|
7 | else: path_info = '/' |
---|
8 | location = re.sub('^/show_[a-z0-9]*/','',path_info) |
---|
9 | location = re.sub('^/play_[a-z0-9]*/','',location) |
---|
10 | location = re.sub('^/index/','',location) |
---|
11 | location = re.sub('^/','',location) |
---|
12 | location = re.sub('/$','',location) |
---|
13 | datapath = "%s/%s" % (DATADIR,location) |
---|
14 | respath = "%s/%s" % (DATADIR,location) |
---|
15 | last = re.sub('/$','',location) |
---|
16 | last = last.split('/')[-1] |
---|
17 | first = path_info.split('/')[1] |
---|
18 | # store some of this in the mp_request |
---|
19 | req.location, req.datapath, req.respath = location, datapath, respath |
---|
20 | req.first, req.last = first, last |
---|
21 | |
---|
22 | if location: |
---|
23 | if not (os.path.isfile(datapath) or |
---|
24 | os.path.isdir(datapath) or |
---|
25 | location in ['feedback','email']): |
---|
26 | # the path was not understood |
---|
27 | from mod_python import apache |
---|
28 | req.write("<html> path not found %s</html>" % (datapath)) |
---|
29 | raise apache.SERVER_RETURN, apache.OK |
---|
30 | #from mod_python import apache |
---|
31 | #raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND |
---|
32 | |
---|
33 | def navigation(req): |
---|
34 | """ main html navigation header """ |
---|
35 | from mod_python import psp |
---|
36 | req.content_type = "text/html" |
---|
37 | parse_args(req) |
---|
38 | datapath = req.datapath |
---|
39 | location = req.location |
---|
40 | |
---|
41 | # deal with session |
---|
42 | if req.sess.is_new(): |
---|
43 | msg = "<b>Welcome %s</b><br>" % req.sess['login'] |
---|
44 | else: |
---|
45 | msg = "<b>Welcome back %s</b><br>" % req.sess['login'] |
---|
46 | |
---|
47 | # start writing |
---|
48 | tmpl = psp.PSP(req, filename='header.tmpl') |
---|
49 | tmpl.run(vars = { 'title': "aubioweb / %s / %s" % (req.first,location), |
---|
50 | 'basehref': '/~piem/', |
---|
51 | 'message': msg, |
---|
52 | 'action': req.first}) |
---|
53 | |
---|
54 | req.write("<h2>Content of ") |
---|
55 | print_link(req,"","/") |
---|
56 | y = location.split('/') |
---|
57 | for i in range(len(y)-1): |
---|
58 | print_link(req,"/".join(y[:i+1]),y[i]) |
---|
59 | req.write(" / ") |
---|
60 | req.write("%s</h2>\n" % y[-1]) |
---|
61 | |
---|
62 | a = {'show_info' : 'info', |
---|
63 | 'show_sound': 'waveform', |
---|
64 | 'show_onset': 'onset', |
---|
65 | 'index' : 'index', |
---|
66 | 'show_pitch': 'pitch', |
---|
67 | 'play_m3u': 'stream (m3u/ogg)', |
---|
68 | 'play_ogg': 'save (ogg)', |
---|
69 | 'play_wav': 'save (wav)', |
---|
70 | } |
---|
71 | |
---|
72 | # print task lists (only remaining tasks) |
---|
73 | print_link(req,re.sub('%s.*'%req.last,'',location),"go up") |
---|
74 | akeys = a.keys(); akeys.sort(); |
---|
75 | curkey = req.first |
---|
76 | for akey in akeys: |
---|
77 | if akey != curkey: |
---|
78 | req.write(":: ") |
---|
79 | print_link(req,"/".join((akey,location)),a[akey]) |
---|
80 | else: |
---|
81 | req.write(":: ") |
---|
82 | req.write("<b>%s</b>" % a[akey]) |
---|
83 | req.write("<br>") |
---|
84 | |
---|
85 | # list the content of the directories |
---|
86 | listdir,listfiles = [],[] |
---|
87 | if os.path.isdir(datapath): |
---|
88 | listfiles = list_snd_files(datapath) |
---|
89 | listdir = list_dirs(datapath) |
---|
90 | listdir.pop(0) # kick the current dir |
---|
91 | elif os.path.isfile(datapath): |
---|
92 | listfiles = [datapath] |
---|
93 | listdir = [re.sub(req.last,'',location)] |
---|
94 | |
---|
95 | link_list(req,listdir,title="Subdirectories") |
---|
96 | link_list(req,listfiles,title="Files") |
---|
97 | |
---|
98 | def footer(req): |
---|
99 | """ html navigation footer """ |
---|
100 | from mod_python import psp |
---|
101 | tmpl = psp.PSP(req, filename='footer.tmpl') |
---|
102 | tmpl.run(vars = { 'time': -req.mtime+req.request_time }) |
---|
103 | |
---|
104 | def apply_on_data(req, func,**keywords): |
---|
105 | # bug: hardcoded snd file filter |
---|
106 | act_on_data(func,req.datapath,req.respath, |
---|
107 | filter="f -maxdepth 1 -name '*.wav' -o -name '*.aif'",**keywords) |
---|
108 | |
---|
109 | def print_link(req,target,name,basehref=BASEHREF): |
---|
110 | req.write("<a href='%s/%s'>%s</a>\n" % (basehref,target,name)) |
---|
111 | |
---|
112 | def print_img(req,target,name='',basehref=BASEHREF): |
---|
113 | if name == '': name = target |
---|
114 | req.write("<img src='%s/%s' alt='%s' title='%s'>\n" % (basehref,target,name,name)) |
---|
115 | |
---|
116 | def link_list(req,targetlist,basehref=BASEHREF,title=None): |
---|
117 | if len(targetlist) > 1: |
---|
118 | if title: req.write("<h3>%s</h3>"%title) |
---|
119 | req.write('<ul>') |
---|
120 | for i in targetlist: |
---|
121 | s = re.split('%s/'%DATADIR,i,maxsplit=1)[1] |
---|
122 | if s: |
---|
123 | req.write('<li>') |
---|
124 | print_link(req,s,s) |
---|
125 | req.write('</li>') |
---|
126 | req.write('</ul>') |
---|
127 | |
---|
128 | def print_list(req,list): |
---|
129 | req.write("<pre>\n") |
---|
130 | for i in list: req.write("%s\n" % i) |
---|
131 | req.write("</pre>\n") |
---|
132 | |
---|
133 | def print_command(req,command): |
---|
134 | req.write("<h4>%s</h4>\n" % re.sub('%%','%',command)) |
---|
135 | def print_runcommand(input,output): |
---|
136 | cmd = re.sub('(%)?%i','%s' % input, command) |
---|
137 | cmd = re.sub('(%)?%o','%s' % output, cmd) |
---|
138 | print_list(req,runcommand(cmd)) |
---|
139 | apply_on_data(req,print_runcommand) |
---|
140 | |
---|
141 | def datapath_to_location(input): |
---|
142 | location = re.sub(DATADIR,'',input) |
---|
143 | return re.sub('^/*','',location) |
---|
144 | |
---|
145 | ## drawing hacks |
---|
146 | def draw_func(req,func): |
---|
147 | import re |
---|
148 | req.content_type = "image/png" |
---|
149 | # build location (strip the func_path, add DATADIR) |
---|
150 | location = re.sub('^/draw_[a-z]*/','%s/'%DATADIR,req.path_info) |
---|
151 | location = re.sub('.png$','',location) |
---|
152 | if not os.path.isfile(location): |
---|
153 | from mod_python import apache |
---|
154 | raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND |
---|
155 | # replace location in func |
---|
156 | cmd = re.sub('(%)?%i','%s' % location, func) |
---|
157 | # add PYTHONPATH at the beginning, |
---|
158 | cmd = "%s%s 2> /dev/null" % (PYTHONPATH,cmd) |
---|
159 | for each in runcommand(cmd): |
---|
160 | req.write("%s\n"%each) |
---|
161 | |
---|
162 | def show_task(req,task): |
---|
163 | def show_task_file(input,output,task): |
---|
164 | location = datapath_to_location(input) |
---|
165 | print_img(req,"draw_%s/%s" % (task,location)) |
---|
166 | navigation(req) |
---|
167 | req.write("<h3>%s</h3>\n" % task) |
---|
168 | apply_on_data(req,show_task_file,task=task) |
---|
169 | footer(req) |
---|
170 | |
---|
171 | ## waveform_foo |
---|
172 | def draw_sound(req): |
---|
173 | draw_func(req,"aubioplot-audio %%i stdout 2> /dev/null") |
---|
174 | |
---|
175 | def show_sound(req): |
---|
176 | show_task(req,"sound") |
---|
177 | |
---|
178 | ## pitch foo |
---|
179 | def draw_pitch(req,threshold='0.3'): |
---|
180 | draw_func(req,"aubiopitch -i %%i -p -m yin -t %s -O stdout" % threshold) |
---|
181 | |
---|
182 | def show_pitch(req): |
---|
183 | show_task(req,"pitch") |
---|
184 | |
---|
185 | ## onset foo |
---|
186 | def draw_onset(req,threshold='0.3'): |
---|
187 | draw_func(req,"aubiocut -i %%i -p -m complex -t %s -O stdout" % threshold) |
---|
188 | |
---|
189 | def show_onset(req,threshold='0.3',details=''): |
---|
190 | def onset_file(input,output): |
---|
191 | location = datapath_to_location(input) |
---|
192 | print_img(req,"draw_onset/%s?threshold=%s"%(location,threshold)) |
---|
193 | print_link(req,"?threshold=%s" % (float(threshold)-0.1),"-") |
---|
194 | req.write("%s\n" % threshold) |
---|
195 | print_link(req,"?threshold=%s" % (float(threshold)+0.1),"+") |
---|
196 | # bug: hardcoded sndfile extension |
---|
197 | anote = re.sub('\.wav$','.txt',input) |
---|
198 | if anote == input: anote = "" |
---|
199 | res = get_extract(input,threshold) |
---|
200 | if os.path.isfile(anote): |
---|
201 | tru = get_anote(anote) |
---|
202 | print_list(req,get_results(tru,res,0.05)) |
---|
203 | else: |
---|
204 | req.write("no ground truth found<br>\n") |
---|
205 | if details: |
---|
206 | req.write("<h4>Extraction</h4>\n") |
---|
207 | print_list(req,res) |
---|
208 | else: |
---|
209 | req.write("<a href='%s/show_onset/%s?details=yes&threshold=%s'>details</a><br>\n" % |
---|
210 | (req.basehref,location,threshold)) |
---|
211 | if details and os.path.isfile(anote): |
---|
212 | req.write("<h4>Computed differences</h4>\n") |
---|
213 | ldiffs = get_diffs(tru,res,0.05) |
---|
214 | print_list(req,ldiffs) |
---|
215 | req.write("<h4>Annotations</h4>\n") |
---|
216 | print_list(req,tru) |
---|
217 | navigation(req) |
---|
218 | req.write("<h3>Onset</h3>\n") |
---|
219 | apply_on_data(req,onset_file) |
---|
220 | footer(req) |
---|
221 | |
---|
222 | def get_anote(anote): |
---|
223 | import aubio.onsetcompare |
---|
224 | # FIXME: should import with txtfile.read_datafile |
---|
225 | return aubio.onsetcompare.load_onsets(anote) |
---|
226 | |
---|
227 | def get_diffs(anote,extract,tol): |
---|
228 | import aubio.onsetcompare |
---|
229 | return aubio.onsetcompare.onset_diffs(anote,extract,tol) |
---|
230 | |
---|
231 | def get_extract(datapath,threshold='0.3'): |
---|
232 | cmd = "%saubiocut -v -m complex -t %s -i %s" % (PYTHONPATH,threshold,datapath) |
---|
233 | lo = runcommand(cmd) |
---|
234 | for i in range(len(lo)): lo[i] = float(lo[i]) |
---|
235 | return lo |
---|
236 | |
---|
237 | def get_results(anote,extract,tol): |
---|
238 | import aubio.onsetcompare |
---|
239 | orig, missed, merged, expc, bad, doubled = aubio.onsetcompare.onset_roc(anote,extract,tol) |
---|
240 | s =("GD %2.8f\t" % (100*float(orig-missed-merged)/(orig)), |
---|
241 | "FP %2.8f\t" % (100*float(bad+doubled)/(orig)) , |
---|
242 | "GD-merged %2.8f\t" % (100*float(orig-missed)/(orig)) , |
---|
243 | "FP-pruned %2.8f\t" % (100*float(bad)/(orig)) ) |
---|
244 | return s |
---|
245 | |
---|
246 | # play m3u foo |
---|
247 | def play_m3u(req): |
---|
248 | def show_task_file(input,output,task): |
---|
249 | location = datapath_to_location(input) |
---|
250 | req.write("http://%s%s/play_ogg/%s\n" % (HOSTNAME,BASEHREF,re.sub("play_m3u",task,location))) |
---|
251 | req.content_type = "audio/mpegurl" |
---|
252 | parse_args(req) |
---|
253 | apply_on_data(req,show_task_file,task="play_ogg") |
---|
254 | |
---|
255 | # play wav foo |
---|
256 | def play_wav(req): |
---|
257 | req.content_type = "audio/x-wav" |
---|
258 | func = "cat %%i" |
---|
259 | # build location (strip the func_path, add DATADIR) |
---|
260 | location = re.sub('^/play_wav/','%s/'%DATADIR,req.path_info) |
---|
261 | if not os.path.isfile(location): |
---|
262 | from mod_python import apache |
---|
263 | raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND |
---|
264 | # replace location in func |
---|
265 | cmd = re.sub('(%)?%i','%s' % location, func) |
---|
266 | # add PYTHONPATH at the beginning, |
---|
267 | cmd = "%s 2> /dev/null" % cmd |
---|
268 | for each in runcommand(cmd): |
---|
269 | req.write("%s\n"%each) |
---|
270 | |
---|
271 | # play ogg foo |
---|
272 | def play_ogg(req): |
---|
273 | req.content_type = "application/ogg" |
---|
274 | func = "oggenc -o - %%i" |
---|
275 | # build location (strip the func_path, add DATADIR) |
---|
276 | location = re.sub('^/play_ogg/','%s/'%DATADIR,req.path_info) |
---|
277 | location = re.sub('.ogg$','',location) |
---|
278 | if not os.path.isfile(location): |
---|
279 | from mod_python import apache |
---|
280 | raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND |
---|
281 | # replace location in func |
---|
282 | cmd = re.sub('(%)?%i','%s' % location, func) |
---|
283 | # add PYTHONPATH at the beginning, |
---|
284 | cmd = "%s 2> /dev/null" % cmd |
---|
285 | for each in runcommand(cmd): |
---|
286 | req.write("%s\n"%each) |
---|