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:
parent
46ea5f5f58
commit
3ea10b38bb
|
@ -55,6 +55,7 @@ class InternalPort;
|
||||||
class MidiPort;
|
class MidiPort;
|
||||||
class Port;
|
class Port;
|
||||||
class Session;
|
class Session;
|
||||||
|
class ProcessThread;
|
||||||
|
|
||||||
class AudioEngine : public SessionHandlePtr
|
class AudioEngine : public SessionHandlePtr
|
||||||
{
|
{
|
||||||
|
@ -69,6 +70,8 @@ class AudioEngine : public SessionHandlePtr
|
||||||
|
|
||||||
bool is_realtime () const;
|
bool is_realtime () const;
|
||||||
|
|
||||||
|
ProcessThread* main_thread() const { return _main_thread; }
|
||||||
|
|
||||||
std::string client_name() const { return jack_client_name; }
|
std::string client_name() const { return jack_client_name; }
|
||||||
|
|
||||||
int reconnect_to_jack ();
|
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);
|
Port *register_port (DataType type, const std::string& portname, bool input);
|
||||||
|
|
||||||
int process_callback (nframes_t nframes);
|
int process_callback (nframes_t nframes);
|
||||||
|
void* process_thread ();
|
||||||
|
void finish_process_cycle (int status);
|
||||||
void remove_all_ports ();
|
void remove_all_ports ();
|
||||||
|
|
||||||
std::string get_nth_physical (DataType type, uint32_t n, int flags);
|
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
|
#endif
|
||||||
static int _graph_order_callback (void *arg);
|
static int _graph_order_callback (void *arg);
|
||||||
static int _process_callback (nframes_t nframes, 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 _sample_rate_callback (nframes_t nframes, void *arg);
|
||||||
static int _bufsize_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*);
|
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;
|
Glib::Thread* m_meter_thread;
|
||||||
static gint m_meter_exit;
|
static gint m_meter_exit;
|
||||||
|
|
||||||
|
ProcessThread* _main_thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
31
libs/ardour/ardour/buffer_manager.h
Normal file
31
libs/ardour/ardour/buffer_manager.h
Normal 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__ */
|
44
libs/ardour/ardour/process_thread.h
Normal file
44
libs/ardour/ardour/process_thread.h
Normal 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__ */
|
|
@ -106,6 +106,7 @@ class Playlist;
|
||||||
class PluginInsert;
|
class PluginInsert;
|
||||||
class Port;
|
class Port;
|
||||||
class PortInsert;
|
class PortInsert;
|
||||||
|
class ProcessThread;
|
||||||
class Processor;
|
class Processor;
|
||||||
class Region;
|
class Region;
|
||||||
class Return;
|
class Return;
|
||||||
|
@ -736,8 +737,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
|
|
||||||
/* buffers for gain and pan */
|
/* buffers for gain and pan */
|
||||||
|
|
||||||
gain_t* gain_automation_buffer () const { return _gain_automation_buffer; }
|
gain_t* gain_automation_buffer () const;
|
||||||
pan_t** pan_automation_buffer () const { return _pan_automation_buffer; }
|
pan_t** pan_automation_buffer () const;
|
||||||
|
|
||||||
void ensure_buffer_set (BufferSet& buffers, const ChanCount& howmany);
|
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;
|
nframes64_t _last_slave_transport_frame;
|
||||||
nframes_t maximum_output_latency;
|
nframes_t maximum_output_latency;
|
||||||
volatile nframes64_t _requested_return_frame;
|
volatile nframes64_t _requested_return_frame;
|
||||||
BufferSet* _scratch_buffers;
|
|
||||||
BufferSet* _silent_buffers;
|
|
||||||
BufferSet* _mix_buffers;
|
|
||||||
nframes_t current_block_size;
|
nframes_t current_block_size;
|
||||||
nframes_t _worst_output_latency;
|
nframes_t _worst_output_latency;
|
||||||
nframes_t _worst_input_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 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_scrub (nframes_t);
|
||||||
void process_without_events (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); }
|
void unblock_processing() { g_atomic_int_set (&processing_prohibited, 0); }
|
||||||
bool processing_blocked() const { return g_atomic_int_get (&processing_prohibited); }
|
bool processing_blocked() const { return g_atomic_int_get (&processing_prohibited); }
|
||||||
|
|
||||||
|
Glib::Mutex process_thread_lock;
|
||||||
|
std::list<ProcessThread*> process_threads;
|
||||||
|
|
||||||
/* slave tracking */
|
/* slave tracking */
|
||||||
|
|
||||||
static const int delta_accumulator_size = 25;
|
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> _master_out;
|
||||||
boost::shared_ptr<Route> _monitor_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 */
|
/* VST support */
|
||||||
|
|
||||||
long _vst_callback (VSTPlugin*,
|
long _vst_callback (VSTPlugin*,
|
||||||
|
|
33
libs/ardour/ardour/thread_buffers.h
Normal file
33
libs/ardour/ardour/thread_buffers.h
Normal 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__ */
|
|
@ -43,6 +43,7 @@
|
||||||
#include "ardour/io.h"
|
#include "ardour/io.h"
|
||||||
#include "ardour/meter.h"
|
#include "ardour/meter.h"
|
||||||
#include "ardour/midi_port.h"
|
#include "ardour/midi_port.h"
|
||||||
|
#include "ardour/process_thread.h"
|
||||||
#include "ardour/port.h"
|
#include "ardour/port.h"
|
||||||
#include "ardour/port_set.h"
|
#include "ardour/port_set.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
|
@ -77,6 +78,7 @@ AudioEngine::AudioEngine (string client_name, string session_uuid)
|
||||||
_frame_rate = 0;
|
_frame_rate = 0;
|
||||||
_buffer_size = 0;
|
_buffer_size = 0;
|
||||||
_freewheeling = false;
|
_freewheeling = false;
|
||||||
|
_main_thread = 0;
|
||||||
|
|
||||||
m_meter_thread = 0;
|
m_meter_thread = 0;
|
||||||
g_atomic_int_set (&m_meter_exit, 0);
|
g_atomic_int_set (&m_meter_exit, 0);
|
||||||
|
@ -184,7 +186,8 @@ AudioEngine::start ()
|
||||||
jack_on_shutdown (_priv_jack, halted, this);
|
jack_on_shutdown (_priv_jack, halted, this);
|
||||||
jack_set_graph_order_callback (_priv_jack, _graph_order_callback, 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_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_sample_rate_callback (_priv_jack, _sample_rate_callback, this);
|
||||||
jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
|
jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
|
||||||
jack_set_xrun_callback (_priv_jack, _xrun_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);
|
return static_cast<AudioEngine *> (arg)->process_callback (nframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
AudioEngine::_process_thread (void *arg)
|
||||||
|
{
|
||||||
|
return static_cast<AudioEngine *> (arg)->process_thread ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioEngine::_freewheel_callback (int onoff, void *arg)
|
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
|
/** Method called by JACK (via _process_callback) which says that there
|
||||||
* is work to be done.
|
* is work to be done.
|
||||||
* @param nframes Number of frames to process.
|
* @param nframes Number of frames to process.
|
||||||
|
@ -379,7 +429,7 @@ AudioEngine::split_cycle (nframes_t offset)
|
||||||
int
|
int
|
||||||
AudioEngine::process_callback (nframes_t nframes)
|
AudioEngine::process_callback (nframes_t nframes)
|
||||||
{
|
{
|
||||||
GET_PRIVATE_JACK_POINTER_RET(_jack,0)
|
GET_PRIVATE_JACK_POINTER_RET(_jack,0);
|
||||||
// CycleTimer ct ("AudioEngine::process");
|
// CycleTimer ct ("AudioEngine::process");
|
||||||
Glib::Mutex::Lock tm (_process_lock, Glib::TRY_LOCK);
|
Glib::Mutex::Lock tm (_process_lock, Glib::TRY_LOCK);
|
||||||
|
|
||||||
|
@ -434,6 +484,7 @@ AudioEngine::process_callback (nframes_t nframes)
|
||||||
} else {
|
} else {
|
||||||
if (_session) {
|
if (_session) {
|
||||||
_session->process (nframes);
|
_session->process (nframes);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,6 +981,8 @@ AudioEngine::get_ports (const string& port_name_pattern, const string& type_name
|
||||||
void
|
void
|
||||||
AudioEngine::halted (void *arg)
|
AudioEngine::halted (void *arg)
|
||||||
{
|
{
|
||||||
|
cerr << "HALTED by JACK\n";
|
||||||
|
|
||||||
/* called from jack shutdown handler */
|
/* called from jack shutdown handler */
|
||||||
|
|
||||||
AudioEngine* ae = static_cast<AudioEngine *> (arg);
|
AudioEngine* ae = static_cast<AudioEngine *> (arg);
|
||||||
|
@ -1246,13 +1299,8 @@ AudioEngine::reconnect_to_jack ()
|
||||||
|
|
||||||
if (_session) {
|
if (_session) {
|
||||||
_session->reset_jack_connection (_priv_jack);
|
_session->reset_jack_connection (_priv_jack);
|
||||||
nframes_t blocksize = jack_get_buffer_size (_priv_jack);
|
jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
|
||||||
_session->set_block_size (blocksize);
|
|
||||||
_session->set_frame_rate (jack_get_sample_rate (_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;
|
last_monitor_check = 0;
|
||||||
|
@ -1260,7 +1308,8 @@ AudioEngine::reconnect_to_jack ()
|
||||||
jack_on_shutdown (_priv_jack, halted, this);
|
jack_on_shutdown (_priv_jack, halted, this);
|
||||||
jack_set_graph_order_callback (_priv_jack, _graph_order_callback, 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_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_sample_rate_callback (_priv_jack, _sample_rate_callback, this);
|
||||||
jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
|
jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
|
||||||
jack_set_xrun_callback (_priv_jack, _xrun_callback, this);
|
jack_set_xrun_callback (_priv_jack, _xrun_callback, this);
|
||||||
|
|
82
libs/ardour/buffer_manager.cc
Normal file
82
libs/ardour/buffer_manager.cc
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,12 +64,14 @@
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
#include "ardour/audioregion.h"
|
#include "ardour/audioregion.h"
|
||||||
#include "ardour/audiosource.h"
|
#include "ardour/audiosource.h"
|
||||||
|
#include "ardour/buffer_manager.h"
|
||||||
#include "ardour/control_protocol_manager.h"
|
#include "ardour/control_protocol_manager.h"
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
#include "ardour/filesystem_paths.h"
|
#include "ardour/filesystem_paths.h"
|
||||||
#include "ardour/mix.h"
|
#include "ardour/mix.h"
|
||||||
#include "ardour/playlist.h"
|
#include "ardour/playlist.h"
|
||||||
#include "ardour/plugin_manager.h"
|
#include "ardour/plugin_manager.h"
|
||||||
|
#include "ardour/process_thread.h"
|
||||||
#include "ardour/profile.h"
|
#include "ardour/profile.h"
|
||||||
#include "ardour/region.h"
|
#include "ardour/region.h"
|
||||||
#include "ardour/rc_configuration.h"
|
#include "ardour/rc_configuration.h"
|
||||||
|
@ -405,6 +407,9 @@ ARDOUR::init (bool use_vst, bool try_optimization)
|
||||||
/* singleton - first object is "it" */
|
/* singleton - first object is "it" */
|
||||||
new PluginManager ();
|
new PluginManager ();
|
||||||
|
|
||||||
|
ProcessThread::init ();
|
||||||
|
BufferManager::init (2); // XX should be num_processors_for_dsp
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
149
libs/ardour/process_thread.cc
Normal file
149
libs/ardour/process_thread.cc
Normal 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;
|
||||||
|
}
|
|
@ -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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -52,6 +52,7 @@
|
||||||
#include "ardour/audioplaylist.h"
|
#include "ardour/audioplaylist.h"
|
||||||
#include "ardour/audioregion.h"
|
#include "ardour/audioregion.h"
|
||||||
#include "ardour/auditioner.h"
|
#include "ardour/auditioner.h"
|
||||||
|
#include "ardour/buffer_manager.h"
|
||||||
#include "ardour/buffer_set.h"
|
#include "ardour/buffer_set.h"
|
||||||
#include "ardour/bundle.h"
|
#include "ardour/bundle.h"
|
||||||
#include "ardour/butler.h"
|
#include "ardour/butler.h"
|
||||||
|
@ -70,6 +71,7 @@
|
||||||
#include "ardour/midi_track.h"
|
#include "ardour/midi_track.h"
|
||||||
#include "ardour/midi_ui.h"
|
#include "ardour/midi_ui.h"
|
||||||
#include "ardour/named_selection.h"
|
#include "ardour/named_selection.h"
|
||||||
|
#include "ardour/process_thread.h"
|
||||||
#include "ardour/playlist.h"
|
#include "ardour/playlist.h"
|
||||||
#include "ardour/plugin_insert.h"
|
#include "ardour/plugin_insert.h"
|
||||||
#include "ardour/port_insert.h"
|
#include "ardour/port_insert.h"
|
||||||
|
@ -129,9 +131,6 @@ Session::Session (AudioEngine &eng,
|
||||||
: _engine (eng),
|
: _engine (eng),
|
||||||
_target_transport_speed (0.0),
|
_target_transport_speed (0.0),
|
||||||
_requested_return_frame (-1),
|
_requested_return_frame (-1),
|
||||||
_scratch_buffers(new BufferSet()),
|
|
||||||
_silent_buffers(new BufferSet()),
|
|
||||||
_mix_buffers(new BufferSet()),
|
|
||||||
mmc (0),
|
mmc (0),
|
||||||
_mmc_port (default_mmc_port),
|
_mmc_port (default_mmc_port),
|
||||||
_mtc_port (default_mtc_port),
|
_mtc_port (default_mtc_port),
|
||||||
|
@ -243,10 +242,6 @@ Session::destroy ()
|
||||||
|
|
||||||
clear_clicks ();
|
clear_clicks ();
|
||||||
|
|
||||||
delete _scratch_buffers;
|
|
||||||
delete _silent_buffers;
|
|
||||||
delete _mix_buffers;
|
|
||||||
|
|
||||||
/* clear out any pending dead wood from RCU managed objects */
|
/* clear out any pending dead wood from RCU managed objects */
|
||||||
|
|
||||||
routes.flush ();
|
routes.flush ();
|
||||||
|
@ -1193,12 +1188,7 @@ Session::set_block_size (nframes_t nframes)
|
||||||
{
|
{
|
||||||
current_block_size = nframes;
|
current_block_size = nframes;
|
||||||
|
|
||||||
ensure_buffers(_scratch_buffers->available());
|
ensure_buffers ();
|
||||||
|
|
||||||
delete [] _gain_automation_buffer;
|
|
||||||
_gain_automation_buffer = new gain_t[nframes];
|
|
||||||
|
|
||||||
allocate_pan_automation_buffers (nframes, _npan_buffers, true);
|
|
||||||
|
|
||||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||||
|
|
||||||
|
@ -3209,18 +3199,7 @@ Session::tempo_map_changed (const PropertyChange&)
|
||||||
void
|
void
|
||||||
Session::ensure_buffers (ChanCount howmany)
|
Session::ensure_buffers (ChanCount howmany)
|
||||||
{
|
{
|
||||||
if (current_block_size == 0) {
|
BufferManager::ensure_buffers (howmany);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -3439,31 +3418,6 @@ Session::route_name_internal (string n) const
|
||||||
return false;
|
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
|
int
|
||||||
Session::freeze_all (InterThreadInfo& itt)
|
Session::freeze_all (InterThreadInfo& itt)
|
||||||
{
|
{
|
||||||
|
@ -3649,9 +3603,23 @@ Session::write_one_track (AudioTrack& track, nframes_t start, nframes_t end,
|
||||||
return result;
|
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&
|
BufferSet&
|
||||||
Session::get_silent_buffers (ChanCount count)
|
Session::get_silent_buffers (ChanCount count)
|
||||||
{
|
{
|
||||||
|
return ProcessThread::get_silent_buffers (count);
|
||||||
|
#if 0
|
||||||
assert(_silent_buffers->available() >= count);
|
assert(_silent_buffers->available() >= count);
|
||||||
_silent_buffers->set_count(count);
|
_silent_buffers->set_count(count);
|
||||||
|
|
||||||
|
@ -3662,11 +3630,14 @@ Session::get_silent_buffers (ChanCount count)
|
||||||
}
|
}
|
||||||
|
|
||||||
return *_silent_buffers;
|
return *_silent_buffers;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferSet&
|
BufferSet&
|
||||||
Session::get_scratch_buffers (ChanCount count)
|
Session::get_scratch_buffers (ChanCount count)
|
||||||
{
|
{
|
||||||
|
return ProcessThread::get_scratch_buffers (count);
|
||||||
|
#if 0
|
||||||
if (count != ChanCount::ZERO) {
|
if (count != ChanCount::ZERO) {
|
||||||
assert(_scratch_buffers->available() >= count);
|
assert(_scratch_buffers->available() >= count);
|
||||||
_scratch_buffers->set_count(count);
|
_scratch_buffers->set_count(count);
|
||||||
|
@ -3675,14 +3646,18 @@ Session::get_scratch_buffers (ChanCount count)
|
||||||
}
|
}
|
||||||
|
|
||||||
return *_scratch_buffers;
|
return *_scratch_buffers;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferSet&
|
BufferSet&
|
||||||
Session::get_mix_buffers (ChanCount count)
|
Session::get_mix_buffers (ChanCount count)
|
||||||
{
|
{
|
||||||
|
return ProcessThread::get_mix_buffers (count);
|
||||||
|
#if 0
|
||||||
assert(_mix_buffers->available() >= count);
|
assert(_mix_buffers->available() >= count);
|
||||||
_mix_buffers->set_count(count);
|
_mix_buffers->set_count(count);
|
||||||
return *_mix_buffers;
|
return *_mix_buffers;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "ardour/auditioner.h"
|
#include "ardour/auditioner.h"
|
||||||
#include "ardour/butler.h"
|
#include "ardour/butler.h"
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
|
#include "ardour/process_thread.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/slave.h"
|
#include "ardour/slave.h"
|
||||||
#include "ardour/timestamps.h"
|
#include "ardour/timestamps.h"
|
||||||
|
@ -65,9 +66,13 @@ Session::process (nframes_t nframes)
|
||||||
post_transport ();
|
post_transport ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_engine.main_thread()->get_buffers ();
|
||||||
|
|
||||||
(this->*process_function) (nframes);
|
(this->*process_function) (nframes);
|
||||||
|
|
||||||
|
_engine.main_thread()->drop_buffers ();
|
||||||
|
|
||||||
// the ticker is for sending time information like MidiClock
|
// the ticker is for sending time information like MidiClock
|
||||||
nframes_t transport_frames = transport_frame();
|
nframes_t transport_frames = transport_frame();
|
||||||
BBT_Time transport_bbt;
|
BBT_Time transport_bbt;
|
||||||
|
|
|
@ -210,9 +210,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
||||||
g_atomic_int_set (&_capture_load_min, 100);
|
g_atomic_int_set (&_capture_load_min, 100);
|
||||||
_play_range = false;
|
_play_range = false;
|
||||||
_exporting = false;
|
_exporting = false;
|
||||||
_gain_automation_buffer = 0;
|
|
||||||
_pan_automation_buffer = 0;
|
|
||||||
_npan_buffers = 0;
|
|
||||||
pending_abort = false;
|
pending_abort = false;
|
||||||
destructive_index = 0;
|
destructive_index = 0;
|
||||||
first_file_data_format_reset = true;
|
first_file_data_format_reset = true;
|
||||||
|
|
91
libs/ardour/thread_buffers.cc
Normal file
91
libs/ardour/thread_buffers.cc
Normal 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;
|
||||||
|
}
|
|
@ -57,6 +57,7 @@ libardour_sources = [
|
||||||
'beats_frames_converter.cc',
|
'beats_frames_converter.cc',
|
||||||
'broadcast_info.cc',
|
'broadcast_info.cc',
|
||||||
'buffer.cc',
|
'buffer.cc',
|
||||||
|
'buffer_manager.cc',
|
||||||
'buffer_set.cc',
|
'buffer_set.cc',
|
||||||
'bundle.cc',
|
'bundle.cc',
|
||||||
'butler.cc',
|
'butler.cc',
|
||||||
|
@ -140,6 +141,7 @@ libardour_sources = [
|
||||||
'port.cc',
|
'port.cc',
|
||||||
'port_insert.cc',
|
'port_insert.cc',
|
||||||
'port_set.cc',
|
'port_set.cc',
|
||||||
|
'process_thread.cc',
|
||||||
'processor.cc',
|
'processor.cc',
|
||||||
'quantize.cc',
|
'quantize.cc',
|
||||||
'rc_configuration.cc',
|
'rc_configuration.cc',
|
||||||
|
@ -187,6 +189,7 @@ libardour_sources = [
|
||||||
'template_utils.cc',
|
'template_utils.cc',
|
||||||
'tempo.cc',
|
'tempo.cc',
|
||||||
'tempo_map_importer.cc',
|
'tempo_map_importer.cc',
|
||||||
|
'thread_buffers.cc',
|
||||||
'ticker.cc',
|
'ticker.cc',
|
||||||
'track.cc',
|
'track.cc',
|
||||||
'transient_detector.cc',
|
'transient_detector.cc',
|
||||||
|
@ -218,7 +221,7 @@ def configure(conf):
|
||||||
autowaf.configure(conf)
|
autowaf.configure(conf)
|
||||||
conf.check_tool('compiler_cxx gas')
|
conf.check_tool('compiler_cxx gas')
|
||||||
autowaf.check_pkg(conf, 'aubio', uselib_store='AUBIO', atleast_version='0.3.2')
|
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, 'libxml-2.0', uselib_store='XML')
|
||||||
autowaf.check_pkg(conf, 'lrdf', uselib_store='LRDF', atleast_version='0.4.0')
|
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')
|
autowaf.check_pkg(conf, 'samplerate', uselib_store='SAMPLERATE', atleast_version='0.1.0')
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
//#include <sys/mman.h>
|
//#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
/* ringbuffer class where the element size is not required to be a power of two */
|
/* ringbuffer class where the element size is not required to be a power of two */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user