summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2017-03-01 11:36:17 +0000
committerCarl Hetherington <cth@carlh.net>2017-04-19 23:04:32 +0100
commitdc78a40b0c7ce4569874fd1e77a86df907937d50 (patch)
tree3167c3a9f047d3b5af1c5aefc7b8640f4adbf4d9
parent20fb703d5298c0376f1fe7c724cdc9625172e4d0 (diff)
Restore upmixer_a_test and fix resampler flushing.
-rw-r--r--src/lib/player.cc116
-rw-r--r--src/lib/player.h4
-rw-r--r--src/lib/resampler.cc4
-rw-r--r--src/lib/resampler.h2
-rw-r--r--test/upmixer_a_test.cc42
-rw-r--r--test/wscript4
6 files changed, 110 insertions, 62 deletions
diff --git a/src/lib/player.cc b/src/lib/player.cc
index c14b55be0..076bd61bc 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -554,6 +554,12 @@ Player::pass ()
}
earliest->done = earliest->decoder->pass ();
+ if (earliest->done && earliest->content->audio) {
+ /* Flush the Player audio system for this piece */
+ BOOST_FOREACH (AudioStreamPtr i, earliest->content->audio->streams()) {
+ audio_flush (earliest, i);
+ }
+ }
/* Emit any audio that is ready */
@@ -668,52 +674,37 @@ Player::video (weak_ptr<Piece> wp, ContentVideo video)
}
void
-Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_audio)
+Player::audio_flush (shared_ptr<Piece> piece, AudioStreamPtr stream)
{
- shared_ptr<Piece> piece = wp.lock ();
- if (!piece) {
- return;
- }
-
shared_ptr<AudioContent> content = piece->content->audio;
DCPOMATIC_ASSERT (content);
+ shared_ptr<Resampler> r = resampler (content, stream);
+ pair<shared_ptr<const AudioBuffers>, Frame> ro = r->flush ();
+ ContentAudio content_audio;
+ content_audio.audio = ro.first;
+ content_audio.frame = ro.second;
+
+ /* Compute time in the DCP */
+ DCPTime time = resampled_audio_to_dcp (piece, content_audio.frame) + DCPTime::from_seconds (content->delay() / 1000.0);
+
+ audio_transform (content, stream, content_audio, time);
+}
+
+/** Do our common processing on some audio */
+void
+Player::audio_transform (shared_ptr<AudioContent> content, AudioStreamPtr stream, ContentAudio content_audio, DCPTime time)
+{
/* Gain */
+
if (content->gain() != 0) {
shared_ptr<AudioBuffers> gain (new AudioBuffers (content_audio.audio));
gain->apply_gain (content->gain ());
content_audio.audio = gain;
}
- /* Resample */
- if (stream->frame_rate() != content->resampled_frame_rate()) {
- shared_ptr<Resampler> r = resampler (content, stream, true);
- pair<shared_ptr<const AudioBuffers>, Frame> ro = r->run (content_audio.audio, content_audio.frame);
- content_audio.audio = ro.first;
- content_audio.frame = ro.second;
- }
-
- /* XXX: end-trimming used to be checked here */
-
- /* Compute time in the DCP */
- DCPTime time = resampled_audio_to_dcp (piece, content_audio.frame) + DCPTime::from_seconds (content->delay() / 1000.0);
+ /* Remap */
- /* Remove anything that comes before the start of the content */
- if (time < piece->content->position()) {
- DCPTime const discard_time = piece->content->position() - time;
- Frame discard_frames = discard_time.frames_round(_film->audio_frame_rate());
- Frame remaining_frames = content_audio.audio->frames() - discard_frames;
- if (remaining_frames <= 0) {
- /* This audio is entirely discarded */
- return;
- }
- shared_ptr<AudioBuffers> cut (new AudioBuffers (content_audio.audio->channels(), remaining_frames));
- cut->copy_from (content_audio.audio.get(), remaining_frames, discard_frames, 0);
- content_audio.audio = cut;
- time += discard_time;
- }
-
- /* Remap channels */
shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), content_audio.audio->frames()));
dcp_mapped->make_silent ();
@@ -733,17 +724,62 @@ Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_a
content_audio.audio = dcp_mapped;
+ /* Process */
+
if (_audio_processor) {
content_audio.audio = _audio_processor->run (content_audio.audio, _film->audio_channels ());
}
- _audio_merger.push (content_audio.audio, time);
+ /* Push */
+ _audio_merger.push (content_audio.audio, time);
DCPOMATIC_ASSERT (_stream_states.find (stream) != _stream_states.end ());
_stream_states[stream].last_push_end = time + DCPTime::from_frames (content_audio.audio->frames(), _film->audio_frame_rate());
}
void
+Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_audio)
+{
+ shared_ptr<Piece> piece = wp.lock ();
+ if (!piece) {
+ return;
+ }
+
+ shared_ptr<AudioContent> content = piece->content->audio;
+ DCPOMATIC_ASSERT (content);
+
+ /* Resample */
+ if (stream->frame_rate() != content->resampled_frame_rate()) {
+ shared_ptr<Resampler> r = resampler (content, stream);
+ pair<shared_ptr<const AudioBuffers>, Frame> ro = r->run (content_audio.audio, content_audio.frame);
+ content_audio.audio = ro.first;
+ content_audio.frame = ro.second;
+ }
+
+ /* XXX: end-trimming used to be checked here */
+
+ /* Compute time in the DCP */
+ DCPTime time = resampled_audio_to_dcp (piece, content_audio.frame) + DCPTime::from_seconds (content->delay() / 1000.0);
+
+ /* Remove anything that comes before the start of the content */
+ if (time < piece->content->position()) {
+ DCPTime const discard_time = piece->content->position() - time;
+ Frame discard_frames = discard_time.frames_round(_film->audio_frame_rate());
+ Frame remaining_frames = content_audio.audio->frames() - discard_frames;
+ if (remaining_frames <= 0) {
+ /* This audio is entirely discarded */
+ return;
+ }
+ shared_ptr<AudioBuffers> cut (new AudioBuffers (content_audio.audio->channels(), remaining_frames));
+ cut->copy_from (content_audio.audio.get(), remaining_frames, discard_frames, 0);
+ content_audio.audio = cut;
+ time += discard_time;
+ }
+
+ audio_transform (content, stream, content_audio, time);
+}
+
+void
Player::image_subtitle (weak_ptr<Piece> wp, ContentImageSubtitle subtitle)
{
shared_ptr<Piece> piece = wp.lock ();
@@ -821,6 +857,10 @@ Player::text_subtitle (weak_ptr<Piece> wp, ContentTextSubtitle subtitle)
void
Player::seek (DCPTime time, bool accurate)
{
+ if (_audio_processor) {
+ _audio_processor->flush ();
+ }
+
BOOST_FOREACH (shared_ptr<Piece> i, _pieces) {
if (i->content->position() <= time && time < i->content->end()) {
i->decoder->seek (dcp_to_content_time (i, time), accurate);
@@ -836,17 +876,13 @@ Player::seek (DCPTime time, bool accurate)
}
shared_ptr<Resampler>
-Player::resampler (shared_ptr<const AudioContent> content, AudioStreamPtr stream, bool create)
+Player::resampler (shared_ptr<const AudioContent> content, AudioStreamPtr stream)
{
ResamplerMap::const_iterator i = _resamplers.find (make_pair (content, stream));
if (i != _resamplers.end ()) {
return i->second;
}
- if (!create) {
- return shared_ptr<Resampler> ();
- }
-
LOG_GENERAL (
"Creating new resampler from %1 to %2 with %3 channels",
stream->frame_rate(),
diff --git a/src/lib/player.h b/src/lib/player.h
index c10f7adaa..dd7c5dfa1 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -106,10 +106,12 @@ private:
void audio (boost::weak_ptr<Piece>, AudioStreamPtr, ContentAudio);
void image_subtitle (boost::weak_ptr<Piece>, ContentImageSubtitle);
void text_subtitle (boost::weak_ptr<Piece>, ContentTextSubtitle);
- boost::shared_ptr<Resampler> resampler (boost::shared_ptr<const AudioContent> content, AudioStreamPtr stream, bool create);
+ boost::shared_ptr<Resampler> resampler (boost::shared_ptr<const AudioContent> content, AudioStreamPtr stream);
DCPTime one_video_frame () const;
void fill_video (DCPTimePeriod period);
void fill_audio (DCPTimePeriod period);
+ void audio_flush (boost::shared_ptr<Piece>, AudioStreamPtr stream);
+ void audio_transform (boost::shared_ptr<AudioContent> content, AudioStreamPtr stream, ContentAudio content_audio, DCPTime time);
boost::shared_ptr<const Film> _film;
boost::shared_ptr<const Playlist> _playlist;
diff --git a/src/lib/resampler.cc b/src/lib/resampler.cc
index d08e7bc38..1a0c6073d 100644
--- a/src/lib/resampler.cc
+++ b/src/lib/resampler.cc
@@ -160,7 +160,7 @@ Resampler::run (shared_ptr<const AudioBuffers> in, Frame frame)
return make_pair (resampled, out_frame);
}
-shared_ptr<const AudioBuffers>
+pair<shared_ptr<const AudioBuffers>, Frame>
Resampler::flush ()
{
shared_ptr<AudioBuffers> out (new AudioBuffers (_channels, 0));
@@ -198,5 +198,5 @@ Resampler::flush ()
out->set_frames (out_offset);
delete[] buffer;
- return out;
+ return make_pair (out, _next_out.get ());
}
diff --git a/src/lib/resampler.h b/src/lib/resampler.h
index 359598b12..9d620b962 100644
--- a/src/lib/resampler.h
+++ b/src/lib/resampler.h
@@ -32,7 +32,7 @@ public:
~Resampler ();
std::pair<boost::shared_ptr<const AudioBuffers>, Frame> run (boost::shared_ptr<const AudioBuffers>, Frame);
- boost::shared_ptr<const AudioBuffers> flush ();
+ std::pair<boost::shared_ptr<const AudioBuffers>, Frame> flush ();
void set_fast ();
private:
diff --git a/test/upmixer_a_test.cc b/test/upmixer_a_test.cc
index e0117c734..99c897252 100644
--- a/test/upmixer_a_test.cc
+++ b/test/upmixer_a_test.cc
@@ -31,6 +31,25 @@
using boost::shared_ptr;
+static SNDFILE* L;
+static SNDFILE* R;
+static SNDFILE* C;
+static SNDFILE* Lfe;
+static SNDFILE* Ls;
+static SNDFILE* Rs;
+
+static void
+write (shared_ptr<AudioBuffers> b, DCPTime)
+{
+ sf_write_float (L, b->data(0), b->frames());
+ sf_write_float (R, b->data(1), b->frames());
+ sf_write_float (C, b->data(2), b->frames());
+ sf_write_float (Lfe, b->data(3), b->frames());
+ sf_write_float (Ls, b->data(4), b->frames());
+ sf_write_float (Rs, b->data(5), b->frames());
+
+}
+
BOOST_AUTO_TEST_CASE (upmixer_a_test)
{
shared_ptr<Film> film = new_test_film ("upmixer_a_test");
@@ -47,23 +66,16 @@ BOOST_AUTO_TEST_CASE (upmixer_a_test)
info.samplerate = 48000;
info.channels = 1;
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
- SNDFILE* L = sf_open ("build/test/upmixer_a_test/L.wav", SFM_WRITE, &info);
- SNDFILE* R = sf_open ("build/test/upmixer_a_test/R.wav", SFM_WRITE, &info);
- SNDFILE* C = sf_open ("build/test/upmixer_a_test/C.wav", SFM_WRITE, &info);
- SNDFILE* Lfe = sf_open ("build/test/upmixer_a_test/Lfe.wav", SFM_WRITE, &info);
- SNDFILE* Ls = sf_open ("build/test/upmixer_a_test/Ls.wav", SFM_WRITE, &info);
- SNDFILE* Rs = sf_open ("build/test/upmixer_a_test/Rs.wav", SFM_WRITE, &info);
+ L = sf_open ("build/test/upmixer_a_test/L.wav", SFM_WRITE, &info);
+ R = sf_open ("build/test/upmixer_a_test/R.wav", SFM_WRITE, &info);
+ C = sf_open ("build/test/upmixer_a_test/C.wav", SFM_WRITE, &info);
+ Lfe = sf_open ("build/test/upmixer_a_test/Lfe.wav", SFM_WRITE, &info);
+ Ls = sf_open ("build/test/upmixer_a_test/Ls.wav", SFM_WRITE, &info);
+ Rs = sf_open ("build/test/upmixer_a_test/Rs.wav", SFM_WRITE, &info);
shared_ptr<Player> player (new Player (film, film->playlist ()));
- for (DCPTime t; t < film->length(); t += DCPTime::from_seconds (1)) {
- shared_ptr<AudioBuffers> b = player->get_audio (t, DCPTime::from_seconds (1), true);
- sf_write_float (L, b->data(0), b->frames());
- sf_write_float (R, b->data(1), b->frames());
- sf_write_float (C, b->data(2), b->frames());
- sf_write_float (Lfe, b->data(3), b->frames());
- sf_write_float (Ls, b->data(4), b->frames());
- sf_write_float (Rs, b->data(5), b->frames());
- }
+ player->Audio.connect (bind (&write, _1, _2));
+ while (!player->pass()) {}
sf_close (L);
sf_close (R);
diff --git a/test/wscript b/test/wscript
index 85a573f0c..0edb4ab88 100644
--- a/test/wscript
+++ b/test/wscript
@@ -92,6 +92,7 @@ def build(bld):
threed_test.cc
time_calculation_test.cc
update_checker_test.cc
+ upmixer_a_test.cc
util_test.cc
vf_test.cc
video_content_scale_test.cc
@@ -104,8 +105,5 @@ def build(bld):
# This one doesn't check anything
# resampler_test.cc
- # XXX
- # upmixer_a_test.cc
-
obj.target = 'unit-tests'
obj.install_path = ''