comparison data/fileio/MatchFileReader.cpp @ 297:c022976d18e8

* Merge from sv-match-alignment branch (excluding alignment-specific document). - add aggregate wave model (not yet complete enough to be added as a true model in a layer, but there's potential) - add play solo mode - add alignment model -- unused in plain SV - fix two plugin leaks - add m3u playlist support (opens all files at once, potentially hazardous) - fix retrieval of pre-encoded URLs - add ability to resample audio files on import, so as to match rates with other files previously loaded; add preference for same - add preliminary support in transform code for range and rate of transform input - reorganise preferences dialog, move dark-background option to preferences, add option for temporary directory location
author Chris Cannam
date Fri, 28 Sep 2007 13:56:38 +0000
parents
children 06f13a3b9e9e
comparison
equal deleted inserted replaced
296:2b6c99b607f1 297:c022976d18e8
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2007 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 "MatchFileReader.h"
17
18 #include <QFile>
19 #include <QTextStream>
20
21 #include <cmath>
22 #include <iostream>
23
24 Alignment::Alignment() :
25 thisHopTime(0.0),
26 refHopTime(0.0)
27 {
28 }
29
30 double
31 Alignment::fromReference(double t) const
32 {
33 int ri = lrint(t / refHopTime);
34 int index = search(refIndex, ri);
35 return thisIndex[index] * thisHopTime;
36 }
37
38 double
39 Alignment::toReference(double t) const
40 {
41 int ti = lrint(t / thisHopTime);
42 int index = search(thisIndex, ti);
43 return refIndex[index] * refHopTime;
44 }
45
46 int
47 Alignment::search(const FrameArray &arr, int val) const
48 {
49 int len = arr.size();
50 int max = len - 1;
51 int min = 0;
52 while (max > min) {
53 int mid = (max + min) / 2;
54 if (val > arr[mid]) {
55 min = mid + 1;
56 } else {
57 max = mid;
58 }
59 } // max = MIN_j (arr[j] >= val) i.e. the first equal or next highest
60 while ((max + 1 < len) && (arr[max + 1] == val)) {
61 max++;
62 }
63 return (min + max) / 2;
64 }
65
66 MatchFileReader::MatchFileReader(QString path) :
67 m_file(0)
68 {
69 m_file = new QFile(path);
70 bool good = false;
71
72 if (!m_file->exists()) {
73 m_error = QFile::tr("File \"%1\" does not exist").arg(path);
74 } else if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text)) {
75 m_error = QFile::tr("Failed to open file \"%1\"").arg(path);
76 } else {
77 good = true;
78 }
79
80 if (!good) {
81 delete m_file;
82 m_file = 0;
83 }
84 }
85
86 MatchFileReader::~MatchFileReader()
87 {
88 if (m_file) {
89 std::cerr << "MatchFileReader::MatchFileReader: Closing file" << std::endl;
90 m_file->close();
91 }
92 delete m_file;
93 }
94
95 bool
96 MatchFileReader::isOK() const
97 {
98 return (m_file != 0);
99 }
100
101 QString
102 MatchFileReader::getError() const
103 {
104 return m_error;
105 }
106
107 Alignment
108 MatchFileReader::load() const
109 {
110 Alignment alignment;
111
112 if (!m_file) return alignment;
113
114 QTextStream in(m_file);
115
116 /*
117 File: /home/studio/match-test/mahler-3-boulez-5.wav
118 Marks: -1
119 FixedPoints: true 0
120 0
121 0
122 0
123 0
124 File: /home/studio/match-test/mahler-3-haitink-5.wav
125 Marks: 0
126 FixedPoints: true 0
127 0.02
128 0.02
129 12836
130 */
131
132 int fileCount = 0;
133 int state = 0;
134 int count = 0;
135
136 while (!in.atEnd()) {
137
138 QString line = in.readLine().trimmed();
139 if (line.startsWith("File: ")) {
140 ++fileCount;
141 continue;
142 }
143 if (fileCount != 2) continue;
144 if (line.startsWith("Marks:") || line.startsWith("FixedPoints:")) {
145 continue;
146 }
147
148 switch (state) {
149 case 0:
150 alignment.thisHopTime = line.toDouble();
151 break;
152 case 1:
153 alignment.refHopTime = line.toDouble();
154 break;
155 case 2:
156 count = line.toInt();
157 break;
158 case 3:
159 alignment.thisIndex.push_back(line.toInt());
160 break;
161 case 4:
162 alignment.refIndex.push_back(line.toInt());
163 break;
164 }
165
166 if (state < 3) ++state;
167 else if (state == 3 && alignment.thisIndex.size() == count) ++state;
168 }
169
170 if (alignment.thisHopTime == 0.0) {
171 std::cerr << "ERROR in Match file: this hop time == 0, using 0.01 instead" << std::endl;
172 alignment.thisHopTime = 0.01;
173 }
174
175 if (alignment.refHopTime == 0.0) {
176 std::cerr << "ERROR in Match file: ref hop time == 0, using 0.01 instead" << std::endl;
177 alignment.refHopTime = 0.01;
178 }
179
180 std::cerr << "MatchFileReader: this hop = " << alignment.thisHopTime << ", ref hop = " << alignment.refHopTime << ", this index count = " << alignment.thisIndex.size() << ", ref index count = " << alignment.refIndex.size() << std::endl;
181
182 return alignment;
183 }