comparison runner/MIDIFeatureWriter.cpp @ 143:ad425b9096bd

Merge from branch 'midi'
author Chris Cannam
date Mon, 13 Oct 2014 13:53:09 +0100
parents d7a91e07ca57
children b3d73c08b6ce
comparison
equal deleted inserted replaced
138:ee56e3e9eeb5 143:ad425b9096bd
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Annotator
5 A utility for batch feature extraction from audio files.
6 Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London.
7 Copyright 2007-2014 QMUL.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "MIDIFeatureWriter.h"
17
18 using namespace std;
19 using Vamp::Plugin;
20 using Vamp::PluginBase;
21
22 #include "base/Exceptions.h"
23 #include "data/fileio/MIDIFileWriter.h"
24
25 MIDIFeatureWriter::MIDIFeatureWriter() :
26 FileFeatureWriter(SupportOneFilePerTrackTransform |
27 SupportOneFilePerTrack |
28 SupportOneFileTotal,
29 "mid")
30 {
31 }
32
33 MIDIFeatureWriter::~MIDIFeatureWriter()
34 {
35 }
36
37 MIDIFeatureWriter::ParameterList
38 MIDIFeatureWriter::getSupportedParameters() const
39 {
40 ParameterList pl = FileFeatureWriter::getSupportedParameters();
41 return pl;
42 }
43
44 void
45 MIDIFeatureWriter::setParameters(map<string, string> &params)
46 {
47 FileFeatureWriter::setParameters(params);
48 }
49
50 void
51 MIDIFeatureWriter::setTrackMetadata(QString, TrackMetadata)
52 {
53 cerr << "MIDIFeatureWriter::setTrackMetadata: not supported (yet?)" << endl;
54 }
55
56 void
57 MIDIFeatureWriter::write(QString trackId,
58 const Transform &transform,
59 const Plugin::OutputDescriptor& output,
60 const Plugin::FeatureList& features,
61 std::string /* summaryType */)
62 {
63 QString transformId = transform.getIdentifier();
64
65 QString filename = getOutputFilename(trackId, transformId);
66 if (filename == "") {
67 throw FailedToOpenOutputStream(trackId, transformId);
68 }
69
70 int sampleRate = transform.getSampleRate();
71
72 if (m_rates.find(filename) == m_rates.end()) {
73 m_rates[filename] = sampleRate;
74 }
75
76 if (m_fileTransforms[filename].find(transformId) ==
77 m_fileTransforms[filename].end()) {
78
79 // This transform is new to the file, give it a channel number
80
81 int channel = m_nextChannels[filename];
82 m_nextChannels[filename] = channel + 1;
83
84 m_fileTransforms[filename].insert(transformId);
85 m_channels[transformId] = channel;
86 }
87
88 NoteList notes = m_notes[filename];
89
90 bool freq = (output.unit == "Hz" ||
91 output.unit == "hz" ||
92 output.unit == "HZ");
93
94 for (int i = 0; i < (int)features.size(); ++i) {
95
96 const Plugin::Feature &feature(features[i]);
97
98 Vamp::RealTime timestamp = feature.timestamp;
99 int frame = Vamp::RealTime::realTime2Frame(timestamp, sampleRate);
100
101 int duration = 1;
102 if (feature.hasDuration) {
103 duration = Vamp::RealTime::realTime2Frame(feature.duration, sampleRate);
104 }
105
106 int pitch = 60;
107 if (feature.values.size() > 0) {
108 float pval = feature.values[0];
109 if (freq) {
110 pitch = Pitch::getPitchForFrequency(pval);
111 } else {
112 pitch = int(pval + 0.5);
113 }
114 }
115
116 int velocity = 100;
117 if (feature.values.size() > 1) {
118 float vval = feature.values[1];
119 if (vval < 128) {
120 velocity = int(vval + 0.5);
121 }
122 }
123
124 NoteData note(frame, duration, pitch, velocity);
125
126 note.channel = m_channels[transformId];
127
128 notes.push_back(note);
129 }
130
131 m_notes[filename] = notes;
132 }
133
134 void
135 MIDIFeatureWriter::finish()
136 {
137 for (NoteMap::const_iterator i = m_notes.begin(); i != m_notes.end(); ++i) {
138
139 QString filename = i->first;
140 NoteList notes = i->second;
141 float rate = m_rates[filename];
142
143 TrivialNoteExportable exportable(notes);
144
145 {
146 MIDIFileWriter writer(filename, &exportable, rate);
147 if (!writer.isOK()) {
148 cerr << "ERROR: Failed to create MIDI writer: "
149 << writer.getError() << endl;
150 throw FileOperationFailed(filename, "create MIDI writer");
151 }
152 writer.write();
153 }
154 }
155 }
156