comparison data/fileio/CSVFileReader.cpp @ 897:69cc0454ed72

Make it possible to import CSV files directly into Note layers
author Chris Cannam
date Mon, 07 Apr 2014 10:47:15 +0100
parents f5cd33909744
children 59e7fe1b1003
comparison
equal deleted inserted replaced
892:451f7f3ab6e7 897:69cc0454ed72
20 #include "base/StringBits.h" 20 #include "base/StringBits.h"
21 #include "model/SparseOneDimensionalModel.h" 21 #include "model/SparseOneDimensionalModel.h"
22 #include "model/SparseTimeValueModel.h" 22 #include "model/SparseTimeValueModel.h"
23 #include "model/EditableDenseThreeDimensionalModel.h" 23 #include "model/EditableDenseThreeDimensionalModel.h"
24 #include "model/RegionModel.h" 24 #include "model/RegionModel.h"
25 #include "model/NoteModel.h"
25 #include "DataFileReaderFactory.h" 26 #include "DataFileReaderFactory.h"
26 27
27 #include <QFile> 28 #include <QFile>
28 #include <QString> 29 #include <QString>
29 #include <QRegExp> 30 #include <QRegExp>
83 size_t 84 size_t
84 CSVFileReader::convertTimeValue(QString s, int lineno, size_t sampleRate, 85 CSVFileReader::convertTimeValue(QString s, int lineno, size_t sampleRate,
85 size_t windowSize) const 86 size_t windowSize) const
86 { 87 {
87 QRegExp nonNumericRx("[^0-9eE.,+-]"); 88 QRegExp nonNumericRx("[^0-9eE.,+-]");
88 unsigned int warnLimit = 10; 89 int warnLimit = 10;
89 90
90 CSVFormat::TimeUnits timeUnits = m_format.getTimeUnits(); 91 CSVFormat::TimeUnits timeUnits = m_format.getTimeUnits();
91 92
92 size_t calculatedFrame = 0; 93 size_t calculatedFrame = 0;
93 94
154 } 155 }
155 156
156 SparseOneDimensionalModel *model1 = 0; 157 SparseOneDimensionalModel *model1 = 0;
157 SparseTimeValueModel *model2 = 0; 158 SparseTimeValueModel *model2 = 0;
158 RegionModel *model2a = 0; 159 RegionModel *model2a = 0;
160 NoteModel *model2b = 0;
159 EditableDenseThreeDimensionalModel *model3 = 0; 161 EditableDenseThreeDimensionalModel *model3 = 0;
160 Model *model = 0; 162 Model *model = 0;
161 163
162 QTextStream in(m_file); 164 QTextStream in(m_file);
163 in.seek(0); 165 in.seek(0);
171 size_t duration = 0; 173 size_t duration = 0;
172 size_t endFrame = 0; 174 size_t endFrame = 0;
173 175
174 bool haveAnyValue = false; 176 bool haveAnyValue = false;
175 bool haveEndTime = false; 177 bool haveEndTime = false;
178 bool pitchLooksLikeMIDI = true;
176 179
177 size_t startFrame = 0; // for calculation of dense model resolution 180 size_t startFrame = 0; // for calculation of dense model resolution
178 bool firstEverValue = true; 181 bool firstEverValue = true;
179 182
180 std::map<QString, int> labelCountMap; 183 std::map<QString, int> labelCountMap;
200 // read a line at a time, and that's obviously OK. 203 // read a line at a time, and that's obviously OK.
201 204
202 QString chunk = in.readLine(); 205 QString chunk = in.readLine();
203 QStringList lines = chunk.split('\r', QString::SkipEmptyParts); 206 QStringList lines = chunk.split('\r', QString::SkipEmptyParts);
204 207
205 for (size_t li = 0; li < lines.size(); ++li) { 208 for (int li = 0; li < lines.size(); ++li) {
206 209
207 QString line = lines[li]; 210 QString line = lines[li];
208 211
209 if (line.startsWith("#")) continue; 212 if (line.startsWith("#")) continue;
210 213
224 break; 227 break;
225 228
226 case CSVFormat::TwoDimensionalModelWithDuration: 229 case CSVFormat::TwoDimensionalModelWithDuration:
227 model2a = new RegionModel(sampleRate, windowSize, false); 230 model2a = new RegionModel(sampleRate, windowSize, false);
228 model = model2a; 231 model = model2a;
232 break;
233
234 case CSVFormat::TwoDimensionalModelWithDurationAndPitch:
235 model2b = new NoteModel(sampleRate, windowSize, false);
236 model = model2b;
229 break; 237 break;
230 238
231 case CSVFormat::ThreeDimensionalModel: 239 case CSVFormat::ThreeDimensionalModel:
232 model3 = new EditableDenseThreeDimensionalModel 240 model3 = new EditableDenseThreeDimensionalModel
233 (sampleRate, 241 (sampleRate,
238 break; 246 break;
239 } 247 }
240 } 248 }
241 249
242 float value = 0.f; 250 float value = 0.f;
251 float pitch = 0.f;
243 QString label = ""; 252 QString label = "";
244 253
245 duration = 0.f; 254 duration = 0.f;
246 haveEndTime = false; 255 haveEndTime = false;
247 256
272 case CSVFormat::ColumnValue: 281 case CSVFormat::ColumnValue:
273 value = s.toFloat(); 282 value = s.toFloat();
274 haveAnyValue = true; 283 haveAnyValue = true;
275 break; 284 break;
276 285
286 case CSVFormat::ColumnPitch:
287 pitch = s.toFloat();
288 if (pitch < 0.f || pitch > 127.f) {
289 pitchLooksLikeMIDI = false;
290 }
291 break;
292
277 case CSVFormat::ColumnLabel: 293 case CSVFormat::ColumnLabel:
278 label = s; 294 label = s;
279 ++labelCountMap[label]; 295 ++labelCountMap[label];
280 break; 296 break;
281 } 297 }
299 315
300 } else if (modelType == CSVFormat::TwoDimensionalModelWithDuration) { 316 } else if (modelType == CSVFormat::TwoDimensionalModelWithDuration) {
301 317
302 RegionModel::Point point(frameNo, value, duration, label); 318 RegionModel::Point point(frameNo, value, duration, label);
303 model2a->addPoint(point); 319 model2a->addPoint(point);
320
321 } else if (modelType == CSVFormat::TwoDimensionalModelWithDurationAndPitch) {
322
323 float level = ((value >= 0.f && value <= 1.f) ? value : 1.f);
324 NoteModel::Point point(frameNo, pitch, duration, level, label);
325 model2b->addPoint(point);
304 326
305 } else if (modelType == CSVFormat::ThreeDimensionalModel) { 327 } else if (modelType == CSVFormat::ThreeDimensionalModel) {
306 328
307 DenseThreeDimensionalModel::Column values; 329 DenseThreeDimensionalModel::Column values;
308 330
398 model2a->addPoint(i->second); 420 model2a->addPoint(i->second);
399 } 421 }
400 } 422 }
401 } 423 }
402 424
425 if (model2b) {
426 if (pitchLooksLikeMIDI) {
427 model2b->setScaleUnits("MIDI Pitch");
428 } else {
429 model2b->setScaleUnits("Hz");
430 }
431 }
432
403 if (modelType == CSVFormat::ThreeDimensionalModel) { 433 if (modelType == CSVFormat::ThreeDimensionalModel) {
404 model3->setMinimumLevel(min); 434 model3->setMinimumLevel(min);
405 model3->setMaximumLevel(max); 435 model3->setMaximumLevel(max);
406 } 436 }
407 437