changeset 879:eb6b6a88faed

Unit-test RangeMapper, fix a couple of bugs
author Chris Cannam
date Fri, 31 Jan 2014 13:39:37 +0000
parents 786ee8d1f30e
children b4787b595db3
files base/RangeMapper.cpp base/RangeMapper.h base/test/RangeMapperTest.h base/test/main.cpp base/test/test.pro data/fileio/test/main.cpp data/fileio/test/test.pro
diffstat 7 files changed, 268 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/base/RangeMapper.cpp	Wed Dec 11 21:40:27 2013 +0000
+++ b/base/RangeMapper.cpp	Fri Jan 31 13:39:37 2014 +0000
@@ -43,23 +43,19 @@
                * (m_maxpos - m_minpos));
     if (position < m_minpos) position = m_minpos;
     if (position > m_maxpos) position = m_maxpos;
-//    SVDEBUG << "LinearRangeMapper::getPositionForValue: " << value << " -> "
-//              << position << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", minval " << m_minval << ", maxval " << m_maxval << ")" << endl;
-    if (m_inverted) return m_maxpos - position;
+    if (m_inverted) return m_maxpos - (position - m_minpos);
     else return position;
 }
 
 float
 LinearRangeMapper::getValueForPosition(int position) const
 {
-    if (m_inverted) position = m_maxpos - position;
+    if (m_inverted) position = m_maxpos - (position - m_minpos);
+    if (position < m_minpos) position = m_minpos;
+    if (position > m_maxpos) position = m_maxpos;
     float value = m_minval +
         ((float(position - m_minpos) / float(m_maxpos - m_minpos))
          * (m_maxval - m_minval));
-    if (value < m_minval) value = m_minval;
-    if (value > m_maxval) value = m_maxval;
-//    SVDEBUG << "LinearRangeMapper::getValueForPosition: " << position << " -> "
-//              << value << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", minval " << m_minval << ", maxval " << m_maxval << ")" << endl;
     return value;
 }
 
@@ -73,14 +69,16 @@
 {
     convertMinMax(minpos, maxpos, minval, maxval, m_minlog, m_ratio);
 
-    cerr << "LogRangeMapper: minpos " << minpos << ", maxpos "
-              << maxpos << ", minval " << minval << ", maxval "
-              << maxval << ", minlog " << m_minlog << ", ratio " << m_ratio
-              << ", unit " << unit << endl;
+//    cerr << "LogRangeMapper: minpos " << minpos << ", maxpos "
+//              << maxpos << ", minval " << minval << ", maxval "
+//              << maxval << ", minlog " << m_minlog << ", ratio " << m_ratio
+//              << ", unit " << unit << endl;
 
     assert(m_maxpos != m_minpos);
 
     m_maxlog = (m_maxpos - m_minpos) / m_ratio + m_minlog;
+
+//    cerr << "LogRangeMapper: maxlog = " << m_maxlog << endl;
 }
 
 void
@@ -106,21 +104,23 @@
 int
 LogRangeMapper::getPositionForValue(float value) const
 {
-    int position = (log10(value) - m_minlog) * m_ratio + m_minpos;
+    int position = lrintf((log10(value) - m_minlog) * m_ratio) + m_minpos;
     if (position < m_minpos) position = m_minpos;
     if (position > m_maxpos) position = m_maxpos;
-//    SVDEBUG << "LogRangeMapper::getPositionForValue: " << value << " -> "
+//    cerr << "LogRangeMapper::getPositionForValue: " << value << " -> "
 //              << position << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", ratio " << m_ratio << ", minlog " << m_minlog << ")" << endl;
-    if (m_inverted) return m_maxpos - position;
+    if (m_inverted) return m_maxpos - (position - m_minpos);
     else return position;
 }
 
 float
 LogRangeMapper::getValueForPosition(int position) const
 {
-    if (m_inverted) position = m_maxpos - position;
+    if (m_inverted) position = m_maxpos - (position - m_minpos);
+    if (position < m_minpos) position = m_minpos;
+    if (position > m_maxpos) position = m_maxpos;
     float value = powf(10, (position - m_minpos) / m_ratio + m_minlog);
-//    SVDEBUG << "LogRangeMapper::getValueForPosition: " << position << " -> "
+//    cerr << "LogRangeMapper::getValueForPosition: " << position << " -> "
 //              << value << " (minpos " << m_minpos << ", maxpos " << m_maxpos << ", ratio " << m_ratio << ", minlog " << m_minlog << ")" << endl;
     return value;
 }
