diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index e630e1a95e..63f9afeb2b 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -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 diff --git a/libs/ardour/ardour/buffer_manager.h b/libs/ardour/ardour/buffer_manager.h new file mode 100644 index 0000000000..4da8d0637f --- /dev/null +++ b/libs/ardour/ardour/buffer_manager.h @@ -0,0 +1,31 @@ +#ifndef __libardour_buffer_manager__ +#define __libardour_buffer_manager__ + +#include + +#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 ThreadBufferFIFO; + static ThreadBufferFIFO* thread_buffers; +}; + +} + +#endif /* __libardour_buffer_manager__ */ diff --git a/libs/ardour/ardour/process_thread.h b/libs/ardour/ardour/process_thread.h new file mode 100644 index 0000000000..d6bbbfc6fc --- /dev/null +++ b/libs/ardour/ardour/process_thread.h @@ -0,0 +1,44 @@ +#ifndef __libardour_process_thread__ +#define __libardour_process_thread__ + +#include + +#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* _private_thread_buffers; +}; + +} // namespace + +#endif /* __libardour_process_thread__ */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 2b51e3f8ec..b5c818e6a2 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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 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 _master_out; boost::shared_ptr _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*, diff --git a/libs/ardour/ardour/thread_buffers.h b/libs/ardour/ardour/thread_buffers.h new file mode 100644 index 0000000000..3c312176a8 --- /dev/null +++ b/libs/ardour/ardour/thread_buffers.h @@ -0,0 +1,33 @@ +#ifndef __libardour_thread_buffers__ +#define __libardour_thread_buffers__ + +#include + +#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__ */ diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index db1c4f2ef5..196482f143 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -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 (arg)->process_callback (nframes); } +void* +AudioEngine::_process_thread (void *arg) +{ + return static_cast (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 (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); diff --git a/libs/ardour/buffer_manager.cc b/libs/ardour/buffer_manager.cc new file mode 100644 index 0000000000..3436dac72d --- /dev/null +++ b/libs/ardour/buffer_manager.cc @@ -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 +#include "ardour/buffer_manager.h" +#include "ardour/thread_buffers.h" + +using namespace ARDOUR; +using namespace PBD; + +RingBufferNPT* 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); + } +} diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 9f3d99ead4..b78edc11d2 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -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; } diff --git a/libs/ardour/process_thread.cc b/libs/ardour/process_thread.cc new file mode 100644 index 0000000000..e36639aaf5 --- /dev/null +++ b/libs/ardour/process_thread.cc @@ -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 +#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* 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 (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; +} diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 21ed454c29..ac8d5d030f 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -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 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 diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 834280de91..85c424e40c 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -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; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index f67714401f..1f116d82bc 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -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; diff --git a/libs/ardour/thread_buffers.cc b/libs/ardour/thread_buffers.cc new file mode 100644 index 0000000000..e319acc329 --- /dev/null +++ b/libs/ardour/thread_buffers.cc @@ -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 + +#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; +} diff --git a/libs/ardour/wscript b/libs/ardour/wscript index ce9d41d795..32127b6f7f 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -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') diff --git a/libs/pbd/pbd/ringbufferNPT.h b/libs/pbd/pbd/ringbufferNPT.h index 30c71a8b1a..2b6aa03d62 100644 --- a/libs/pbd/pbd/ringbufferNPT.h +++ b/libs/pbd/pbd/ringbufferNPT.h @@ -22,6 +22,7 @@ //#include +#include #include /* ringbuffer class where the element size is not required to be a power of two */