Mercurial > hg > svcore
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 } |