Use a static string variable for dll path.
[ardour.git] / libs / ardour / test / playlist_read_test.cc
1 /*
2     Copyright (C) 2012 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include "ardour/playlist.h"
20 #include "ardour/region.h"
21 #include "ardour/audioplaylist.h"
22 #include "ardour/audioregion.h"
23 #include "ardour/session.h"
24 #include "playlist_read_test.h"
25 #include "test_globals.h"
26
27 CPPUNIT_TEST_SUITE_REGISTRATION (PlaylistReadTest);
28
29 using namespace std;
30 using namespace ARDOUR;
31
32 void
33 PlaylistReadTest::setUp ()
34 {
35         AudioRegionTest::setUp ();
36
37         _N = 1024;
38         _buf = new Sample[_N];
39         _mbuf = new Sample[_N];
40         _gbuf = new float[_N];
41
42         //_session->config.set_auto_xfade (false);
43
44         for (int i = 0; i < _N; ++i) {
45                 _buf[i] = 0;
46         }
47 }
48
49 void
50 PlaylistReadTest::tearDown ()
51 {
52         delete[] _buf;
53         delete[] _mbuf;
54         delete[] _gbuf;
55
56         AudioRegionTest::tearDown ();
57 }
58
59 void
60 PlaylistReadTest::singleReadTest ()
61 {
62         /* Single-region read with fades */
63
64         _audio_playlist->add_region (_ar[0], 0);
65         _ar[0]->set_default_fade_in ();
66         _ar[0]->set_default_fade_out ();
67         CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_in->back()->when);
68         CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
69         _ar[0]->set_length (1024);
70         _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 256, 0);
71         
72         for (int i = 0; i < 64; ++i) {
73                 /* Note: this specific float casting is necessary so that the rounding
74                    is done here the same as it is done in AudioPlaylist.
75                 */
76                 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * float (i / 63.0)), _buf[i], 1e-16);
77         }
78         
79         for (int i = 64; i < 256; ++i) {
80                 CPPUNIT_ASSERT_EQUAL (i, int (_buf[i]));
81         }
82 }
83
84 void
85 PlaylistReadTest::overlappingReadTest ()
86 {
87         /* Overlapping read; _ar[0] and _ar[1] are both 1024 frames long, _ar[0] starts at 0,
88            _ar[1] starts at 128.  We test a read from 0 to 256, which should consist
89            of the start of _ar[0], with its fade in, followed by _ar[1]'s fade in (mixed with _ar[0]
90            faded out with the inverse gain), and some more of _ar[1].
91         */
92
93         _audio_playlist->add_region (_ar[0], 0);
94         _ar[0]->set_default_fade_in ();
95         _ar[0]->set_default_fade_out ();
96         CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_in->back()->when);
97         CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
98         _ar[0]->set_length (1024);
99
100 #if 0
101         /* Note: these are ordinary fades, not xfades */
102         CPPUNIT_ASSERT_EQUAL (false, _ar[0]->fade_in_is_xfade());
103         CPPUNIT_ASSERT_EQUAL (false, _ar[0]->fade_out_is_xfade());
104 #endif
105         
106         _audio_playlist->add_region (_ar[1], 128);
107         _ar[1]->set_default_fade_in ();
108         _ar[1]->set_default_fade_out ();
109
110 #if 0
111         /* Note: these are ordinary fades, not xfades */
112         CPPUNIT_ASSERT_EQUAL (false, _ar[1]->fade_in_is_xfade());
113         CPPUNIT_ASSERT_EQUAL (false, _ar[1]->fade_out_is_xfade());
114 #endif
115         
116         CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_in->back()->when);
117         CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_out->back()->when);
118         
119         _ar[1]->set_length (1024);
120         _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 256, 0);
121
122         /* _ar[0]'s fade in */
123         for (int i = 0; i < 64; ++i) {
124                 /* Note: this specific float casting is necessary so that the rounding
125                    is done here the same as it is done in AudioPlaylist; the gain factor
126                    must be computed using double precision, with the result then cast
127                    to float.
128                 */
129                 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * float (i / (double) 63)), _buf[i], 1e-16);
130         }
131
132         /* bit of _ar[0] */
133         for (int i = 64; i < 128; ++i) {
134                 CPPUNIT_ASSERT_EQUAL (i, int (_buf[i]));
135         }
136
137         /* _ar[1]'s fade in with faded-out _ar[0] */
138         for (int i = 0; i < 64; ++i) {
139                 /* Similar carry-on to above with float rounding */
140                 float const from_ar0 = (128 + i) * float (1 - (i / (double) 63));
141                 float const from_ar1 = i * float (i / (double) 63);
142                 CPPUNIT_ASSERT_DOUBLES_EQUAL (from_ar0 + from_ar1, _buf[i + 128], 1e-16);
143         }
144 }
145
146 void
147 PlaylistReadTest::transparentReadTest ()
148 {
149         _audio_playlist->add_region (_ar[0], 0);
150         _ar[0]->set_default_fade_in ();
151         _ar[0]->set_default_fade_out ();
152         CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_in->back()->when);
153         CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
154         _ar[0]->set_length (1024);
155         
156         _audio_playlist->add_region (_ar[1], 0);
157         _ar[1]->set_default_fade_in ();
158         _ar[1]->set_default_fade_out ();
159         CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_in->back()->when);
160         CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_out->back()->when);
161         _ar[1]->set_length (1024);
162         _ar[1]->set_opaque (false);
163
164         _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 1024, 0);
165
166         /* _ar[0] and _ar[1] fade-ins; _ar[1] is on top, but it is transparent, so
167            its fade in will not affect _ar[0]; _ar[0] will just fade in by itself,
168            and the two will be mixed.
169         */
170         for (int i = 0; i < 64; ++i) {
171                 float const fade = i / (double) 63;
172                 float const ar0 = i * fade;
173                 float const ar1 = i * fade;
174                 CPPUNIT_ASSERT_DOUBLES_EQUAL (ar0 + ar1, _buf[i], 1e-16);
175         }
176
177         /* _ar[0] and _ar[1] bodies, mixed */
178         for (int i = 64; i < (1024 - 64); ++i) {
179                 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * 2), _buf[i], 1e-16);
180         }
181
182         /* _ar[0] and _ar[1] fade-outs, mixed */
183         for (int i = (1024 - 64); i < 1024; ++i) {
184                 /* Ardour fades out from 1 to VERY_SMALL_SIGNAL, which is 0.0000001,
185                    so this fade out expression is a little long-winded.
186                 */
187                 float const fade = (((double) 1 - 0.0000001) / 63) * (1023 - i) + 0.0000001;
188                 float const ar0 = i * fade;
189                 float const ar1 = i * fade;
190                 CPPUNIT_ASSERT_DOUBLES_EQUAL (ar0 + ar1, _buf[i], 1e-16);
191         }
192 }
193
194 /* A few tests just to check that nothing nasty is happening with
195    memory corruption, really (for running with valgrind).
196 */
197 void
198 PlaylistReadTest::miscReadTest ()
199 {
200         _audio_playlist->add_region (_ar[0], 0);
201         _ar[0]->set_default_fade_in ();
202         _ar[0]->set_default_fade_out ();
203         CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_in->back()->when);
204         CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
205         _ar[0]->set_length (128);
206
207         /* Read for just longer than the region */
208         _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 129, 0);
209
210         /* Read for much longer than the region */
211         _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 1024, 0);
212
213         /* Read one sample */
214         _audio_playlist->read (_buf, _mbuf, _gbuf, 53, 54, 0);
215 }
216
217 void
218 PlaylistReadTest::check_staircase (Sample* b, int offset, int N)
219 {
220         for (int i = 0; i < N; ++i) {
221                 int const j = i + offset;
222                 CPPUNIT_ASSERT_EQUAL (j, int (b[i]));
223         }
224 }
225
226 /* Check the case where we have
227  *    |----------- Region A (transparent) ------------------|
228  *                     |---- Region B (opaque) --|
229  *
230  * The result should be a mix of the two during region B's time.
231  */
232
233 void
234 PlaylistReadTest::enclosedTransparentReadTest ()
235 {
236         _audio_playlist->add_region (_ar[0], 256);
237         /* These calls will result in a 64-sample fade */
238         _ar[0]->set_fade_in_length (0);
239         _ar[0]->set_fade_out_length (0);
240         _ar[0]->set_length (256);
241         
242         _audio_playlist->add_region (_ar[1], 0);
243         /* These calls will result in a 64-sample fade */
244         _ar[1]->set_fade_in_length (0);
245         _ar[1]->set_fade_out_length (0);
246         _ar[1]->set_length (1024);
247         _ar[1]->set_opaque (false);
248
249         _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 1024, 0);
250
251         /* First 64 samples should just be _ar[1], faded in */
252         for (int i = 0; i < 64; ++i) {
253                 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * float (i / 63.0)), _buf[i], 1e-16);
254         }
255
256         /* Then some of _ar[1] with no fade */
257         for (int i = 64; i < 256; ++i) {
258                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i, _buf[i], 1e-16);
259         }
260
261         /* Then _ar[1] + _ar[0] (faded in) for 64 samples */
262         for (int i = 256; i < (256 + 64); ++i) {
263                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i + float ((i - 256) * float ((i - 256) / 63.0)), _buf[i], 1e-16);
264         }
265
266         /* Then _ar[1] + _ar[0] for 128 samples */
267         for (int i = (256 + 64); i < (256 + 64 + 128); ++i) {
268                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i + i - (256 + 64) + 64, _buf[i], 1e-16);
269         }
270         
271         /* Then _ar[1] + _ar[0] (faded out) for 64 samples */
272         for (int i = (256 + 64 + 128); i < 512; ++i) {
273                 float const ar0_without_fade = i - 256;
274                 /* See above regarding VERY_SMALL_SIGNAL SNAFU */
275                 float const fade = (((double) 1 - 0.0000001) / 63) * (511 - i) + 0.0000001;
276                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i + float (ar0_without_fade * fade), _buf[i], 1e-16);
277         }
278
279         /* Then just _ar[1] for a while */
280         for (int i = 512; i < (1024 - 64); ++i) {
281                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i, _buf[i], 1e-16);
282         }
283
284         /* And finally _ar[1]'s fade out */
285         for (int i = (1024 - 64); i < 1024; ++i) {
286                 /* See above regarding VERY_SMALL_SIGNAL SNAFU */
287                 float const fade = (((double) 1 - 0.0000001) / 63) * (1023 - i) + 0.0000001;
288                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i * fade, _buf[i], 1e-16);
289
290         }
291 }