diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/fileio/MatchFileReader.cpp	Fri Sep 28 13:56:38 2007 +0000
@@ -0,0 +1,183 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2007 QMUL.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "MatchFileReader.h"
+
+#include <QFile>
+#include <QTextStream>
+
+#include <cmath>
+#include <iostream>
+
+Alignment::Alignment() :
+    thisHopTime(0.0),
+    refHopTime(0.0)
+{
+}
+
+double
+Alignment::fromReference(double t) const
+{
+    int ri = lrint(t / refHopTime);
+    int index = search(refIndex, ri);
+    return thisIndex[index] * thisHopTime;
+}
+
+double
+Alignment::toReference(double t) const
+{
+    int ti = lrint(t / thisHopTime);
+    int index = search(thisIndex, ti);
+    return refIndex[index] * refHopTime;
+}
+
+int
+Alignment::search(const FrameArray &arr, int val) const
+{
+    int len = arr.size();
+    int max = len - 1;
+    int min = 0;
+    while (max > min) {
+        int mid = (max + min) / 2;
+        if (val > arr[mid]) {
+            min = mid + 1;
+        } else {
+            max = mid;
+        }
+    } // max = MIN_j (arr[j] >= val)   i.e. the first equal or next highest
+    while ((max + 1 < len) && (arr[max + 1] == val)) {
+        max++;
+    }
+    return (min + max) / 2;
+}
+
+MatchFileReader::MatchFileReader(QString path) :
+    m_file(0)
+{
+    m_file = new QFile(path);
+    bool good = false;
+    
+    if (!m_file->exists()) {
+	m_error = QFile::tr("File \"%1\" does not exist").arg(path);
+    } else if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text)) {
+	m_error = QFile::tr("Failed to open file \"%1\"").arg(path);
+    } else {
+	good = true;
+    }
+
+    if (!good) {
+	delete m_file;
+	m_file = 0;
+    }
+}
+
+MatchFileReader::~MatchFileReader()
+{
+    if (m_file) {
+        std::cerr << "MatchFileReader::MatchFileReader: Closing file" << std::endl;
+        m_file->close();
+    }
+    delete m_file;
+}
+
+bool
+MatchFileReader::isOK() const
+{
+    return (m_file != 0);
+}
+
+QString
+MatchFileReader::getError() const
+{
+    return m_error;
+}
+
+Alignment
+MatchFileReader::load() const
+{
+    Alignment alignment;
+
+    if (!m_file) return alignment;
+
+    QTextStream in(m_file);
+
+/*
+File: /home/studio/match-test/mahler-3-boulez-5.wav
+Marks: -1
+FixedPoints: true 0
+0
+0
+0
+0
+File: /home/studio/match-test/mahler-3-haitink-5.wav
+Marks: 0
+FixedPoints: true 0
+0.02
+0.02
+12836
+*/
+
+    int fileCount = 0;
+    int state = 0;
+    int count = 0;
+
+    while (!in.atEnd()) {
+
+        QString line = in.readLine().trimmed();
+        if (line.startsWith("File: ")) {
+            ++fileCount;
+            continue;
+        }
+        if (fileCount != 2) continue;
+        if (line.startsWith("Marks:") || line.startsWith("FixedPoints:")) {
+            continue;
+        }
+
+        switch (state) {
+        case 0:
+            alignment.thisHopTime = line.toDouble();
+            break;
+        case 1:
+            alignment.refHopTime = line.toDouble();
+            break;
+        case 2: 
+            count = line.toInt();
+            break;
+        case 3:
+            alignment.thisIndex.push_back(line.toInt());
+            break;
+        case 4:
+            alignment.refIndex.push_back(line.toInt());
+            break;
+        }
+
+        if (state < 3) ++state;
+        else if (state == 3 && alignment.thisIndex.size() == count) ++state;
+    }
+
+    if (alignment.thisHopTime == 0.0) {
+        std::cerr << "ERROR in Match file: this hop time == 0, using 0.01 instead" << std::endl;
+        alignment.thisHopTime = 0.01;
+    }
+
+    if (alignment.refHopTime == 0.0) {
+        std::cerr << "ERROR in Match file: ref hop time == 0, using 0.01 instead" << std::endl;
+        alignment.refHopTime = 0.01;
+    }
+
+    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;
+
+    return alignment;
+}