From: Carl Hetherington Date: Wed, 1 Mar 2017 11:36:17 +0000 (+0000) Subject: Restore upmixer_a_test and fix resampler flushing. X-Git-Tag: v2.11.1~73 X-Git-Url: https://git.carlh.net/gitweb/?a=commitdiff_plain;h=dc78a40b0c7ce4569874fd1e77a86df907937d50;p=dcpomatic.git Restore upmixer_a_test and fix resampler flushing. --- 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 wp, ContentVideo video) } void -Player::audio (weak_ptr wp, AudioStreamPtr stream, ContentAudio content_audio) +Player::audio_flush (shared_ptr piece, AudioStreamPtr stream) { - shared_ptr piece = wp.lock (); - if (!piece) { - return; - } - shared_ptr content = piece->content->audio; DCPOMATIC_ASSERT (content); + shared_ptr r = resampler (content, stream); + pair, 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 content, AudioStreamPtr stream, ContentAudio content_audio, DCPTime time) +{ /* Gain */ + if (content->gain() != 0) { shared_ptr 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 r = resampler (content, stream, true); - pair, 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 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 dcp_mapped (new AudioBuffers (_film->audio_channels(), content_audio.audio->frames())); dcp_mapped->make_silent (); @@ -733,16 +724,61 @@ Player::audio (weak_ptr 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 wp, AudioStreamPtr stream, ContentAudio content_audio) +{ + shared_ptr piece = wp.lock (); + if (!piece) { + return; + } + + shared_ptr content = piece->content->audio; + DCPOMATIC_ASSERT (content); + + /* Resample */ + if (stream->frame_rate() != content->resampled_frame_rate()) { + shared_ptr r = resampler (content, stream); + pair, 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 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 wp, ContentImageSubtitle subtitle) { @@ -821,6 +857,10 @@ Player::text_subtitle (weak_ptr wp, ContentTextSubtitle subtitle) void Player::seek (DCPTime time, bool accurate) { + if (_audio_processor) { + _audio_processor->flush (); + } + BOOST_FOREACH (shared_ptr 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 -Player::resampler (shared_ptr content, AudioStreamPtr stream, bool create) +Player::resampler (shared_ptr 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 (); - } - 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, AudioStreamPtr, ContentAudio); void image_subtitle (boost::weak_ptr, ContentImageSubtitle); void text_subtitle (boost::weak_ptr, ContentTextSubtitle); - boost::shared_ptr resampler (boost::shared_ptr content, AudioStreamPtr stream, bool create); + boost::shared_ptr resampler (boost::shared_ptr content, AudioStreamPtr stream); DCPTime one_video_frame () const; void fill_video (DCPTimePeriod period); void fill_audio (DCPTimePeriod period); + void audio_flush (boost::shared_ptr, AudioStreamPtr stream); + void audio_transform (boost::shared_ptr content, AudioStreamPtr stream, ContentAudio content_audio, DCPTime time); boost::shared_ptr _film; boost::shared_ptr _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 in, Frame frame) return make_pair (resampled, out_frame); } -shared_ptr +pair, Frame> Resampler::flush () { shared_ptr 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, Frame> run (boost::shared_ptr, Frame); - boost::shared_ptr flush (); + std::pair, 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 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 = 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 (new Player (film, film->playlist ())); - for (DCPTime t; t < film->length(); t += DCPTime::from_seconds (1)) { - shared_ptr 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 = ''