substantive change: use the JACK wait API and provide "thread buffers" separately from session in preparation for parallelization. lots of debug output at present. If using JACK1, requires a very current version of JACK1 SVN (0.119.0)

git-svn-id: svn://localhost/ardour2/branches/3.0@6888 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-04-13 20:48:33 +00:00
parent 46ea5f5f58
commit 3ea10b38bb
15 changed files with 544 additions and 75 deletions

View File

@ -55,6 +55,7 @@ class InternalPort;
class MidiPort;
class Port;
class Session;
class ProcessThread;
class AudioEngine : public SessionHandlePtr
{
@ -69,6 +70,8 @@ class AudioEngine : public SessionHandlePtr
bool is_realtime () const;
ProcessThread* main_thread() const { return _main_thread; }
std::string client_name() const { return jack_client_name; }
int reconnect_to_jack ();
@ -272,6 +275,8 @@ _ the regular process() call to session->process() is not made.
Port *register_port (DataType type, const std::string& portname, bool input);
int process_callback (nframes_t nframes);
void* process_thread ();
void finish_process_cycle (int status);
void remove_all_ports ();
std::string get_nth_physical (DataType type, uint32_t n, int flags);
@ -284,6 +289,7 @@ _ the regular process() call to session->process() is not made.
#endif
static int _graph_order_callback (void *arg);
static int _process_callback (nframes_t nframes, void *arg);
static void* _process_thread (void *arg);
static int _sample_rate_callback (nframes_t nframes, void *arg);
static int _bufsize_callback (nframes_t nframes, void *arg);
static void _jack_timebase_callback (jack_transport_state_t, nframes_t, jack_position_t*, int, void*);
@ -307,6 +313,8 @@ _ the regular process() call to session->process() is not made.
Glib::Thread* m_meter_thread;
static gint m_meter_exit;
ProcessThread* _main_thread;
};
} // namespace ARDOUR

View File

@ -0,0 +1,31 @@
#ifndef __libardour_buffer_manager__
#define __libardour_buffer_manager__
#include <stdint.h>
#include "pbd/ringbufferNPT.h"
#include "ardour/chan_count.h"
namespace ARDOUR {
class ThreadBuffers;
class BufferManager
{
public:
static void init (uint32_t);
static ThreadBuffers* get_thread_buffers ();
static void put_thread_buffers (ThreadBuffers*);
static void ensure_buffers (ChanCount howmany = ChanCount::ZERO);
private:
typedef RingBufferNPT<ThreadBuffers*> ThreadBufferFIFO;
static ThreadBufferFIFO* thread_buffers;
};
}
#endif /* __libardour_buffer_manager__ */

View File

@ -0,0 +1,44 @@
#ifndef __libardour_process_thread__
#define __libardour_process_thread__
#include <glibmm/thread.h>
#include "ardour/chan_count.h"
#include "ardour/types.h"
namespace ARDOUR {
class ThreadBuffers;
class ProcessThread
{
public:
ProcessThread ();
~ProcessThread ();
static void init();
void get_buffers ();
void drop_buffers ();
/* these MUST be called by a process thread's thread, nothing else
*/
static BufferSet& get_silent_buffers (ChanCount count = ChanCount::ZERO);
static BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO);
static BufferSet& get_mix_buffers (ChanCount count = ChanCount::ZERO);
static gain_t* gain_automation_buffer ();
static pan_t** pan_automation_buffer ();
protected:
void session_going_away ();
private:
Glib::Thread* _thread;
static Glib::Private<ThreadBuffers>* _private_thread_buffers;
};
} // namespace
#endif /* __libardour_process_thread__ */

View File

