Chris@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@0: Sonic Annotator Chris@0: A utility for batch feature extraction from audio files. Chris@0: Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. Chris@0: Copyright 2007-2008 QMUL. Chris@0: Chris@0: This program is free software; you can redistribute it and/or Chris@0: modify it under the terms of the GNU General Public License as Chris@0: published by the Free Software Foundation; either version 2 of the Chris@0: License, or (at your option) any later version. See the file Chris@0: COPYING included with this distribution for more information. Chris@0: */ Chris@0: Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@45: #include Chris@0: Chris@0: using std::cout; Chris@0: using std::cerr; Chris@0: using std::endl; Chris@0: using std::vector; Chris@0: using std::string; Chris@0: Chris@2: #include "../version.h" Chris@2: Chris@0: #include "base/Exceptions.h" Chris@0: #include "base/TempDirectory.h" Chris@111: #include "base/ProgressPrinter.h" Chris@0: Chris@0: #include "data/fileio/AudioFileReaderFactory.h" Chris@0: #include "data/fileio/PlaylistFileReader.h" Chris@0: Chris@0: #include "transform/Transform.h" Chris@0: #include "transform/TransformFactory.h" Chris@0: Chris@0: #include "FeatureExtractionManager.h" Chris@0: #include "transform/FeatureWriter.h" Chris@0: #include "FeatureWriterFactory.h" Chris@0: Chris@0: #include "rdf/RDFTransformFactory.h" Chris@0: Chris@0: #include Chris@0: Chris@0: #ifdef HAVE_FFTW3 Chris@0: #include Chris@0: #endif Chris@0: Chris@0: // Desired options: Chris@0: // Chris@0: // * output preference: Chris@0: // - all data in one file Chris@0: // - one file per input file Chris@0: // - one file per input file per transform Chris@0: // - (any use for: one file per transform?) Chris@0: // Chris@0: // * output location: Chris@0: // - same directory as input file Chris@0: // - current directory Chris@0: // Chris@0: // * output filename: Chris@0: // - based on input (obvious choice for one file per input file modes) Chris@0: // - specified on command line (obvious choice for all in one file mode) Chris@0: // Chris@0: // * output format: one or more of Chris@0: // - RDF Chris@0: // - AudioDB Chris@0: // - Vamp Simple Host format Chris@0: // - CSV Chris@0: // Chris@0: // * input handling: Chris@0: // - run each transform on each input file separately Chris@0: // - provide all input files to the same transform, one per channel Chris@0: // Chris@0: // * format-specific options: Chris@0: // - RDF format: fancy/plain RDF Chris@0: // - CSV format: separator, timestamp type Chris@0: // note: do the output file/location also count as format-specific options? Chris@0: // an output writer that wrote to a database would have different options... Chris@0: // Chris@0: // * debug level and progress output Chris@0: // Chris@0: // * other potential options: Chris@0: // - ignore version mismatches in Transform specifications Chris@0: // - sample rate: force a given rate; use file rate instead of rate in Chris@0: // Transform spec Chris@0: // Chris@0: // * other potential instructions: Chris@0: // - write out a skeleton Transform file for a specified plugin Chris@0: // - write out skeleton RDF for a plugin library (i.e. do the job of Chris@0: // RDF template_generator) Chris@0: // - verify that RDF for a plugin library matches the plugin Chris@0: // Chris@0: // MAYBE: Chris@0: // * transform(s) to run: Chris@0: // - supply transform file names on command line Chris@0: // - use all transforms found in a given directory? Chris@0: // Chris@0: // MAYBE: Chris@0: // * input files to transform: Chris@0: // - supply file names or URIs on command line Chris@0: // - use all files in a given directory or tree Chris@0: Chris@0: static QString Chris@0: wrap(QString s, int len, int pfx = 0) Chris@0: { Chris@0: QString ws; Chris@0: QStringList sl(s.split(' ')); Chris@0: int i = 0, c = 0; Chris@0: while (i < sl.size()) { Chris@0: int wl = sl[i].length(); Chris@0: if (c + wl < len) { Chris@0: if (c > 0) { Chris@0: ws += ' '; Chris@0: ++c; Chris@0: } Chris@0: } else { Chris@0: if (c > 0) { Chris@0: ws += '\n'; Chris@0: for (int j = 0; j < pfx; ++j) ws += ' '; Chris@0: c = 0; Chris@0: } Chris@0: } Chris@0: ws += sl[i]; Chris@0: c += wl; Chris@0: ++i; Chris@0: } Chris@0: return ws; Chris@0: } Chris@0: Chris@240: static QString wrapCol(QString s) { Chris@240: return wrap(s, 56, 22); Chris@240: } Chris@240: Chris@127: static bool Chris@127: isVersionNewerThan(QString a, QString b) // from VersionTester in svapp Chris@127: { Chris@127: QRegExp re("[._-]"); Chris@127: QStringList alist = a.split(re, QString::SkipEmptyParts); Chris@127: QStringList blist = b.split(re, QString::SkipEmptyParts); Chris@127: int ae = alist.size(); Chris@127: int be = blist.size(); Chris@127: int e = std::max(ae, be); Chris@127: for (int i = 0; i < e; ++i) { Chris@127: int an = 0, bn = 0; Chris@127: if (i < ae) { Chris@127: an = alist[i].toInt(); Chris@127: if (an == 0 && alist[i] != "0") { Chris@127: an = -1; // non-numeric field -> "-pre1" etc Chris@127: } Chris@127: } Chris@127: if (i < be) { Chris@127: bn = blist[i].toInt(); Chris@127: if (bn == 0 && blist[i] != "0") { Chris@127: bn = -1; Chris@127: } Chris@127: } Chris@127: if (an < bn) return false; Chris@127: if (an > bn) return true; Chris@127: } Chris@127: return false; Chris@127: } Chris@127: Chris@127: static int Chris@127: checkMinVersion(QString myname, QString v) Chris@127: { Chris@127: if (v == RUNNER_VERSION) { Chris@127: return 0; Chris@127: } else if (isVersionNewerThan(RUNNER_VERSION, v)) { Chris@127: return 0; Chris@127: } else { Chris@127: cerr << myname << ": version " Chris@127: << RUNNER_VERSION << " is less than requested min version " Chris@127: << v << ", failing" << endl; Chris@127: return 1; Chris@127: } Chris@127: } Chris@127: Chris@125: void printUsage(QString myname) Chris@0: { Chris@0: cerr << endl; Chris@2: cerr << "Sonic Annotator v" << RUNNER_VERSION << endl; Chris@0: cerr << "A utility for batch feature extraction from audio files." << endl; Chris@240: cerr << "Mark Levy, Chris Sutton, and Chris Cannam, Queen Mary, University of London." << endl; Chris@197: cerr << "Copyright 2007-2015 Queen Mary, University of London." << endl; Chris@0: cerr << endl; Chris@0: cerr << "This program is free software. You may redistribute copies of it under the" << endl; Chris@0: cerr << "terms of the GNU General Public License ." << endl; Chris@0: cerr << "This program is supplied with NO WARRANTY, to the extent permitted by law." << endl; Chris@0: cerr << endl; Chris@125: cerr << "Usage: " << endl; Chris@127: cerr << " " << myname Chris@125: << " [-mrnf] -t transform.ttl [..] -w [..]