annotate runner/LabFeatureWriter.cpp @ 154:6ff4da31db8b labfile

Implement .lab file writer
author Chris Cannam
date Tue, 14 Oct 2014 17:30:44 +0100
parents
children 946115b8badd
rev   line source
Chris@154 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@154 2
Chris@154 3 /*
Chris@154 4 Sonic Visualiser
Chris@154 5 An audio file viewer and annotation editor.
Chris@154 6
Chris@154 7 Sonic Annotator
Chris@154 8 A utility for batch feature extraction from audio files.
Chris@154 9
Chris@154 10 Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London.
Chris@154 11 Copyright 2007-2008 QMUL.
Chris@154 12
Chris@154 13 This program is free software; you can redistribute it and/or
Chris@154 14 modify it under the terms of the GNU General Public License as
Chris@154 15 published by the Free Software Foundation; either version 2 of the
Chris@154 16 License, or (at your option) any later version. See the file
Chris@154 17 COPYING included with this distribution for more information.
Chris@154 18 */
Chris@154 19
Chris@154 20 #include "LabFeatureWriter.h"
Chris@154 21
Chris@154 22 #include <iostream>
Chris@154 23
Chris@154 24 #include <QRegExp>
Chris@154 25 #include <QTextStream>
Chris@154 26
Chris@154 27 using namespace std;
Chris@154 28 using namespace Vamp;
Chris@154 29
Chris@154 30 LabFeatureWriter::LabFeatureWriter() :
Chris@154 31 FileFeatureWriter(SupportOneFilePerTrackTransform |
Chris@154 32 SupportStdOut,
Chris@154 33 "lab"),
Chris@154 34 m_forceEnd(false)
Chris@154 35 {
Chris@154 36 }
Chris@154 37
Chris@154 38 LabFeatureWriter::~LabFeatureWriter()
Chris@154 39 {
Chris@154 40 }
Chris@154 41
Chris@154 42 string
Chris@154 43 LabFeatureWriter::getDescription() const
Chris@154 44 {
Chris@154 45 return "Write features in .lab, a tab-separated columnar format. The first column is always the feature start time in seconds. If the features have duration, the second column will be the feature end time in seconds. Remaining columns are the feature values (if any) and finally the feature label (if any). There is no identification of the audio file or the transform, so confusion will result if features from different audio or transforms are mixed. For more control over the output, consider using the CSV writer.";
Chris@154 46 }
Chris@154 47
Chris@154 48 LabFeatureWriter::ParameterList
Chris@154 49 LabFeatureWriter::getSupportedParameters() const
Chris@154 50 {
Chris@154 51 ParameterList pl = FileFeatureWriter::getSupportedParameters();
Chris@154 52
Chris@154 53 Parameter p;
Chris@154 54
Chris@154 55 p.name = "fill-ends";
Chris@154 56 p.description = "Include end times even for features without duration, by using the gap to the next feature instead.";
Chris@154 57 p.hasArg = false;
Chris@154 58 pl.push_back(p);
Chris@154 59
Chris@154 60 return pl;
Chris@154 61 }
Chris@154 62
Chris@154 63 void
Chris@154 64 LabFeatureWriter::setParameters(map<string, string> &params)
Chris@154 65 {
Chris@154 66 FileFeatureWriter::setParameters(params);
Chris@154 67
Chris@154 68 for (map<string, string>::iterator i = params.begin();
Chris@154 69 i != params.end(); ++i) {
Chris@154 70 if (i->first == "fill-ends") {
Chris@154 71 m_forceEnd = true;
Chris@154 72 }
Chris@154 73 }
Chris@154 74 }
Chris@154 75
Chris@154 76 void
Chris@154 77 LabFeatureWriter::write(QString trackId,
Chris@154 78 const Transform &transform,
Chris@154 79 const Plugin::OutputDescriptor& ,
Chris@154 80 const Plugin::FeatureList& features,
Chris@154 81 std::string summaryType)
Chris@154 82 {
Chris@154 83 // Select appropriate output file for our track/transform
Chris@154 84 // combination
Chris@154 85
Chris@154 86 QTextStream *sptr = getOutputStream(trackId, transform.getIdentifier());
Chris@154 87 if (!sptr) {
Chris@154 88 throw FailedToOpenOutputStream(trackId, transform.getIdentifier());
Chris@154 89 }
Chris@154 90
Chris@154 91 QTextStream &stream = *sptr;
Chris@154 92
Chris@154 93 QString sep = "\t";
Chris@154 94
Chris@154 95 for (unsigned int i = 0; i < features.size(); ++i) {
Chris@154 96
Chris@154 97 QString timestamp = features[i].timestamp.toString().c_str();
Chris@154 98 timestamp.replace(QRegExp("^ +"), "");
Chris@154 99 stream << timestamp;
Chris@154 100
Chris@154 101 Vamp::RealTime endTime;
Chris@154 102 bool haveEndTime = true;
Chris@154 103
Chris@154 104 if (features[i].hasDuration) {
Chris@154 105 endTime = features[i].timestamp + features[i].duration;
Chris@154 106 } else if (m_forceEnd) {
Chris@154 107 if (i+1 < features.size()) {
Chris@154 108 endTime = features[i+1].timestamp;
Chris@154 109 } else {
Chris@154 110 //!!! what to do??? can we get the end time of the input file?
Chris@154 111 endTime = features[i].timestamp;
Chris@154 112 }
Chris@154 113 } else {
Chris@154 114 haveEndTime = false;
Chris@154 115 }
Chris@154 116
Chris@154 117 if (haveEndTime) {
Chris@154 118 QString e = endTime.toString().c_str();
Chris@154 119 e.replace(QRegExp("^ +"), "");
Chris@154 120 stream << sep << e;
Chris@154 121 }
Chris@154 122
Chris@154 123 for (unsigned int j = 0; j < features[i].values.size(); ++j) {
Chris@154 124 stream << sep << features[i].values[j];
Chris@154 125 }
Chris@154 126
Chris@154 127 if (features[i].label != "") {
Chris@154 128 stream << sep << "\"" << features[i].label.c_str() << "\"";
Chris@154 129 }
Chris@154 130
Chris@154 131 stream << "\n";
Chris@154 132 }
Chris@154 133 }
Chris@154 134
Chris@154 135