9fd9282813144a76e542c32670faa9c7b03ce988
[dcpomatic.git] / test / audio_analysis_test.cc
1 /*
2     Copyright (C) 2012-2016 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_analysis_test.cc
22  *  @brief Check audio analysis code.
23  */
24
25 #include "lib/audio_analysis.h"
26 #include "lib/analyse_audio_job.h"
27 #include "lib/film.h"
28 #include "lib/ffmpeg_content.h"
29 #include "lib/dcp_content_type.h"
30 #include "lib/ffmpeg_content.h"
31 #include "lib/ratio.h"
32 #include "lib/job_manager.h"
33 #include "lib/audio_content.h"
34 #include "test.h"
35 #include <boost/make_shared.hpp>
36 #include <boost/test/unit_test.hpp>
37
38 using boost::shared_ptr;
39 using boost::make_shared;
40
41 static float
42 random_float ()
43 {
44         return (float (rand ()) / RAND_MAX) * 2 - 1;
45 }
46
47 BOOST_AUTO_TEST_CASE (audio_analysis_serialisation_test)
48 {
49         int const channels = 3;
50         int const points = 4096;
51
52         srand (1);
53
54         AudioAnalysis a (3);
55         for (int i = 0; i < channels; ++i) {
56                 for (int j = 0; j < points; ++j) {
57                         AudioPoint p;
58                         p[AudioPoint::PEAK] = random_float ();
59                         p[AudioPoint::RMS] = random_float ();
60                         a.add_point (i, p);
61                 }
62         }
63
64         float const peak = random_float ();
65         DCPTime const peak_time = DCPTime (rand ());
66         a.set_sample_peak (peak, peak_time);
67
68         a.write ("build/test/audio_analysis_serialisation_test");
69
70         srand (1);
71
72         AudioAnalysis b ("build/test/audio_analysis_serialisation_test");
73         for (int i = 0; i < channels; ++i) {
74                 BOOST_CHECK_EQUAL (b.points(i), points);
75                 for (int j = 0; j < points; ++j) {
76                         AudioPoint p = b.get_point (i, j);
77                         BOOST_CHECK_CLOSE (p[AudioPoint::PEAK], random_float (), 1);
78                         BOOST_CHECK_CLOSE (p[AudioPoint::RMS],  random_float (), 1);
79                 }
80         }
81
82         BOOST_CHECK (b.sample_peak ());
83         BOOST_CHECK_CLOSE (b.sample_peak().get(), peak, 1);
84         BOOST_CHECK (b.sample_peak_time ());
85         BOOST_CHECK_EQUAL (b.sample_peak_time().get(), peak_time);
86 }
87
88 static void
89 finished ()
90 {
91
92 }
93
94 BOOST_AUTO_TEST_CASE (audio_analysis_test)
95 {
96         shared_ptr<Film> film = new_test_film ("audio_analysis_test");
97         film->set_dcp_content_type (DCPContentType::from_isdcf_name ("FTR"));
98         film->set_container (Ratio::from_id ("185"));
99         film->set_name ("audio_analysis_test");
100         boost::filesystem::path p = private_data / "betty_L.wav";
101
102         shared_ptr<FFmpegContent> c = make_shared<FFmpegContent> (film, p);
103         film->examine_and_add_content (c);
104         wait_for_jobs ();
105
106         shared_ptr<AnalyseAudioJob> job = make_shared<AnalyseAudioJob> (film, film->playlist ());
107         job->Finished.connect (boost::bind (&finished));
108         JobManager::instance()->add (job);
109         wait_for_jobs ();
110 }
111
112 /** Check that audio analysis works (i.e. runs without error) with a -ve delay */
113 BOOST_AUTO_TEST_CASE (audio_analysis_negative_delay_test)
114 {
115         shared_ptr<Film> film = new_test_film ("audio_analysis_negative_delay_test");
116         film->set_name ("audio_analysis_negative_delay_test");
117         shared_ptr<FFmpegContent> c = make_shared<FFmpegContent> (film, private_data / "boon_telly.mkv");
118         film->examine_and_add_content (c);
119         wait_for_jobs ();
120
121         c->audio->set_delay (-250);
122
123         shared_ptr<AnalyseAudioJob> job = make_shared<AnalyseAudioJob> (film, film->playlist ());
124         job->Finished.connect (boost::bind (&finished));
125         JobManager::instance()->add (job);
126         wait_for_jobs ();
127 }
128
129 /** Check audio analysis that is incorrect in 2e98263 */
130 BOOST_AUTO_TEST_CASE (audio_analysis_test2)
131 {
132         shared_ptr<Film> film = new_test_film ("audio_analysis_test2");
133         film->set_name ("audio_analysis_test2");
134         shared_ptr<FFmpegContent> c = make_shared<FFmpegContent> (film, private_data / "3d_thx_broadway_2010_lossless.m2ts");
135         film->examine_and_add_content (c);
136         wait_for_jobs ();
137
138         shared_ptr<AnalyseAudioJob> job = make_shared<AnalyseAudioJob> (film, film->playlist ());
139         job->Finished.connect (boost::bind (&finished));
140         JobManager::instance()->add (job);
141         wait_for_jobs ();
142 }
143
144
145 static bool done = false;
146
147 static void
148 analysis_finished ()
149 {
150         done = true;
151 }
152
153 /* Test a case which was reported to throw an exception; analysing
154  * a 12-channel DCP's audio.
155  */
156 BOOST_AUTO_TEST_CASE (audio_analysis_test3)
157 {
158         shared_ptr<Film> film = new_test_film ("analyse_audio_test");
159         film->set_container (Ratio::from_id ("185"));
160         film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TLR"));
161         film->set_name ("frobozz");
162
163         shared_ptr<FFmpegContent> content = make_shared<FFmpegContent> (film, "test/data/white.wav");
164         film->examine_and_add_content (content);
165         wait_for_jobs ();
166
167         film->set_audio_channels (12);
168         boost::signals2::connection connection;
169         JobManager::instance()->analyse_audio (film, film->playlist(), connection, boost::bind (&analysis_finished));
170         wait_for_jobs ();
171         BOOST_CHECK (done);
172 }