X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Faudio_ring_buffers.cc;h=1a216ab33749399fadf51b24eb3392a3b3ee895d;hb=b56ca8250b8eae123c0992a50f5cabe99e655763;hp=4471f6cda1897eba6f0a74f3f69ad793e6453678;hpb=a0a3fc3c54a45f30e2d2253094a38f3c75e03c34;p=dcpomatic.git diff --git a/src/lib/audio_ring_buffers.cc b/src/lib/audio_ring_buffers.cc index 4471f6cda..1a216ab33 100644 --- a/src/lib/audio_ring_buffers.cc +++ b/src/lib/audio_ring_buffers.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2016-2017 Carl Hetherington + Copyright (C) 2016-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,39 +18,56 @@ */ + #include "audio_ring_buffers.h" #include "dcpomatic_assert.h" #include "exceptions.h" -#include +#include + using std::min; using std::cout; -using boost::shared_ptr; +using std::make_pair; +using std::pair; +using std::list; +using std::shared_ptr; +using boost::optional; +using namespace dcpomatic; + AudioRingBuffers::AudioRingBuffers () - : _used_in_head (0) { } + +/** @param frame_rate Frame rate in use; this is only used to check timing consistency of the incoming data */ void -AudioRingBuffers::put (shared_ptr data, DCPTime time) +AudioRingBuffers::put (shared_ptr data, DCPTime time, int frame_rate) { boost::mutex::scoped_lock lm (_mutex); - if (!_buffers.empty ()) { - DCPOMATIC_ASSERT (_buffers.front()->channels() == data->channels()); + if (!_buffers.empty()) { + DCPOMATIC_ASSERT (_buffers.front().first->channels() == data->channels()); + DCPTime const end = (_buffers.back().second + DCPTime::from_frames(_buffers.back().first->frames(), frame_rate)); + if (labs(end.get() - time.get()) > 1) { + cout << "bad put " << to_string(_buffers.back().second) << " " << _buffers.back().first->frames() << " " << to_string(time) << "\n"; + } + DCPOMATIC_ASSERT (labs(end.get() - time.get()) < 2); } - _buffers.push_back (data); - _latest = time; + _buffers.push_back(make_pair(data, time)); } -void + +/** @return time of the returned data; if it's not set this indicates an underrun */ +optional AudioRingBuffers::get (float* out, int channels, int frames) { boost::mutex::scoped_lock lm (_mutex); + optional time; + while (frames > 0) { if (_buffers.empty ()) { for (int i = 0; i < frames; ++i) { @@ -59,14 +76,17 @@ AudioRingBuffers::get (float* out, int channels, int frames) } } cout << "audio underrun; missing " << frames << "!\n"; - return; + return time; } - shared_ptr front = _buffers.front (); + auto front = _buffers.front (); + if (!time) { + time = front.second + DCPTime::from_frames(_used_in_head, 48000); + } - int const to_do = min (frames, front->frames() - _used_in_head); - float** p = front->data(); - int const c = min (front->channels(), channels); + int const to_do = min (frames, front.first->frames() - _used_in_head); + float** p = front.first->data(); + int const c = min (front.first->channels(), channels); for (int i = 0; i < to_do; ++i) { for (int j = 0; j < c; ++j) { *out++ = p[j][i + _used_in_head]; @@ -78,29 +98,43 @@ AudioRingBuffers::get (float* out, int channels, int frames) _used_in_head += to_do; frames -= to_do; - if (_used_in_head == front->frames()) { + if (_used_in_head == front.first->frames()) { _buffers.pop_front (); _used_in_head = 0; } } + + return time; } + +optional +AudioRingBuffers::peek () const +{ + boost::mutex::scoped_lock lm (_mutex); + if (_buffers.empty()) { + return {}; + } + return _buffers.front().second; +} + + void AudioRingBuffers::clear () { boost::mutex::scoped_lock lm (_mutex); _buffers.clear (); _used_in_head = 0; - _latest = DCPTime (); } + Frame AudioRingBuffers::size () const { boost::mutex::scoped_lock lm (_mutex); Frame s = 0; - BOOST_FOREACH (shared_ptr i, _buffers) { - s += i->frames (); + for (auto const& i: _buffers) { + s += i.first->frames(); } return s - _used_in_head; }