@ -106,6 +106,7 @@ class Playlist;
class PluginInsert;
class Port;
class PortInsert;
class ProcessThread;
class Processor;
class Region;
class Return;
@ -736,8 +737,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
/* buffers for gain and pan */
gain_t* gain_automation_buffer () const { return _gain_automation_buffer; }
pan_t** pan_automation_buffer () const { return _pan_automation_buffer; }
gain_t* gain_automation_buffer () const;
pan_t** pan_automation_buffer () const;
void ensure_buffer_set (BufferSet& buffers, const ChanCount& howmany);
@ -859,9 +860,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
nframes64_t _last_slave_transport_frame;
nframes_t maximum_output_latency;
volatile nframes64_t _requested_return_frame;
BufferSet* _scratch_buffers;
BufferSet* _silent_buffers;
BufferSet* _mix_buffers;
nframes_t current_block_size;
nframes_t _worst_output_latency;
nframes_t _worst_input_latency;
@ -881,7 +879,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void update_latency_compensation_proxy (void* ignored);
void ensure_buffers (ChanCount howmany);
void ensure_buffers (ChanCount howmany = ChanCount::ZERO);
void process_scrub (nframes_t);
void process_without_events (nframes_t);
@ -894,6 +892,9 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void unblock_processing() { g_atomic_int_set (&processing_prohibited, 0); }
bool processing_blocked() const { return g_atomic_int_get (&processing_prohibited); }
Glib::Mutex process_thread_lock;
std::list<ProcessThread*> process_threads;
/* slave tracking */
static const int delta_accumulator_size = 25;
@ -1389,11 +1390,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
boost::shared_ptr<Route> _master_out;
boost::shared_ptr<Route> _monitor_out;
gain_t* _gain_automation_buffer;
pan_t** _pan_automation_buffer;
void allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force);
uint32_t _npan_buffers;
/* VST support */
long _vst_callback (VSTPlugin*,

View File

@ -0,0 +1,33 @@
#ifndef __libardour_thread_buffers__
#define __libardour_thread_buffers__
#include <glibmm/thread.h>
#include "ardour/chan_count.h"
#include "ardour/types.h"
namespace ARDOUR {
class BufferSet;
class ThreadBuffers {
public:
ThreadBuffers ();
~ThreadBuffers ();
void ensure_buffers (ChanCount howmany = ChanCount::ZERO);
BufferSet* silent_buffers;
BufferSet* scratch_buffers;
BufferSet* mix_buffers;
gain_t* gain_automation_buffer;
pan_t** pan_automation_buffer;
uint32_t npan_buffers;
private:
void allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force);
};
} // namespace
#endif /* __libardour_thread_buffers__ */

View File

@ -43,6 +43,7 @@
#include "ardour/io.h"
#include "ardour/meter.h"
#include "ardour/midi_port.h"
#include "ardour/process_thread.h"
#include "ardour/port.h"
#include "ardour/port_set.h"
#include "ardour/session.h"
@ -77,6 +78,7 @@ AudioEngine::AudioEngine (string client_name, string session_uuid)
_frame_rate = 0;
_buffer_size = 0;
_freewheeling = false;
_main_thread = 0;
m_meter_thread = 0;
g_atomic_int_set (&m_meter_exit, 0);
@ -184,7 +186,8 @@ AudioEngine::start ()
jack_on_shutdown (_priv_jack, halted, this);
jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this);
jack_set_thread_init_callback (_priv_jack, _thread_init_callback, this);
jack_set_process_callback (_priv_jack, _process_callback, this);
// jack_set_process_callback (_priv_jack, _process_callback, this);
jack_set_process_thread (_priv_jack, _process_thread, this);
jack_set_sample_rate_callback (_priv_jack, _sample_rate_callback, this);
jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
jack_set_xrun_callback (_priv_jack, _xrun_callback, this);
@ -336,6 +339,12 @@ AudioEngine::_process_callback (nframes_t nframes, void *arg)
return static_cast<AudioEngine *> (arg)->process_callback (nframes);
}
void*
AudioEngine::_process_thread (void *arg)
{
return static_cast<AudioEngine *> (arg)->process_thread ();
}
void
AudioEngine::_freewheel_callback (int onoff, void *arg)
{
@ -372,6 +381,47 @@ AudioEngine::split_cycle (nframes_t offset)
}
}
void
AudioEngine::finish_process_cycle (int status)
{
GET_PRIVATE_JACK_POINTER(_jack);
cerr << "signal process cycle end\n";
jack_cycle_signal (_jack, 0);
}
void*
AudioEngine::process_thread ()
{
/* JACK doesn't do this for us when we use the wait API
*/
cerr << "JACK process thread is here\n";
_thread_init_callback (0);
cerr << " its initialized\n";
_main_thread = new ProcessThread;
cerr << " we have ProcThread\n";
while (1) {
cerr << "getting client ptr from " << _jack << endl;
GET_PRIVATE_JACK_POINTER_RET(_jack,0);
cerr << "Wait for JACK\n";
jack_nframes_t nframes = jack_cycle_wait (_jack);
cerr << "run process\n";
if (process_callback (nframes)) {
return 0;
}
finish_process_cycle (0);
}
return 0;
}
/** Method called by JACK (via _process_callback) which says that there
* is work to be done.
* @param nframes Number of frames to process.
@ -379,7 +429,7 @@ AudioEngine::split_cycle (nframes_t offset)
int
AudioEngine::process_callback (nframes_t nframes)
{
GET_PRIVATE_JACK_POINTER_RET(_jack,0)
GET_PRIVATE_JACK_POINTER_RET(_jack,0);
// CycleTimer ct ("AudioEngine::process");
Glib::Mutex::Lock tm (_process_lock, Glib::TRY_LOCK);
@ -434,6 +484,7 @@ AudioEngine::process_callback (nframes_t nframes)
} else {
if (_session) {
_session->process (nframes);
}
}
@ -930,6 +981,8 @@ AudioEngine::get_ports (const string& port_name_pattern, const string& type_name
void
AudioEngine::halted (void *arg)
{
cerr << "HALTED by JACK\n";
/* called from jack shutdown handler */
AudioEngine* ae = static_cast<AudioEngine *> (arg);
@ -1246,13 +1299,8 @@ AudioEngine::reconnect_to_jack ()
if (_session) {
_session->reset_jack_connection (_priv_jack);
nframes_t blocksize = jack_get_buffer_size (_priv_jack);
_session->set_block_size (blocksize);
jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
_session->set_frame_rate (jack_get_sample_rate (_priv_jack));
_raw_buffer_sizes[DataType::AUDIO] = blocksize * sizeof(float);
cout << "FIXME: Assuming maximum MIDI buffer size " << blocksize * 4 << "bytes" << endl;
_raw_buffer_sizes[DataType::MIDI] = blocksize * 4;
}
last_monitor_check = 0;
@ -1260,7 +1308,8 @@ AudioEngine::reconnect_to_jack ()
jack_on_shutdown (_priv_jack, halted, this);
jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this);
jack_set_thread_init_callback (_priv_jack, _thread_init_callback, this);
jack_set_process_callback (_priv_jack, _process_callback, this);
// jack_set_process_callback (_priv_jack, _process_callback, this);
jack_set_process_thread (_priv_jack, _process_thread, this);
jack_set_sample_rate_callback (_priv_jack, _sample_rate_callback, this);
jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
jack_set_xrun_callback (_priv_jack, _xrun_callback, this);

