BBTTest::addTest() should add a meter rather than replacing the first one.
[ardour.git] / libs / ardour / test / combine_regions_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 "combine_regions_test.h"
20 #include "ardour/types.h"
21 #include "ardour/audioplaylist.h"
22 #include "ardour/region.h"
23 #include "ardour/audioregion.h"
24 #include "evoral/Curve.hpp"
25
26 CPPUNIT_TEST_SUITE_REGISTRATION (CombineRegionsTest);
27
28 using namespace std;
29 using namespace ARDOUR;
30
31 void
32 CombineRegionsTest::check_crossfade1 ()
33 {
34         ARDOUR::Sample buf[512];
35         ARDOUR::Sample mbuf[512];
36         float gbuf[512];
37
38         /* Read from the playlist */
39         _audio_playlist->read (buf, mbuf, gbuf, 0, 256 * 2 - 128, 0);
40
41         /* _r[0]'s fade in */
42         for (int i = 0; i < 64; ++i) {
43                 float const fade = i / (double) 63;
44                 float const r0 = i * fade;
45                 CPPUNIT_ASSERT_DOUBLES_EQUAL (r0, buf[i], 1e-16);
46         }
47
48         /* Some more of _r[0] */
49         for (int i = 64; i < 128; ++i) {
50                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i, buf[i], 1e-16);
51         }
52
53         float fade_in[128];
54         float fade_out[128];
55
56         _ar[1]->fade_in()->curve().get_vector (0, 128, fade_in, 128);
57         _ar[1]->inverse_fade_in()->curve().get_vector (0, 128, fade_out, 128);
58
59         /* Crossfading _r[0] to _r[1] using _r[1]'s fade in and inverse fade in.
60            _r[0] also has a standard region fade out to add to the fun.
61         */
62         for (int i = 128; i < 256; ++i) {
63
64                 float region_fade_out = 1;
65                 if (i >= 192) {
66                         /* Ardour fades out from 1 to VERY_SMALL_SIGNAL, which is 0.0000001,
67                            so this fade out expression is a little long-winded.
68                         */
69                         region_fade_out = (((double) 1 - 0.0000001) / 63) * (255 - i) + 0.0000001;
70                 }
71
72                 /* This computation of r0 cannot be compressed into one line, or there
73                    is a small floating point `error'
74                 */
75                 float r0 = i * region_fade_out;
76                 r0 *= fade_out[i - 128];
77
78                 float const r1 = (i - 128) * fade_in[i - 128];
79                 CPPUNIT_ASSERT_DOUBLES_EQUAL (r0 + r1, buf[i], 1e-16);
80         }
81
82         /* Rest of _r[1] */
83         for (int i = 256; i < (384 - 64); ++i) {
84                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i - 128, buf[i], 1e-16);
85         }
86
87         /* And _r[1]'s fade out */
88         for (int i = (384 - 64); i < 384; ++i) {
89                 float const fade_out = (((double) 1 - 0.0000001) / 63) * (383 - i) + 0.0000001;
90                 CPPUNIT_ASSERT_DOUBLES_EQUAL ((i - 128) * fade_out, buf[i], 1e-16);
91         }
92 }
93
94 /** Test combining two cross-faded regions, with the earlier region
95  *  on the lower layer.
96  */
97 void
98 CombineRegionsTest::crossfadeTest1 ()
99 {
100         /* Two regions, both 256 frames in length, overlapping by 128 frames in the middle */
101
102         _ar[0]->set_default_fade_in ();
103         _ar[0]->set_default_fade_out ();
104         _ar[1]->set_default_fade_out ();
105
106         _playlist->add_region (_r[0], 0);
107         _r[0]->set_length (256);
108
109         _playlist->add_region (_r[1], 128);
110         _r[1]->set_length (256);
111
112         /* Check layering */
113         CPPUNIT_ASSERT_EQUAL (layer_t (0), _r[0]->layer ());
114         CPPUNIT_ASSERT_EQUAL (layer_t (1), _r[1]->layer ());
115
116 #if 0
117         /* Check that the right fades have been set up */
118         CPPUNIT_ASSERT_EQUAL (false, _ar[0]->fade_in_is_xfade ());
119         CPPUNIT_ASSERT_EQUAL (false, _ar[0]->fade_out_is_xfade ());
120         CPPUNIT_ASSERT_EQUAL (true, _ar[1]->fade_in_is_xfade ());
121         CPPUNIT_ASSERT_EQUAL (false, _ar[1]->fade_out_is_xfade ());
122 #endif
123
124         /* Check that the read comes back correctly */
125         check_crossfade1 ();
126
127         /* Combine the two regions */
128
129         RegionList rl;
130         rl.push_back (_r[0]);
131         rl.push_back (_r[1]);
132         _playlist->combine (rl);
133
134         /* ...so we just have the one region... */
135         CPPUNIT_ASSERT_EQUAL ((uint32_t) 1, _playlist->n_regions ());
136
137         /* And reading should give the same thing */
138         check_crossfade1 ();
139 }
140
141 void
142 CombineRegionsTest::check_crossfade2 ()
143 {
144         ARDOUR::Sample buf[512];
145         ARDOUR::Sample mbuf[512];
146         float gbuf[512];
147
148         /* Read from the playlist */
149         _audio_playlist->read (buf, mbuf, gbuf, 0, 256 * 2 - 128, 0);
150
151         /* _r[0]'s fade in */
152         for (int i = 0; i < 64; ++i) {
153                 float const fade = i / (double) 63;
154                 float const r0 = i * fade;
155                 CPPUNIT_ASSERT_DOUBLES_EQUAL (r0, buf[i], 1e-16);
156         }
157
158         /* Some more of _r[0] */
159         for (int i = 64; i < 128; ++i) {
160                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i, buf[i], 1e-16);
161         }
162
163         float fade_in[128];
164         float fade_out[128];
165
166         _ar[0]->inverse_fade_out()->curve().get_vector (0, 128, fade_in, 128);
167         _ar[0]->fade_out()->curve().get_vector (0, 128, fade_out, 128);
168
169         /* Crossfading _r[0] to _r[1] using _r[0]'s fade out and inverse fade out.
170            _r[1] also has a standard region fade in to add to the fun.
171         */
172         for (int i = 128; i < 256; ++i) {
173
174                 float region_fade_in = 1;
175                 if (i < (128 + 64)) {
176                         region_fade_in = (i - 128) / ((double) 63);
177                 }
178
179                 float r0 = i * fade_out[i - 128];
180                 float r1 = (i - 128) * region_fade_in;
181                 r1 *= fade_in[i - 128];
182
183                 CPPUNIT_ASSERT_DOUBLES_EQUAL (r0 + r1, buf[i], 1e-16);
184         }
185
186         /* Rest of _r[1] */
187         for (int i = 256; i < (384 - 64); ++i) {
188                 CPPUNIT_ASSERT_DOUBLES_EQUAL (i - 128, buf[i], 1e-16);
189         }
190
191         /* And _r[1]'s fade out */
192         for (int i = (384 - 64); i < 384; ++i) {
193                 float const fade_out = (((double) 1 - 0.0000001) / 63) * (383 - i) + 0.0000001;
194                 CPPUNIT_ASSERT_DOUBLES_EQUAL ((i - 128) * fade_out, buf[i], 1e-16);
195         }
196 }
197
198 /** As per crossfadeTest1, except that the earlier region is on the
199  *  higher layer.
200  */
201 void
202 CombineRegionsTest::crossfadeTest2 ()
203 {
204         /* Two regions, both 256 frames in length, overlapping by 128 frames in the middle */
205
206         _ar[0]->set_default_fade_in ();
207         _ar[0]->set_default_fade_out ();
208         _ar[1]->set_default_fade_out ();
209
210         _playlist->add_region (_r[0], 0);
211         _r[0]->set_length (256);
212
213         _playlist->add_region (_r[1], 128);
214         _r[1]->set_length (256);
215
216         _r[1]->lower_to_bottom ();
217
218         /* Check layering */
219         CPPUNIT_ASSERT_EQUAL (layer_t (1), _r[0]->layer ());
220         CPPUNIT_ASSERT_EQUAL (layer_t (0), _r[1]->layer ());
221
222 #if 0
223         /* Check that the right fades have been set up */
224         CPPUNIT_ASSERT_EQUAL (false, _ar[0]->fade_in_is_xfade ());
225         CPPUNIT_ASSERT_EQUAL (true, _ar[0]->fade_out_is_xfade ());
226         CPPUNIT_ASSERT_EQUAL (false, _ar[1]->fade_in_is_xfade ());
227         CPPUNIT_ASSERT_EQUAL (false, _ar[1]->fade_out_is_xfade ());
228 #endif
229
230         /* Check that the read comes back correctly */
231         check_crossfade2 ();
232
233         /* Combine the two regions */
234
235         RegionList rl;
236         rl.push_back (_r[0]);
237         rl.push_back (_r[1]);
238         _playlist->combine (rl);
239
240         /* ...so we just have the one region... */
241         CPPUNIT_ASSERT_EQUAL ((uint32_t) 1, _playlist->n_regions ());
242
243         /* And reading should give the same thing */
244         check_crossfade2 ();
245 }
246