ac76198ae54cefe5451df5ff615fafcaaba7fe61
[ardour.git] / libs / ardour / test / playlist_read_test.cc
1 #include "ardour/playlist.h"
2 #include "ardour/region.h"
3 #include "ardour/audioplaylist.h"
4 #include "ardour/audioregion.h"
5 #include "ardour/session.h"
6 #include "playlist_read_test.h"
7 #include "test_globals.h"
8
9 CPPUNIT_TEST_SUITE_REGISTRATION (PlaylistReadTest);
10
11 using namespace std;
12 using namespace ARDOUR;
13
14 void
15 PlaylistReadTest::setUp ()
16 {
17         TestNeedingPlaylistAndRegions::setUp ();
18
19         _N = 1024;
20         _buf = new Sample[_N];
21         _mbuf = new Sample[_N];
22         _gbuf = new float[_N];
23
24         _session->config.set_auto_xfade (false);
25
26         _apl = boost::dynamic_pointer_cast<AudioPlaylist> (_playlist);
27
28         for (int i = 0; i < _N; ++i) {
29                 _buf[i] = 0;
30         }
31 }
32
33 void
34 PlaylistReadTest::tearDown ()
35 {
36         delete[] _buf;
37         delete[] _mbuf;
38         delete[] _gbuf;
39
40         _apl.reset ();
41
42         TestNeedingPlaylistAndRegions::tearDown ();
43 }
44
45 void
46 PlaylistReadTest::singleReadTest ()
47 {
48         /* Single-region read with fades */
49
50         boost::shared_ptr<AudioRegion> ar0 = boost::dynamic_pointer_cast<AudioRegion> (_region[0]);
51         ar0->set_name ("ar0");
52         _apl->add_region (ar0, 0);
53         ar0->set_default_fade_in ();
54         ar0->set_default_fade_out ();
55         CPPUNIT_ASSERT_EQUAL (double (64), ar0->_fade_in->back()->when);
56         CPPUNIT_ASSERT_EQUAL (double (64), ar0->_fade_out->back()->when);
57         ar0->set_length (1024);
58         _apl->read (_buf, _mbuf, _gbuf, 0, 256, 0);
59         
60         for (int i = 0; i < 64; ++i) {
61                 /* Note: this specific float casting is necessary so that the rounding
62                    is done here the same as it is done in AudioPlaylist.
63                 */
64                 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * float (i / 63.0)), _buf[i], 1e-16);
65         }
66         
67         for (int i = 64; i < 256; ++i) {
68                 CPPUNIT_ASSERT_EQUAL (i, int (_buf[i]));
69         }
70 }
71
72 void
73 PlaylistReadTest::overlappingReadTest ()
74 {
75         /* Overlapping read; ar0 and ar1 are both 1024 frames long, ar0 starts at 0,
76            ar1 starts at 128.  We test a read from 0 to 256, which should consist
77            of the start of ar0, with its fade in, followed by ar1's fade in (mixed with ar0
78            faded out with the inverse gain), and some more of ar1.
79         */
80
81         boost::shared_ptr<AudioRegion> ar0 = boost::dynamic_pointer_cast<AudioRegion> (_region[0]);
82         ar0->set_name ("ar0");
83         _apl->add_region (ar0, 0);
84         ar0->set_default_fade_in ();
85         ar0->set_default_fade_out ();
86         CPPUNIT_ASSERT_EQUAL (double (64), ar0->_fade_in->back()->when);
87         CPPUNIT_ASSERT_EQUAL (double (64), ar0->_fade_out->back()->when);
88         ar0->set_length (1024);
89         
90         boost::shared_ptr<AudioRegion> ar1 = boost::dynamic_pointer_cast<AudioRegion> (_region[1]);
91         ar1->set_name ("ar1");
92         _apl->add_region (ar1, 128);
93         ar1->set_default_fade_in ();
94         ar1->set_default_fade_out ();
95         
96         CPPUNIT_ASSERT_EQUAL (double (64), ar1->_fade_in->back()->when);
97         CPPUNIT_ASSERT_EQUAL (double (64), ar1->_fade_out->back()->when);
98         
99         ar1->set_length (1024);
100         _apl->read (_buf, _mbuf, _gbuf, 0, 256, 0);
101
102         /* ar0's fade in */
103         for (int i = 0; i < 64; ++i) {
104                 /* Note: this specific float casting is necessary so that the rounding
105                    is done here the same as it is done in AudioPlaylist; the gain factor
106                    must be computed using double precision, with the result then cast
107                    to float.
108                 */
109                 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * float (i / (double) 63)), _buf[i], 1e-16);
110         }
111
112         /* bit of ar0 */
113         for (int i = 64; i < 128; ++i) {
114                 CPPUNIT_ASSERT_EQUAL (i, int (_buf[i]));
115         }
116
117         /* ar1's fade in with faded-out ar0 */
118         for (int i = 0; i < 64; ++i) {
119                 /* Similar carry-on to above with float rounding */
120                 float const from_ar0 = (128 + i) * float (1 - (i / (double) 63));
121                 float const from_ar1 = i * float (i / (double) 63);
122                 CPPUNIT_ASSERT_DOUBLES_EQUAL (from_ar0 + from_ar1, _buf[i + 128], 1e-16);
123         }
124 }
125
126 void
127 PlaylistReadTest::transparentReadTest ()
128 {
129         boost::shared_ptr<AudioRegion> ar0 = boost::dynamic_pointer_cast<AudioRegion> (_region[0]);
130         ar0->set_name ("ar0");
131         _apl->add_region (ar0, 0);
132         ar0->set_default_fade_in ();
133         ar0->set_default_fade_out ();
134         CPPUNIT_ASSERT_EQUAL (double (64), ar0->_fade_in->back()->when);
135         CPPUNIT_ASSERT_EQUAL (double (64), ar0->_fade_out->back()->when);
136         ar0->set_length (1024);
137         
138         boost::shared_ptr<AudioRegion> ar1 = boost::dynamic_pointer_cast<AudioRegion> (_region[1]);
139         ar1->set_name ("ar1");
140         _apl->add_region (ar1, 0);
141         ar1->set_default_fade_in ();
142         ar1->set_default_fade_out ();
143         CPPUNIT_ASSERT_EQUAL (double (64), ar1->_fade_in->back()->when);
144         CPPUNIT_ASSERT_EQUAL (double (64), ar1->_fade_out->back()->when);
145         ar1->set_length (1024);
146         ar1->set_opaque (false);
147
148         _apl->read (_buf, _mbuf, _gbuf, 0, 1024, 0);
149
150         /* ar0 and ar1 fade-ins; ar1 is on top, but it is transparent, so
151            its fade in will not affect ar0; ar0 will just fade in by itself,
152            and the two will be mixed.
153         */
154         for (int i = 0; i < 64; ++i) {
155                 float const fade = i / (double) 63;
156                 float const ar0 = i * fade;
157                 float const ar1 = i * fade;
158                 CPPUNIT_ASSERT_DOUBLES_EQUAL (ar0 + ar1, _buf[i], 1e-16);
159         }
160
161         /* ar0 and ar1 bodies, mixed */
162         for (int i = 64; i < (1024 - 64); ++i) {
163                 CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * 2), _buf[i], 1e-16);
164         }
165
166         /* ar0 and ar1 fade-outs, mixed */
167         for (int i = (1024 - 64); i < 1024; ++i) {
168                 /* Ardour fades out from 1 to VERY_SMALL_SIGNAL, which is 0.0000001,
169                    so this fade out expression is a little long-winded.
170                 */
171                 float const fade = (((double) 1 - 0.0000001) / 63) * (1023 - i) + 0.0000001;
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
178 /* A few tests just to check that nothing nasty is happening with
179    memory corruption, really (for running with valgrind).
180 */
181 void
182 PlaylistReadTest::miscReadTest ()
183 {
184         boost::shared_ptr<AudioRegion> ar0 = boost::dynamic_pointer_cast<AudioRegion> (_region[0]);
185         ar0->set_name ("ar0");
186         _apl->add_region (ar0, 0);
187         ar0->set_default_fade_in ();
188         ar0->set_default_fade_out ();
189         CPPUNIT_ASSERT_EQUAL (double (64), ar0->_fade_in->back()->when);
190         CPPUNIT_ASSERT_EQUAL (double (64), ar0->_fade_out->back()->when);
191         ar0->set_length (128);
192
193         /* Read for just longer than the region */
194         _apl->read (_buf, _mbuf, _gbuf, 0, 129, 0);
195
196         /* Read for much longer than the region */
197         _apl->read (_buf, _mbuf, _gbuf, 0, 1024, 0);
198
199         /* Read one sample */
200         _apl->read (_buf, _mbuf, _gbuf, 53, 54, 0);
201 }
202
203 void
204 PlaylistReadTest::check_staircase (Sample* b, int offset, int N)
205 {
206         for (int i = 0; i < N; ++i) {
207                 int const j = i + offset;
208                 CPPUNIT_ASSERT_EQUAL (j, int (b[i]));
209         }
210 }