View File

@ -0,0 +1,82 @@
/*
Copyright (C) 2010 Paul Davis
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <iostream>
#include "ardour/buffer_manager.h"
#include "ardour/thread_buffers.h"
using namespace ARDOUR;
using namespace PBD;
RingBufferNPT<ThreadBuffers*>* BufferManager::thread_buffers = 0;
void
BufferManager::init (uint32_t size)
{
thread_buffers = new ThreadBufferFIFO (size+1); // must be one larger than requested
/* and populate with actual ThreadBuffers
*/
std::cerr << "BM: initial read space: " << thread_buffers->read_space() << std::endl;
for (uint32_t n = 0; n < size; ++n) {
ThreadBuffers* ts = new ThreadBuffers;
thread_buffers->write (&ts, 1);
std::cerr << "BM: added one, read = " << thread_buffers->read_space()
<< " write = " << thread_buffers->write_space()
<< std::endl;
}
std::cerr << "BM: final, read = " << thread_buffers->read_space()
<< " write = " << thread_buffers->write_space()
<< std::endl;
std::cerr << "BUFFER MANAGER INITIALIZED WITH " << size << " BUFFERs\n";
}
ThreadBuffers*
BufferManager::get_thread_buffers ()
{
ThreadBuffers* tbp;
if (thread_buffers->read (&tbp, 1) == 1) {
return tbp;
}
return 0;
}
void
BufferManager::put_thread_buffers (ThreadBuffers* tbp)
{
thread_buffers->write (&tbp, 1);
}
void
BufferManager::ensure_buffers (ChanCount howmany)
{
/* this is protected by the audioengine's process lock: we do not */
std::cerr << "BufMgr: ensure " << thread_buffers->bufsize() - 1 << " buffers match " << howmany << std::endl;
for (uint32_t n = 0; n < thread_buffers->bufsize() - 1; ++n) {
thread_buffers->buffer()[n]->ensure_buffers (howmany);
}
}

View File

