annotate data/fileio/MatchFileReader.cpp @ 999:694301cc71cc

Add MIDI destinations tests and fix feature writer bugs resulting from them
author Chris Cannam
date Tue, 14 Oct 2014 10:07:02 +0100
parents 0a35adfb7b16
children
rev   line source
Chris@297 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@297 2
Chris@297 3 /*
Chris@297 4 Sonic Visualiser
Chris@297 5 An audio file viewer and annotation editor.
Chris@297 6 Centre for Digital Music, Queen Mary, University of London.
Chris@297 7 This file copyright 2007 QMUL.
Chris@297 8
Chris@297 9 This program is free software; you can redistribute it and/or
Chris@297 10 modify it under the terms of the GNU General Public License as
Chris@297 11 published by the Free Software Foundation; either version 2 of the
Chris@297 12 License, or (at your option) any later version. See the file
Chris@297 13 COPYING included with this distribution for more information.
Chris@297 14 */
Chris@297 15
Chris@297 16 #include "MatchFileReader.h"
Chris@297 17
Chris@297 18 #include <QFile>
Chris@297 19 #include <QTextStream>
Chris@297 20
Chris@297 21 #include <cmath>
Chris@297 22 #include <iostream>
Chris@297 23
Chris@297 24 Alignment::Alignment() :
Chris@297 25 thisHopTime(0.0),
Chris@967 26 refHopTime(0.0),
Chris@967 27 m_mainModel(0)
Chris@297 28 {
Chris@297 29 }
Chris@297 30
Chris@297 31 double
Chris@297 32 Alignment::fromReference(double t) const
Chris@297 33 {
Chris@297 34 int ri = lrint(t / refHopTime);
Chris@297 35 int index = search(refIndex, ri);
Chris@297 36 return thisIndex[index] * thisHopTime;
Chris@297 37 }
Chris@297 38
Chris@297 39 double
Chris@297 40 Alignment::toReference(double t) const
Chris@297 41 {
Chris@297 42 int ti = lrint(t / thisHopTime);
Chris@297 43 int index = search(thisIndex, ti);
Chris@297 44 return refIndex[index] * refHopTime;
Chris@297 45 }
Chris@297 46
Chris@297 47 int
Chris@297 48 Alignment::search(const FrameArray &arr, int val) const
Chris@297 49 {
Chris@297 50 int len = arr.size();
Chris@297 51 int max = len - 1;
Chris@297 52 int min = 0;
Chris@297 53 while (max > min) {
Chris@297 54 int mid = (max + min) / 2;
Chris@297 55 if (val > arr[mid]) {
Chris@297 56 min = mid + 1;
Chris@297 57 } else {
Chris@297 58 max = mid;
Chris@297 59 }
Chris@297 60 } // max = MIN_j (arr[j] >= val) i.e. the first equal or next highest
Chris@297 61 while ((max + 1 < len) && (arr[max + 1] == val)) {
Chris@297 62 max++;
Chris@297 63 }
Chris@297 64 return (min + max) / 2;
Chris@297 65 }
Chris@297 66
Chris@297 67 MatchFileReader::MatchFileReader(QString path) :
Chris@297 68 m_file(0)
Chris@297 69 {
Chris@297 70 m_file = new QFile(path);
Chris@297 71 bool good = false;
Chris@297 72
Chris@297 73 if (!m_file->exists()) {
Chris@297 74 m_error = QFile::tr("File \"%1\" does not exist").arg(path);
Chris@297 75 } else if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text)) {
Chris@297 76 m_error = QFile::tr("Failed to open file \"%1\"").arg(path);
Chris@297 77 } else {
Chris@297 78 good = true;
Chris@297 79 }
Chris@297 80
Chris@297 81 if (!good) {
Chris@297 82 delete m_file;
Chris@297 83 m_file = 0;
Chris@297 84 }
Chris@297 85 }
Chris@297 86
Chris@297 87 MatchFileReader::~MatchFileReader()
Chris@297 88 {
Chris@297 89 if (m_file) {
Chris@690 90 SVDEBUG << "MatchFileReader::MatchFileReader: Closing file" << endl;
Chris@297 91 m_file->close();
Chris@297 92 }
Chris@297 93 delete m_file;
Chris@297 94 }
Chris@297 95
Chris@297 96 bool
Chris@297 97 MatchFileReader::isOK() const
Chris@297 98 {
Chris@297 99 return (m_file != 0);
Chris@297 100 }
Chris@297 101
Chris@297 102 QString
Chris@297 103 MatchFileReader::getError() const
Chris@297 104 {
Chris@297 105 return m_error;
Chris@297 106 }
Chris@297 107
Chris@297 108 Alignment
Chris@297 109 MatchFileReader::load() const
Chris@297 110 {
Chris@297 111 Alignment alignment;
Chris@297 112
Chris@297 113 if (!m_file) return alignment;
Chris@297 114
Chris@297 115 QTextStream in(m_file);
Chris@297 116
Chris@297 117 /*
Chris@297 118 File: /home/studio/match-test/mahler-3-boulez-5.wav
Chris@297 119 Marks: -1
Chris@297 120 FixedPoints: true 0
Chris@297 121 0
Chris@297 122 0
Chris@297 123 0
Chris@297 124 0
Chris@297 125 File: /home/studio/match-test/mahler-3-haitink-5.wav
Chris@297 126 Marks: 0
Chris@297 127 FixedPoints: true 0
Chris@297 128 0.02
Chris@297 129 0.02
Chris@297 130 12836
Chris@297 131 */
Chris@297 132
Chris@297 133 int fileCount = 0;
Chris@297 134 int state = 0;
Chris@297 135 int count = 0;
Chris@297 136
Chris@297 137 while (!in.atEnd()) {
Chris@297 138
Chris@297 139 QString line = in.readLine().trimmed();
Chris@297 140 if (line.startsWith("File: ")) {
Chris@297 141 ++fileCount;
Chris@297 142 continue;
Chris@297 143 }
Chris@297 144 if (fileCount != 2) continue;
Chris@297 145 if (line.startsWith("Marks:") || line.startsWith("FixedPoints:")) {
Chris@297 146 continue;
Chris@297 147 }
Chris@297 148
Chris@297 149 switch (state) {
Chris@297 150 case 0:
Chris@297 151 alignment.thisHopTime = line.toDouble();
Chris@297 152 break;
Chris@297 153 case 1:
Chris@297 154 alignment.refHopTime = line.toDouble();
Chris@297 155 break;
Chris@297 156 case 2:
Chris@297 157 count = line.toInt();
Chris@297 158 break;
Chris@297 159 case 3:
Chris@297 160 alignment.thisIndex.push_back(line.toInt());
Chris@297 161 break;
Chris@297 162 case 4:
Chris@297 163 alignment.refIndex.push_back(line.toInt());
Chris@297 164 break;
Chris@297 165 }
Chris@297 166
Chris@929 167 if (state < 3) {
Chris@929 168 ++state;
Chris@929 169 } else if (state == 3 && int(alignment.thisIndex.size()) == count) {
Chris@929 170 ++state;
Chris@929 171 }
Chris@297 172 }
Chris@297 173
Chris@297 174 if (alignment.thisHopTime == 0.0) {
Chris@843 175 cerr << "ERROR in Match file: this hop time == 0, using 0.01 instead" << endl;
Chris@297 176 alignment.thisHopTime = 0.01;
Chris@297 177 }
Chris@297 178
Chris@297 179 if (alignment.refHopTime == 0.0) {
Chris@843 180 cerr << "ERROR in Match file: ref hop time == 0, using 0.01 instead" << endl;
Chris@297 181 alignment.refHopTime = 0.01;
Chris@297 182 }
Chris@297 183
Chris@843 184 cerr << "MatchFileReader: this hop = " << alignment.thisHopTime << ", ref hop = " << alignment.refHopTime << ", this index count = " << alignment.thisIndex.size() << ", ref index count = " << alignment.refIndex.size() << endl;
Chris@297 185
Chris@297 186 return alignment;
Chris@297 187 }