--- a/base/RangeMapper.h	Wed Dec 11 21:40:27 2013 +0000
+++ b/base/RangeMapper.h	Fri Jan 31 13:39:37 2014 +0000
@@ -34,6 +34,12 @@
 class LinearRangeMapper : public RangeMapper
 {
 public:
+    /**
+     * Map values in range minval->maxval linearly into integer range
+     * minpos->maxpos. minval and minpos must be less than maxval and
+     * maxpos respectively. If inverted is true, the range will be
+     * mapped "backwards" (minval to maxpos and maxval to minpos).
+     */
     LinearRangeMapper(int minpos, int maxpos,
                       float minval, float maxval,
                       QString unit = "", bool inverted = false);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base/test/RangeMapperTest.h	Fri Jan 31 13:39:37 2014 +0000
@@ -0,0 +1,138 @@
+/* -*- 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 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.
+*/
+
+#ifndef TEST_RANGE_MAPPER_H
+#define TEST_RANGE_MAPPER_H
+
+#include "../RangeMapper.h"
+
+#include <QObject>
+#include <QtTest>
+#include <QDir>
+
+#include <iostream>
+
+using namespace std;
+
+class RangeMapperTest : public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void linearUpForward()
+    {
+	LinearRangeMapper rm(1, 8, 0.5, 4.0, "x", false);
+	QCOMPARE(rm.getUnit(), QString("x"));
+	QCOMPARE(rm.getPositionForValue(0.5), 1);
+	QCOMPARE(rm.getPositionForValue(4.0), 8);
+	QCOMPARE(rm.getPositionForValue(3.0), 6);
+	QCOMPARE(rm.getPositionForValue(3.1), 6);
+	QCOMPARE(rm.getPositionForValue(3.4), 7);
+	QCOMPARE(rm.getPositionForValue(0.2), 1);
+	QCOMPARE(rm.getPositionForValue(-12), 1);
+	QCOMPARE(rm.getPositionForValue(6.1), 8);
+    }
+
+    void linearDownForward()
+    {
+	LinearRangeMapper rm(1, 8, 0.5, 4.0, "x", true);
+	QCOMPARE(rm.getUnit(), QString("x"));
+	QCOMPARE(rm.getPositionForValue(0.5), 8);
+	QCOMPARE(rm.getPositionForValue(4.0), 1);
+	QCOMPARE(rm.getPositionForValue(3.0), 3);
+	QCOMPARE(rm.getPositionForValue(3.1), 3);
+	QCOMPARE(rm.getPositionForValue(3.4), 2);
+	QCOMPARE(rm.getPositionForValue(0.2), 8);
+	QCOMPARE(rm.getPositionForValue(-12), 8);
+	QCOMPARE(rm.getPositionForValue(6.1), 1);
+    }
+
+    void linearUpBackward()
+    {
+	LinearRangeMapper rm(1, 8, 0.5, 4.0, "x", false);
+	QCOMPARE(rm.getUnit(), QString("x"));
+	QCOMPARE(rm.getValueForPosition(1), 0.5);
+	QCOMPARE(rm.getValueForPosition(8), 4.0);
+	QCOMPARE(rm.getValueForPosition(6), 3.0);
+	QCOMPARE(rm.getValueForPosition(7), 3.5);
+	QCOMPARE(rm.getValueForPosition(0), rm.getValueForPosition(1));
+	QCOMPARE(rm.getValueForPosition(9), rm.getValueForPosition(8));
+    }
+
+    void linearDownBackward()
+    {
+	LinearRangeMapper rm(1, 8, 0.5, 4.0, "x", true);
+	QCOMPARE(rm.getUnit(), QString("x"));
+	QCOMPARE(rm.getValueForPosition(8), 0.5);
+	QCOMPARE(rm.getValueForPosition(1), 4.0);
+	QCOMPARE(rm.getValueForPosition(3), 3.0);
+	QCOMPARE(rm.getValueForPosition(2), 3.5);
+	QCOMPARE(rm.getValueForPosition(0), rm.getValueForPosition(1));
+	QCOMPARE(rm.getValueForPosition(9), rm.getValueForPosition(8));
+    }
+
+    void logUpForward()
+    {
+	LogRangeMapper rm(3, 7, 10, 100000, "x", false);
+	QCOMPARE(rm.getUnit(), QString("x"));
+	QCOMPARE(rm.getPositionForValue(10.0), 3);
+	QCOMPARE(rm.getPositionForValue(100000.0), 7);
+	QCOMPARE(rm.getPositionForValue(1.0), 3);
+	QCOMPARE(rm.getPositionForValue(1000000.0), 7);
+	QCOMPARE(rm.getPositionForValue(1000.0), 5);
+	QCOMPARE(rm.getPositionForValue(900.0), 5);
+	QCOMPARE(rm.getPositionForValue(20000), 6);
+    }
+
+    void logDownForward()
+    {
+	LogRangeMapper rm(3, 7, 10, 100000, "x", true);
+	QCOMPARE(rm.getUnit(), QString("x"));
+	QCOMPARE(rm.getPositionForValue(10.0), 7);
+	QCOMPARE(rm.getPositionForValue(100000.0), 3);
+	QCOMPARE(rm.getPositionForValue(1.0), 7);
+	QCOMPARE(rm.getPositionForValue(1000000.0), 3);
+	QCOMPARE(rm.getPositionForValue(1000.0), 5);
+	QCOMPARE(rm.getPositionForValue(900.0), 5);
+	QCOMPARE(rm.getPositionForValue(20000), 4);
+    }
+
+    void logUpBackward()
+    {
+	LogRangeMapper rm(3, 7, 10, 100000, "x", false);
+	QCOMPARE(rm.getUnit(), QString("x"));
+	QCOMPARE(rm.getValueForPosition(3), 10.0);
+	QCOMPARE(rm.getValueForPosition(7), 100000.0);
+	QCOMPARE(rm.getValueForPosition(5), 1000.0);
+	QCOMPARE(rm.getValueForPosition(6), 10000.0);
+	QCOMPARE(rm.getValueForPosition(0), rm.getValueForPosition(3));
+	QCOMPARE(rm.getValueForPosition(9), rm.getValueForPosition(7));
+    }
+
+    void logDownBackward()
+    {
+	LogRangeMapper rm(3, 7, 10, 100000, "x", true);
+	QCOMPARE(rm.getUnit(), QString("x"));
+	QCOMPARE(rm.getValueForPosition(7), 10.0);
+	QCOMPARE(rm.getValueForPosition(3), 100000.0);
+	QCOMPARE(rm.getValueForPosition(5), 1000.0);
+	QCOMPARE(rm.getValueForPosition(4), 10000.0);
+	QCOMPARE(rm.getValueForPosition(0), rm.getValueForPosition(3));
+	QCOMPARE(rm.getValueForPosition(9), rm.getValueForPosition(7));
+    }
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base/test/main.cpp	Fri Jan 31 13:39:37 2014 +0000
@@ -0,0 +1,41 @@
+/* -*- 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 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 "RangeMapperTest.h"
+
+#include <QtTest>
+
+#include <iostream>
+
+int main(int argc, char *argv[])
+{
+    int good = 0, bad = 0;
+
+    QCoreApplication app(argc, argv);
+    app.setOrganizationName("Sonic Visualiser");
+    app.setApplicationName("test-svcore-base");
+
+    {
+	RangeMapperTest t;
+	if (QTest::qExec(&t, argc, argv) == 0) ++good;
+	else ++bad;
+    }
+
+    if (bad > 0) {
+	cerr << "\n********* " << bad << " test suite(s) failed!\n" << endl;
+	return 1;
+    } else {
+	cerr << "All tests passed" << endl;
+	return 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base/test/test.pro	Fri Jan 31 13:39:37 2014 +0000
@@ -0,0 +1,53 @@
+
+TEMPLATE = app
+
+LIBS += -L../.. -L../../../dataquay -L../../release -L../../../dataquay/release -lsvcore -ldataquay
+
+win32-g++ {
+    INCLUDEPATH += ../../../sv-dependency-builds/win32-mingw/include
+    LIBS += -L../../../sv-dependency-builds/win32-mingw/lib
+}
+
+exists(../../config.pri) {
+    include(../../config.pri)
+}
+
+win* {
+    !exists(../../config.pri) {
+        DEFINES += HAVE_BZ2 HAVE_FFTW3 HAVE_FFTW3F HAVE_SNDFILE HAVE_SAMPLERATE HAVE_VAMP HAVE_VAMPHOSTSDK HAVE_RUBBERBAND HAVE_DATAQUAY HAVE_LIBLO HAVE_MAD HAVE_ID3TAG HAVE_PORTAUDIO_2_0
+        LIBS += -lbz2 -lrubberband -lvamp-hostsdk -lfftw3 -lfftw3f -lsndfile -lFLAC -logg -lvorbis -lvorbisenc -lvorbisfile -logg -lmad -lid3tag -lportaudio -lsamplerate -llo -lz -lsord-0 -lserd-0 -lwinmm -lws2_32
+    }
+}
+
+CONFIG += qt thread warn_on stl rtti exceptions console
+QT += network xml testlib
+QT -= gui
+
+TARGET = svcore-base-test
+
+DEPENDPATH += ../..
+INCLUDEPATH += ../..
+OBJECTS_DIR = o
+MOC_DIR = o
+
+HEADERS += RangeMapperTest.h
+SOURCES += main.cpp
+
+win* {
+//PRE_TARGETDEPS += ../../svcore.lib
+}
+!win* {
+PRE_TARGETDEPS += ../../libsvcore.a
+}
+
+!win32 {
+    !macx* {
+        QMAKE_POST_LINK=./$${TARGET}
+    }
+    macx* {
+        QMAKE_POST_LINK=./$${TARGET}.app/Contents/MacOS/$${TARGET}
+    }
+}
+
+win32:QMAKE_POST_LINK=./release/$${TARGET}.exe
+
--- a/data/fileio/test/main.cpp	Wed Dec 11 21:40:27 2013 +0000
+++ b/data/fileio/test/main.cpp	Fri Jan 31 13:39:37 2014 +0000
@@ -1,5 +1,16 @@
 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-/* Copyright Chris Cannam - All Rights Reserved */
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2013 Chris Cannam.
+    
+    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 "AudioFileReaderTest.h"
 
--- a/data/fileio/test/test.pro	Wed Dec 11 21:40:27 2013 +0000
+++ b/data/fileio/test/test.pro	Fri Jan 31 13:39:37 2014 +0000
@@ -23,7 +23,7 @@
 QT += network xml testlib
 QT -= gui
 
-TARGET = svcore-test
+TARGET = svcore-data-fileio-test
 
 DEPENDPATH += ../../..
 INCLUDEPATH += ../../..