@ -64,12 +64,14 @@
#include "ardour/audioengine.h"
#include "ardour/audioregion.h"
#include "ardour/audiosource.h"
#include "ardour/buffer_manager.h"
#include "ardour/control_protocol_manager.h"
#include "ardour/debug.h"
#include "ardour/filesystem_paths.h"
#include "ardour/mix.h"
#include "ardour/playlist.h"
#include "ardour/plugin_manager.h"
#include "ardour/process_thread.h"
#include "ardour/profile.h"
#include "ardour/region.h"
#include "ardour/rc_configuration.h"
@ -405,6 +407,9 @@ ARDOUR::init (bool use_vst, bool try_optimization)
/* singleton - first object is "it" */
new PluginManager ();
ProcessThread::init ();
BufferManager::init (2); // XX should be num_processors_for_dsp
return 0;
}

View File

@ -0,0 +1,149 @@
/*
Copyright (C) 2010 Paul Davis
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <iostream>
#include "ardour/audioengine.h"
#include "ardour/buffer.h"
#include "ardour/buffer_manager.h"
#include "ardour/buffer_set.h"
#include "ardour/process_thread.h"
#include "ardour/thread_buffers.h"
using namespace ARDOUR;
using namespace Glib;
using namespace std;
Private<ThreadBuffers>* ProcessThread::_private_thread_buffers = 0;
static void
release_thread_buffer (void* arg)
{
BufferManager::put_thread_buffers ((ThreadBuffers*) arg);
}
void
ProcessThread::init ()
{
_private_thread_buffers = new Private<ThreadBuffers> (release_thread_buffer);
}
ProcessThread::ProcessThread ()
: _thread (0)
{
}
ProcessThread::~ProcessThread ()
{
}
void
ProcessThread::get_buffers ()
{
ThreadBuffers* tb = BufferManager::get_thread_buffers ();
assert (tb);
_private_thread_buffers->set (tb);
cerr << "ProcThread " << this << " using TBs at " << tb << " (aka. " << _private_thread_buffers->get() << endl;
}
void
ProcessThread::drop_buffers ()
{
ThreadBuffers* tb = _private_thread_buffers->get();
assert (tb);
BufferManager::put_thread_buffers (tb);
_private_thread_buffers->set (0);
cerr << "ProcThread " << this << " dropped TBs\n";
}
BufferSet&
ProcessThread::get_silent_buffers (ChanCount count)
{
ThreadBuffers* tb = _private_thread_buffers->get();
assert (tb);
BufferSet* sb = tb->silent_buffers;
assert (sb);
assert(sb->available() >= count);
sb->set_count(count);
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
for (size_t i= 0; i < count.get(*t); ++i) {
sb->get(*t, i).clear();
}
}
return *sb;
}
BufferSet&
ProcessThread::get_scratch_buffers (ChanCount count)
{
ThreadBuffers* tb = _private_thread_buffers->get();
assert (tb);
BufferSet* sb = tb->scratch_buffers;
assert (sb);
if (count != ChanCount::ZERO) {
assert(sb->available() >= count);
sb->set_count (count);
} else {
sb->set_count (sb->available());
}
return *sb;
}
BufferSet&
ProcessThread::get_mix_buffers (ChanCount count)
{
ThreadBuffers* tb = _private_thread_buffers->get();
assert (tb);
BufferSet* mb = tb->mix_buffers;
assert (mb);
assert (mb->available() >= count);
mb->set_count(count);
return *mb;
}
gain_t*
ProcessThread::gain_automation_buffer()
{
ThreadBuffers* tb = _private_thread_buffers->get();
assert (tb);
gain_t *g = tb->gain_automation_buffer;
assert (g);
return g;
}
pan_t**
ProcessThread::pan_automation_buffer()
{
ThreadBuffers* tb = _private_thread_buffers->get();
assert (tb);
pan_t** p = tb->pan_automation_buffer;
assert (p);
return p;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 1999-2004 Paul Davis
Copyright (C) 1999-2010 Paul Davis
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
@ -52,6 +52,7 @@
#include "ardour/audioplaylist.h"
#include "ardour/audioregion.h"
#include "ardour/auditioner.h"
#include "ardour/buffer_manager.h"
#include "ardour/buffer_set.h"
#include "ardour/bundle.h"
#include "ardour/butler.h"
@ -70,6 +71,7 @@
#include "ardour/midi_track.h"
#include "ardour/midi_ui.h"
#include "ardour/named_selection.h"
#include "ardour/process_thread.h"
#include "ardour/playlist.h"
#include "ardour/plugin_insert.h"
#include "ardour/port_insert.h"
@ -129,9 +131,6 @@ Session::Session (AudioEngine &eng,
: _engine (eng),
_target_transport_speed (0.0),
_requested_return_frame (-1),
_scratch_buffers(new BufferSet()),
_silent_buffers(new BufferSet()),
_mix_buffers(new BufferSet()),
mmc (0),
_mmc_port (default_mmc_port),
_mtc_port (default_mtc_port),
@ -243,10 +242,6 @@ Session::destroy ()
clear_clicks ();
delete _scratch_buffers;
delete _silent_buffers;
delete _mix_buffers;
/* clear out any pending dead wood from RCU managed objects */
routes.flush ();
@ -1193,12 +1188,7 @@ Session::set_block_size (nframes_t nframes)
{
current_block_size = nframes;
ensure_buffers(_scratch_buffers->available());
delete [] _gain_automation_buffer;
_gain_automation_buffer = new gain_t[nframes];
allocate_pan_automation_buffers (nframes, _npan_buffers, true);
ensure_buffers ();
boost::shared_ptr<RouteList> r = routes.reader ();
@ -3209,18 +3199,7 @@ Session::tempo_map_changed (const PropertyChange&)
void
Session::ensure_buffers (ChanCount howmany)
{
if (current_block_size == 0) {
return; // too early? (is this ok?)
}
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
size_t count = std::max(_scratch_buffers->available().get(*t), howmany.get(*t));
_scratch_buffers->ensure_buffers (*t, count, _engine.raw_buffer_size(*t));
_mix_buffers->ensure_buffers (*t, count, _engine.raw_buffer_size(*t));
_silent_buffers->ensure_buffers (*t, count, _engine.raw_buffer_size(*t));
}
allocate_pan_automation_buffers (current_block_size, howmany.n_audio(), false);
BufferManager::ensure_buffers (howmany);
}
void
@ -3439,31 +3418,6 @@ Session::route_name_internal (string n) const
return false;
}
void
Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force)
{
if (!force && howmany <= _npan_buffers) {
return;
}
if (_pan_automation_buffer) {
for (uint32_t i = 0; i < _npan_buffers; ++i) {
delete [] _pan_automation_buffer[i];
}
delete [] _pan_automation_buffer;
}
_pan_automation_buffer = new pan_t*[howmany];
for (uint32_t i = 0; i < howmany; ++i) {
_pan_automation_buffer[i] = new pan_t[nframes];
}
_npan_buffers = howmany;
}
int
Session::freeze_all (InterThreadInfo& itt)
{
@ -3649,9 +3603,23 @@ Session::write_one_track (AudioTrack& track, nframes_t start, nframes_t end,
return result;
}
gain_t*
Session::gain_automation_buffer() const
{
return ProcessThread::gain_automation_buffer ();
}
pan_t**
Session::pan_automation_buffer() const
{
return ProcessThread::pan_automation_buffer ();
}
BufferSet&
Session::get_silent_buffers (ChanCount count)
{
return ProcessThread::get_silent_buffers (count);
#if 0
assert(_silent_buffers->available() >= count);
_silent_buffers->set_count(count);
@ -3662,11 +3630,14 @@ Session::get_silent_buffers (ChanCount count)
}
return *_silent_buffers;
#endif
}
BufferSet&
Session::get_scratch_buffers (ChanCount count)
{
return ProcessThread::get_scratch_buffers (count);
#if 0
if (count != ChanCount::ZERO) {
assert(_scratch_buffers->available() >= count);
_scratch_buffers->set_count(count);
@ -3675,14 +3646,18 @@ Session::get_scratch_buffers (ChanCount count)
}
return *_scratch_buffers;
#endif
}
BufferSet&
Session::get_mix_buffers (ChanCount count)
{
return ProcessThread::get_mix_buffers (count);
#if 0
assert(_mix_buffers->available() >= count);
_mix_buffers->set_count(count);
return *_mix_buffers;
#endif
}
uint32_t

