summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-02-09 21:27:54 +0100
committerCarl Hetherington <cth@carlh.net>2025-02-09 21:27:54 +0100
commit1ce09f162354c2933eece74bb0935638a20d1cd9 (patch)
tree9383ad6d4b3667eece5528bfd0b7c245a22b403a
parent0e34bd5aebe27f7cb69abacbbc0523accf14b77d (diff)
Add --audio-channels option to dcpomatic2_create (#2966).
-rw-r--r--src/lib/create_cli.cc43
-rw-r--r--src/lib/create_cli.h1
-rw-r--r--test/create_cli_test.cc25
3 files changed, 58 insertions, 11 deletions
diff --git a/src/lib/create_cli.cc b/src/lib/create_cli.cc
index c2378e603..f726aa0ae 100644
--- a/src/lib/create_cli.cc
+++ b/src/lib/create_cli.cc
@@ -58,6 +58,7 @@ string CreateCLI::_help =
" --config <dir> directory containing config.xml and cinemas.sqlite3\n"
" --twok make a 2K DCP instead of choosing a resolution based on the content\n"
" --fourk make a 4K DCP instead of choosing a resolution based on the content\n"
+ " -a, --audio-channels <n> specify the number of audio channels in the DCP\n"
" -o, --output <dir> output directory\n"
" --twod make a 2D DCP\n"
" --threed make a 3D DCP\n"
@@ -154,6 +155,7 @@ CreateCLI::CreateCLI (int argc, char* argv[])
int dcp_frame_rate_int = 0;
string template_name_string;
int64_t video_bit_rate_int = 0;
+ optional<int> audio_channels;
auto next_frame_type = VideoFrameType::TWO_D;
optional<dcp::Channel> channel;
optional<float> gain;
@@ -227,6 +229,7 @@ CreateCLI::CreateCLI (int argc, char* argv[])
argument_option(i, argc, argv, "", "--config", &claimed, &error, &config_dir, string_to_path);
argument_option(i, argc, argv, "-o", "--output", &claimed, &error, &output_dir, string_to_path);
argument_option(i, argc, argv, "", "--video-bit-rate", &claimed, &error, &video_bit_rate_int);
+ argument_option(i, argc, argv, "-a", "--audio-channels", &claimed, &error, &audio_channels);
std::function<optional<dcp::Channel> (string)> convert_channel = [](string channel) -> optional<dcp::Channel>{
if (channel == "L") {
@@ -346,6 +349,34 @@ CreateCLI::CreateCLI (int argc, char* argv[])
error = String::compose("%1: video-bit-rate must be between 10 and %2 Mbit/s", argv[0], (Config::instance()->maximum_video_bit_rate(VideoEncoding::JPEG2000) / 1000000));
return;
}
+
+ /* See how many audio channels we would need to accommmodate the requested channel mappings */
+ int channels_for_content_specs = 0;
+ for (auto cli_content: content) {
+ if (cli_content.channel) {
+ channels_for_content_specs = std::max(channels_for_content_specs, static_cast<int>(*cli_content.channel) + 1);
+ }
+ }
+
+ /* Complain if we asked for a smaller number */
+ if (audio_channels && *audio_channels < channels_for_content_specs) {
+ error = fmt::format("{}: cannot map audio as requested with only {} channels", argv[0], *audio_channels);
+ return;
+ }
+
+ if (audio_channels && (*audio_channels % 2) != 0) {
+ error = fmt::format("{}: audio channel count must be even", argv[0]);
+ return;
+ }
+
+ if (audio_channels) {
+ _audio_channels = *audio_channels;
+ } else {
+ _audio_channels = std::max(channels_for_content_specs, 6);
+ if (_audio_channels % 2) {
+ ++_audio_channels;
+ }
+ }
}
@@ -398,17 +429,7 @@ CreateCLI::make_film() const
film->set_video_bit_rate(VideoEncoding::JPEG2000, *_video_bit_rate);
}
- int channels = 6;
- for (auto cli_content: content) {
- if (cli_content.channel) {
- channels = std::max(channels, static_cast<int>(*cli_content.channel) + 1);
- }
- }
- if (channels % 2) {
- ++channels;
- }
-
- film->set_audio_channels(channels);
+ film->set_audio_channels(_audio_channels);
return film;
}
diff --git a/src/lib/create_cli.h b/src/lib/create_cli.h
index 850cddea9..18115b4ca 100644
--- a/src/lib/create_cli.h
+++ b/src/lib/create_cli.h
@@ -73,6 +73,7 @@ private:
bool _twok = false;
bool _fourk = false;
boost::optional<int64_t> _video_bit_rate;
+ int _audio_channels = 0;
static std::string _help;
};
diff --git a/test/create_cli_test.cc b/test/create_cli_test.cc
index 7006fa6a0..ac184203d 100644
--- a/test/create_cli_test.cc
+++ b/test/create_cli_test.cc
@@ -196,6 +196,8 @@ BOOST_AUTO_TEST_CASE (create_cli_test)
BOOST_CHECK (*cc.content[1].channel == dcp::Channel::RIGHT);
BOOST_CHECK_EQUAL (cc.content[2].path, "sheila.wav");
BOOST_CHECK (!cc.content[2].channel);
+ auto film = cc.make_film();
+ BOOST_CHECK_EQUAL(film->audio_channels(), 6);
cc = run ("dcpomatic2_create --channel foo fred.wav");
BOOST_REQUIRE (cc.error);
@@ -219,6 +221,29 @@ BOOST_AUTO_TEST_CASE (create_cli_test)
cc = run("dcpomatic2_create -s SMPTE sheila.wav");
BOOST_CHECK(!cc.still_length);
BOOST_CHECK(cc.error);
+
+ cc = run("dcpomatic2_create --channel L fred.wav --channel R jim.wav --channel C sheila.wav --audio-channels 2");
+ BOOST_REQUIRE(cc.error);
+ BOOST_CHECK_EQUAL(*cc.error, "dcpomatic2_create: cannot map audio as requested with only 2 channels");
+
+ cc = run("dcpomatic2_create --channel L fred.wav --channel R jim.wav --channel C sheila.wav --audio-channels 3");
+ BOOST_REQUIRE(cc.error);
+ BOOST_CHECK_EQUAL(*cc.error, "dcpomatic2_create: audio channel count must be even");
+
+ cc = run("dcpomatic2_create --channel L fred.wav --channel R jim.wav --channel C sheila.wav");
+ BOOST_CHECK(!cc.error);
+ film = cc.make_film();
+ BOOST_CHECK_EQUAL(film->audio_channels(), 6);
+
+ cc = run("dcpomatic2_create --channel L fred.wav --channel R jim.wav --channel HI sheila.wav");
+ BOOST_CHECK(!cc.error);
+ film = cc.make_film();
+ BOOST_CHECK_EQUAL(film->audio_channels(), 8);
+
+ cc = run("dcpomatic2_create --channel L fred.wav --channel R jim.wav --channel C sheila.wav --audio-channels 16");
+ BOOST_CHECK(!cc.error);
+ film = cc.make_film();
+ BOOST_CHECK_EQUAL(film->audio_channels(), 16);
}