diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-10-18 18:55:31 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-10-18 18:55:31 +0000 |
commit | dc521b5d48e11fbccbea07b450e21f63c28066ef (patch) | |
tree | 2c9be086996b587496c468fcbd3cbaad80ff3e77 /utils/parse_testcodec.rb | |
parent | df867fa44cfb492dac8537ba3cce090404378ef4 (diff) | |
download | rockbox-dc521b5d48e11fbccbea07b450e21f63c28066ef.tar.gz rockbox-dc521b5d48e11fbccbea07b450e21f63c28066ef.zip |
Replace parse_testcodec.pl with a bit more powerful script.
It can compare more than one result file at a time giving additional speedup colums, is more robust
(RaaA results don't have the "MHz needed for realtime" line which is handled with this one) and
has a mode to output the results in a form readable by spreadsheet software for nice graphs.
Needs Ruby 1.9.x
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28305 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/parse_testcodec.rb')
-rwxr-xr-x | utils/parse_testcodec.rb | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/utils/parse_testcodec.rb b/utils/parse_testcodec.rb new file mode 100755 index 0000000000..9a2a6e9170 --- /dev/null +++ b/utils/parse_testcodec.rb | |||
@@ -0,0 +1,284 @@ | |||
1 | #!/usr/bin/ruby | ||
2 | # (c) 2010 by Thomas Martitz | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation; either version 2 of the License, or | ||
7 | # (at your option) any later version. | ||
8 | |||
9 | # | ||
10 | # parse test codec output files and give wiki or spreadsheet formatted output | ||
11 | # | ||
12 | class CodecResult | ||
13 | include Comparable | ||
14 | private | ||
15 | |||
16 | attr_writer :codec | ||
17 | attr_writer :decoded_frames | ||
18 | attr_writer :max_frames | ||
19 | attr_writer :decode_time | ||
20 | attr_writer :file_duration | ||
21 | attr_writer :percent_realtime | ||
22 | attr_writer :mhz_needed | ||
23 | |||
24 | def get_codec(filename) | ||
25 | case filename | ||
26 | when /.+aache.+/, /nero_he_.+/ | ||
27 | self.codec = "Nero AAC-HE" | ||
28 | when /a52.+/ | ||
29 | self.codec = "AC3 (A52)" | ||
30 | when /ape_.+/ | ||
31 | self.codec = "Monkey Audio" | ||
32 | when /lame_.+/ | ||
33 | self.codec = "MP3" | ||
34 | when /.+\.m4a/ | ||
35 | self.codec = "AAC-LC" | ||
36 | when /vorbis.+/ | ||
37 | self.codec = "Vorbis" | ||
38 | when /wma_.+/ | ||
39 | self.codec = "WMA Standard" | ||
40 | when /wv_.+/ | ||
41 | self.codec = "WAVPACK" | ||
42 | when /applelossless.+/ | ||
43 | self.codec = "Apple Lossless" | ||
44 | when /mpc_.+/ | ||
45 | self.codec = "Musepack" | ||
46 | when /flac_.+/ | ||
47 | self.codec = "FLAC" | ||
48 | when /cook_.+/ | ||
49 | self.codec = "Cook (RA)" | ||
50 | when /atrac3.+/ | ||
51 | self.codec = "Atrac3" | ||
52 | when /true.+/ | ||
53 | self.codec = "True Audio" | ||
54 | when /toolame.+/ | ||
55 | self.codec = "MP2" | ||
56 | when /atrack1.+/ | ||
57 | self.codec = "Atrac1" | ||
58 | when /wmapro.+/ | ||
59 | self.codec = "WMA Professional" | ||
60 | when /wmal.+/ | ||
61 | self.codec = "WMA Lossless" | ||
62 | when /speex.+/ | ||
63 | self.codec = "Speex" | ||
64 | else | ||
65 | self.codec = "CODEC UNKNOWN (#{name})" | ||
66 | end | ||
67 | end | ||
68 | |||
69 | def file_name=(name) | ||
70 | @file_name = name | ||
71 | get_codec(name) | ||
72 | end | ||
73 | |||
74 | public | ||
75 | |||
76 | attr_reader :file_name | ||
77 | attr_reader :codec | ||
78 | attr_reader :decoded_frames | ||
79 | attr_reader :max_frames | ||
80 | attr_reader :decode_time | ||
81 | attr_reader :file_duration | ||
82 | attr_reader :percent_realtime | ||
83 | attr_reader :mhz_needed | ||
84 | |||
85 | # make results comparable, allows for simple faster/slower/equal | ||
86 | def <=>(other) | ||
87 | if self.file_name != other.file_name | ||
88 | raise ArgumentError, "Cannot compare different files" | ||
89 | end | ||
90 | return self.decode_time <=> other.decode_time | ||
91 | end | ||
92 | |||
93 | def initialize(text_block, cpu_freq = nil) | ||
94 | # we need an Array | ||
95 | c = text_block.class | ||
96 | if (c != Array && c.superclass != Array) | ||
97 | raise ArgumentError, | ||
98 | "Argument must be an array but is " + text_block.class.to_s | ||
99 | end | ||
100 | |||
101 | #~ lame_192.mp3 | ||
102 | #~ 175909 of 175960 | ||
103 | #~ Decode time - 8.84s | ||
104 | #~ File duration - 175.96s | ||
105 | #~ 1990.49% realtime | ||
106 | #~ 30.14MHz needed for realtime (not there in RaaA) | ||
107 | |||
108 | # file name | ||
109 | self.file_name = text_block[0] | ||
110 | |||
111 | # decoded & max frames | ||
112 | test = Regexp.new(/(\d+) of (\d+)/) | ||
113 | res = text_block[1].match(test) | ||
114 | self.decoded_frames = res[1].to_i | ||
115 | self.max_frames = res[2].to_i | ||
116 | |||
117 | # decode time, in centiseconds | ||
118 | test = Regexp.new(/Decode time - ([.\d]+)s/) | ||
119 | self.decode_time = text_block[2].match(test)[1].to_f | ||
120 | |||
121 | # file duration, in centiseconds | ||
122 | test = Regexp.new(/File duration - ([.\d]+)s/) | ||
123 | self.file_duration = text_block[3].match(test)[1].to_f | ||
124 | |||
125 | # % realtime | ||
126 | self.percent_realtime = text_block[4].to_f | ||
127 | |||
128 | # MHz needed for rt | ||
129 | test = Regexp.new(/[.\d]+MHz needed for realtime/) | ||
130 | self.mhz_needed = nil | ||
131 | if (text_block[5] != nil && text_block[5].length > 0) | ||
132 | self.mhz_needed = text_block[5].match(test)[1].to_f | ||
133 | elsif (cpu_freq) | ||
134 | # if not given, calculate it as per passed cpu frequency | ||
135 | # duration to microseconds | ||
136 | speed = self.file_duration / self.decode_time | ||
137 | self.mhz_needed = cpu_freq / speed | ||
138 | end | ||
139 | end | ||
140 | end | ||
141 | |||
142 | class TestCodecResults < Array | ||
143 | def initialize(file_name, cpu_freq) | ||
144 | super() | ||
145 | temp = self.clone | ||
146 | # go through the results, create a CodecResult for each block | ||
147 | # of text (results for the codecs are seperated by an empty line) | ||
148 | File.open(file_name, File::RDONLY) do |file| | ||
149 | file.each_chomp do |line| | ||
150 | if (line.length == 0) then | ||
151 | self << CodecResult.new(temp, cpu_freq);temp.clear | ||
152 | else | ||
153 | temp << line | ||
154 | end | ||
155 | end | ||
156 | end | ||
157 | end | ||
158 | |||
159 | # sort the results by filename (so files of the same codec are near) | ||
160 | def sort | ||
161 | super { |x, y| x.file_name <=> y.file_name } | ||
162 | end | ||
163 | end | ||
164 | |||
165 | class File | ||
166 | # walk through each line but have the \n removed | ||
167 | def each_chomp | ||
168 | self.each_line do |line| | ||
169 | yield(line.chomp) | ||
170 | end | ||
171 | end | ||
172 | end | ||
173 | |||
174 | class Float | ||
175 | alias_method(:old_to_s, :to_s) | ||
176 | # add the ability to use a different decimal seperator in to_s | ||
177 | def to_s | ||
178 | string = old_to_s | ||
179 | string.sub!(/[.]/ , @@dec_sep) if @@dec_sep | ||
180 | string | ||
181 | end | ||
182 | |||
183 | @@dec_sep = nil | ||
184 | def self.decimal_seperator=(sep) | ||
185 | @@dec_sep=sep | ||
186 | end | ||
187 | end | ||
188 | |||
189 | #files is an Array of TestCodecResultss | ||
190 | def for_calc(files) | ||
191 | files[0].each_index do |i| | ||
192 | string = files[0][i].file_name + "\t" | ||
193 | for f in files | ||
194 | string += f[i].percent_realtime.to_s + "%\t" | ||
195 | end | ||
196 | puts string | ||
197 | end | ||
198 | end | ||
199 | |||
200 | #files is an Array of TestCodecResultss | ||
201 | def for_wiki(files) | ||
202 | basefile = files.shift | ||
203 | codec = nil | ||
204 | basefile.each_index do |i| res = basefile[i] | ||
205 | # make a joined row for each codec | ||
206 | if (codec == nil || res.codec != codec) then | ||
207 | codec = res.codec | ||
208 | puts "| *%s* ||||%s" % [codec, "|"*files.length] | ||
209 | end | ||
210 | row = sprintf("| %s | %.2f%%%% realtime | Decode time - %.2fs |" % | ||
211 | [res.file_name, res.percent_realtime, res.decode_time]) | ||
212 | if (res.mhz_needed != nil) # column for mhz needed, | - | if unknown | ||
213 | row += sprintf(" %.2fMHz |" % res.mhz_needed.to_s) | ||
214 | else | ||
215 | row += " - |" | ||
216 | end | ||
217 | for f in files # calculate speed up compared to the rest files | ||
218 | delta = (res.percent_realtime / f[i].percent_realtime)*100 | ||
219 | row += sprintf(" %.2f%%%% |" % delta) | ||
220 | end | ||
221 | puts row | ||
222 | end | ||
223 | end | ||
224 | |||
225 | # for_xml() anyone? :) | ||
226 | |||
227 | def help | ||
228 | puts "#{$0} [OPTIONS] FILE [FILES]..." | ||
229 | puts "Options:\t-w\tOutput in Fosswiki format (default)" | ||
230 | puts "\t\t-c\tOutput in Spreadsheet-compatible format (tab-seperated)" | ||
231 | puts "\t\t-s=MHZ\tAssume MHZ cpu frequency for \"MHz needed for realtime\" calculation" | ||
232 | puts "\t\t\t(if not given by the log files, e.g. for RaaA)" | ||
233 | puts "\t\t-d=CHAR\tUse CHAR as decimal seperator in the -c output" | ||
234 | puts "\t\t\t(if your spreadsheed tool localized and making problems)" | ||
235 | puts | ||
236 | puts "\tOne file is needed. This is the basefile." | ||
237 | puts "\tIn -c output, the % realtime values of each" | ||
238 | puts "\tcodec from each file is printed on the screen onto the screen" | ||
239 | puts "\tIn -w output, a wiki table is made from the basefile with one column" | ||
240 | puts "\tfor each additional file representing relative speed of the basefile" | ||
241 | exit | ||
242 | end | ||
243 | |||
244 | to_call = method(:for_wiki) | ||
245 | mhz = nil | ||
246 | files = [] | ||
247 | |||
248 | help if (ARGV.length == 0) | ||
249 | |||
250 | ARGV.each do |e| | ||
251 | a = e.chars.to_a | ||
252 | if (a[0] == '-') # option | ||
253 | case a[1] | ||
254 | when 'c' | ||
255 | to_call = method(:for_calc) | ||
256 | when 'w' | ||
257 | to_call = method(:for_wiki) | ||
258 | when 'd' | ||
259 | if (a[2] == '=') | ||
260 | sep = a[3] | ||
261 | else | ||
262 | sep = a[2] | ||
263 | end | ||
264 | Float.decimal_seperator = sep | ||
265 | when 's' | ||
266 | if (a[2] == '=') | ||
267 | mhz = a[3..-1].join.to_i | ||
268 | else | ||
269 | mhz = a[2..-1].join.to_i | ||
270 | end | ||
271 | else | ||
272 | help | ||
273 | end | ||
274 | else # filename | ||
275 | files << e | ||
276 | end | ||
277 | end | ||
278 | |||
279 | |||
280 | tmp = [] | ||
281 | for file in files do | ||
282 | tmp << TestCodecResults.new(file, mhz).sort | ||
283 | end | ||
284 | to_call.call(tmp) # invoke selected method | ||