source: gs2-extensions/music-ir-src/trunk/perllib/plugins/jAudioExtractor.pm@ 28471

Last change on this file since 28471 was 28471, checked in by davidb, 11 years ago

Change to use new java support methods in util.pm to help operation under Cygwin

  • Property svn:executable set to *
File size: 10.1 KB
Line 
1###########################################################################
2#
3# jAudioExtractor - helper plugin that computers audio features for
4# music information retrieval use, using jAudio
5#
6# A component of the Greenstone digital library software
7# from the New Zealand Digital Library Project at the
8# University of Waikato, New Zealand.
9#
10# Copyright (C) 2010 New Zealand Digital Library Project
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by
14# the Free Software Foundation; either version 2 of the License, or
15# (at your option) any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program; if not, write to the Free Software
24# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25#
26###########################################################################
27package jAudioExtractor;
28
29use BaseMediaConverter;
30
31use Cwd;
32
33use FileUtils;
34
35use strict;
36no strict 'refs'; # allow filehandles to be variables and viceversa
37
38
39BEGIN {
40 @jAudioExtractor::ISA = ('BaseMediaConverter');
41}
42
43
44my $arguments = [
45 { 'name' => "window_size",
46 'desc' => "{jAudioExtractor.window_size}",
47 'type' => "int",
48 'range' => "128,",
49 'deft' => '512',
50 'reqd' => "no" },
51 { 'name' => "window_overlap",
52 'desc' => "{jAudioExtractor.window_overlap}",
53 'type' => "string",
54 'range' => "0.0",
55 'deft' => '0.0',
56 'reqd' => "no" },
57 { 'name' => "sample_rate",
58 'desc' => "{jAudioExtractor.sample_rate}",
59 'type' => "enum",
60 'list' => [{'name' => "8 kHz", 'desc' => "{jAudioExtractor.8000Hz}"},
61 {'name' => "11.025 kHz", 'desc' => "{jAudioExtractor.11025Hz}"},
62 {'name' => "16 kHz", 'desc' => "{jAudioExtractor.16000Hz}"},
63 {'name' => "22.05 kHz", 'desc' => "{jAudioExtractor.22050Hz}"},
64 {'name' => "44.1 kHz", 'desc' => "{jAudioExtractor.44100Hz}"} ],
65 'deft' => '16 kHz',
66 'reqd' => "no" },
67 { 'name' => "extracted_data",
68 'desc' => "{jAudioExtractor.extracted_data}",
69 'type' => "enum",
70 'list' => [{'name' => "Overall and Windowed", 'desc' => "{jAudioExtractor.overall_and_windowed}"},
71 {'name' => "Windowed only", 'desc' => "{jAudioExtractor.windowed_only}"},
72 {'name' => "Overall only", 'desc' => "{jAudioExtractor.overall_only}"}],
73 'deft' => 'Overall and Windowed',
74 'reqd' => "no" },
75 { 'name' => "output_type",
76 'desc' => "{jAudioExtractor.output_type}",
77 'type' => "enum",
78 'list' => [{'name' => "ACE XML", 'desc' => "{jAudioExtractor.ace_xml}"},
79 {'name' => "Weka ARFF", 'desc' => "{jAudioExtractor.weka_arff}"}],
80 'deft' => 'ACE XML',
81 'reqd' => "no" }
82 ];
83
84
85
86my $options = { 'name' => "jAudioExtractor",
87 'desc' => "{jAudioExtractor.desc}",
88 'abstract' => "yes",
89 'inherits' => "yes",
90 'args' => $arguments };
91
92sub new {
93 my ($class) = shift (@_);
94 my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
95 push(@$pluginlist, $class);
96
97 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
98 push(@{$hashArgOptLists->{"OptList"}},$options);
99
100 my $self = new BaseMediaConverter($pluginlist, $inputargs, $hashArgOptLists, 1);
101
102 # Set controlling variables
103 my $gsdl_home = $ENV{'GSDLHOME'};
104 my $music_ir_home = $ENV{'GEXT_MUSICIR'};
105
106 my $ace_xml_output_directory = &util::filename_cat($gsdl_home,"tmp"); # Set the directory to save the the ACE XML output files in
107 if (!FileUtils::directoryExists($ace_xml_output_directory)) {
108 FileUtils::makeDirectory($ace_xml_output_directory);
109 }
110 $self->{'ace_xml_output_directory'} = $ace_xml_output_directory;
111
112 $self->{'jmir_directory'} = &util::filename_cat($music_ir_home,"lib","java"); # Set the directory holding the jMIR .jar files
113
114
115
116 return bless $self, $class;
117}
118
119
120# Create and save a temporary jAudio batch file referring to a file to extract
121# features from
122sub prepareTempJAudioBatchFile
123{
124 # ARG Ob1: $new_batch_file_path refers to the path of the temporary batch file to create
125 # ARG Ob2: $model_batch_file_path refers to the path of the model batch file to base the temporary one on
126 # ARG Ob3: $input_music_file_path refers to the file to extract features with
127 # ARG Ob4: $feature_values_file_path refers to the path of the ACE XML Feature Values file that the jMIR component will output to
128 # ARG Ob5: $feature_values_file_path refers to the path of the ACE XML Feature Descriptions file that the jMIR component will output to
129 my ( $self, $new_batch_file_path, $model_batch_file_path, $input_music_file_path, $feature_values_file_path, $feature_descriptions_file_path ) = @_;
130
131 # Retrieve settings for jAudioPlugin and use in batch file that is generated
132 my $sample_rate = $self->{'sample_rate'}; # sample of how to get parameter from Greenstone/GLI
133
134
135 # Read the contents of the model batch file
136 my $batch_file_contents;
137 local $/=undef;
138 open (INPUT, "$model_batch_file_path") or die "Could not read the model jAudio batch file $model_batch_file_path";
139 binmode INPUT;
140 $batch_file_contents = <INPUT>;
141 close INPUT;
142
143 # Set the batch ID tag in the temporary file
144 $batch_file_contents =~ s/<batch ID="SampleJAudioBatch">/<batch ID="$input_music_file_path">/;
145
146 # Set the input file name in the file tag in the temporary file
147 if ($^O eq "cygwin") {
148 $input_music_file_path = `cygpath -m "$input_music_file_path"`;
149 $input_music_file_path=~ s/\s+$//;
150 }
151 $batch_file_contents =~ s/<file><\/file>/<file>$input_music_file_path<\/file>/;
152
153 # Set the feature vales save path in the temporary file
154 if ($^O eq "cygwin") {
155 $feature_descriptions_file_path = `cygpath -m "$feature_descriptions_file_path"`;
156 $feature_descriptions_file_path=~ s/\s+$//;
157 }
158
159 $batch_file_contents =~ s/<destination><\/destination>/<destination>$feature_descriptions_file_path<\/destination>/;
160
161 # Set the feature vales save path in the temporary file
162 if ($^O eq "cygwin") {
163 $feature_values_file_path = `cygpath -m "$feature_values_file_path"`;
164 $feature_values_file_path=~ s/\s+$//;
165 }
166 $batch_file_contents =~ s/<destination><\/destination>/<destination>$feature_values_file_path<\/destination>/;
167
168 # Save the temporary batch file
169 open (OUTPUT, ">$new_batch_file_path") or die "Could not create the temporary jAudio batch file $new_batch_file_path";
170 print OUTPUT "$batch_file_contents";
171 close OUTPUT;
172
173 # Done
174 return 0;
175}
176
177
178sub compute_features
179{
180 my $self = shift(@_);
181 my $source_file_path = shift(@_);
182 my $convert_options = shift(@_) || "";
183
184 my $outhandle = $self->{'outhandle'};
185 my $verbosity = $self->{'verbosity'};
186
187 my $source_file_no_path = &File::Basename::basename($source_file_path);
188
189 $self->init_cache_for_file($source_file_path);
190
191 # Determine the full name and path of the output file
192 my $target_file_path;
193 my $feature_values_file_path;
194 my $feature_descriptions_file_path;
195
196 my $target_file_type;
197 if ($self->{'output_type'} eq "ACE XML") {
198 $target_file_type="xml";
199 }
200 else {
201 # ARFF
202 $target_file_type="arff";
203 }
204
205 if ($self->{'enable_cache'}) {
206 my $cached_dir = $self->{'cached_dir'};
207 my $file_root = $self->{'cached_file_root'};
208
209 my $target_file = "$file_root.$target_file_type";
210
211 $target_file_path = &util::filename_cat($cached_dir,$target_file);
212 }
213 else {
214 $target_file_path = &util::get_tmp_filename($target_file_type);
215 }
216
217 if ($self->{'output_type'} eq "ACE XML") {
218 $feature_values_file_path = $target_file_path;
219 $feature_values_file_path =~ s/\.xml$/_FV.xml/;
220
221 $feature_descriptions_file_path = $target_file_path;
222 $feature_descriptions_file_path =~ s/\.xml$/_FD.xml/;
223
224 # Make target_file_path be the principle file generated by jAudio when using ACE XML
225 $target_file_path = $feature_values_file_path;
226 }
227
228 my $ace_xml_output_directory = $self->{'ace_xml_output_directory'};
229 my $jmir_directory = $self->{'jmir_directory'};
230
231
232 my $store_cwd = cwd();
233
234 if (!-d $jmir_directory) {
235 print STDERR "Error: Unable able to find directory '$jmir_directory'\n";
236 print STDERR " Cannot run jAudio\n";
237 }
238 elsif (chdir($jmir_directory)) {
239
240 # Run the feature extraction.
241
242 # Specify the name for a temporary jAudio batch file
243 my $template_batch_file_path = &util::filename_cat($jmir_directory,"SampleJAudioBatchFile.xml.in");
244 my $batch_file_path = &util::filename_cat($ace_xml_output_directory,"tempjaudiobatchfile.xml");
245
246 # Create the batch file
247 $self->prepareTempJAudioBatchFile( $batch_file_path, $template_batch_file_path,
248 $source_file_path, $feature_values_file_path, $feature_descriptions_file_path );
249
250 # Input and Output files to use are stored in the batch_file
251 my $batch_file_path_os = $batch_file_path;
252
253 $batch_file_path_os = &util::makeFilenameJavaCygwinCompatible($batch_file_path_os);
254# if ($^O eq "cygwin") {
255# $batch_file_path_os = `cygpath -w "$batch_file_path"`;
256# $batch_file_path_os =~ s/\s+$//;
257# }
258
259 my $jaudio_cmd = "java -Xmx1024M -jar jAudio.jar $convert_options -b \"$batch_file_path_os\"";
260
261 # Test the execution path
262 # print("EXECUTION CMD: $jaudio_cmd\n");
263
264 my $print_info = { 'message_prefix' => "jAudio",
265 'message' => "Extracting audio features from $source_file_no_path" };
266
267 my ($regenerated,$result,$had_error)
268 = $self->autorun_general_cmd($jaudio_cmd,$source_file_path,$target_file_path,$print_info);
269
270 # Delete the jAudio batch file
271 unlink($batch_file_path);
272 }
273 else {
274 print STDERR "Error: failed to change directory to '$jmir_directory'\n";
275 print STDERR " Cannot run jAudio\n";
276 }
277
278 chdir($store_cwd);
279
280 return ($target_file_path);
281}
282
283
284
285
2861;
Note: See TracBrowser for help on using the repository browser.