c9231ae7f71f1eee49705cbb7f6d295e1235819b
[dcpomatic.git] / test / audio_buffers_test.cc
1 /*
2     Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 /** @file  test/audio_buffers_test.cc
22  *  @brief Test AudioBuffers in various ways.
23  */
24
25 #include <cmath>
26 #include <boost/test/unit_test.hpp>
27 #include "lib/audio_buffers.h"
28
29 using std::pow;
30
31 static float tolerance = 1e-3;
32
33 static float
34 random_float ()
35 {
36         return float (rand ()) / RAND_MAX;
37 }
38
39 static void
40 random_fill (AudioBuffers& buffers)
41 {
42         for (int i = 0; i < buffers.frames(); ++i) {
43                 for (int j = 0; j < buffers.channels(); ++j) {
44                         buffers.data(j)[i] = random_float ();
45                 }
46         }
47 }
48
49 static void
50 random_check (AudioBuffers& buffers, int from, int frames)
51 {
52         for (int i = from; i < (from + frames); ++i) {
53                 for (int j = 0; j < buffers.channels(); ++j) {
54                         BOOST_CHECK_CLOSE (buffers.data(j)[i], random_float (), tolerance);
55                 }
56         }
57 }
58
59 /** Basic setup */
60 BOOST_AUTO_TEST_CASE (audio_buffers_setup_test)
61 {
62         AudioBuffers buffers (4, 9155);
63
64         BOOST_CHECK (buffers.data ());
65         for (int i = 0; i < 4; ++i) {
66                 BOOST_CHECK (buffers.data (i));
67         }
68
69         BOOST_CHECK_EQUAL (buffers.channels(), 4);
70         BOOST_CHECK_EQUAL (buffers.frames(), 9155);
71 }
72
73 /** Extending some buffers */
74 BOOST_AUTO_TEST_CASE (audio_buffers_extend_test)
75 {
76         AudioBuffers buffers (3, 150);
77         srand (1);
78         random_fill (buffers);
79
80         /* Extend */
81         buffers.ensure_size (299);
82
83         srand (1);
84         random_check (buffers, 0, 150);
85
86         /* New space should be silent */
87         for (int i = 150; i < 299; ++i) {
88                 for (int c = 0; c < 3; ++c) {
89                         BOOST_CHECK_EQUAL (buffers.data(c)[i], 0);
90                 }
91         }
92 }
93
94 /** make_silent() */
95 BOOST_AUTO_TEST_CASE (audio_buffers_make_silent_test)
96 {
97         AudioBuffers buffers (9, 9933);
98         srand (2);
99         random_fill (buffers);
100
101         buffers.make_silent ();
102
103         for (int i = 0; i < 9933; ++i) {
104                 for (int c = 0; c < 9; ++c) {
105                         BOOST_CHECK_EQUAL (buffers.data(c)[i], 0);
106                 }
107         }
108 }
109
110 /** make_silent (int c) */
111 BOOST_AUTO_TEST_CASE (audio_buffers_make_silent_channel_test)
112 {
113         AudioBuffers buffers (9, 9933);
114         srand (3);
115         random_fill (buffers);
116
117         buffers.make_silent (4);
118
119         srand (3);
120         for (int i = 0; i < 9933; ++i) {
121                 for (int c = 0; c < 9; ++c) {
122                         if (c == 4) {
123                                 random_float ();
124                                 BOOST_CHECK_EQUAL (buffers.data(c)[i], 0);
125                         } else {
126                                 BOOST_CHECK_CLOSE (buffers.data(c)[i], random_float (), tolerance);
127                         }
128                 }
129         }
130 }
131
132 /** make_silent (int from, int frames) */
133 BOOST_AUTO_TEST_CASE (audio_buffers_make_silent_part_test)
134 {
135         AudioBuffers buffers (9, 9933);
136         srand (4);
137         random_fill (buffers);
138
139         buffers.make_silent (145, 833);
140
141         srand (4);
142         for (int i = 0; i < 145; ++i) {
143                 for (int c = 0; c < 9; ++c) {
144                         BOOST_CHECK_EQUAL (buffers.data(c)[i], random_float ());
145                 }
146         }
147
148         for (int i = 145; i < (145 + 833); ++i) {
149                 for (int c = 0; c < 9; ++c) {
150                         random_float ();
151                         BOOST_CHECK_EQUAL (buffers.data(c)[i], 0);
152                 }
153         }
154
155         for (int i = (145 + 833); i < 9933; ++i) {
156                 for (int c = 0; c < 9; ++c) {
157                         BOOST_CHECK_EQUAL (buffers.data(c)[i], random_float ());
158                 }
159         }
160 }
161
162 /* apply_gain */
163 BOOST_AUTO_TEST_CASE (audio_buffers_apply_gain)
164 {
165         AudioBuffers buffers (2, 417315);
166         srand (9);
167         random_fill (buffers);
168
169         buffers.apply_gain (5.4);
170
171         srand (9);
172         for (int i = 0; i < 417315; ++i) {
173                 for (int c = 0; c < 2; ++c) {
174                         BOOST_CHECK_CLOSE (buffers.data(c)[i], random_float() * pow (10, 5.4 / 20), tolerance);
175                 }
176         }
177 }
178
179 /* copy_from */
180 BOOST_AUTO_TEST_CASE (audio_buffers_copy_from)
181 {
182         AudioBuffers a (5, 63711);
183         AudioBuffers b (5, 12345);
184
185         srand (42);
186         random_fill (a);
187
188         srand (99);
189         random_fill (b);
190
191         a.copy_from (&b, 517, 233, 194);
192
193         /* Re-seed a's generator and check the numbers that came from it */
194
195         /* First part; not copied-over */
196         srand (42);
197         random_check (a, 0, 194);
198
199         /* Second part; copied-over (just burn generator a's numbers) */
200         for (int i = 0; i < (517 * 5); ++i) {
201                 random_float ();
202         }
203
204         /* Third part; not copied-over */
205         random_check (a, 194 + 517, a.frames() - 194 - 517);
206
207         /* Re-seed b's generator and check the numbers that came from it */
208         srand (99);
209
210         /* First part; burn */
211         for (int i = 0; i < 194 * 5; ++i) {
212                 random_float ();
213         }
214
215         /* Second part; copied */
216         random_check (b, 194, 517);
217 }
218
219 /* move */
220 BOOST_AUTO_TEST_CASE (audio_buffers_move)
221 {
222         AudioBuffers buffers (7, 65536);
223
224         srand (84);
225         random_fill (buffers);
226
227         int const from = 888;
228         int const to = 666;
229         int const frames = 444;
230
231         buffers.move (frames, from, to);
232
233         /* Re-seed and check the un-moved parts */
234         srand (84);
235
236         random_check (buffers, 0, to);
237
238         /* Burn a few */
239         for (int i = 0; i < (from - to + frames) * 7; ++i) {
240                 random_float ();
241         }
242
243         random_check (buffers, from + frames, 65536 - frames - from);
244
245         /* Re-seed and check the moved part */
246         srand (84);
247
248         /* Burn a few */
249         for (int i = 0; i < from * 7; ++i) {
250                 random_float ();
251         }
252
253         random_check (buffers, to, frames);
254 }
255
256 /** accumulate_channel */
257 BOOST_AUTO_TEST_CASE (audio_buffers_accumulate_channel)
258 {
259         AudioBuffers a (3, 256);
260         srand (38);
261         random_fill (a);
262
263         AudioBuffers b (3, 256);
264         random_fill (b);
265
266         a.accumulate_channel (&b, 2, 1, 1.2);
267
268         srand (38);
269         for (int i = 0; i < 256; ++i) {
270                 for (int c = 0; c < 3; ++c) {
271                         float const A = random_float ();
272                         if (c == 1) {
273                                 BOOST_CHECK_CLOSE (a.data(c)[i], A + b.data(2)[i] * 1.2, tolerance);
274                         } else {
275                                 BOOST_CHECK_CLOSE (a.data(c)[i], A, tolerance);
276                         }
277                 }
278         }
279 }
280
281 /** accumulate_frames */
282 BOOST_AUTO_TEST_CASE (audio_buffers_accumulate_frames)
283 {
284         AudioBuffers a (3, 256);
285         srand (38);
286         random_fill (a);
287
288         AudioBuffers b (3, 256);
289         random_fill (b);
290
291         a.accumulate_frames (&b, 129, 91, 44);
292
293         srand (38);
294         for (int i = 0; i < 256; ++i) {
295                 for (int c = 0; c < 3; ++c) {
296                         float const A = random_float ();
297                         if (i < 44 || i >= (44 + 129)) {
298                                 BOOST_CHECK_CLOSE (a.data(c)[i], A, tolerance);
299                         } else {
300                                 BOOST_CHECK_CLOSE (a.data(c)[i], A + b.data(c)[i + 91 - 44], tolerance);
301                         }
302                 }
303         }
304 }