Chris@0
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 Sonic Annotator
|
Chris@0
|
5 A utility for batch feature extraction from audio files.
|
Chris@0
|
6 Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London.
|
Chris@0
|
7 Copyright 2007-2008 QMUL.
|
Chris@0
|
8
|
Chris@0
|
9 This program is free software; you can redistribute it and/or
|
Chris@0
|
10 modify it under the terms of the GNU General Public License as
|
Chris@0
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@0
|
12 License, or (at your option) any later version. See the file
|
Chris@0
|
13 COPYING included with this distribution for more information.
|
Chris@0
|
14 */
|
Chris@0
|
15
|
Chris@0
|
16 #include <iostream>
|
Chris@0
|
17 #include <map>
|
Chris@0
|
18
|
Chris@0
|
19 using namespace std;
|
Chris@0
|
20
|
Chris@0
|
21 #include "DefaultFeatureWriter.h"
|
Chris@0
|
22
|
Chris@325
|
23 #include <QTextStream>
|
Chris@325
|
24 #include <QTextCodec>
|
Chris@325
|
25
|
Chris@325
|
26 DefaultFeatureWriter::DefaultFeatureWriter() :
|
Chris@325
|
27 FileFeatureWriter(SupportStdOut,
|
Chris@325
|
28 "xml")
|
Chris@325
|
29 {
|
Chris@325
|
30 }
|
Chris@325
|
31
|
Chris@325
|
32 DefaultFeatureWriter::~DefaultFeatureWriter()
|
Chris@325
|
33 {
|
Chris@325
|
34 }
|
Chris@325
|
35
|
Chris@144
|
36 string
|
Chris@144
|
37 DefaultFeatureWriter::getDescription() const
|
Chris@144
|
38 {
|
Chris@144
|
39 return "Write features in a generic XML format, with <feature> or <summary> elements containing output name and some or all of timestamp, duration, values, and label.";
|
Chris@144
|
40 }
|
Chris@144
|
41
|
Chris@325
|
42 static QString
|
Chris@325
|
43 toQStringAsStream(const RealTime &rt)
|
Chris@325
|
44 {
|
Chris@325
|
45 // just for historical compatibility, get the same formatting as
|
Chris@325
|
46 // when streaming to an iostream
|
Chris@325
|
47 std::stringstream out;
|
Chris@325
|
48 out << rt;
|
Chris@325
|
49 std::string s = out.str();
|
Chris@325
|
50 return QString::fromStdString(s);
|
Chris@325
|
51 }
|
Chris@325
|
52
|
Chris@325
|
53 void DefaultFeatureWriter::write(QString trackId,
|
Chris@325
|
54 const Transform &transform,
|
Chris@0
|
55 const Vamp::Plugin::OutputDescriptor& output,
|
Chris@325
|
56 const Vamp::Plugin::FeatureList& features,
|
Chris@0
|
57 std::string summaryType)
|
Chris@0
|
58 {
|
Chris@325
|
59 // Select appropriate output file for our track/transform
|
Chris@325
|
60 // combination
|
Chris@325
|
61
|
Chris@325
|
62 TransformId transformId = transform.getIdentifier();
|
Chris@325
|
63
|
Chris@325
|
64 QTextStream *sptr = getOutputStream
|
Chris@325
|
65 (trackId, transformId, QTextCodec::codecForName("UTF-8"));
|
Chris@325
|
66 if (!sptr) {
|
Chris@325
|
67 throw FailedToOpenOutputStream(trackId, transformId);
|
Chris@325
|
68 }
|
Chris@325
|
69
|
Chris@325
|
70 QTextStream &stream = *sptr;
|
Chris@325
|
71
|
Chris@325
|
72 int n = int(features.size());
|
Chris@325
|
73
|
Chris@325
|
74 if (n == 0) return;
|
Chris@0
|
75
|
Chris@325
|
76 /* we write a generic XML output of the form
|
Chris@0
|
77
|
Chris@325
|
78 <feature>
|
Chris@325
|
79 <name>output.name</name>
|
Chris@325
|
80 <timestamp>feature.timestamp</timestamp>
|
Chris@325
|
81 <values>output.binName[0]:feature.value[0]...</values>
|
Chris@325
|
82 <label>feature.label</label>
|
Chris@325
|
83 </feature>
|
Chris@0
|
84 */
|
Chris@0
|
85
|
Chris@325
|
86 for (int i = 0; i < n; ++i) {
|
Chris@0
|
87 if (summaryType == "") {
|
Chris@325
|
88 stream << "<feature>" << endl;
|
Chris@0
|
89 } else {
|
Chris@325
|
90 stream << "<summary type=\"" << QString::fromStdString(summaryType)
|
Chris@325
|
91 << "\">" << endl;
|
Chris@0
|
92 }
|
Chris@325
|
93 stream << "\t<name>" << QString::fromStdString(output.name)
|
Chris@325
|
94 << "</name>" << endl;
|
Chris@325
|
95 if (features[i].hasTimestamp) {
|
Chris@325
|
96 stream << "\t<timestamp>"
|
Chris@325
|
97 << toQStringAsStream(features[i].timestamp)
|
Chris@325
|
98 << "</timestamp>" << endl;
|
Chris@0
|
99 }
|
Chris@325
|
100 if (features[i].hasDuration) {
|
Chris@325
|
101 stream << "\t<duration>"
|
Chris@325
|
102 << toQStringAsStream(features[i].duration)
|
Chris@325
|
103 << "</duration>" << endl;
|
Chris@0
|
104 }
|
Chris@325
|
105 if (features[i].values.size() > 0)
|
Chris@0
|
106 {
|
Chris@325
|
107 stream << "\t<values>";
|
Chris@325
|
108 for (int j = 0; j < (int)features[i].values.size(); ++j) {
|
Chris@325
|
109 if (j > 0) {
|
Chris@325
|
110 stream << " ";
|
Chris@325
|
111 }
|
Chris@325
|
112 if (output.binNames.size() > 0) {
|
Chris@325
|
113 stream << QString::fromStdString(output.binNames[j]) << ":";
|
Chris@325
|
114 }
|
Chris@325
|
115 stream << features[i].values[j];
|
Chris@0
|
116 }
|
Chris@325
|
117 stream << "</values>" << endl;
|
Chris@0
|
118 }
|
Chris@325
|
119 if (features[i].label.length() > 0)
|
Chris@325
|
120 stream << "\t<label>"
|
Chris@325
|
121 << QString::fromStdString(features[i].label)
|
Chris@325
|
122 << "</label>" << endl;
|
Chris@0
|
123 if (summaryType == "") {
|
Chris@325
|
124 stream << "</feature>" << endl;
|
Chris@0
|
125 } else {
|
Chris@325
|
126 stream << "</summary>" << endl;
|
Chris@0
|
127 }
|
Chris@0
|
128 }
|
Chris@0
|
129 }
|