source: gs3-extensions/audioDB/trunk/src/perllib/plugins/AudioDBPlugin.pm@ 26288

Last change on this file since 26288 was 26288, checked in by davidb, 12 years ago

Plugin changed so it now also generates '.ogg' audio files (useful for Firefox playing audio with HTML5 <audio> element

File size: 7.8 KB
Line 
1###########################################################################
2#
3# AudioDBPlugin.pm -- for extracting Chroma and Power Log features to work
4# with Queen Marys audioDB
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) 2011 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###########################################################################
27
28package AudioDBPlugin;
29
30use BasePlugin;
31use FFTExtractor;
32
33use strict;
34no strict 'refs'; # allow filehandles to be variables and viceversa
35no strict 'subs';
36
37use gsprintf 'gsprintf';
38
39sub BEGIN {
40 @AudioDBPlugin::ISA = ('BasePlugin', 'FFTExtractor');
41}
42
43my $enable_streaming_list =
44 [{'name' => "disabled", 'desc' => "Do not create any video file optimised for streaming over the Internet."},
45 {'name' => "flv", 'desc' => "Uses the FLV format for streaming media. Better to target old computers."},
46 {'name' => "mp4", 'desc' => "Uses the MP4 container with H264 and AAC codecs. Better quality at very low bitrates but more ressources intensive."},
47 {'name' => "mp3", 'desc' => "(audio only) Uses MP3 for psuedo streaming."}
48 ];
49
50my $streaming_mime_types = { "flv" => "video/flv",
51 "mp4" => "video/mp4",
52 "mp3" => "audio/mpeg" };
53
54my $arguments =
55 [
56 { 'name' => "compute_fft_features",
57 'desc' => "{FFTExtractor.compute_fft_features}",
58 'type' => "enum",
59 'list' => [{'name' => "true", 'desc' => "{common.true}"},
60 {'name' => "false", 'desc' => "{common.false}"}],
61 'deft' => "false",
62 'reqd' => "no" },
63 { 'name' => "process_exp",
64 'desc' => "{BasePlugin.process_exp}",
65 'type' => "regexp",
66 'deft' => &get_default_process_exp(),
67 'reqd' => "no" },
68
69 { 'name' => "enable_streaming",
70 'desc' => "{MultimediaPlug.enable_streaming}",
71 'type' => "enum",
72 'list' => $enable_streaming_list,
73 'deft' => "disabled",
74 'reqd' => "no" }
75 ];
76
77my $options = { 'name' => "AudioDBPlugin",
78 'desc' => "{AudioDBPlugin.desc}",
79 'abstract' => "no",
80 'inherits' => "yes",
81 'args' => $arguments };
82
83
84
85sub new {
86 my ($class) = shift (@_);
87 my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
88 push(@$pluginlist, $class);
89
90 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
91 push(@{$hashArgOptLists->{"OptList"}},$options);
92
93 my $ffte_self = new FFTExtractor($pluginlist, $inputargs, $hashArgOptLists,1);
94
95 my $jsme_self = undef;
96 eval("require MusicIRPlugin");
97 if ($@) {
98 # Useful debugging statement below if there is a syntax error in the plugin
99 # and you expecting jSongMinerExtractor to be found
100 # print STDERR "$@\n";
101 }
102 else {
103 print STDERR "Dynamically loading jSongMinerExtractor\n";
104 push(@AudioDBPlugin::ISA,"MusicIRPlugin");
105 $jsme_self = new MusicIRPlugin($pluginlist, $inputargs, $hashArgOptLists);
106 }
107
108 my $base_self = new BasePlugin($pluginlist, $inputargs, $hashArgOptLists);
109
110 my $self = BasePlugin::merge_inheritance($ffte_self,$jsme_self,$base_self);
111
112 $self->{'jSongMinerExtractor-found'} = (defined $jsme_self) ? 1 : 0;
113
114 return bless $self, $class;
115}
116
117sub get_default_process_exp {
118 my $self = shift (@_);
119
120 return q^(?i)(\.mp3|\.wave?|\.aif[fc]?|\.au|\.snd|\.og[ga])$^;
121}
122
123sub begin {
124 my $self = shift (@_);
125 my ($pluginfo, $base_dir, $processor, $maxdocs) = @_;
126
127 $self->SUPER::begin(@_);
128 $self->FFTExtractor::begin(@_);
129}
130
131
132
133# do plugin specific processing of doc_obj
134sub process {
135 my $self = shift (@_);
136 my ($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli) = @_;
137
138 my $outhandle = $self->{'outhandle'};
139 my ($filename_full_path, $filename_no_path) = &util::get_full_filenames($base_dir, $file);
140
141 my $top_section = $doc_obj->get_top_section();
142
143 # associate original file
144 # if filename ext not .wav convert (optionally cached) to wav
145
146
147 my ($input_ext) = ($filename_full_path =~ m/\.(.*?)$/);
148 $input_ext = lc($input_ext);
149
150
151 my $wav_filename;
152 if ($input_ext ne "wav") {
153 $wav_filename = $self->convert_audio_format($filename_full_path,"wav");
154 }
155 else {
156 $wav_filename = $filename_full_path;
157 }
158 $doc_obj->associate_file($wav_filename, "doc.wav", "audio/wav", $top_section);
159
160 my $ogg_filename;
161 if ($input_ext ne "ogg") {
162 $ogg_filename = $self->convert_audio_format($filename_full_path,"ogg", "-acodec libvorbis");
163 # $ogg_filename = $self->convert_audio_format($filename_full_path,"ogg", "-acodec libvorbis -ab 160000");
164 }
165 else {
166 $ogg_filename = $filename_full_path;
167 }
168 $doc_obj->associate_file($ogg_filename, "doc.ogg", "audio/ogg", $top_section);
169
170
171 if ($self->{'enable_streaming'} ne "disabled") {
172
173 my $streamable_ext = lc($self->{'enable_streaming'});
174 my $streamable_filename;
175
176 if ($input_ext ne $streamable_ext) {
177 # make streamable version
178 $streamable_filename
179 = $self->convert_audio_format($filename_full_path,$streamable_ext);
180 }
181 else {
182 $streamable_filename = $filename_full_path;
183 }
184
185 $doc_obj->associate_file($streamable_filename,
186 "doc.$streamable_ext",
187 $streaming_mime_types->{$streamable_ext},
188 $top_section);
189
190 }
191
192 #
193 # Opportunity here to segment, use beat-tracking ...
194 #
195
196 if ($self->{'compute_fft_features'} eq "true")
197 {
198 # compute chroma 12 and associate file
199 my $chr12_filename = $self->compute_fft_features($wav_filename,"chroma");
200 $doc_obj->associate_file($chr12_filename, "doc.chr12",
201 "text/plain", $top_section);
202
203 # compute power log and associate file
204 my $powerlog_filename = $self->compute_fft_features($wav_filename,"power-log");
205 $doc_obj->associate_file($powerlog_filename, "doc.power",
206 "text/plain", $top_section);
207 }
208
209
210 if ($self->{'jSongMinerExtractor-found'}) {
211 # calling this version of process has the side effect of setting dummy text
212 $self->MusicIRPlugin::process($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli);
213 }
214 else {
215 #we have no text - adds dummy text and NoText metadata
216 $self->add_dummy_text($doc_obj, $doc_obj->get_top_section());
217 }
218
219 return 1;
220}
221
222
223
224sub post_process_doc_obj {
225 my $self = shift (@_);
226 my ($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli) = @_;
227
228 my $outhandle = $self->{'outhandle'};
229 my ($filename_full_path, $filename_no_path) = &util::get_full_filenames($base_dir, $file);
230
231 # Opportunity to use jAudioMinerExtractor if dynamically and loaded
232 #
233 if ($self->{'retrieve_mir_metadata'} eq "true") {
234 my $top_section = $doc_obj->get_top_section();
235
236 my $id3_titles = $doc_obj->get_metadata($top_section,"ex.ID3.Title");
237 # my $id3_title = shift @$id3_titles || "Unknown";
238 my $id3_title = shift @$id3_titles || undef;
239
240 my $id3_artists = $doc_obj->get_metadata($top_section,"ex.ID3.Artist");
241 # my $id3_artist = shift @$id3_artists || "Unknown";
242 my $id3_artist = shift @$id3_artists || undef;
243
244 my ($metadata_acexml_filename,$metadata_txt_filename)
245 = $self->retrieve_metadata($filename_full_path,$id3_title,$id3_artist);
246
247 if (-e $metadata_txt_filename) {
248 $self->parse_txt_metadata($doc_obj,$metadata_txt_filename);
249 }
250
251 $doc_obj->associate_file($metadata_acexml_filename, "jsongminer.xml",
252 "text/xml", $top_section);
253 }
254
255
256 return 1;
257}
258
259
2601;
261
262
263
Note: See TracBrowser for help on using the repository browser.