summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-06-03 22:58:46 +0100
committerCarl Hetherington <cth@carlh.net>2014-06-03 22:58:46 +0100
commit82926443230084739cb673a83b2ab1f9d733a07b (patch)
tree72ff6a2564bc5950f52730b9d00151a5ebbbe00f /src/lib
parent5ff10668facca32723efae3f08dfaab8a3d8bd44 (diff)
All audio content should resample if the output frame rate and content
frame rates differ; make Sndfile sources use the video-frame-rate-based calculation for output frame rate (like FFmpeg sources do). Also, fix small problems when flushing Resamplers used to get fed back to Resamplers again.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/audio_content.cc26
-rw-r--r--src/lib/audio_content.h3
-rw-r--r--src/lib/content.h2
-rw-r--r--src/lib/ffmpeg_content.cc24
-rw-r--r--src/lib/ffmpeg_content.h1
-rw-r--r--src/lib/player.cc39
-rw-r--r--src/lib/player.h2
-rw-r--r--src/lib/sndfile_content.cc9
-rw-r--r--src/lib/sndfile_content.h2
9 files changed, 52 insertions, 56 deletions
diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc
index dbca6652c..79912f1ae 100644
--- a/src/lib/audio_content.cc
+++ b/src/lib/audio_content.cc
@@ -29,6 +29,7 @@
#include "i18n.h"
using std::string;
+using std::cout;
using std::vector;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
@@ -148,3 +149,28 @@ AudioContent::technical_summary () const
{
return String::compose ("audio: channels %1, length %2, raw rate %3, out rate %4", audio_channels(), audio_length(), content_audio_frame_rate(), output_audio_frame_rate());
}
+
+int
+AudioContent::output_audio_frame_rate () const
+{
+ shared_ptr<const Film> film = _film.lock ();
+ assert (film);
+
+ /* Resample to a DCI-approved sample rate */
+ double t = dcp_audio_frame_rate (content_audio_frame_rate ());
+
+ FrameRateConversion frc (video_frame_rate(), film->video_frame_rate());
+
+ /* Compensate if the DCP is being run at a different frame rate
+ to the source; that is, if the video is run such that it will
+ look different in the DCP compared to the source (slower or faster).
+ skip/repeat doesn't come into effect here.
+ */
+
+ if (frc.change_speed) {
+ t *= video_frame_rate() * frc.factor() / film->video_frame_rate();
+ }
+
+ return rint (t);
+}
+
diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h
index d30db02d7..2a1216d86 100644
--- a/src/lib/audio_content.h
+++ b/src/lib/audio_content.h
@@ -54,11 +54,12 @@ public:
virtual int audio_channels () const = 0;
virtual AudioContent::Frame audio_length () const = 0;
virtual int content_audio_frame_rate () const = 0;
- virtual int output_audio_frame_rate () const = 0;
virtual AudioMapping audio_mapping () const = 0;
virtual void set_audio_mapping (AudioMapping) = 0;
virtual boost::filesystem::path audio_analysis_path () const;
+ int output_audio_frame_rate () const;
+
boost::signals2::connection analyse_audio (boost::function<void()>);
void set_audio_gain (float);
diff --git a/src/lib/content.h b/src/lib/content.h
index 596a0a905..3cea93cfc 100644
--- a/src/lib/content.h
+++ b/src/lib/content.h
@@ -65,6 +65,8 @@ public:
virtual void as_xml (xmlpp::Node *) const;
virtual Time full_length () const = 0;
virtual std::string identifier () const;
+ /** @return the video frame rate that this content has or was prepared to be used with */
+ virtual float video_frame_rate () const = 0;
boost::shared_ptr<Content> clone () const;
diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc
index 41a3724a2..4ea6dbc6a 100644
--- a/src/lib/ffmpeg_content.cc
+++ b/src/lib/ffmpeg_content.cc
@@ -309,30 +309,6 @@ FFmpegContent::content_audio_frame_rate () const
return _audio_stream->frame_rate;
}
-int
-FFmpegContent::output_audio_frame_rate () const
-{
- shared_ptr<const Film> film = _film.lock ();
- assert (film);
-
- /* Resample to a DCI-approved sample rate */
- double t = dcp_audio_frame_rate (content_audio_frame_rate ());
-
- FrameRateConversion frc (video_frame_rate(), film->video_frame_rate());
-
- /* Compensate if the DCP is being run at a different frame rate
- to the source; that is, if the video is run such that it will
- look different in the DCP compared to the source (slower or faster).
- skip/repeat doesn't come into effect here.
- */
-
- if (frc.change_speed) {
- t *= video_frame_rate() * frc.factor() / film->video_frame_rate();
- }
-
- return rint (t);
-}
-
bool
operator== (FFmpegStream const & a, FFmpegStream const & b)
{
diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h
index 6ab95d2fe..c15e5c10e 100644
--- a/src/lib/ffmpeg_content.h
+++ b/src/lib/ffmpeg_content.h
@@ -147,7 +147,6 @@ public:
int audio_channels () const;
AudioContent::Frame audio_length () const;
int content_audio_frame_rate () const;
- int output_audio_frame_rate () const;
AudioMapping audio_mapping () const;
void set_audio_mapping (AudioMapping);
boost::filesystem::path audio_analysis_path () const;
diff --git a/src/lib/player.cc b/src/lib/player.cc
index b112760ef..68df8ea70 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -149,7 +149,7 @@ Player::pass ()
if (re) {
shared_ptr<const AudioBuffers> b = re->flush ();
if (b->frames ()) {
- process_audio (earliest, b, ac->audio_length ());
+ process_audio (earliest, b, ac->audio_length (), true);
}
}
}
@@ -269,8 +269,9 @@ Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const ImageProxy>
}
}
+/** @param already_resampled true if this data has already been through the chain up to the resampler */
void
-Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame)
+Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers> audio, AudioContent::Frame frame, bool already_resampled)
{
shared_ptr<Piece> piece = weak_piece.lock ();
if (!piece) {
@@ -280,19 +281,21 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers
shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
assert (content);
- /* Gain */
- if (content->audio_gain() != 0) {
- shared_ptr<AudioBuffers> gain (new AudioBuffers (audio));
- gain->apply_gain (content->audio_gain ());
- audio = gain;
- }
-
- /* Resample */
- if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
- shared_ptr<Resampler> r = resampler (content, true);
- pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
- audio = ro.first;
- frame = ro.second;
+ if (!already_resampled) {
+ /* Gain */
+ if (content->audio_gain() != 0) {
+ shared_ptr<AudioBuffers> gain (new AudioBuffers (audio));
+ gain->apply_gain (content->audio_gain ());
+ audio = gain;
+ }
+
+ /* Resample */
+ if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
+ shared_ptr<Resampler> r = resampler (content, true);
+ pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
+ audio = ro.first;
+ frame = ro.second;
+ }
}
Time const relative_time = _film->audio_frames_to_time (frame);
@@ -427,7 +430,7 @@ Player::setup_pieces ()
shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
fd->Video.connect (bind (&Player::process_video, this, weak_ptr<Piece> (piece), _1, _2, _3, _4, _5, 0));
- fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
+ fd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2, false));
fd->Subtitle.connect (bind (&Player::process_subtitle, this, weak_ptr<Piece> (piece), _1, _2, _3, _4));
fd->seek (fc->time_to_content_video_frames (fc->trim_start ()), true);
@@ -457,7 +460,7 @@ Player::setup_pieces ()
shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
if (sc) {
shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
- sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2));
+ sd->Audio.connect (bind (&Player::process_audio, this, weak_ptr<Piece> (piece), _1, _2, false));
piece->decoder = sd;
}
@@ -555,7 +558,7 @@ Player::resampler (shared_ptr<AudioContent> c, bool create)
LOG_GENERAL (
"Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()
);
-
+
shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
_resamplers[c] = r;
return r;
diff --git a/src/lib/player.h b/src/lib/player.h
index bf6260c0a..6e70ad707 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -87,7 +87,7 @@ private:
friend class Piece;
void process_video (boost::weak_ptr<Piece>, boost::shared_ptr<const ImageProxy>, Eyes, Part, bool, VideoContent::Frame, Time);
- void process_audio (boost::weak_ptr<Piece>, boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
+ void process_audio (boost::weak_ptr<Piece>, boost::shared_ptr<const AudioBuffers>, AudioContent::Frame, bool);
void process_subtitle (boost::weak_ptr<Piece>, boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time);
void setup_pieces ();
void playlist_changed ();
diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc
index fcdf88778..6f18ebbb4 100644
--- a/src/lib/sndfile_content.cc
+++ b/src/lib/sndfile_content.cc
@@ -159,15 +159,6 @@ SndfileContent::full_length () const
return film->audio_frames_to_time (len);
}
-int
-SndfileContent::output_audio_frame_rate () const
-{
- shared_ptr<const Film> film = _film.lock ();
- assert (film);
-
- return film->audio_frame_rate ();
-}
-
void
SndfileContent::set_audio_mapping (AudioMapping m)
{
diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h
index a79fb99b6..dcfdfd8d7 100644
--- a/src/lib/sndfile_content.h
+++ b/src/lib/sndfile_content.h
@@ -68,8 +68,6 @@ public:
return _audio_frame_rate;
}
- int output_audio_frame_rate () const;
-
AudioMapping audio_mapping () const {
boost::mutex::scoped_lock lm (_mutex);
return _audio_mapping;