2 Copyright (C) 2012 Paul Davis
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.
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.
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.
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"
26 CPPUNIT_TEST_SUITE_REGISTRATION (PlaylistReadTest);
29 using namespace ARDOUR;
32 PlaylistReadTest::setUp ()
34 AudioRegionTest::setUp ();
37 _buf = new Sample[_N];
38 _mbuf = new Sample[_N];
39 _gbuf = new float[_N];
41 //_session->config.set_auto_xfade (false);
43 for (int i = 0; i < _N; ++i) {
49 PlaylistReadTest::tearDown ()
55 AudioRegionTest::tearDown ();
59 PlaylistReadTest::singleReadTest ()
61 /* Single-region read with fades */
63 _audio_playlist->add_region (_ar[0], 0);
64 _ar[0]->set_default_fade_in ();
65 _ar[0]->set_default_fade_out ();
66 CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_in->back()->when);
67 CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
68 _ar[0]->set_length (1024);
69 _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 256, 0);
71 for (int i = 0; i < 64; ++i) {
72 /* Note: this specific float casting is necessary so that the rounding
73 is done here the same as it is done in AudioPlaylist.
75 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * float (i / 63.0)), _buf[i], 1e-16);
78 for (int i = 64; i < 256; ++i) {
79 CPPUNIT_ASSERT_EQUAL (i, int (_buf[i]));
84 PlaylistReadTest::overlappingReadTest ()
86 /* Overlapping read; _ar[0] and _ar[1] are both 1024 samples long, _ar[0] starts at 0,
87 _ar[1] starts at 128. We test a read from 0 to 256, which should consist
88 of the start of _ar[0], with its fade in, followed by _ar[1]'s fade in (mixed with _ar[0]
89 faded out with the inverse gain), and some more of _ar[1].
92 _audio_playlist->add_region (_ar[0], 0);
93 _ar[0]->set_default_fade_in ();
94 _ar[0]->set_default_fade_out ();
95 CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_in->back()->when);
96 CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
97 _ar[0]->set_length (1024);
100 /* Note: these are ordinary fades, not xfades */
101 CPPUNIT_ASSERT_EQUAL (false, _ar[0]->fade_in_is_xfade());
102 CPPUNIT_ASSERT_EQUAL (false, _ar[0]->fade_out_is_xfade());
105 _audio_playlist->add_region (_ar[1], 128);
106 _ar[1]->set_default_fade_in ();
107 _ar[1]->set_default_fade_out ();
110 /* Note: these are ordinary fades, not xfades */
111 CPPUNIT_ASSERT_EQUAL (false, _ar[1]->fade_in_is_xfade());
112 CPPUNIT_ASSERT_EQUAL (false, _ar[1]->fade_out_is_xfade());
115 CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_in->back()->when);
116 CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_out->back()->when);
118 _ar[1]->set_length (1024);
119 _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 256, 0);
121 /* _ar[0]'s fade in */
122 for (int i = 0; i < 64; ++i) {
123 /* Note: this specific float casting is necessary so that the rounding
124 is done here the same as it is done in AudioPlaylist; the gain factor
125 must be computed using double precision, with the result then cast
128 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * float (i / (double) 63)), _buf[i], 1e-16);
132 for (int i = 64; i < 128; ++i) {
133 CPPUNIT_ASSERT_EQUAL (i, int (_buf[i]));
136 /* _ar[1]'s fade in with faded-out _ar[0] */
137 for (int i = 0; i < 64; ++i) {
138 /* Similar carry-on to above with float rounding */
139 float const from_ar0 = (128 + i) * float (1 - (i / (double) 63));
140 float const from_ar1 = i * float (i / (double) 63);
141 CPPUNIT_ASSERT_DOUBLES_EQUAL (from_ar0 + from_ar1, _buf[i + 128], 1e-16);
146 PlaylistReadTest::transparentReadTest ()
148 _audio_playlist->add_region (_ar[0], 0);
149 _ar[0]->set_default_fade_in ();
150 _ar[0]->set_default_fade_out ();
151 CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_in->back()->when);
152 CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
153 _ar[0]->set_length (1024);
155 _audio_playlist->add_region (_ar[1], 0);
156 _ar[1]->set_default_fade_in ();
157 _ar[1]->set_default_fade_out ();
158 CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_in->back()->when);
159 CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_out->back()->when);
160 _ar[1]->set_length (1024);
161 _ar[1]->set_opaque (false);
163 _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 1024, 0);
165 /* _ar[0] and _ar[1] fade-ins; _ar[1] is on top, but it is transparent, so
166 its fade in will not affect _ar[0]; _ar[0] will just fade in by itself,
167 and the two will be mixed.
169 for (int i = 0; i < 64; ++i) {
170 float const fade = i / (double) 63;
171 float const ar0 = i * fade;
172 float const ar1 = i * fade;
173 CPPUNIT_ASSERT_DOUBLES_EQUAL (ar0 + ar1, _buf[i], 1e-16);
176 /* _ar[0] and _ar[1] bodies, mixed */
177 for (int i = 64; i < (1024 - 64); ++i) {
178 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * 2), _buf[i], 1e-16);
181 /* _ar[0] and _ar[1] fade-outs, mixed */
182 for (int i = (1024 - 64); i < 1024; ++i) {
183 /* Ardour fades out from 1 to VERY_SMALL_SIGNAL, which is 0.0000001,
184 so this fade out expression is a little long-winded.
186 float const fade = (((double) 1 - 0.0000001) / 63) * (1023 - i) + 0.0000001;
187 float const ar0 = i * fade;
188 float const ar1 = i * fade;
189 CPPUNIT_ASSERT_DOUBLES_EQUAL (ar0 + ar1, _buf[i], 1e-16);
193 /* A few tests just to check that nothing nasty is happening with
194 memory corruption, really (for running with valgrind).
197 PlaylistReadTest::miscReadTest ()
199 _audio_playlist->add_region (_ar[0], 0);
200 _ar[0]->set_default_fade_in ();
201 _ar[0]->set_default_fade_out ();
202 CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_in->back()->when);
203 CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
204 _ar[0]->set_length (128);
206 /* Read for just longer than the region */
207 _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 129, 0);
209 /* Read for much longer than the region */
210 _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 1024, 0);
212 /* Read one sample */
213 _audio_playlist->read (_buf, _mbuf, _gbuf, 53, 54, 0);
217 PlaylistReadTest::check_staircase (Sample* b, int offset, int N)
219 for (int i = 0; i < N; ++i) {
220 int const j = i + offset;
221 CPPUNIT_ASSERT_EQUAL (j, int (b[i]));
225 /* Check the case where we have
226 * |----------- Region A (transparent) ------------------|
227 * |---- Region B (opaque) --|
229 * The result should be a mix of the two during region B's time.
233 PlaylistReadTest::enclosedTransparentReadTest ()
235 _audio_playlist->add_region (_ar[0], 256);
236 /* These calls will result in a 64-sample fade */
237 _ar[0]->set_fade_in_length (0);
238 _ar[0]->set_fade_out_length (0);
239 _ar[0]->set_length (256);
241 _audio_playlist->add_region (_ar[1], 0);
242 /* These calls will result in a 64-sample fade */
243 _ar[1]->set_fade_in_length (0);
244 _ar[1]->set_fade_out_length (0);
245 _ar[1]->set_length (1024);
246 _ar[1]->set_opaque (false);
248 _audio_playlist->read (_buf, _mbuf, _gbuf, 0, 1024, 0);
250 /* First 64 samples should just be _ar[1], faded in */
251 for (int i = 0; i < 64; ++i) {
252 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * float (i / 63.0)), _buf[i], 1e-16);
255 /* Then some of _ar[1] with no fade */
256 for (int i = 64; i < 256; ++i) {
257 CPPUNIT_ASSERT_DOUBLES_EQUAL (i, _buf[i], 1e-16);
260 /* Then _ar[1] + _ar[0] (faded in) for 64 samples */
261 for (int i = 256; i < (256 + 64); ++i) {
262 CPPUNIT_ASSERT_DOUBLES_EQUAL (i + float ((i - 256) * float ((i - 256) / 63.0)), _buf[i], 1e-16);
265 /* Then _ar[1] + _ar[0] for 128 samples */
266 for (int i = (256 + 64); i < (256 + 64 + 128); ++i) {
267 CPPUNIT_ASSERT_DOUBLES_EQUAL (i + i - (256 + 64) + 64, _buf[i], 1e-16);
270 /* Then _ar[1] + _ar[0] (faded out) for 64 samples */
271 for (int i = (256 + 64 + 128); i < 512; ++i) {
272 float const ar0_without_fade = i - 256;
273 /* See above regarding VERY_SMALL_SIGNAL SNAFU */
274 float const fade = (((double) 1 - 0.0000001) / 63) * (511 - i) + 0.0000001;
275 CPPUNIT_ASSERT_DOUBLES_EQUAL (i + float (ar0_without_fade * fade), _buf[i], 1e-16);
278 /* Then just _ar[1] for a while */
279 for (int i = 512; i < (1024 - 64); ++i) {
280 CPPUNIT_ASSERT_DOUBLES_EQUAL (i, _buf[i], 1e-16);
283 /* And finally _ar[1]'s fade out */
284 for (int i = (1024 - 64); i < 1024; ++i) {
285 /* See above regarding VERY_SMALL_SIGNAL SNAFU */
286 float const fade = (((double) 1 - 0.0000001) / 63) * (1023 - i) + 0.0000001;
287 CPPUNIT_ASSERT_DOUBLES_EQUAL (i * fade, _buf[i], 1e-16);