summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-07-06 23:23:26 +0200
committercah <cth@carlh.net>2025-07-10 22:49:00 +0200
commit4e244c8a4b34268445123b7d6df54ff303561fa5 (patch)
tree54b92d242ea518ee0e9d55c20265d5ab963fc7a0 /src/lib
parenta564301f86068484d98d329971f59b10c7de892e (diff)
Allow audio processors to pass through HI/VI/DBox etc (#3020).
Previously you couldn't map these things if you were using a processor.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/audio_processor.cc63
-rw-r--r--src/lib/audio_processor.h7
-rw-r--r--src/lib/film.cc23
-rw-r--r--src/lib/mid_side_decoder.cc19
-rw-r--r--src/lib/mid_side_decoder.h4
-rw-r--r--src/lib/upmixer_a.cc2
-rw-r--r--src/lib/upmixer_a.h4
-rw-r--r--src/lib/upmixer_b.cc2
-rw-r--r--src/lib/upmixer_b.h4
9 files changed, 115 insertions, 13 deletions
diff --git a/src/lib/audio_processor.cc b/src/lib/audio_processor.cc
index e13ba017b..26c906635 100644
--- a/src/lib/audio_processor.cc
+++ b/src/lib/audio_processor.cc
@@ -25,7 +25,10 @@
#include "upmixer_a.h"
#include "upmixer_b.h"
+#include "i18n.h"
+
+using std::shared_ptr;
using std::string;
using std::unique_ptr;
using std::vector;
@@ -96,3 +99,63 @@ AudioProcessor::all()
return raw;
}
+
+
+shared_ptr<AudioBuffers>
+AudioProcessor::run(std::shared_ptr<const AudioBuffers> in, int channels)
+{
+ auto out = do_run(in, std::min(channels, out_channels()));
+
+ if (out->channels() < channels) {
+ out->set_channels(channels);
+ }
+
+ for (auto const pass: pass_through()) {
+ if (static_cast<int>(pass) < channels && static_cast<int>(pass) < out->channels()) {
+ out->copy_channel_from(in.get(), static_cast<int>(pass), static_cast<int>(pass));
+ }
+ }
+
+ return out;
+}
+
+
+void
+AudioProcessor::make_audio_mapping_default(AudioMapping& mapping) const
+{
+ mapping.make_zero();
+
+ auto const channels = std::min(mapping.input_channels(), mapping.output_channels());
+
+ for (auto pass: pass_through()) {
+ if (static_cast<int>(pass) < channels) {
+ mapping.set(pass, static_cast<int>(pass), 1);
+ }
+ }
+}
+
+
+vector<NamedChannel>
+AudioProcessor::input_names() const
+{
+ return {
+ NamedChannel(_("HI"), 6),
+ NamedChannel(_("VI"), 7),
+ NamedChannel(_("DBP"), 13),
+ NamedChannel(_("DBS"), 14),
+ NamedChannel(_("Sign"), 15)
+ };
+}
+
+
+vector<dcp::Channel>
+AudioProcessor::pass_through()
+{
+ return {
+ dcp::Channel::HI,
+ dcp::Channel::VI,
+ dcp::Channel::MOTION_DATA,
+ dcp::Channel::SYNC_SIGNAL,
+ dcp::Channel::SIGN_LANGUAGE
+ };
+}
diff --git a/src/lib/audio_processor.h b/src/lib/audio_processor.h
index 2c3df3add..f469f07c0 100644
--- a/src/lib/audio_processor.h
+++ b/src/lib/audio_processor.h
@@ -29,6 +29,7 @@
#include "named_channel.h"
+#include <dcp/types.h>
#include <memory>
#include <string>
#include <vector>
@@ -58,7 +59,7 @@ public:
/** @return A clone of this AudioProcessor for operation at the specified sampling rate */
virtual std::shared_ptr<AudioProcessor> clone(int sampling_rate) const = 0;
/** Process some data, returning the processed result truncated or padded to `channels' */
- virtual std::shared_ptr<AudioBuffers> run(std::shared_ptr<const AudioBuffers>, int channels) = 0;
+ std::shared_ptr<AudioBuffers> run(std::shared_ptr<const AudioBuffers>, int channels);
virtual void flush() {}
/** Make the supplied audio mapping into a sensible default for this processor */
virtual void make_audio_mapping_default(AudioMapping& mapping) const = 0;
@@ -69,6 +70,10 @@ public:
static std::vector<AudioProcessor const *> visible();
static void setup_audio_processors();
static AudioProcessor const * from_id(std::string);
+ static std::vector<dcp::Channel> pass_through();
+
+protected:
+ virtual std::shared_ptr<AudioBuffers> do_run(std::shared_ptr<const AudioBuffers>, int channels) = 0;
private:
static std::vector<std::unique_ptr<const AudioProcessor>> _experimental;
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 58699743b..b73c2bac6 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -791,10 +791,23 @@ Film::mapped_audio_channels() const
list<int> mapped;
if (audio_processor()) {
- /* Processors are mapped 1:1 to DCP outputs so we can work out mappings from there */
+ /* Assume all a processor's declared output channels are mapped */
for (int i = 0; i < audio_processor()->out_channels(); ++i) {
mapped.push_back(i);
}
+
+ /* Check to see if channels that the processor passes through are mapped */
+ auto pass = AudioProcessor::pass_through();
+ for (auto i: content()) {
+ if (i->audio) {
+ for (auto c: i->audio->mapping().mapped_output_channels()) {
+ if (std::find(pass.begin(), pass.end(), dcp::Channel(c)) != pass.end()) {
+ mapped.push_back(c);
+ }
+ }
+ }
+ }
+
} else {
for (auto i: content()) {
if (i->audio) {
@@ -1885,7 +1898,13 @@ vector<NamedChannel>
Film::audio_output_channel_names() const
{
if (audio_processor()) {
- return audio_processor()->input_names();
+ vector<NamedChannel> channels;
+ for (auto input: audio_processor()->input_names()) {
+ if (input.index < audio_channels()) {
+ channels.push_back(input);
+ }
+ }
+ return channels;
}
DCPOMATIC_ASSERT(MAX_DCP_AUDIO_CHANNELS == 16);
diff --git a/src/lib/mid_side_decoder.cc b/src/lib/mid_side_decoder.cc
index 695e4cad7..719dbce92 100644
--- a/src/lib/mid_side_decoder.cc
+++ b/src/lib/mid_side_decoder.cc
@@ -62,7 +62,7 @@ MidSideDecoder::clone(int) const
shared_ptr<AudioBuffers>
-MidSideDecoder::run(shared_ptr<const AudioBuffers> in, int channels)
+MidSideDecoder::do_run(shared_ptr<const AudioBuffers> in, int channels)
{
int const N = min(channels, 3);
auto out = make_shared<AudioBuffers>(channels, in->frames());
@@ -88,9 +88,12 @@ MidSideDecoder::run(shared_ptr<const AudioBuffers> in, int channels)
void
MidSideDecoder::make_audio_mapping_default(AudioMapping& mapping) const
{
- /* Just map the first two input channels to our M/S */
- mapping.make_zero();
- for (int i = 0; i < min(2, mapping.input_channels()); ++i) {
+ AudioProcessor::make_audio_mapping_default(mapping);
+
+ auto const inputs = mapping.input_channels();
+
+ /* Map the first two input channels to our M/S */
+ for (int i = 0; i < min(2, inputs); ++i) {
mapping.set(i, i, 1);
}
}
@@ -99,8 +102,14 @@ MidSideDecoder::make_audio_mapping_default(AudioMapping& mapping) const
vector<NamedChannel>
MidSideDecoder::input_names() const
{
- return {
+ vector<NamedChannel> names = {
NamedChannel(_("Left"), 0),
NamedChannel(_("Right"), 1)
};
+
+ for (auto name: AudioProcessor::input_names()) {
+ names.push_back(name);
+ }
+
+ return names;
}
diff --git a/src/lib/mid_side_decoder.h b/src/lib/mid_side_decoder.h
index 34c3eecb5..0505d5953 100644
--- a/src/lib/mid_side_decoder.h
+++ b/src/lib/mid_side_decoder.h
@@ -29,7 +29,9 @@ public:
std::string id() const override;
int out_channels() const override;
std::shared_ptr<AudioProcessor> clone(int) const override;
- std::shared_ptr<AudioBuffers> run(std::shared_ptr<const AudioBuffers>, int channels) override;
void make_audio_mapping_default(AudioMapping& mapping) const override;
std::vector<NamedChannel> input_names() const override;
+
+protected:
+ std::shared_ptr<AudioBuffers> do_run(std::shared_ptr<const AudioBuffers>, int channels) override;
};
diff --git a/src/lib/upmixer_a.cc b/src/lib/upmixer_a.cc
index d87546a76..6eaaf0a52 100644
--- a/src/lib/upmixer_a.cc
+++ b/src/lib/upmixer_a.cc
@@ -74,7 +74,7 @@ UpmixerA::clone(int sampling_rate) const
shared_ptr<AudioBuffers>
-UpmixerA::run(shared_ptr<const AudioBuffers> in, int channels)
+UpmixerA::do_run(shared_ptr<const AudioBuffers> in, int channels)
{
/* Input L and R */
auto in_L = in->channel(0);
diff --git a/src/lib/upmixer_a.h b/src/lib/upmixer_a.h
index 9b1e09ee5..fef6af056 100644
--- a/src/lib/upmixer_a.h
+++ b/src/lib/upmixer_a.h
@@ -40,11 +40,13 @@ public:
std::string id() const override;
int out_channels() const override;
std::shared_ptr<AudioProcessor> clone(int) const override;
- std::shared_ptr<AudioBuffers> run(std::shared_ptr<const AudioBuffers>, int channels) override;
void flush() override;
void make_audio_mapping_default(AudioMapping& mapping) const override;
std::vector<NamedChannel> input_names() const override;
+protected:
+ std::shared_ptr<AudioBuffers> do_run(std::shared_ptr<const AudioBuffers>, int channels) override;
+
private:
BandPassAudioFilter _left;
BandPassAudioFilter _right;
diff --git a/src/lib/upmixer_b.cc b/src/lib/upmixer_b.cc
index 40bed6b6e..1e084d03f 100644
--- a/src/lib/upmixer_b.cc
+++ b/src/lib/upmixer_b.cc
@@ -70,7 +70,7 @@ UpmixerB::clone(int sampling_rate) const
shared_ptr<AudioBuffers>
-UpmixerB::run(shared_ptr<const AudioBuffers> in, int channels)
+UpmixerB::do_run(shared_ptr<const AudioBuffers> in, int channels)
{
auto out = make_shared<AudioBuffers>(channels, in->frames());
diff --git a/src/lib/upmixer_b.h b/src/lib/upmixer_b.h
index 6ac310bdb..1fc89f704 100644
--- a/src/lib/upmixer_b.h
+++ b/src/lib/upmixer_b.h
@@ -38,11 +38,13 @@ public:
std::string id() const override;
int out_channels() const override;
std::shared_ptr<AudioProcessor> clone(int) const override;
- std::shared_ptr<AudioBuffers> run(std::shared_ptr<const AudioBuffers>, int channels) override;
void flush() override;
void make_audio_mapping_default(AudioMapping& mapping) const override;
std::vector<NamedChannel> input_names() const override;
+protected:
+ std::shared_ptr<AudioBuffers> do_run(std::shared_ptr<const AudioBuffers>, int channels) override;
+
private:
LowPassAudioFilter _lfe;
AudioDelay _delay;