svcore  1.9
MatchFileReader.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2007 QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "MatchFileReader.h"
00017 
00018 #include <QFile>
00019 #include <QTextStream>
00020 
00021 #include <cmath>
00022 #include <iostream>
00023 
00024 Alignment::Alignment() :
00025     thisHopTime(0.0),
00026     refHopTime(0.0),
00027     m_mainModel(0)
00028 {
00029 }
00030 
00031 double
00032 Alignment::fromReference(double t) const
00033 {
00034     int ri = lrint(t / refHopTime);
00035     int index = search(refIndex, ri);
00036     return thisIndex[index] * thisHopTime;
00037 }
00038 
00039 double
00040 Alignment::toReference(double t) const
00041 {
00042     int ti = lrint(t / thisHopTime);
00043     int index = search(thisIndex, ti);
00044     return refIndex[index] * refHopTime;
00045 }
00046 
00047 int
00048 Alignment::search(const FrameArray &arr, int val) const
00049 {
00050     int len = arr.size();
00051     int max = len - 1;
00052     int min = 0;
00053     while (max > min) {
00054         int mid = (max + min) / 2;
00055         if (val > arr[mid]) {
00056             min = mid + 1;
00057         } else {
00058             max = mid;
00059         }
00060     } // max = MIN_j (arr[j] >= val)   i.e. the first equal or next highest
00061     while ((max + 1 < len) && (arr[max + 1] == val)) {
00062         max++;
00063     }
00064     return (min + max) / 2;
00065 }
00066 
00067 MatchFileReader::MatchFileReader(QString path) :
00068     m_file(0)
00069 {
00070     m_file = new QFile(path);
00071     bool good = false;
00072     
00073     if (!m_file->exists()) {
00074         m_error = QFile::tr("File \"%1\" does not exist").arg(path);
00075     } else if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text)) {
00076         m_error = QFile::tr("Failed to open file \"%1\"").arg(path);
00077     } else {
00078         good = true;
00079     }
00080 
00081     if (!good) {
00082         delete m_file;
00083         m_file = 0;
00084     }
00085 }
00086 
00087 MatchFileReader::~MatchFileReader()
00088 {
00089     if (m_file) {
00090         SVDEBUG << "MatchFileReader::MatchFileReader: Closing file" << endl;
00091         m_file->close();
00092     }
00093     delete m_file;
00094 }
00095 
00096 bool
00097 MatchFileReader::isOK() const
00098 {
00099     return (m_file != 0);
00100 }
00101 
00102 QString
00103 MatchFileReader::getError() const
00104 {
00105     return m_error;
00106 }
00107 
00108 Alignment
00109 MatchFileReader::load() const
00110 {
00111     Alignment alignment;
00112 
00113     if (!m_file) return alignment;
00114 
00115     QTextStream in(m_file);
00116 
00117 /*
00118 File: /home/studio/match-test/mahler-3-boulez-5.wav
00119 Marks: -1
00120 FixedPoints: true 0
00121 0
00122 0
00123 0
00124 0
00125 File: /home/studio/match-test/mahler-3-haitink-5.wav
00126 Marks: 0
00127 FixedPoints: true 0
00128 0.02
00129 0.02
00130 12836
00131 */
00132 
00133     int fileCount = 0;
00134     int state = 0;
00135     int count = 0;
00136 
00137     while (!in.atEnd()) {
00138 
00139         QString line = in.readLine().trimmed();
00140         if (line.startsWith("File: ")) {
00141             ++fileCount;
00142             continue;
00143         }
00144         if (fileCount != 2) continue;
00145         if (line.startsWith("Marks:") || line.startsWith("FixedPoints:")) {
00146             continue;
00147         }
00148 
00149         switch (state) {
00150         case 0:
00151             alignment.thisHopTime = line.toDouble();
00152             break;
00153         case 1:
00154             alignment.refHopTime = line.toDouble();
00155             break;
00156         case 2: 
00157             count = line.toInt();
00158             break;
00159         case 3:
00160             alignment.thisIndex.push_back(line.toInt());
00161             break;
00162         case 4:
00163             alignment.refIndex.push_back(line.toInt());
00164             break;
00165         }
00166 
00167         if (state < 3) {
00168             ++state;
00169         } else if (state == 3 && int(alignment.thisIndex.size()) == count) {
00170             ++state;
00171         }
00172     }
00173 
00174     if (alignment.thisHopTime == 0.0) {
00175         cerr << "ERROR in Match file: this hop time == 0, using 0.01 instead" << endl;
00176         alignment.thisHopTime = 0.01;
00177     }
00178 
00179     if (alignment.refHopTime == 0.0) {
00180         cerr << "ERROR in Match file: ref hop time == 0, using 0.01 instead" << endl;
00181         alignment.refHopTime = 0.01;
00182     }
00183 
00184     cerr << "MatchFileReader: this hop = " << alignment.thisHopTime << ", ref hop = " << alignment.refHopTime << ", this index count = " << alignment.thisIndex.size() << ", ref index count = " << alignment.refIndex.size() << endl;
00185 
00186     return alignment;
00187 }