summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-04-06 23:57:46 +0100
committerCarl Hetherington <cth@carlh.net>2013-04-06 23:57:46 +0100
commitc921cfe23b593d7c367ad76094308c5f08037374 (patch)
treed010137615eb3817e57edaf0b0753ef924569965 /src/lib
parent8750efb9e072cf3b42e6c3c29521c7031c0b5dfd (diff)
Various work on audio channel mapping.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/analyse_audio_job.cc4
-rw-r--r--src/lib/audio_mapping.cc100
-rw-r--r--src/lib/audio_mapping.h52
-rw-r--r--src/lib/encoder.cc3
-rw-r--r--src/lib/ffmpeg_content.cc3
-rw-r--r--src/lib/film.cc16
-rw-r--r--src/lib/film.h12
-rw-r--r--src/lib/imagemagick_content.cc2
-rw-r--r--src/lib/playlist.cc45
-rw-r--r--src/lib/playlist.h3
-rw-r--r--src/lib/sndfile_content.cc7
-rw-r--r--src/lib/writer.cc6
12 files changed, 165 insertions, 88 deletions
diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc
index 5ef6515dd..50096d7c1 100644
--- a/src/lib/analyse_audio_job.cc
+++ b/src/lib/analyse_audio_job.cc
@@ -57,8 +57,8 @@ AnalyseAudioJob::run ()
_samples_per_point = max (int64_t (1), _film->audio_length() / _num_points);
- _current.resize (_film->audio_channels ());
- _analysis.reset (new AudioAnalysis (_film->audio_channels()));
+ _current.resize (MAX_AUDIO_CHANNELS);
+ _analysis.reset (new AudioAnalysis (MAX_AUDIO_CHANNELS));
while (!player->pass()) {
set_progress (float (_done) / _film->audio_length ());
diff --git a/src/lib/audio_mapping.cc b/src/lib/audio_mapping.cc
index 3fc423e10..48cc23307 100644
--- a/src/lib/audio_mapping.cc
+++ b/src/lib/audio_mapping.cc
@@ -19,85 +19,77 @@
#include "audio_mapping.h"
-using std::map;
-using boost::optional;
-
-AutomaticAudioMapping::AutomaticAudioMapping (int c)
- : _source_channels (c)
+using std::list;
+using std::cout;
+using std::make_pair;
+using std::pair;
+using boost::shared_ptr;
+
+void
+AudioMapping::add (Channel c, libdcp::Channel d)
{
-
+ _content_to_dcp.push_back (make_pair (c, d));
}
-optional<libdcp::Channel>
-AutomaticAudioMapping::source_to_dcp (int c) const
+/* XXX: this is grotty */
+int
+AudioMapping::dcp_channels () const
{
- if (c >= _source_channels) {
- return optional<libdcp::Channel> ();
+ for (list<pair<Channel, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
+ if (((int) i->second) > 2) {
+ return 6;
+ }
}
- if (_source_channels == 1) {
- /* mono sources to centre */
- return libdcp::CENTRE;
- }
-
- return static_cast<libdcp::Channel> (c);
+ return 2;
}
-optional<int>
-AutomaticAudioMapping::dcp_to_source (libdcp::Channel c) const
+list<AudioMapping::Channel>
+AudioMapping::dcp_to_content (libdcp::Channel d) const
{
- if (_source_channels == 1) {
- if (c == libdcp::CENTRE) {
- return 0;
- } else {
- return optional<int> ();
+ list<AudioMapping::Channel> c;
+ for (list<pair<Channel, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
+ if (i->second == d) {
+ c.push_back (i->first);
}
}
- if (static_cast<int> (c) >= _source_channels) {
- return optional<int> ();
- }
-
- return static_cast<int> (c);
+ return c;
}
-int
-AutomaticAudioMapping::dcp_channels () const
+list<AudioMapping::Channel>
+AudioMapping::content_channels () const
{
- if (_source_channels == 1) {
- /* The source is mono, so to put the mono channel into
- the centre we need to generate a 5.1 soundtrack.
- */
- return 6;
+ list<AudioMapping::Channel> c;
+ for (list<pair<Channel, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
+ if (find (c.begin(), c.end(), i->first) == c.end ()) {
+ c.push_back (i->first);
+ }
}
- return _source_channels;
+ return c;
}
-optional<int>
-ConfiguredAudioMapping::dcp_to_source (libdcp::Channel c) const
+list<libdcp::Channel>
+AudioMapping::content_to_dcp (Channel c) const
{
- map<int, libdcp::Channel>::const_iterator i = _source_to_dcp.begin ();
- while (i != _source_to_dcp.end() && i->second != c) {
- ++i;
- }
-
- if (i == _source_to_dcp.end ()) {
- return boost::none;
+ list<libdcp::Channel> d;
+ for (list<pair<Channel, libdcp::Channel> >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) {
+ if (i->first == c) {
+ d.push_back (i->second);
+ }
}
- return i->first;
+ return d;
}
-optional<libdcp::Channel>
-ConfiguredAudioMapping::source_to_dcp (int c) const
+bool
+operator== (AudioMapping::Channel const & a, AudioMapping::Channel const & b)
{
- map<int, libdcp::Channel>::const_iterator i = _source_to_dcp.find (c);
- if (i == _source_to_dcp.end ()) {
- return boost::none;
- }
-
- return i->second;
+ shared_ptr<const AudioContent> sa = a.content.lock ();
+ shared_ptr<const AudioContent> sb = b.content.lock ();
+ return sa == sb && a.index == b.index;
}
+
diff --git a/src/lib/audio_mapping.h b/src/lib/audio_mapping.h
index 8804bde06..10ac20b48 100644
--- a/src/lib/audio_mapping.h
+++ b/src/lib/audio_mapping.h
@@ -17,37 +17,43 @@
*/
-#include <vector>
-#include <map>
-#include <boost/optional.hpp>
+#ifndef DVDOMATIC_AUDIO_MAPPING_H
+#define DVDOMATIC_AUDIO_MAPPING_H
+
+#include <list>
+#include <string>
#include <libdcp/types.h>
+#include <boost/shared_ptr.hpp>
+#include "audio_content.h"
class AudioMapping
{
public:
- virtual boost::optional<libdcp::Channel> source_to_dcp (int c) const = 0;
- virtual boost::optional<int> dcp_to_source (libdcp::Channel c) const = 0;
-};
-
-class AutomaticAudioMapping : public AudioMapping
-{
-public:
- AutomaticAudioMapping (int);
+ struct Channel {
+ Channel (boost::weak_ptr<const AudioContent> c, int i)
+ : content (c)
+ , index (i)
+ {}
+
+ boost::weak_ptr<const AudioContent> content;
+ int index;
+ };
+
+ void add (Channel, libdcp::Channel);
- boost::optional<libdcp::Channel> source_to_dcp (int c) const;
- boost::optional<int> dcp_to_source (libdcp::Channel c) const;
int dcp_channels () const;
-
-private:
- int _source_channels;
-};
+ std::list<Channel> dcp_to_content (libdcp::Channel) const;
+ std::list<std::pair<Channel, libdcp::Channel> > content_to_dcp () const {
+ return _content_to_dcp;
+ }
-class ConfiguredAudioMapping : public AudioMapping
-{
-public:
- boost::optional<libdcp::Channel> source_to_dcp (int c) const;
- boost::optional<int> dcp_to_source (libdcp::Channel c) const;
+ std::list<Channel> content_channels () const;
+ std::list<libdcp::Channel> content_to_dcp (Channel) const;
private:
- std::map<int, libdcp::Channel> _source_to_dcp;
+ std::list<std::pair<Channel, libdcp::Channel> > _content_to_dcp;
};
+
+extern bool operator== (AudioMapping::Channel const &, AudioMapping::Channel const &);
+
+#endif
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index a0b88e33e..0542587a0 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -427,6 +427,8 @@ Encoder::encoder_thread (ServerDescription* server)
void
Encoder::write_audio (shared_ptr<const AudioBuffers> data)
{
+#if 0
+ XXX
AutomaticAudioMapping m (_film->audio_channels ());
if (m.dcp_channels() != _film->audio_channels()) {
@@ -444,6 +446,7 @@ Encoder::write_audio (shared_ptr<const AudioBuffers> data)
data = b;
}
+#endif
_writer->write (data);
}
diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc
index cc95105e5..d36abe2c3 100644
--- a/src/lib/ffmpeg_content.cc
+++ b/src/lib/ffmpeg_content.cc
@@ -152,12 +152,13 @@ FFmpegContent::examine (shared_ptr<Film> film, shared_ptr<Job> job, bool quick)
signal_changed (FFmpegContentProperty::SUBTITLE_STREAM);
signal_changed (FFmpegContentProperty::AUDIO_STREAMS);
signal_changed (FFmpegContentProperty::AUDIO_STREAM);
+ signal_changed (AudioContentProperty::AUDIO_CHANNELS);
}
string
FFmpegContent::summary () const
{
- return String::compose (_("Movie: %1"), file().filename ());
+ return String::compose (_("Movie: %1"), file().filename().string());
}
string
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 69d2a28e2..b1f740ec2 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -960,6 +960,7 @@ Film::signal_changed (Property p)
case Film::CONTENT:
_playlist->setup (content ());
set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ()));
+ set_audio_mapping (_playlist->default_audio_mapping ());
break;
default:
break;
@@ -1236,11 +1237,24 @@ Film::set_ffmpeg_audio_stream (FFmpegAudioStream s)
}
void
+Film::set_audio_mapping (AudioMapping m)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _audio_mapping = m;
+ }
+
+ signal_changed (AUDIO_MAPPING);
+}
+
+void
Film::content_changed (boost::weak_ptr<Content> c, int p)
{
if (p == VideoContentProperty::VIDEO_FRAME_RATE) {
set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ()));
- }
+ } else if (p == AudioContentProperty::AUDIO_CHANNELS) {
+ set_audio_mapping (_playlist->default_audio_mapping ());
+ }
if (ui_signaller) {
ui_signaller->emit (boost::bind (boost::ref (ContentChanged), c, p));
diff --git a/src/lib/film.h b/src/lib/film.h
index 9c5f561e6..532d32bdc 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -36,6 +36,7 @@
#include "dci_metadata.h"
#include "types.h"
#include "ffmpeg_content.h"
+#include "audio_mapping.h"
class DCPContentType;
class Format;
@@ -146,7 +147,8 @@ public:
COLOUR_LUT,
J2K_BANDWIDTH,
DCI_METADATA,
- DCP_FRAME_RATE
+ DCP_FRAME_RATE,
+ AUDIO_MAPPING
};
@@ -262,6 +264,11 @@ public:
return _dcp_frame_rate;
}
+ AudioMapping audio_mapping () const {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ return _audio_mapping;
+ }
+
/* SET */
void set_directory (std::string);
@@ -294,6 +301,7 @@ public:
void set_dci_metadata (DCIMetadata);
void set_dcp_frame_rate (int);
void set_dci_date_today ();
+ void set_audio_mapping (AudioMapping);
/** Emitted when some property has of the Film has changed */
mutable boost::signals2::signal<void (Property)> Changed;
@@ -314,6 +322,7 @@ private:
void read_metadata ();
void content_changed (boost::weak_ptr<Content>, int);
boost::shared_ptr<FFmpegContent> ffmpeg () const;
+ void setup_default_audio_mapping ();
/** Log to write to */
boost::shared_ptr<Log> _log;
@@ -378,6 +387,7 @@ private:
int _dcp_frame_rate;
/** The date that we should use in a DCI name */
boost::gregorian::date _dci_date;
+ AudioMapping _audio_mapping;
/** true if our state has changed since we last saved it */
mutable bool _dirty;
diff --git a/src/lib/imagemagick_content.cc b/src/lib/imagemagick_content.cc
index 912c180a8..59fde40bb 100644
--- a/src/lib/imagemagick_content.cc
+++ b/src/lib/imagemagick_content.cc
@@ -45,7 +45,7 @@ ImageMagickContent::ImageMagickContent (shared_ptr<const cxml::Node> node)
string
ImageMagickContent::summary () const
{
- return String::compose (_("Image: %1"), file().filename ());
+ return String::compose (_("Image: %1"), file().filename().string());
}
bool
diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc
index e0220ef6f..3f7905fa9 100644
--- a/src/lib/playlist.cc
+++ b/src/lib/playlist.cc
@@ -30,6 +30,7 @@
using std::list;
using std::cout;
using std::vector;
+using std::min;
using boost::shared_ptr;
using boost::weak_ptr;
using boost::dynamic_pointer_cast;
@@ -224,3 +225,47 @@ Playlist::content_changed (weak_ptr<Content> c, int p)
{
ContentChanged (c, p);
}
+
+AudioMapping
+Playlist::default_audio_mapping () const
+{
+ AudioMapping m;
+
+ switch (_audio_from) {
+ case AUDIO_NONE:
+ break;
+ case AUDIO_FFMPEG:
+ if (_ffmpeg->audio_channels() == 1) {
+ /* Map mono sources to centre */
+ m.add (AudioMapping::Channel (_ffmpeg, 0), libdcp::CENTRE);
+ } else {
+ int const N = min (_ffmpeg->audio_channels (), MAX_AUDIO_CHANNELS);
+ /* Otherwise just start with a 1:1 mapping */
+ for (int i = 0; i < N; ++i) {
+ m.add (AudioMapping::Channel (_ffmpeg, i), (libdcp::Channel) i);
+ }
+ }
+ break;
+
+ case AUDIO_SNDFILE:
+ {
+ int n = 0;
+ for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
+ cout << "sndfile " << (*i)->audio_channels() << "\n";
+ for (int j = 0; j < (*i)->audio_channels(); ++j) {
+ m.add (AudioMapping::Channel (*i, j), (libdcp::Channel) n);
+ ++n;
+ if (n >= MAX_AUDIO_CHANNELS) {
+ break;
+ }
+ }
+ if (n >= MAX_AUDIO_CHANNELS) {
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return m;
+}
diff --git a/src/lib/playlist.h b/src/lib/playlist.h
index 1a24a0227..1d189cb07 100644
--- a/src/lib/playlist.h
+++ b/src/lib/playlist.h
@@ -25,6 +25,7 @@
#include "video_sink.h"
#include "audio_sink.h"
#include "ffmpeg_content.h"
+#include "audio_mapping.h"
class Content;
class FFmpegContent;
@@ -53,6 +54,8 @@ public:
libdcp::Size video_size () const;
ContentVideoFrame video_length () const;
+ AudioMapping default_audio_mapping () const;
+
enum VideoFrom {
VIDEO_NONE,
VIDEO_FFMPEG,
diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc
index ee4f21eef..539b0dfb5 100644
--- a/src/lib/sndfile_content.cc
+++ b/src/lib/sndfile_content.cc
@@ -27,12 +27,16 @@
using std::string;
using std::stringstream;
+using std::cout;
using boost::shared_ptr;
using boost::lexical_cast;
SndfileContent::SndfileContent (boost::filesystem::path f)
: Content (f)
, AudioContent (f)
+ , _audio_channels (0)
+ , _audio_length (0)
+ , _audio_frame_rate (0)
{
}
@@ -49,7 +53,7 @@ SndfileContent::SndfileContent (shared_ptr<const cxml::Node> node)
string
SndfileContent::summary () const
{
- return String::compose (_("Sound file: %1"), file().filename ());
+ return String::compose (_("Sound file: %1"), file().filename().string());
}
string
@@ -115,3 +119,4 @@ SndfileContent::as_xml (xmlpp::Node* node) const
node->add_child("AudioLength")->add_child_text (lexical_cast<string> (_audio_length));
node->add_child("AudioFrameRate")->add_child_text (lexical_cast<string> (_audio_frame_rate));
}
+
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index 6df1a1f21..7258826ba 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -78,15 +78,13 @@ Writer::Writer (shared_ptr<Film> f)
_picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
- AutomaticAudioMapping m (_film->audio_channels ());
-
- if (m.dcp_channels() > 0) {
+ if (_film->audio_channels() > 0) {
_sound_asset.reset (
new libdcp::SoundAsset (
_film->dir (_film->dcp_name()),
N_("audio.mxf"),
_film->dcp_frame_rate (),
- m.dcp_channels (),
+ _film->audio_mapping().dcp_channels (),
dcp_audio_sample_rate (_film->audio_frame_rate())
)
);