View File

@ -33,6 +33,7 @@
#include "ardour/auditioner.h"
#include "ardour/butler.h"
#include "ardour/debug.h"
#include "ardour/process_thread.h"
#include "ardour/session.h"
#include "ardour/slave.h"
#include "ardour/timestamps.h"
@ -65,9 +66,13 @@ Session::process (nframes_t nframes)
post_transport ();
}
}
_engine.main_thread()->get_buffers ();
(this->*process_function) (nframes);
_engine.main_thread()->drop_buffers ();
// the ticker is for sending time information like MidiClock
nframes_t transport_frames = transport_frame();
BBT_Time transport_bbt;

View File

@ -210,9 +210,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
g_atomic_int_set (&_capture_load_min, 100);
_play_range = false;
_exporting = false;
_gain_automation_buffer = 0;
_pan_automation_buffer = 0;
_npan_buffers = 0;
pending_abort = false;
destructive_index = 0;
first_file_data_format_reset = true;

View File

@ -0,0 +1,91 @@
/*
Copyright (C) 2010 Paul Davis
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <iostream>
#include "ardour/audioengine.h"
#include "ardour/buffer_set.h"
#include "ardour/thread_buffers.h"
using namespace ARDOUR;
using namespace std;
ThreadBuffers::ThreadBuffers ()
: silent_buffers (new BufferSet)
, scratch_buffers (new BufferSet)
, mix_buffers (new BufferSet)
, gain_automation_buffer (0)
, pan_automation_buffer (0)
, npan_buffers (0)
{
}
void
ThreadBuffers::ensure_buffers (ChanCount howmany)
{
// std::cerr << "ThreadBuffers " << this << " resize buffers with count = " << howmany << std::endl;
/* this is all protected by the process lock in the Session
*/
if (howmany.n_total() == 0) {
return;
}
AudioEngine* _engine = AudioEngine::instance ();
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
size_t count = std::max (scratch_buffers->available().get(*t), howmany.get(*t));
size_t size = _engine->raw_buffer_size (*t);
scratch_buffers->ensure_buffers (*t, count, size);
mix_buffers->ensure_buffers (*t, count, size);
silent_buffers->ensure_buffers (*t, count, size);
}
delete [] gain_automation_buffer;
gain_automation_buffer = new gain_t[_engine->raw_buffer_size (DataType::AUDIO)];
allocate_pan_automation_buffers (_engine->raw_buffer_size (DataType::AUDIO), howmany.n_audio(), false);
}
void
ThreadBuffers::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force)
{
if (!force && howmany <= npan_buffers) {
return;
}
if (pan_automation_buffer) {
for (uint32_t i = 0; i < npan_buffers; ++i) {
delete [] pan_automation_buffer[i];
}
delete [] pan_automation_buffer;
}
pan_automation_buffer = new pan_t*[howmany];
for (uint32_t i = 0; i < howmany; ++i) {
pan_automation_buffer[i] = new pan_t[nframes];
}
npan_buffers = howmany;
}

