summaryrefslogtreecommitdiff
path: root/libs/evoral/test/CurveTest.cpp
blob: 36c4d808d2518aeb402d1c8836d8a3b9c863525d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#include "CurveTest.hpp"
#include "evoral/ControlList.hpp"
#include "evoral/Curve.hpp"
#include <stdlib.h>

CPPUNIT_TEST_SUITE_REGISTRATION (CurveTest);

using namespace Evoral;

// linear y = Y0 + YS * x ;  with x = i * (X1 - X0) + X0; and i = [0..1023]
#define VEC1024LINCMP(X0, X1, Y0, YS)                                        \
    cl->curve ().get_vector ((X0), (X1), vec, 1024);                         \
    for (int i = 0; i < 1024; ++i) {                                         \
        char msg[64];                                                        \
        snprintf (msg, 64, "at i=%d (x0=%.1f, x1=%.1f, y0=%.1f, ys=%.3f)",   \
            i, X0, X1, Y0, YS);                                              \
        CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE (                               \
            msg,                                                             \
            (Y0) + i * (YS), vec[i],                                         \
            1e-24                                                            \
            );                                                               \
    }

void
CurveTest::twoPointLinear ()
{
	float vec[1024];

	boost::shared_ptr<Evoral::ControlList> cl = TestCtrlList();

	cl->create_curve ();
	cl->set_interpolation (ControlList::Linear);

	// add two points to curve
	cl->fast_simple_add (   0.0 , 2048.0);
	cl->fast_simple_add (8192.0 , 4096.0);

	cl->curve ().get_vector (1024.0, 2047.0, vec, 1024);

	VEC1024LINCMP (1024.0, 2047.0, 2304.f,  .25f);
	VEC1024LINCMP (2048.0, 2559.5, 2560.f,  .125f);
	VEC1024LINCMP (   0.0, 4092.0, 2048.f, 1.f);

	// greetings to tartina
	cl->curve ().get_vector (2048.0, 2048.0, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 @ 2048..2048", 2560.f, vec[0]);

	/* XXX WHAT DO WE EXPECT WITH veclen=1 AND  x1 > x0 ? */
#if 0
	/* .. interpolated value at (x1+x0)/2 */
	cl->curve ().get_vector (2048.0, 2049.0, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 @ 2048-2049", 2560.125f, vec[0]);

	cl->curve ().get_vector (2048.0, 2056.0, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 @ 2048-2049", 2561.f, vec[0]);
#else
	/* .. value at x0 */
	cl->curve ().get_vector (2048.0, 2049.0, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 , 2048..2049", 2560.f, vec[0]);

	cl->curve ().get_vector (2048.0, 2056.0, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 , 2048..2049", 2560.f, vec[0]);
#endif

	cl->curve ().get_vector (2048.0, 2048.0, vec, 2);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=2 , 2048..2048 @ 0", 2560.f, vec[0]);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=2 , 2048..2048 @ 1", 2560.f, vec[1]);

	cl->curve ().get_vector (2048.0, 2056.0, vec, 2);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=2 , 2048..2056 @ 0", 2560.f, vec[0]);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=2 , 2048..2056 @ 0", 2562.f, vec[1]);

	cl->curve ().get_vector (2048.0, 2056.0, vec, 3);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=3 , 2048..2056 @ 0", 2560.f, vec[0]);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=3 , 2048..2056 @ 1", 2561.f, vec[1]);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=3 , 2048..2056 @ 2", 2562.f, vec[2]);

	/* check out-of range..
	 * we expect the first and last value - no interpolation
	 */
	cl->curve ().get_vector (-1, -1, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 @ -1", 2048.f, vec[0]);

	cl->curve ().get_vector (9999.0, 9999.0, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 @ 9999", 4096.f, vec[0]);

	cl->curve ().get_vector (-999.0, 0, vec, 13);
	for (int i = 0; i < 13; ++i) {
		CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=13 @ -999..0", 2048.f, vec[i]);
	}

	cl->curve ().get_vector (9998.0, 9999.0, vec, 8);
	for (int i = 0; i < 8; ++i) {
		CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=8 @ 9998..9999", 4096.f, vec[i]);
	}
}

void
CurveTest::threePointLinear ()
{
	float vec[4];

	boost::shared_ptr<Evoral::ControlList> cl = TestCtrlList();

	cl->create_curve ();
	cl->set_interpolation (ControlList::Linear);

	// add 3 points to curve
	cl->fast_simple_add (   0.0 , 2.0);
	cl->fast_simple_add ( 100.0 , 4.0);
	cl->fast_simple_add ( 200.0 , 0.0);

	cl->curve ().get_vector (50.0, 60.0, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 @ 50", 3.f, vec[0]);

	cl->curve ().get_vector (100.0, 100.0, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 @ 100", 4.f, vec[0]);

	cl->curve ().get_vector (150.0, 150.0, vec, 1);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=1 @ 150", 2.f, vec[0]);

	cl->curve ().get_vector (130.0, 150.0, vec, 3);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=3 130..150 @ 0", 2.8f, vec[0]);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=3 130..150 @ 2", 2.4f, vec[1]);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=3 130..150 @ 3", 2.0f, vec[2]);

	cl->curve ().get_vector (80.0, 160.0, vec, 3);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=3 80..160 @ 0", 3.6f, vec[0]);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=3 80..160 @ 2", 3.2f, vec[1]);
	CPPUNIT_ASSERT_EQUAL_MESSAGE ("veclen=3 80..160 @ 3", 1.6f, vec[2]);
}

void
CurveTest::threePointDiscete ()
{
	boost::shared_ptr<Evoral::ControlList> cl = TestCtrlList();
	cl->set_interpolation (ControlList::Discrete);

	// add 3 points to curve
	cl->fast_simple_add (   0.0 , 2.0);
	cl->fast_simple_add ( 100.0 , 4.0);
	cl->fast_simple_add ( 200.0 , 0.0);

	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(160.));

	cl->set_interpolation (ControlList::Linear);

	CPPUNIT_ASSERT_EQUAL(3.6, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(3.2, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(1.6, cl->unlocked_eval(160.));
}

void
CurveTest::ctrlListEval ()
{
	boost::shared_ptr<Evoral::ControlList> cl = TestCtrlList();

	cl->fast_simple_add (   0.0 , 2.0);

	cl->set_interpolation (ControlList::Discrete);
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(160.));

	cl->set_interpolation (ControlList::Linear);
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(160.));

	cl->fast_simple_add ( 100.0 , 4.0);

	cl->set_interpolation (ControlList::Discrete);
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(160.));

	cl->set_interpolation (ControlList::Linear);
	CPPUNIT_ASSERT_EQUAL(3.6, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(160.));

	cl->fast_simple_add ( 200.0 , 0.0);

	cl->set_interpolation (ControlList::Discrete);
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(160.));

	cl->set_interpolation (ControlList::Linear);
	CPPUNIT_ASSERT_EQUAL(3.6, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(3.2, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(1.6, cl->unlocked_eval(160.));

	cl->fast_simple_add ( 300.0 , 8.0);

	cl->set_interpolation (ControlList::Discrete);
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(160.));
	CPPUNIT_ASSERT_EQUAL(0.0, cl->unlocked_eval(250.));
	CPPUNIT_ASSERT_EQUAL(8.0, cl->unlocked_eval(999.));

	cl->set_interpolation (ControlList::Linear);
	CPPUNIT_ASSERT_EQUAL(3.6, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(3.2, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(1.6, cl->unlocked_eval(160.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(250.));
	CPPUNIT_ASSERT_EQUAL(8.0, cl->unlocked_eval(999.));

	cl->fast_simple_add ( 400.0 , 9.0);

	cl->set_interpolation (ControlList::Discrete);
	CPPUNIT_ASSERT_EQUAL(2.0, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(160.));
	CPPUNIT_ASSERT_EQUAL(0.0, cl->unlocked_eval(250.));
	CPPUNIT_ASSERT_EQUAL(8.0, cl->unlocked_eval(350.));
	CPPUNIT_ASSERT_EQUAL(9.0, cl->unlocked_eval(999.));

	cl->set_interpolation (ControlList::Linear);
	CPPUNIT_ASSERT_EQUAL(3.6, cl->unlocked_eval(80.));
	CPPUNIT_ASSERT_EQUAL(3.2, cl->unlocked_eval(120.));
	CPPUNIT_ASSERT_EQUAL(1.6, cl->unlocked_eval(160.));
	CPPUNIT_ASSERT_EQUAL(4.0, cl->unlocked_eval(250.));
	CPPUNIT_ASSERT_EQUAL(8.5, cl->unlocked_eval(350.));
	CPPUNIT_ASSERT_EQUAL(9.0, cl->unlocked_eval(999.));
}