Mercurial > hg > sonic-annotator
view runner/MIDIFeatureWriter.cpp @ 141:d7a91e07ca57 midi
Flesh out MIDI writer
author | Chris Cannam |
---|---|
date | Mon, 13 Oct 2014 13:37:31 +0100 |
parents | 9b94545a7fdc |
children | b3d73c08b6ce |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Sonic Annotator A utility for batch feature extraction from audio files. Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. Copyright 2007-2014 QMUL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "MIDIFeatureWriter.h" using namespace std; using Vamp::Plugin; using Vamp::PluginBase; #include "base/Exceptions.h" #include "data/fileio/MIDIFileWriter.h" MIDIFeatureWriter::MIDIFeatureWriter() : FileFeatureWriter(SupportOneFilePerTrackTransform | SupportOneFilePerTrack | SupportOneFileTotal, "mid") { } MIDIFeatureWriter::~MIDIFeatureWriter() { } MIDIFeatureWriter::ParameterList MIDIFeatureWriter::getSupportedParameters() const { ParameterList pl = FileFeatureWriter::getSupportedParameters(); return pl; } void MIDIFeatureWriter::setParameters(map<string, string> ¶ms) { FileFeatureWriter::setParameters(params); } void MIDIFeatureWriter::setTrackMetadata(QString, TrackMetadata) { cerr << "MIDIFeatureWriter::setTrackMetadata: not supported (yet?)" << endl; } void MIDIFeatureWriter::write(QString trackId, const Transform &transform, const Plugin::OutputDescriptor& output, const Plugin::FeatureList& features, std::string /* summaryType */) { QString transformId = transform.getIdentifier(); QString filename = getOutputFilename(trackId, transformId); if (filename == "") { throw FailedToOpenOutputStream(trackId, transformId); } int sampleRate = transform.getSampleRate(); if (m_rates.find(filename) == m_rates.end()) { m_rates[filename] = sampleRate; } if (m_fileTransforms[filename].find(transformId) == m_fileTransforms[filename].end()) { // This transform is new to the file, give it a channel number int channel = m_nextChannels[filename]; m_nextChannels[filename] = channel + 1; m_fileTransforms[filename].insert(transformId); m_channels[transformId] = channel; } NoteList notes = m_notes[filename]; bool freq = (output.unit == "Hz" || output.unit == "hz" || output.unit == "HZ"); for (int i = 0; i < (int)features.size(); ++i) { const Plugin::Feature &feature(features[i]); Vamp::RealTime timestamp = feature.timestamp; int frame = Vamp::RealTime::realTime2Frame(timestamp, sampleRate); int duration = 1; if (feature.hasDuration) { duration = Vamp::RealTime::realTime2Frame(feature.duration, sampleRate); } int pitch = 60; if (feature.values.size() > 0) { float pval = feature.values[0]; if (freq) { pitch = Pitch::getPitchForFrequency(pval); } else { pitch = int(pval + 0.5); } } int velocity = 100; if (feature.values.size() > 1) { float vval = feature.values[1]; if (vval < 128) { velocity = int(vval + 0.5); } } NoteData note(frame, duration, pitch, velocity); note.channel = m_channels[transformId]; notes.push_back(note); } m_notes[filename] = notes; } void MIDIFeatureWriter::finish() { for (NoteMap::const_iterator i = m_notes.begin(); i != m_notes.end(); ++i) { QString filename = i->first; NoteList notes = i->second; float rate = m_rates[filename]; TrivialNoteExportable exportable(notes); { MIDIFileWriter writer(filename, &exportable, rate); if (!writer.isOK()) { cerr << "ERROR: Failed to create MIDI writer: " << writer.getError() << endl; throw FileOperationFailed(filename, "create MIDI writer"); } writer.write(); } } }