View File

@ -57,6 +57,7 @@ libardour_sources = [
'beats_frames_converter.cc',
'broadcast_info.cc',
'buffer.cc',
'buffer_manager.cc',
'buffer_set.cc',
'bundle.cc',
'butler.cc',
@ -140,6 +141,7 @@ libardour_sources = [
'port.cc',
'port_insert.cc',
'port_set.cc',
'process_thread.cc',
'processor.cc',
'quantize.cc',
'rc_configuration.cc',
@ -187,6 +189,7 @@ libardour_sources = [
'template_utils.cc',
'tempo.cc',
'tempo_map_importer.cc',
'thread_buffers.cc',
'ticker.cc',
'track.cc',
'transient_detector.cc',
@ -218,7 +221,7 @@ def configure(conf):
autowaf.configure(conf)
conf.check_tool('compiler_cxx gas')
autowaf.check_pkg(conf, 'aubio', uselib_store='AUBIO', atleast_version='0.3.2')
autowaf.check_pkg(conf, 'jack', uselib_store='JACK', atleast_version='0.109.0')
autowaf.check_pkg(conf, 'jack', uselib_store='JACK', atleast_version='0.119.0')
autowaf.check_pkg(conf, 'libxml-2.0', uselib_store='XML')
autowaf.check_pkg(conf, 'lrdf', uselib_store='LRDF', atleast_version='0.4.0')
autowaf.check_pkg(conf, 'samplerate', uselib_store='SAMPLERATE', atleast_version='0.1.0')

View File

@ -22,6 +22,7 @@
//#include <sys/mman.h>
#include <cstring>
#include <glib.h>
/* ringbuffer class where the element size is not required to be a power of two */