Chris@189
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@189
|
2
|
Chris@189
|
3 /*
|
Chris@189
|
4 Sonic Visualiser
|
Chris@189
|
5 An audio file viewer and annotation editor.
|
Chris@189
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@202
|
7 This file copyright 2006 QMUL.
|
Chris@189
|
8
|
Chris@189
|
9 This program is free software; you can redistribute it and/or
|
Chris@189
|
10 modify it under the terms of the GNU General Public License as
|
Chris@189
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@189
|
12 License, or (at your option) any later version. See the file
|
Chris@189
|
13 COPYING included with this distribution for more information.
|
Chris@189
|
14 */
|
Chris@189
|
15
|
Chris@189
|
16 #ifndef _RANGE_MAPPER_H_
|
Chris@189
|
17 #define _RANGE_MAPPER_H_
|
Chris@189
|
18
|
Chris@189
|
19 #include <QString>
|
Chris@189
|
20
|
Chris@686
|
21 #include "Debug.h"
|
Chris@880
|
22 #include <map>
|
Chris@189
|
23
|
Chris@189
|
24 class RangeMapper
|
Chris@189
|
25 {
|
Chris@189
|
26 public:
|
Chris@189
|
27 virtual ~RangeMapper() { }
|
Chris@189
|
28 virtual int getPositionForValue(float value) const = 0;
|
Chris@189
|
29 virtual float getValueForPosition(int position) const = 0;
|
Chris@189
|
30 virtual QString getUnit() const { return ""; }
|
Chris@189
|
31 };
|
Chris@189
|
32
|
Chris@189
|
33
|
Chris@189
|
34 class LinearRangeMapper : public RangeMapper
|
Chris@189
|
35 {
|
Chris@189
|
36 public:
|
Chris@879
|
37 /**
|
Chris@879
|
38 * Map values in range minval->maxval linearly into integer range
|
Chris@879
|
39 * minpos->maxpos. minval and minpos must be less than maxval and
|
Chris@879
|
40 * maxpos respectively. If inverted is true, the range will be
|
Chris@879
|
41 * mapped "backwards" (minval to maxpos and maxval to minpos).
|
Chris@879
|
42 */
|
Chris@189
|
43 LinearRangeMapper(int minpos, int maxpos,
|
Chris@189
|
44 float minval, float maxval,
|
Chris@464
|
45 QString unit = "", bool inverted = false);
|
Chris@189
|
46
|
Chris@189
|
47 virtual int getPositionForValue(float value) const;
|
Chris@189
|
48 virtual float getValueForPosition(int position) const;
|
Chris@189
|
49
|
Chris@189
|
50 virtual QString getUnit() const { return m_unit; }
|
Chris@189
|
51
|
Chris@189
|
52 protected:
|
Chris@189
|
53 int m_minpos;
|
Chris@189
|
54 int m_maxpos;
|
Chris@189
|
55 float m_minval;
|
Chris@189
|
56 float m_maxval;
|
Chris@189
|
57 QString m_unit;
|
Chris@464
|
58 bool m_inverted;
|
Chris@189
|
59 };
|
Chris@189
|
60
|
Chris@189
|
61 class LogRangeMapper : public RangeMapper
|
Chris@189
|
62 {
|
Chris@189
|
63 public:
|
Chris@880
|
64 /**
|
Chris@880
|
65 * Map values in range minval->maxval into integer range
|
Chris@880
|
66 * minpos->maxpos such that logs of the values are mapped
|
Chris@880
|
67 * linearly. minval and minpos must be less than maxval and maxpos
|
Chris@880
|
68 * respectively. If inverted is true, the range will be mapped
|
Chris@880
|
69 * "backwards" (minval to maxpos and maxval to minpos).
|
Chris@880
|
70 */
|
Chris@189
|
71 LogRangeMapper(int minpos, int maxpos,
|
Chris@356
|
72 float minval, float maxval,
|
Chris@464
|
73 QString m_unit = "", bool inverted = false);
|
Chris@189
|
74
|
Chris@356
|
75 static void convertRatioMinLog(float ratio, float minlog,
|
Chris@356
|
76 int minpos, int maxpos,
|
Chris@356
|
77 float &minval, float &maxval);
|
Chris@356
|
78
|
Chris@356
|
79 static void convertMinMax(int minpos, int maxpos,
|
Chris@356
|
80 float minval, float maxval,
|
Chris@356
|
81 float &ratio, float &minlog);
|
Chris@356
|
82
|
Chris@189
|
83 virtual int getPositionForValue(float value) const;
|
Chris@189
|
84 virtual float getValueForPosition(int position) const;
|
Chris@189
|
85
|
Chris@189
|
86 virtual QString getUnit() const { return m_unit; }
|
Chris@189
|
87
|
Chris@189
|
88 protected:
|
Chris@189
|
89 int m_minpos;
|
Chris@189
|
90 int m_maxpos;
|
Chris@189
|
91 float m_ratio;
|
Chris@189
|
92 float m_minlog;
|
Chris@189
|
93 float m_maxlog;
|
Chris@189
|
94 QString m_unit;
|
Chris@464
|
95 bool m_inverted;
|
Chris@189
|
96 };
|
Chris@189
|
97
|
Chris@880
|
98 class InterpolatingRangeMapper : public RangeMapper
|
Chris@880
|
99 {
|
Chris@880
|
100 public:
|
Chris@880
|
101 typedef std::map<float, int> CoordMap;
|
Chris@880
|
102
|
Chris@880
|
103 /**
|
Chris@880
|
104 * Given a series of (value, position) coordinate mappings,
|
Chris@880
|
105 * construct a range mapper that maps arbitrary values, in the
|
Chris@880
|
106 * range between minimum and maximum of the provided values, onto
|
Chris@880
|
107 * coordinates using linear interpolation between the supplied
|
Chris@880
|
108 * points.
|
Chris@880
|
109 *
|
Chris@880
|
110 *!!! todo: Cubic -- more generally useful than linear interpolation
|
Chris@880
|
111 *!!! todo: inverted flag
|
Chris@880
|
112 *
|
Chris@880
|
113 * The set of provided mappings must contain at least two
|
Chris@880
|
114 * coordinates.
|
Chris@880
|
115 *
|
Chris@880
|
116 * It is expected that the values and positions in the coordinate
|
Chris@880
|
117 * mappings will both be monotonically increasing (i.e. no
|
Chris@880
|
118 * inflections in the mapping curve). Behaviour is undefined if
|
Chris@880
|
119 * this is not the case.
|
Chris@880
|
120 */
|
Chris@880
|
121 InterpolatingRangeMapper(CoordMap pointMappings,
|
Chris@880
|
122 QString unit);
|
Chris@880
|
123
|
Chris@880
|
124 virtual int getPositionForValue(float value) const;
|
Chris@880
|
125 virtual float getValueForPosition(int position) const;
|
Chris@880
|
126
|
Chris@880
|
127 virtual QString getUnit() const { return m_unit; }
|
Chris@880
|
128
|
Chris@880
|
129 protected:
|
Chris@880
|
130 CoordMap m_mappings;
|
Chris@880
|
131 std::map<int, float> m_reverse;
|
Chris@880
|
132 QString m_unit;
|
Chris@880
|
133 };
|
Chris@880
|
134
|
Chris@880
|
135 class AutoRangeMapper : public RangeMapper
|
Chris@880
|
136 {
|
Chris@880
|
137 public:
|
Chris@880
|
138 enum MappingType {
|
Chris@880
|
139 Interpolating,
|
Chris@880
|
140 StraightLine,
|
Chris@880
|
141 Logarithmic,
|
Chris@880
|
142 };
|
Chris@880
|
143
|
Chris@880
|
144 typedef std::map<float, int> CoordMap;
|
Chris@880
|
145
|
Chris@880
|
146 /**
|
Chris@880
|
147 * Given a series of (value, position) coordinate mappings,
|
Chris@880
|
148 * construct a range mapper that maps arbitrary values, in the
|
Chris@880
|
149 * range between minimum and maximum of the provided values, onto
|
Chris@880
|
150 * coordinates.
|
Chris@880
|
151 *
|
Chris@880
|
152 * The mapping used may be
|
Chris@880
|
153 *
|
Chris@880
|
154 * Interpolating -- an InterpolatingRangeMapper will be used
|
Chris@880
|
155 *
|
Chris@880
|
156 * StraightLine -- a LinearRangeMapper from the minimum to
|
Chris@880
|
157 * maximum value coordinates will be used, ignoring all other
|
Chris@880
|
158 * supplied coordinate mappings
|
Chris@880
|
159 *
|
Chris@880
|
160 * Logarithmic -- a LogRangeMapper from the minimum to
|
Chris@880
|
161 * maximum value coordinates will be used, ignoring all other
|
Chris@880
|
162 * supplied coordinate mappings
|
Chris@880
|
163 *
|
Chris@880
|
164 * The mapping will be chosen automatically by looking at the
|
Chris@880
|
165 * supplied coordinates. If the supplied coordinates fall on a
|
Chris@880
|
166 * straight line, a StraightLine mapping will be used; if they
|
Chris@880
|
167 * fall on a log curve, a Logarithmic mapping will be used;
|
Chris@880
|
168 * otherwise an Interpolating mapping will be used.
|
Chris@880
|
169 *
|
Chris@880
|
170 *!!! todo: inverted flag
|
Chris@880
|
171 *
|
Chris@880
|
172 * The set of provided mappings must contain at least two
|
Chris@880
|
173 * coordinates, or at least three if the points are not supposed
|
Chris@880
|
174 * to be in a straight line.
|
Chris@880
|
175 *
|
Chris@880
|
176 * It is expected that the values and positions in the coordinate
|
Chris@880
|
177 * mappings will both be monotonically increasing (i.e. no
|
Chris@880
|
178 * inflections in the mapping curve). Behaviour is undefined if
|
Chris@880
|
179 * this is not the case.
|
Chris@880
|
180 */
|
Chris@880
|
181 AutoRangeMapper(CoordMap pointMappings,
|
Chris@880
|
182 QString unit);
|
Chris@880
|
183
|
Chris@880
|
184 ~AutoRangeMapper();
|
Chris@880
|
185
|
Chris@880
|
186 /**
|
Chris@880
|
187 * Return the mapping type in use.
|
Chris@880
|
188 */
|
Chris@880
|
189 MappingType getType() const { return m_type; }
|
Chris@880
|
190
|
Chris@880
|
191 virtual int getPositionForValue(float value) const;
|
Chris@880
|
192 virtual float getValueForPosition(int position) const;
|
Chris@880
|
193
|
Chris@880
|
194 virtual QString getUnit() const { return m_unit; }
|
Chris@880
|
195
|
Chris@880
|
196 protected:
|
Chris@880
|
197 MappingType m_type;
|
Chris@880
|
198 CoordMap m_mappings;
|
Chris@880
|
199 QString m_unit;
|
Chris@880
|
200 RangeMapper *m_mapper;
|
Chris@880
|
201
|
Chris@880
|
202 MappingType chooseMappingTypeFor(const CoordMap &);
|
Chris@880
|
203 };
|
Chris@189
|
204
|
Chris@189
|
205 #endif
|