diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-01-12 21:21:30 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-01-19 22:44:58 +0100 |
| commit | d4024848dfe293b06440d20a9f48894b2b008316 (patch) | |
| tree | 86b3e460245131300d92024460e9b5238637365b /src/main_sound_configuration.cc | |
| parent | 3c379a4ec4d030a8f7fbbc0ddf2621e4d39be238 (diff) | |
Move MainSoundConfiguration and MCASoundField into separate files.
Diffstat (limited to 'src/main_sound_configuration.cc')
| -rw-r--r-- | src/main_sound_configuration.cc | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/src/main_sound_configuration.cc b/src/main_sound_configuration.cc new file mode 100644 index 00000000..1a081321 --- /dev/null +++ b/src/main_sound_configuration.cc @@ -0,0 +1,305 @@ +/* + Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net> + + This file is part of libdcp. + + libdcp is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + libdcp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libdcp. If not, see <http://www.gnu.org/licenses/>. + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + + +#include "dcp_assert.h" +#include "exceptions.h" +#include "main_sound_configuration.h" +#include <boost/algorithm/string.hpp> +#include <vector> + + +using std::string; +using std::vector; +using boost::optional; +using namespace dcp; + + + +MainSoundConfiguration::MainSoundConfiguration (string s) +{ + vector<string> parts; + boost::split (parts, s, boost::is_any_of("/")); + if (parts.empty()) { + throw MainSoundConfigurationError(s); + } + + if (parts[0] == "51") { + _field = MCASoundField::FIVE_POINT_ONE; + } else if (parts[0] == "71") { + _field = MCASoundField::SEVEN_POINT_ONE; + } else { + _field = MCASoundField::OTHER; + } + + if (parts.size() < 2) { + /* I think it's OK to just have the sound field descriptor with no channels, though + * to me it's not clear and I might be wrong. + */ + return; + } + + vector<string> channels; + boost::split (channels, parts[1], boost::is_any_of(",")); + + if (channels.size() > 16) { + throw MainSoundConfigurationError (s); + } + + for (auto i: channels) { + if (i == "-") { + _channels.push_back(optional<Channel>()); + } else { + _channels.push_back(mca_id_to_channel(i)); + } + } +} + + +MainSoundConfiguration::MainSoundConfiguration (MCASoundField field, int channels) + : _field (field) +{ + _channels.resize (channels); +} + + +string +MainSoundConfiguration::to_string () const +{ + string c; + switch (_field) { + case MCASoundField::FIVE_POINT_ONE: + c = "51/"; + break; + case MCASoundField::SEVEN_POINT_ONE: + c = "71/"; + break; + default: + DCP_ASSERT(false); + } + + for (auto i: _channels) { + if (!i) { + c += "-,"; + } else { + c += channel_to_mca_id(*i, _field) + ","; + } + } + + if (c.length() > 0) { + c = c.substr(0, c.length() - 1); + } + + return c; +} + + +optional<Channel> +MainSoundConfiguration::mapping (int index) const +{ + DCP_ASSERT (static_cast<size_t>(index) < _channels.size()); + return _channels[index]; +} + + +void +MainSoundConfiguration::set_mapping (int index, Channel c) +{ + DCP_ASSERT (static_cast<size_t>(index) < _channels.size()); + _channels[index] = c; +} + + +Channel +dcp::mca_id_to_channel (string id) +{ + transform(id.begin(), id.end(), id.begin(), ::tolower); + + if (id == "l") { + return Channel::LEFT; + } else if (id == "r") { + return Channel::RIGHT; + } else if (id == "c") { + return Channel::CENTRE; + } else if (id == "lfe") { + return Channel::LFE; + } else if (id == "ls" || id == "lss" || id == "lslss") { + return Channel::LS; + } else if (id == "rs" || id == "rss" || id == "rsrss") { + return Channel::RS; + } else if (id == "hi") { + return Channel::HI; + } else if (id == "vin" || id == "vi-n") { + return Channel::VI; + } else if (id == "lc") { + return Channel::LC; + } else if (id == "rc") { + return Channel::RC; + } else if (id == "lrs" || id == "lsr") { + return Channel::BSL; + } else if (id == "rrs" || id == "rsr") { + return Channel::BSR; + } else if (id == "dbox" || id == "dbox2" || id == "mtn") { + return Channel::MOTION_DATA; + } else if (id == "sync" || id == "fsksync") { + return Channel::SYNC_SIGNAL; + } else if (id == "slvs") { + return Channel::SIGN_LANGUAGE; + } + + throw UnknownChannelIdError (id); +} + + +string +dcp::channel_to_mca_id (Channel c, MCASoundField field) +{ + switch (c) { + case Channel::LEFT: + return "L"; + case Channel::RIGHT: + return "R"; + case Channel::CENTRE: + return "C"; + case Channel::LFE: + return "LFE"; + case Channel::LS: + return field == MCASoundField::FIVE_POINT_ONE ? "Ls" : "Lss"; + case Channel::RS: + return field == MCASoundField::FIVE_POINT_ONE ? "Rs" : "Rss"; + case Channel::HI: + return "HI"; + case Channel::VI: + return "VIN"; + case Channel::BSL: + return "Lrs"; + case Channel::BSR: + return "Rrs"; + case Channel::MOTION_DATA: + return "DBOX"; + case Channel::SYNC_SIGNAL: + return "FSKSync"; + case Channel::SIGN_LANGUAGE: + return "SLVS"; + default: + break; + } + + DCP_ASSERT (false); +} + + +string +dcp::channel_to_mca_name (Channel c, MCASoundField field) +{ + switch (c) { + case Channel::LEFT: + return "Left"; + case Channel::RIGHT: + return "Right"; + case Channel::CENTRE: + return "Center"; + case Channel::LFE: + return "LFE"; + case Channel::LS: + return field == MCASoundField::FIVE_POINT_ONE ? "Left Surround" : "Left Side Surround"; + case Channel::RS: + return field == MCASoundField::FIVE_POINT_ONE ? "Right Surround" : "Right Side Surround"; + case Channel::HI: + return "Hearing Impaired"; + case Channel::VI: + return "Visually Impaired-Narrative"; + case Channel::BSL: + return "Left Rear Surround"; + case Channel::BSR: + return "Right Rear Surround"; + case Channel::MOTION_DATA: + return "D-BOX Motion Code Primary Stream"; + case Channel::SYNC_SIGNAL: + return "FSK Sync"; + case Channel::SIGN_LANGUAGE: + return "Sign Language Video Stream"; + default: + break; + } + + DCP_ASSERT (false); +} + + +ASDCP::UL +dcp::channel_to_mca_universal_label (Channel c, MCASoundField field, ASDCP::Dictionary const* dict) +{ + static byte_t sync_signal[] = { + 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x03, 0x02, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00 + }; + + static byte_t sign_language[] = { + 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x0d, 0x0f, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00 + }; + + switch (c) { + case Channel::LEFT: + return dict->ul(ASDCP::MDD_DCAudioChannel_L); + case Channel::RIGHT: + return dict->ul(ASDCP::MDD_DCAudioChannel_R); + case Channel::CENTRE: + return dict->ul(ASDCP::MDD_DCAudioChannel_C); + case Channel::LFE: + return dict->ul(ASDCP::MDD_DCAudioChannel_LFE); + case Channel::LS: + return dict->ul(field == MCASoundField::FIVE_POINT_ONE ? ASDCP::MDD_DCAudioChannel_Ls : ASDCP::MDD_DCAudioChannel_Lss); + case Channel::RS: + return dict->ul(field == MCASoundField::FIVE_POINT_ONE ? ASDCP::MDD_DCAudioChannel_Rs : ASDCP::MDD_DCAudioChannel_Rss); + case Channel::HI: + return dict->ul(ASDCP::MDD_DCAudioChannel_HI); + case Channel::VI: + return dict->ul(ASDCP::MDD_DCAudioChannel_VIN); + case Channel::BSL: + return dict->ul(ASDCP::MDD_DCAudioChannel_Lrs); + case Channel::BSR: + return dict->ul(ASDCP::MDD_DCAudioChannel_Rrs); + case Channel::MOTION_DATA: + return dict->ul(ASDCP::MDD_DBOXMotionCodePrimaryStream); + case Channel::SYNC_SIGNAL: + return ASDCP::UL(sync_signal); + case Channel::SIGN_LANGUAGE: + return ASDCP::UL(sign_language); + default: + break; + } + + DCP_ASSERT (false); +} + + |
