/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
AudioContent::technical_summary () const
{
return String::compose (
- "audio: channels %1, length %2, raw rate %3, out rate %4",
+ "audio: channels %1, length %2, content rate %3, resampled rate %4",
audio_channels(),
audio_length().seconds(),
- content_audio_frame_rate(),
- output_audio_frame_rate()
+ audio_frame_rate(),
+ resampled_audio_frame_rate()
);
}
{
signal_changed (AudioContentProperty::AUDIO_MAPPING);
}
+
+/** @return the frame rate that this content should be resampled to in order
+ * that it is in sync with the active video content at its start time.
+ */
+int
+AudioContent::resampled_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 (audio_frame_rate ());
+
+ FrameRateChange frc = film->active_frame_rate_change (position ());
+
+ /* 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).
+ */
+
+ if (frc.change_speed) {
+ t /= frc.speed_up;
+ }
+
+ return rint (t);
+}
/** @return the length of the audio in the content */
virtual ContentTime audio_length () const = 0;
/** @return the frame rate of the content */
- virtual int content_audio_frame_rate () const = 0;
- virtual int output_audio_frame_rate () const = 0;
+ virtual int audio_frame_rate () const = 0;
virtual AudioMapping audio_mapping () const = 0;
virtual void set_audio_mapping (AudioMapping);
virtual boost::filesystem::path audio_analysis_path () const;
+ int resampled_audio_frame_rate () const;
+
boost::signals2::connection analyse_audio (boost::function<void()>);
void set_audio_gain (float);
AudioDecoder::AudioDecoder (shared_ptr<const AudioContent> content)
: _audio_content (content)
{
- if (content->output_audio_frame_rate() != content->content_audio_frame_rate() && content->audio_channels ()) {
- _resampler.reset (new Resampler (content->content_audio_frame_rate(), content->output_audio_frame_rate(), content->audio_channels ()));
+ if (content->resampled_audio_frame_rate() != content->audio_frame_rate() && content->audio_channels ()) {
+ _resampler.reset (new Resampler (content->audio_frame_rate(), content->resampled_audio_frame_rate(), content->audio_channels ()));
}
reset_decoded_audio ();
if (frame < _decoded_audio.frame || end > (_decoded_audio.frame + length * 4)) {
/* Either we have no decoded data, or what we do have is a long way from what we want: seek */
- seek (ContentTime::from_frames (frame, _audio_content->content_audio_frame_rate()), accurate);
+ seek (ContentTime::from_frames (frame, _audio_content->audio_frame_rate()), accurate);
}
/* Offset of the data that we want from the start of _decoded_audio.audio
}
if (!_audio_position) {
- _audio_position = time.frames (_audio_content->output_audio_frame_rate ());
+ _audio_position = time.frames (_audio_content->resampled_audio_frame_rate ());
}
assert (_audio_position.get() >= (_decoded_audio.frame + _decoded_audio.audio->frames()));
}
int
-FFmpegContent::content_audio_frame_rate () const
+FFmpegContent::audio_frame_rate () const
{
boost::mutex::scoped_lock lm (_mutex);
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 ());
-
- FrameRateChange 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).
- */
-
- if (frc.change_speed) {
- t /= frc.speed_up;
- }
-
- return rint (t);
-}
-
bool
operator== (FFmpegStream const & a, FFmpegStream const & b)
{
/* AudioContent */
int audio_channels () const;
ContentTime audio_length () const;
- int content_audio_frame_rate () const;
- int output_audio_frame_rate () const;
+ int audio_frame_rate () const;
AudioMapping audio_mapping () const;
void set_audio_mapping (AudioMapping);
boost::filesystem::path audio_analysis_path () const;
shared_ptr<AudioDecoder> decoder = dynamic_pointer_cast<AudioDecoder> ((*i)->decoder);
assert (decoder);
- if (content->content_audio_frame_rate() == 0) {
+ if (content->audio_frame_rate() == 0) {
/* This AudioContent has no audio (e.g. if it is an FFmpegContent with no
* audio stream).
*/
s << String::compose (
_("%1 channels, %2kHz, %3 samples"),
audio_channels(),
- content_audio_frame_rate() / 1000.0,
- audio_length().frames (content_audio_frame_rate ())
+ audio_frame_rate() / 1000.0,
+ audio_length().frames (audio_frame_rate ())
);
return s.str ();
node->add_child("AudioChannels")->add_child_text (lexical_cast<string> (audio_channels ()));
node->add_child("AudioLength")->add_child_text (lexical_cast<string> (audio_length().get ()));
- node->add_child("AudioFrameRate")->add_child_text (lexical_cast<string> (content_audio_frame_rate ()));
+ node->add_child("AudioFrameRate")->add_child_text (lexical_cast<string> (audio_frame_rate ()));
_audio_mapping.as_xml (node->add_child("AudioMapping"));
}
return DCPTime (audio_length(), film->active_frame_rate_change (position ()));
}
-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)
{
return _audio_length;
}
- int content_audio_frame_rate () const {
+ int audio_frame_rate () const {
boost::mutex::scoped_lock lm (_mutex);
return _audio_frame_rate;
}
- int output_audio_frame_rate () const;
-
AudioMapping audio_mapping () const {
boost::mutex::scoped_lock lm (_mutex);
return _audio_mapping;
/* Do things in half second blocks as I think there may be limits
to what FFmpeg (and in particular the resampler) can cope with.
*/
- sf_count_t const block = _sndfile_content->content_audio_frame_rate() / 2;
+ sf_count_t const block = _sndfile_content->audio_frame_rate() / 2;
sf_count_t const this_time = min (block, _remaining);
int const channels = _sndfile_content->audio_channels ();
} else {
s << fcs->audio_channels() << wxT (" ") << _("channels");
}
- s << wxT (", ") << fcs->content_audio_frame_rate() << _("Hz");
+ s << wxT (", ") << fcs->audio_frame_rate() << _("Hz");
_description->SetLabel (s);
}
}
{
AudioFrame const N = min (
AudioFrame (2000),
- _audio_content->audio_length().frames (_audio_content->output_audio_frame_rate ()) - _position
+ _audio_content->audio_length().frames (_audio_content->resampled_audio_frame_rate ()) - _position
);
shared_ptr<AudioBuffers> buffers (new AudioBuffers (_audio_content->audio_channels(), N));
}
}
- audio (buffers, ContentTime::from_frames (_position, _audio_content->output_audio_frame_rate ()));
+ audio (buffers, ContentTime::from_frames (_position, _audio_content->resampled_audio_frame_rate ()));
_position += N;
return N < 2000;
void seek (ContentTime t, bool accurate)
{
AudioDecoder::seek (t, accurate);
- _position = t.frames (_audio_content->output_audio_frame_rate ());
+ _position = t.frames (_audio_content->resampled_audio_frame_rate ());
}
private:
return ContentTime::from_seconds (61.2942);
}
- int content_audio_frame_rate () const {
- return 48000;
- }
-
- int output_audio_frame_rate () const {
+ int audio_frame_rate () const {
return 48000;
}
static shared_ptr<ContentAudio>
get (AudioFrame from, AudioFrame length)
{
- decoder->seek (ContentTime::from_frames (from, content->output_audio_frame_rate ()), true);
+ decoder->seek (ContentTime::from_frames (from, content->resampled_audio_frame_rate ()), true);
shared_ptr<ContentAudio> ca = decoder->get_audio (from, length, true);
BOOST_CHECK_EQUAL (ca->frame, from);
return ca;
/* Read off the end */
- AudioFrame const from = content->output_audio_frame_rate() * 61;
- AudioFrame const length = content->output_audio_frame_rate() * 4;
+ AudioFrame const from = content->resampled_audio_frame_rate() * 61;
+ AudioFrame const length = content->resampled_audio_frame_rate() * 4;
shared_ptr<ContentAudio> ca = get (from, length);
for (int i = 0; i < content->audio_channels(); ++i) {
shared_ptr<Film> film = new_test_film ("audio_sampling_rate_test");
/* Get any piece of content, it doesn't matter what */
shared_ptr<FFmpegContent> content (new FFmpegContent (film, "test/data/test.mp4"));
- film->add_content (content);
+ film->examine_and_add_content (content);
wait_for_jobs ();
std::list<int> afr;
content->_video_frame_rate = 24;
film->set_video_frame_rate (24);
content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
- BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 48000);
+ BOOST_CHECK_EQUAL (content->resampled_audio_frame_rate(), 48000);
content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
- BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 48000);
+ BOOST_CHECK_EQUAL (content->resampled_audio_frame_rate(), 48000);
content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 80000, 0)));
- BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 96000);
+ BOOST_CHECK_EQUAL (content->resampled_audio_frame_rate(), 96000);
content->_video_frame_rate = 23.976;
film->set_video_frame_rate (24);
content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
- BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 47952);
+ BOOST_CHECK_EQUAL (content->resampled_audio_frame_rate(), 47952);
content->_video_frame_rate = 29.97;
film->set_video_frame_rate (30);
BOOST_CHECK_EQUAL (film->video_frame_rate (), 30);
content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
- BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 47952);
+ BOOST_CHECK_EQUAL (content->resampled_audio_frame_rate(), 47952);
content->_video_frame_rate = 25;
film->set_video_frame_rate (24);
content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
- BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 50000);
+ BOOST_CHECK_EQUAL (content->resampled_audio_frame_rate(), 50000);
content->_video_frame_rate = 25;
film->set_video_frame_rate (24);
content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
- BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), 50000);
+ BOOST_CHECK_EQUAL (content->resampled_audio_frame_rate(), 50000);
/* Check some out-there conversions (not the best) */
content->_video_frame_rate = 14.99;
film->set_video_frame_rate (25);
content->set_audio_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream ("a", 42, 16000, 0)));
- /* The FrameRateChange within output_audio_frame_rate should choose to double-up
+ /* The FrameRateChange within resampled_audio_frame_rate should choose to double-up
the 14.99 fps video to 30 and then run it slow at 25.
*/
- BOOST_CHECK_EQUAL (content->output_audio_frame_rate(), rint (48000 * 2 * 14.99 / 25));
+ BOOST_CHECK_EQUAL (content->resampled_audio_frame_rate(), rint (48000 * 2 * 14.99 / 25));
}