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 "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"
26 CPPUNIT_TEST_SUITE_REGISTRATION (CombineRegionsTest);
29 using namespace ARDOUR;
32 CombineRegionsTest::check_crossfade1 ()
34 ARDOUR::Sample buf[512];
35 ARDOUR::Sample mbuf[512];
38 /* Read from the playlist */
39 _audio_playlist->read (buf, mbuf, gbuf, 0, 256 * 2 - 128, 0);
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);
48 /* Some more of _r[0] */
49 for (int i = 64; i < 128; ++i) {
50 CPPUNIT_ASSERT_DOUBLES_EQUAL (i, buf[i], 1e-16);
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);
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.
62 for (int i = 128; i < 256; ++i) {
64 float region_fade_out = 1;
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.
69 region_fade_out = (((double) 1 - 0.0000001) / 63) * (255 - i) + 0.0000001;
72 /* This computation of r0 cannot be compressed into one line, or there
73 is a small floating point `error'
75 float r0 = i * region_fade_out;
76 r0 *= fade_out[i - 128];
78 float const r1 = (i - 128) * fade_in[i - 128];
79 CPPUNIT_ASSERT_DOUBLES_EQUAL (r0 + r1, buf[i], 1e-16);
83 for (int i = 256; i < (384 - 64); ++i) {
84 CPPUNIT_ASSERT_DOUBLES_EQUAL (i - 128, buf[i], 1e-16);
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);
94 /** Test combining two cross-faded regions, with the earlier region
98 CombineRegionsTest::crossfadeTest1 ()
100 /* Two regions, both 256 frames in length, overlapping by 128 frames in the middle */
102 _ar[0]->set_default_fade_in ();
103 _ar[0]->set_default_fade_out ();
104 _ar[1]->set_default_fade_out ();
106 _playlist->add_region (_r[0], 0);
107 _r[0]->set_length (256);
109 _playlist->add_region (_r[1], 128);
110 _r[1]->set_length (256);
113 CPPUNIT_ASSERT_EQUAL (layer_t (0), _r[0]->layer ());
114 CPPUNIT_ASSERT_EQUAL (layer_t (1), _r[1]->layer ());
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 ());
124 /* Check that the read comes back correctly */
127 /* Combine the two regions */
130 rl.push_back (_r[0]);
131 rl.push_back (_r[1]);
132 _playlist->combine (rl);
134 /* ...so we just have the one region... */
135 CPPUNIT_ASSERT_EQUAL ((uint32_t) 1, _playlist->n_regions ());
137 /* And reading should give the same thing */
142 CombineRegionsTest::check_crossfade2 ()
144 ARDOUR::Sample buf[512];
145 ARDOUR::Sample mbuf[512];
148 /* Read from the playlist */
149 _audio_playlist->read (buf, mbuf, gbuf, 0, 256 * 2 - 128, 0);
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);
158 /* Some more of _r[0] */
159 for (int i = 64; i < 128; ++i) {
160 CPPUNIT_ASSERT_DOUBLES_EQUAL (i, buf[i], 1e-16);
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);
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.
172 for (int i = 128; i < 256; ++i) {
174 float region_fade_in = 1;
175 if (i < (128 + 64)) {
176 region_fade_in = (i - 128) / ((double) 63);
179 float r0 = i * fade_out[i - 128];
180 float r1 = (i - 128) * region_fade_in;
181 r1 *= fade_in[i - 128];
183 CPPUNIT_ASSERT_DOUBLES_EQUAL (r0 + r1, buf[i], 1e-16);
187 for (int i = 256; i < (384 - 64); ++i) {
188 CPPUNIT_ASSERT_DOUBLES_EQUAL (i - 128, buf[i], 1e-16);
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);
198 /** As per crossfadeTest1, except that the earlier region is on the
202 CombineRegionsTest::crossfadeTest2 ()
204 /* Two regions, both 256 frames in length, overlapping by 128 frames in the middle */
206 _ar[0]->set_default_fade_in ();
207 _ar[0]->set_default_fade_out ();
208 _ar[1]->set_default_fade_out ();
210 _playlist->add_region (_r[0], 0);
211 _r[0]->set_length (256);
213 _playlist->add_region (_r[1], 128);
214 _r[1]->set_length (256);
216 _r[1]->lower_to_bottom ();
219 CPPUNIT_ASSERT_EQUAL (layer_t (1), _r[0]->layer ());
220 CPPUNIT_ASSERT_EQUAL (layer_t (0), _r[1]->layer ());
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 ());
230 /* Check that the read comes back correctly */
233 /* Combine the two regions */
236 rl.push_back (_r[0]);
237 rl.push_back (_r[1]);
238 _playlist->combine (rl);
240 /* ...so we just have the one region... */
241 CPPUNIT_ASSERT_EQUAL ((uint32_t) 1, _playlist->n_regions ());
243 /* And reading should give the same thing */