mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
Towards MIDI:
- Converted vector<Sample*> to BufferList and numerous counts from int to ChanCount (and related changes) - Added fancy type-generic iterators to BufferList, PortIterator (see IO::collect_input for a good example of the idea - the same code will work to read all input (of various types in a single IO, eg instruments) without modification no matter how many types we add) - Fixed comparison operator bugs with ChanCount (screwed up metering among other things) - Moved peak metering into it's own object, and moved most of the pan related code out of IO to panner (still a touch more to be done here for MIDI playback) Not directly MIDI related fixes for problems in trunk: - Fixed varispeed gain/pan automation to work properly (was reading the wrong range of automation data, probably causing nasty clicks?) - Fixed crash on varispeed looping (possibly only a 64-bit problem). It still doesn't work, but at least it doesn't die Quite a few things broken, and the new classes are pretty filthy still, but I think the direction is a lot better than all my previous plans... git-svn-id: svn://localhost/ardour2/branches/midi@795 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
cbdf686e39
commit
30ab1fd615
59 changed files with 1218 additions and 950 deletions
|
|
@ -767,7 +767,7 @@ AudioRegionView::create_waves ()
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t nchans = atv.get_diskstream()->n_channels();
|
||||
uint32_t nchans = atv.get_diskstream()->n_channels().get(DataType::AUDIO);
|
||||
|
||||
/* in tmp_waves, set up null pointers for each channel so the vector is allocated */
|
||||
for (uint32_t n = 0; n < nchans; ++n) {
|
||||
|
|
@ -806,7 +806,7 @@ void
|
|||
AudioRegionView::create_one_wave (uint32_t which, bool direct)
|
||||
{
|
||||
RouteTimeAxisView& atv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick
|
||||
uint32_t nchans = atv.get_diskstream()->n_channels();
|
||||
uint32_t nchans = atv.get_diskstream()->n_channels().get(DataType::AUDIO);
|
||||
uint32_t n;
|
||||
uint32_t nwaves = std::min (nchans, audio_region().n_channels());
|
||||
gdouble ht;
|
||||
|
|
@ -1024,7 +1024,7 @@ AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
|
|||
GhostRegion* ghost = new GhostRegion (atv, unit_position);
|
||||
uint32_t nchans;
|
||||
|
||||
nchans = rtv->get_diskstream()->n_channels();
|
||||
nchans = rtv->get_diskstream()->n_channels().get(DataType::AUDIO);
|
||||
|
||||
for (uint32_t n = 0; n < nchans; ++n) {
|
||||
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ AudioStreamView::setup_rec_box ()
|
|||
AudioDiskstream* ads = dynamic_cast<AudioDiskstream*>(_trackview.get_diskstream());
|
||||
assert(ads);
|
||||
|
||||
for (uint32_t n=0; n < ads->n_channels(); ++n) {
|
||||
for (uint32_t n=0; n < ads->n_channels().get(DataType::AUDIO); ++n) {
|
||||
AudioSource *src = (AudioSource *) ads->write_source (n);
|
||||
if (src) {
|
||||
sources.push_back (src);
|
||||
|
|
@ -553,7 +553,7 @@ AudioStreamView::rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt,
|
|||
|
||||
rec_peak_ready_map[src] = true;
|
||||
|
||||
if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels()) {
|
||||
if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels().get(DataType::AUDIO)) {
|
||||
this->update_rec_regions ();
|
||||
rec_peak_ready_map.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ namespace ARDOUR {
|
|||
class Session;
|
||||
class AudioFilter;
|
||||
class Crossfade;
|
||||
class ChanCount;
|
||||
}
|
||||
|
||||
namespace LADSPA {
|
||||
|
|
@ -1591,7 +1592,7 @@ class Editor : public PublicEditor
|
|||
void external_edit_region ();
|
||||
|
||||
int write_audio_selection (TimeSelection&);
|
||||
bool write_audio_range (ARDOUR::AudioPlaylist&, uint32_t channels, list<ARDOUR::AudioRange>&);
|
||||
bool write_audio_range (ARDOUR::AudioPlaylist&, const ARDOUR::ChanCount& channels, list<ARDOUR::AudioRange>&);
|
||||
|
||||
void write_selection ();
|
||||
|
||||
|
|
@ -1600,6 +1601,7 @@ class Editor : public PublicEditor
|
|||
UndoAction get_memento() const;
|
||||
|
||||
XMLNode *before; /* used in *_reversible_command */
|
||||
|
||||
void begin_reversible_command (string cmd_name);
|
||||
void commit_reversible_command ();
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include <ardour/audio_diskstream.h>
|
||||
#include <ardour/audioregion.h>
|
||||
#include <ardour/audioplaylist.h>
|
||||
#include <ardour/chan_count.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
|
@ -302,7 +303,7 @@ Editor::write_audio_selection (TimeSelection& ts)
|
|||
}
|
||||
|
||||
bool
|
||||
Editor::write_audio_range (AudioPlaylist& playlist, uint32_t channels, list<AudioRange>& range)
|
||||
Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list<AudioRange>& range)
|
||||
{
|
||||
AudioFileSource* fs;
|
||||
const jack_nframes_t chunk_size = 4096;
|
||||
|
|
@ -315,6 +316,8 @@ Editor::write_audio_range (AudioPlaylist& playlist, uint32_t channels, list<Audi
|
|||
string path;
|
||||
vector<AudioFileSource *> sources;
|
||||
|
||||
uint32_t channels = count.get(DataType::AUDIO);
|
||||
|
||||
for (uint32_t n=0; n < channels; ++n) {
|
||||
|
||||
for (cnt = 0; cnt < 999999; ++cnt) {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include <ardour/session.h>
|
||||
#include <ardour/route.h>
|
||||
#include <ardour/meter.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
|
@ -326,7 +327,7 @@ GainMeter::update_meters ()
|
|||
|
||||
for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
|
||||
if ((*i).packed) {
|
||||
peak = _io->peak_input_power (n);
|
||||
peak = _io->peak_meter().peak_power (n);
|
||||
|
||||
(*i).meter->set (log_meter (peak), peak);
|
||||
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ RedirectBox::choose_send ()
|
|||
|
||||
/* XXX need redirect lock on route */
|
||||
|
||||
send->ensure_io (0, _route->max_redirect_outs(), false, this);
|
||||
send->ensure_io (ChanCount::ZERO, _route->max_redirect_outs(), false, this);
|
||||
|
||||
IOSelectorWindow *ios = new IOSelectorWindow (_session, send, false, true);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ midi_port.cc
|
|||
port_set.cc
|
||||
buffer.cc
|
||||
buffer_set.cc
|
||||
declicker.cc
|
||||
meter.cc
|
||||
audiofilesource.cc
|
||||
audiofilter.cc
|
||||
audioregion.cc
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class AudioPort : public Port {
|
|||
/** Assumes that the port is an audio output port */
|
||||
void silence (jack_nframes_t nframes, jack_nframes_t offset) {
|
||||
if (!_silent) {
|
||||
_buffer.clear(offset);
|
||||
_buffer.silence(nframes, offset);
|
||||
if (offset == 0 && nframes == _buffer.capacity()) {
|
||||
_silent = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class AudioTrack : public Track
|
|||
int use_diskstream (string name);
|
||||
int use_diskstream (const PBD::ID& id);
|
||||
|
||||
int export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t end_frame);
|
||||
int export_stuff (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t end_frame);
|
||||
|
||||
void freeze (InterThreadInfo&);
|
||||
void unfreeze ();
|
||||
|
|
@ -68,7 +68,7 @@ class AudioTrack : public Track
|
|||
jack_nframes_t nframes, jack_nframes_t offset, int declick,
|
||||
bool meter);
|
||||
|
||||
uint32_t n_process_buffers ();
|
||||
ChanCount n_process_buffers ();
|
||||
|
||||
private:
|
||||
int set_diskstream (AudioDiskstream&, void *);
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class AUPlugin : public ARDOUR::Plugin
|
|||
void deactivate ();
|
||||
void set_block_size (jack_nframes_t nframes);
|
||||
|
||||
int connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
std::set<uint32_t> automatable() const;
|
||||
void store_state (ARDOUR::PluginState&);
|
||||
void restore_state (ARDOUR::PluginState&);
|
||||
|
|
|
|||
|
|
@ -108,11 +108,11 @@ class AudioEngine : public sigc::trackable
|
|||
|
||||
Port *register_input_port (DataType type, const std::string& portname);
|
||||
Port *register_output_port (DataType type, const std::string& portname);
|
||||
int unregister_port (Port *);
|
||||
int unregister_port (Port &);
|
||||
|
||||
int connect (const std::string& source, const std::string& destination);
|
||||
int disconnect (const std::string& source, const std::string& destination);
|
||||
int disconnect (Port *);
|
||||
int disconnect (Port &);
|
||||
|
||||
const char ** get_ports (const std::string& port_name_pattern, const std::string& type_name_pattern, uint32_t flags);
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ class AudioEngine : public sigc::trackable
|
|||
typedef std::list<PortConnection> PortConnections;
|
||||
|
||||
PortConnections port_connections;
|
||||
void remove_connections_for (Port*);
|
||||
void remove_connections_for (Port&);
|
||||
|
||||
std::string get_nth_physical (DataType type, uint32_t n, int flags);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,9 +57,12 @@ public:
|
|||
DataType type() const { return _type; }
|
||||
|
||||
/** Clear (eg zero, or empty) buffer starting at TIME @a offset */
|
||||
virtual void clear(jack_nframes_t offset = 0) = 0;
|
||||
virtual void silence(jack_nframes_t len, jack_nframes_t offset=0) = 0;
|
||||
|
||||
virtual void write(const Buffer& src, jack_nframes_t offset, jack_nframes_t len) = 0;
|
||||
/** Clear the entire buffer */
|
||||
virtual void clear() { silence(_capacity, 0); }
|
||||
|
||||
virtual void read_from(const Buffer& src, jack_nframes_t offset, jack_nframes_t len) = 0;
|
||||
|
||||
protected:
|
||||
Buffer(DataType type, size_t capacity)
|
||||
|
|
@ -88,21 +91,49 @@ public:
|
|||
|
||||
~AudioBuffer();
|
||||
|
||||
void clear(jack_nframes_t offset=0) { memset(_data + offset, 0, sizeof (Sample) * _capacity); }
|
||||
|
||||
/** Copy @a len frames starting at @a offset, from the start of @a src */
|
||||
void write(const Buffer& src, jack_nframes_t offset, jack_nframes_t len)
|
||||
void silence(jack_nframes_t len, jack_nframes_t offset=0)
|
||||
{
|
||||
assert(src.type() == _type == DataType::AUDIO);
|
||||
assert(_capacity > 0);
|
||||
assert(offset + len <= _capacity);
|
||||
memcpy(_data + offset, ((AudioBuffer&)src).data(len, offset), sizeof(Sample) * len);
|
||||
memset(_data + offset, 0, sizeof (Sample) * len);
|
||||
}
|
||||
|
||||
/** Copy @a len frames starting at @a offset, from the start of @a src */
|
||||
void write(const Sample* src, jack_nframes_t offset, jack_nframes_t len)
|
||||
/** Read @a len frames FROM THE START OF @a src into self at @a offset */
|
||||
void read_from(const Buffer& src, jack_nframes_t len, jack_nframes_t offset)
|
||||
{
|
||||
assert(_capacity > 0);
|
||||
assert(src.type() == _type == DataType::AUDIO);
|
||||
assert(offset + len <= _capacity);
|
||||
memcpy(_data + offset, src, sizeof(Sample) * len);
|
||||
memcpy(_data + offset, ((AudioBuffer&)src).data(len), sizeof(Sample) * len);
|
||||
}
|
||||
|
||||
/** Accumulate (add)@a len frames FROM THE START OF @a src into self at @a offset */
|
||||
void accumulate_from(const AudioBuffer& src, jack_nframes_t len, jack_nframes_t offset)
|
||||
{
|
||||
assert(_capacity > 0);
|
||||
assert(offset + len <= _capacity);
|
||||
|
||||
Sample* const dst_raw = _data + offset;
|
||||
const Sample* const src_raw = src.data(len);
|
||||
|
||||
for (jack_nframes_t n = 0; n < len; ++n) {
|
||||
dst_raw[n] += src_raw[n];
|
||||
}
|
||||
}
|
||||
|
||||
/** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
|
||||
* scaling by @a gain_coeff */
|
||||
void accumulate_with_gain_from(const AudioBuffer& src, jack_nframes_t len, jack_nframes_t offset, gain_t gain_coeff)
|
||||
{
|
||||
assert(_capacity > 0);
|
||||
assert(offset + len <= _capacity);
|
||||
|
||||
Sample* const dst_raw = _data + offset;
|
||||
const Sample* const src_raw = src.data(len);
|
||||
|
||||
for (jack_nframes_t n = 0; n < len; ++n) {
|
||||
dst_raw[n] += src_raw[n] * gain_coeff;
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the data contained by this buffer manually (for setting directly to jack buffer).
|
||||
|
|
@ -142,10 +173,10 @@ public:
|
|||
|
||||
~MidiBuffer();
|
||||
|
||||
// FIXME: clear events starting at offset
|
||||
void clear(jack_nframes_t offset=0) { assert(offset == 0); _size = 0; }
|
||||
// FIXME: clear events starting at offset in time
|
||||
void silence(jack_nframes_t len, jack_nframes_t offset=0) { assert(offset == 0); _size = 0; }
|
||||
|
||||
void write(const Buffer& src, jack_nframes_t offset, jack_nframes_t nframes);
|
||||
void read_from(const Buffer& src, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
|
||||
void set_size(size_t size) { _size = size; }
|
||||
|
||||
|
|
|
|||
|
|
@ -19,14 +19,17 @@
|
|||
#ifndef __ardour_buffer_set_h__
|
||||
#define __ardour_buffer_set_h__
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <ardour/buffer.h>
|
||||
#include <ardour/chan_count.h>
|
||||
#include <ardour/data_type.h>
|
||||
#include <ardour/port_set.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class Buffer;
|
||||
class AudioBuffer;
|
||||
class PortSet;
|
||||
|
||||
|
||||
/** A set of buffers of various types.
|
||||
*
|
||||
|
|
@ -44,52 +47,91 @@ namespace ARDOUR {
|
|||
class BufferSet
|
||||
{
|
||||
public:
|
||||
BufferSet(const PortSet& ports);
|
||||
BufferSet();
|
||||
~BufferSet();
|
||||
|
||||
void clear();
|
||||
|
||||
void ensure_buffers(const ChanCount& chan_count, size_t buffer_capacity);
|
||||
void ensure_buffers(size_t num_buffers, DataType type, size_t buffer_capacity);
|
||||
void attach_buffers(PortSet& ports);
|
||||
|
||||
// FIXME: add these
|
||||
//const ChanCount& available() const { return _count; }
|
||||
//ChanCount& available() { return _count; }
|
||||
void ensure_buffers(const ChanCount& count, size_t buffer_capacity);
|
||||
void ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capacity);
|
||||
|
||||
const ChanCount& available() const { return _available; }
|
||||
ChanCount& available() { return _available; }
|
||||
|
||||
const ChanCount& count() const { return _count; }
|
||||
ChanCount& count() { return _count; }
|
||||
|
||||
size_t available_buffers(DataType type) const;
|
||||
void set_count(const ChanCount& count) { _count = count; }
|
||||
|
||||
size_t buffer_capacity(DataType type) const;
|
||||
|
||||
Buffer& buffer(DataType type, size_t i)
|
||||
Buffer& get(DataType type, size_t i)
|
||||
{
|
||||
assert(i <= _count.get(type));
|
||||
return *_buffers[type.to_index()][i];
|
||||
}
|
||||
|
||||
AudioBuffer& audio_buffer(size_t i)
|
||||
AudioBuffer& get_audio(size_t i)
|
||||
{
|
||||
return (AudioBuffer&)buffer(DataType::AUDIO, i);
|
||||
return (AudioBuffer&)get(DataType::AUDIO, i);
|
||||
}
|
||||
#if 0
|
||||
/** See PortInsert::run for an example of usage */
|
||||
class IndexSet {
|
||||
|
||||
void read_from(BufferSet& in, jack_nframes_t nframes, jack_nframes_t offset=0)
|
||||
{
|
||||
throw; // FIXME: implement this with spiffy DataType iterator etc.
|
||||
}
|
||||
|
||||
// ITERATORS
|
||||
|
||||
// FIXME: this is a filthy copy-and-paste mess
|
||||
// FIXME: litter these with assertions
|
||||
|
||||
class audio_iterator {
|
||||
public:
|
||||
IndexSet() { reset(); }
|
||||
|
||||
void reset() { _is[0] = 0; _is[1] = 0; }
|
||||
|
||||
size_t index(DataType type) { return _is[type.to_index()]; }
|
||||
void increment(DataType type) { _is[type.to_index()] += 1; }
|
||||
AudioBuffer& operator*() { return _set.get_audio(_index); }
|
||||
AudioBuffer* operator->() { return &_set.get_audio(_index); }
|
||||
audio_iterator& operator++() { ++_index; return *this; } // yes, prefix only
|
||||
bool operator==(const audio_iterator& other) { return (_index == other._index); }
|
||||
bool operator!=(const audio_iterator& other) { return (_index != other._index); }
|
||||
|
||||
private:
|
||||
int _is[2];
|
||||
};
|
||||
#endif
|
||||
friend class BufferSet;
|
||||
|
||||
audio_iterator(BufferSet& list, size_t index) : _set(list), _index(index) {}
|
||||
|
||||
BufferSet& _set;
|
||||
size_t _index;
|
||||
};
|
||||
|
||||
audio_iterator audio_begin() { return audio_iterator(*this, 0); }
|
||||
audio_iterator audio_end() { return audio_iterator(*this, _count.get(DataType::AUDIO)); }
|
||||
|
||||
class iterator {
|
||||
public:
|
||||
|
||||
Buffer& operator*() { return _set.get(_type, _index); }
|
||||
Buffer* operator->() { return &_set.get(_type, _index); }
|
||||
iterator& operator++() { ++_index; return *this; } // yes, prefix only
|
||||
bool operator==(const iterator& other) { return (_index == other._index); }
|
||||
bool operator!=(const iterator& other) { return (_index != other._index); }
|
||||
|
||||
private:
|
||||
friend class BufferSet;
|
||||
|
||||
iterator(BufferSet& list, DataType type, size_t index)
|
||||
: _set(list), _type(type), _index(index) {}
|
||||
|
||||
BufferSet& _set;
|
||||
DataType _type;
|
||||
size_t _index;
|
||||
};
|
||||
|
||||
iterator begin(DataType type) { return iterator(*this, type, 0); }
|
||||
iterator end(DataType type) { return iterator(*this, type, _count.get(type)); }
|
||||
|
||||
const ChanCount& chan_count() const { return _count; }
|
||||
|
||||
private:
|
||||
typedef std::vector<Buffer*> BufferVec;
|
||||
|
|
@ -100,6 +142,9 @@ private:
|
|||
/// Use counts (there may be more actual buffers than this)
|
||||
ChanCount _count;
|
||||
|
||||
/// Available counts (number of buffers actually allocated)
|
||||
ChanCount _available;
|
||||
|
||||
/// Whether we (don't) 'own' the contained buffers (are a mirror of a PortSet)
|
||||
bool _is_mirror;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,43 +71,33 @@ public:
|
|||
}
|
||||
|
||||
bool operator<(const ChanCount& other) const
|
||||
{
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
if (_counts[(*t).to_index()] >= other._counts[(*t).to_index()]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator<=(const ChanCount& other) const
|
||||
{
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
if (_counts[(*t).to_index()] > other._counts[(*t).to_index()]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return (*this != other);
|
||||
}
|
||||
|
||||
bool operator<=(const ChanCount& other) const
|
||||
{
|
||||
return ( (*this < other) || (*this == other) );
|
||||
}
|
||||
|
||||
bool operator>(const ChanCount& other) const
|
||||
{
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
if (_counts[(*t).to_index()] <= other._counts[(*t).to_index()]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator>=(const ChanCount& other) const
|
||||
{
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
if (_counts[(*t).to_index()] < other._counts[(*t).to_index()]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return (*this != other);
|
||||
}
|
||||
|
||||
bool operator>=(const ChanCount& other) const
|
||||
{
|
||||
return ( (*this > other) || (*this == other) );
|
||||
}
|
||||
|
||||
static const ChanCount INFINITE;
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ class Curve : public AutomationList
|
|||
Curve (const Curve& other);
|
||||
Curve (const Curve& other, double start, double end);
|
||||
|
||||
bool rt_safe_get_vector (double x0, double x1, float *arg, int32_t veclen);
|
||||
void get_vector (double x0, double x1, float *arg, int32_t veclen);
|
||||
bool rt_safe_get_vector (double x0, double x1, float *arg, size_t veclen);
|
||||
void get_vector (double x0, double x1, float *arg, size_t veclen);
|
||||
|
||||
AutomationEventList::iterator closest_control_point_before (double xval);
|
||||
AutomationEventList::iterator closest_control_point_after (double xval);
|
||||
|
|
@ -72,14 +72,14 @@ class Curve : public AutomationList
|
|||
double unlocked_eval (double where);
|
||||
double multipoint_eval (double x);
|
||||
|
||||
void _get_vector (double x0, double x1, float *arg, int32_t veclen);
|
||||
void _get_vector (double x0, double x1, float *arg, size_t veclen);
|
||||
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
extern "C" {
|
||||
void curve_get_vector_from_c (void *arg, double, double, float*, int32_t);
|
||||
void curve_get_vector_from_c (void *arg, double, double, float*, size_t);
|
||||
}
|
||||
|
||||
#endif /* __ardour_curve_h__ */
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#ifndef __ardour_data_type_h__
|
||||
#define __ardour_data_type_h__
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <ardour/data_type.h>
|
||||
#include <jack/jack.h>
|
||||
|
|
@ -95,7 +96,7 @@ public:
|
|||
}
|
||||
|
||||
Symbol to_symbol() const { return _symbol; }
|
||||
inline size_t to_index() const { return symbol_index(_symbol); }
|
||||
inline size_t to_index() const { assert(_symbol != NIL); return symbol_index(_symbol); }
|
||||
|
||||
/** DataType iterator, for writing generic loops that iterate over all
|
||||
* available types.
|
||||
|
|
|
|||
40
libs/ardour/ardour/declicker.h
Normal file
40
libs/ardour/ardour/declicker.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#ifndef __ardour_declicker_h__
|
||||
#define __ardour_declicker_h__
|
||||
|
||||
#include <ardour/types.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class BufferSet;
|
||||
|
||||
|
||||
/** Applies a declick operation to all audio inputs, passing the same number of
|
||||
* audio outputs, and passing through any other types unchanged.
|
||||
*/
|
||||
class Declicker {
|
||||
public:
|
||||
static void run (BufferSet& bufs, jack_nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity);
|
||||
};
|
||||
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
#endif // __ardour_declicker_h__
|
||||
|
|
@ -115,7 +115,7 @@ class Diskstream : public Stateful, public sigc::trackable
|
|||
jack_nframes_t get_capture_start_frame (uint32_t n=0);
|
||||
jack_nframes_t get_captured_frames (uint32_t n=0);
|
||||
|
||||
uint32_t n_channels() { return _n_channels; }
|
||||
ChanCount n_channels() { return _n_channels; }
|
||||
|
||||
static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; }
|
||||
static void set_disk_io_chunk_frames (uint32_t n) { disk_io_chunk_frames = n; }
|
||||
|
|
@ -250,7 +250,7 @@ class Diskstream : public Stateful, public sigc::trackable
|
|||
string _name;
|
||||
ARDOUR::Session& _session;
|
||||
ARDOUR::IO* _io;
|
||||
uint32_t _n_channels;
|
||||
ChanCount _n_channels;
|
||||
PBD::ID _id;
|
||||
Playlist* _playlist;
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class Insert : public Redirect
|
|||
|
||||
virtual ~Insert() { }
|
||||
|
||||
virtual void run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset) = 0;
|
||||
virtual void run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset) = 0;
|
||||
virtual void activate () {}
|
||||
virtual void deactivate () {}
|
||||
|
||||
|
|
@ -75,12 +75,12 @@ class PortInsert : public Insert
|
|||
int set_state(const XMLNode&);
|
||||
|
||||
void init ();
|
||||
void run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
|
||||
jack_nframes_t latency();
|
||||
|
||||
uint32_t output_streams() const;
|
||||
uint32_t input_streams() const;
|
||||
ChanCount output_streams() const;
|
||||
ChanCount input_streams() const;
|
||||
|
||||
int32_t can_support_input_configuration (int32_t) const;
|
||||
int32_t configure_io (int32_t magic, int32_t in, int32_t out);
|
||||
|
|
@ -113,17 +113,17 @@ class PluginInsert : public Insert
|
|||
StateManager::State* state_factory (std::string why) const;
|
||||
Change restore_state (StateManager::State&);
|
||||
|
||||
void run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void silence (jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void activate ();
|
||||
void deactivate ();
|
||||
|
||||
void set_block_size (jack_nframes_t nframes);
|
||||
|
||||
uint32_t output_streams() const;
|
||||
uint32_t input_streams() const;
|
||||
uint32_t natural_output_streams() const;
|
||||
uint32_t natural_input_streams() const;
|
||||
ChanCount output_streams() const;
|
||||
ChanCount input_streams() const;
|
||||
ChanCount natural_output_streams() const;
|
||||
ChanCount natural_input_streams() const;
|
||||
|
||||
int set_count (uint32_t num);
|
||||
uint32_t get_count () const { return _plugins.size(); }
|
||||
|
|
@ -167,8 +167,8 @@ class PluginInsert : public Insert
|
|||
void parameter_changed (uint32_t, float);
|
||||
|
||||
vector<boost::shared_ptr<Plugin> > _plugins;
|
||||
void automation_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void connect_and_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, bool with_auto, jack_nframes_t now = 0);
|
||||
void automation_run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void connect_and_run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset, bool with_auto, jack_nframes_t now = 0);
|
||||
|
||||
void init ();
|
||||
void set_automatable ();
|
||||
|
|
|
|||
|
|
@ -54,9 +54,11 @@ class Session;
|
|||
class AudioEngine;
|
||||
class Connection;
|
||||
class Panner;
|
||||
class PeakMeter;
|
||||
class Port;
|
||||
class AudioPort;
|
||||
class MidiPort;
|
||||
class BufferSet;
|
||||
|
||||
/** A collection of input and output ports with connections.
|
||||
*
|
||||
|
|
@ -99,18 +101,15 @@ class IO : public Stateful, public ARDOUR::StateManager
|
|||
|
||||
virtual void silence (jack_nframes_t, jack_nframes_t offset);
|
||||
|
||||
// These should be moved in to a separate object that manipulates an IO
|
||||
|
||||
void pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff);
|
||||
void pan_automated (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void collect_input (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void deliver_output (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void deliver_output_no_pan (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void pan (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff);
|
||||
void pan_automated (BufferSet& bufs, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void collect_input (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void deliver_output (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void deliver_output_no_pan (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t nframes, jack_nframes_t offset);
|
||||
|
||||
virtual uint32_t n_process_buffers () { return 0; }
|
||||
virtual ChanCount n_process_buffers () { return ChanCount::ZERO; }
|
||||
|
||||
virtual void set_gain (gain_t g, void *src);
|
||||
void inc_gain (gain_t delta, void *src);
|
||||
|
|
@ -118,8 +117,10 @@ class IO : public Stateful, public ARDOUR::StateManager
|
|||
virtual gain_t effective_gain () const;
|
||||
|
||||
Panner& panner() { return *_panner; }
|
||||
PeakMeter& peak_meter() { return *_meter; }
|
||||
|
||||
int ensure_io (uint32_t, uint32_t, bool clear, void *src);
|
||||
int ensure_io (const ChanCount& in, const ChanCount& out, bool clear, void *src);
|
||||
|
||||
int use_input_connection (Connection&, void *src);
|
||||
int use_output_connection (Connection&, void *src);
|
||||
|
|
@ -148,6 +149,9 @@ class IO : public Stateful, public ARDOUR::StateManager
|
|||
jack_nframes_t input_latency() const;
|
||||
void set_port_latency (jack_nframes_t);
|
||||
|
||||
const PortSet& inputs() const { return _inputs; }
|
||||
const PortSet& outputs() const { return _outputs; }
|
||||
|
||||
Port *output (uint32_t n) const {
|
||||
if (n < _outputs.num_ports()) {
|
||||
return _outputs.port(n);
|
||||
|
|
@ -169,8 +173,10 @@ class IO : public Stateful, public ARDOUR::StateManager
|
|||
MidiPort* midi_input(uint32_t n) const;
|
||||
MidiPort* midi_output(uint32_t n) const;
|
||||
|
||||
const ChanCount& n_inputs () const { return _inputs.chan_count(); }
|
||||
const ChanCount& n_outputs () const { return _outputs.chan_count(); }
|
||||
const ChanCount& n_inputs () const { return _inputs.count(); }
|
||||
const ChanCount& n_outputs () const { return _outputs.count(); }
|
||||
|
||||
void attach_buffers(ChanCount ignored);
|
||||
|
||||
sigc::signal<void,IOChange,void*> input_changed;
|
||||
sigc::signal<void,IOChange,void*> output_changed;
|
||||
|
|
@ -200,24 +206,13 @@ class IO : public Stateful, public ARDOUR::StateManager
|
|||
static sigc::signal<int> PortsLegal;
|
||||
static sigc::signal<int> PannersLegal;
|
||||
static sigc::signal<int> ConnectingLegal;
|
||||
static sigc::signal<void,ChanCount> MoreOutputs;
|
||||
static sigc::signal<void,ChanCount> MoreChannels;
|
||||
static sigc::signal<int> PortsCreated;
|
||||
|
||||
PBD::Controllable& gain_control() {
|
||||
return _gain_control;
|
||||
}
|
||||
|
||||
/* Peak metering */
|
||||
|
||||
float peak_input_power (uint32_t n) {
|
||||
if (n < std::max (_inputs.chan_count().get(DataType::AUDIO),
|
||||
_outputs.chan_count().get(DataType::AUDIO))) {
|
||||
return _visible_peak_power[n];
|
||||
} else {
|
||||
return minus_infinity();
|
||||
}
|
||||
}
|
||||
|
||||
static void update_meters();
|
||||
|
||||
private:
|
||||
|
|
@ -287,14 +282,14 @@ public:
|
|||
protected:
|
||||
Session& _session;
|
||||
Panner* _panner;
|
||||
BufferSet* _output_buffers; //< Set directly to our output port buffers
|
||||
gain_t _gain;
|
||||
gain_t _effective_gain;
|
||||
gain_t _desired_gain;
|
||||
Glib::Mutex declick_lock;
|
||||
PortSet _outputs;
|
||||
PortSet _inputs;
|
||||
vector<float> _peak_power;
|
||||
vector<float> _visible_peak_power;
|
||||
PeakMeter* _meter;
|
||||
string _name;
|
||||
Connection* _input_connection;
|
||||
Connection* _output_connection;
|
||||
|
|
@ -305,14 +300,10 @@ public:
|
|||
|
||||
virtual void set_deferred_state() {}
|
||||
|
||||
void reset_peak_meters();
|
||||
void reset_panner ();
|
||||
|
||||
virtual uint32_t pans_required() const
|
||||
{ return _inputs.chan_count().get(DataType::AUDIO); }
|
||||
|
||||
static void apply_declick (vector<Sample*>&, uint32_t nbufs, jack_nframes_t nframes,
|
||||
gain_t initial, gain_t target, bool invert_polarity);
|
||||
{ return _inputs.count().get(DataType::AUDIO); }
|
||||
|
||||
struct GainControllable : public PBD::Controllable {
|
||||
GainControllable (IO& i) : io (i) {}
|
||||
|
|
@ -354,8 +345,9 @@ public:
|
|||
static bool connecting_legal;
|
||||
static bool ports_legal;
|
||||
|
||||
private:
|
||||
BufferSet& output_buffers() { return *_output_buffers; }
|
||||
|
||||
private:
|
||||
|
||||
/* are these the best variable names ever, or what? */
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class LadspaPlugin : public ARDOUR::Plugin
|
|||
}
|
||||
void set_block_size (jack_nframes_t nframes) {}
|
||||
|
||||
int connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void store_state (ARDOUR::PluginState&);
|
||||
void restore_state (ARDOUR::PluginState&);
|
||||
string describe_parameter (uint32_t);
|
||||
|
|
|
|||
66
libs/ardour/ardour/meter.h
Normal file
66
libs/ardour/ardour/meter.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#ifndef __ardour_meter_h__
|
||||
#define __ardour_meter_h__
|
||||
|
||||
#include <vector>
|
||||
#include <ardour/types.h>
|
||||
#include <pbd/fastlog.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class BufferSet;
|
||||
class ChanCount;
|
||||
class Session;
|
||||
|
||||
|
||||
/** Meters peaks on the input and stores them for access.
|
||||
*/
|
||||
class PeakMeter {
|
||||
public:
|
||||
PeakMeter(Session& s) : _session(s) {}
|
||||
|
||||
void setup (const ChanCount& in);
|
||||
void reset ();
|
||||
|
||||
/** Compute peaks */
|
||||
void run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset=0);
|
||||
|
||||
float peak_power (uint32_t n) {
|
||||
if (n < _visible_peak_power.size()) {
|
||||
return _visible_peak_power[n];
|
||||
} else {
|
||||
return minus_infinity();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class IO;
|
||||
void meter();
|
||||
|
||||
Session& _session;
|
||||
std::vector<float> _peak_power;
|
||||
std::vector<float> _visible_peak_power;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
#endif // __ardour_meter_h__
|
||||
|
|
@ -52,8 +52,7 @@ class MidiPort : public Port {
|
|||
|
||||
/** Assumes that the port is an output port */
|
||||
void silence (jack_nframes_t nframes, jack_nframes_t offset) {
|
||||
// FIXME: silence starting at offset..
|
||||
_buffer->clear();
|
||||
_buffer->silence(nframes, offset);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public:
|
|||
int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t offset, bool can_record, bool rec_monitors_input);
|
||||
|
||||
void process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
||||
void process_output_buffers (BufferSet& bufs,
|
||||
jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick,
|
||||
bool meter);
|
||||
|
|
@ -64,7 +64,7 @@ public:
|
|||
|
||||
void set_latency_delay (jack_nframes_t);
|
||||
|
||||
int export_stuff (vector<unsigned char*>& buffers, uint32_t nbufs,
|
||||
int export_stuff (BufferSet& bufs,
|
||||
jack_nframes_t nframes, jack_nframes_t end_frame);
|
||||
|
||||
void freeze (InterThreadInfo&);
|
||||
|
|
@ -84,7 +84,7 @@ protected:
|
|||
jack_nframes_t nframes, jack_nframes_t offset, int declick,
|
||||
bool meter);
|
||||
|
||||
uint32_t n_process_buffers ();
|
||||
ChanCount n_process_buffers ();
|
||||
|
||||
private:
|
||||
int set_diskstream (MidiDiskstream&);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ namespace ARDOUR {
|
|||
|
||||
class Session;
|
||||
class Panner;
|
||||
class BufferSet;
|
||||
class AudioBuffer;
|
||||
|
||||
class StreamPanner : public sigc::trackable, public Stateful
|
||||
{
|
||||
|
|
@ -62,10 +64,10 @@ class StreamPanner : public sigc::trackable, public Stateful
|
|||
void get_effective_position (float& xpos, float& ypos) const { xpos = effective_x; ypos = effective_y; }
|
||||
void get_effective_position (float& xpos, float& ypos, float& zpos) const { xpos = effective_x; ypos = effective_y; zpos = effective_z; }
|
||||
|
||||
/* the basic panner API */
|
||||
/* the basic StreamPanner API */
|
||||
|
||||
virtual void distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_nframes_t nframes) = 0;
|
||||
virtual void distribute_automated (Sample* src, Sample** obufs,
|
||||
virtual void distribute (AudioBuffer& src, BufferSet& obufs, gain_t gain_coeff, jack_nframes_t nframes) = 0;
|
||||
virtual void distribute_automated (AudioBuffer& src, BufferSet& obufs,
|
||||
jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes, pan_t** buffers) = 0;
|
||||
|
||||
/* automation */
|
||||
|
|
@ -141,7 +143,7 @@ class BaseStereoPanner : public StreamPanner
|
|||
and a type name. See EqualPowerStereoPanner as an example.
|
||||
*/
|
||||
|
||||
void distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_nframes_t nframes);
|
||||
void distribute (AudioBuffer& src, BufferSet& obufs, gain_t gain_coeff, jack_nframes_t nframes);
|
||||
|
||||
int load (istream&, string path, uint32_t&);
|
||||
int save (ostream&) const;
|
||||
|
|
@ -169,7 +171,7 @@ class EqualPowerStereoPanner : public BaseStereoPanner
|
|||
EqualPowerStereoPanner (Panner&);
|
||||
~EqualPowerStereoPanner ();
|
||||
|
||||
void distribute_automated (Sample* src, Sample** obufs,
|
||||
void distribute_automated (AudioBuffer& src, BufferSet& obufs,
|
||||
jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes, pan_t** buffers);
|
||||
|
||||
void get_current_coefficients (pan_t*) const;
|
||||
|
|
@ -203,8 +205,8 @@ class Multi2dPanner : public StreamPanner
|
|||
|
||||
Curve& automation() { return _automation; }
|
||||
|
||||
void distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_nframes_t nframes);
|
||||
void distribute_automated (Sample* src, Sample** obufs,
|
||||
void distribute (AudioBuffer& src, BufferSet& obufs, gain_t gain_coeff, jack_nframes_t nframes);
|
||||
void distribute_automated (AudioBuffer& src, BufferSet& obufs,
|
||||
jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes, pan_t** buffers);
|
||||
|
||||
int load (istream&, string path, uint32_t&);
|
||||
|
|
@ -239,6 +241,14 @@ class Panner : public std::vector<StreamPanner*>, public Stateful, public sigc::
|
|||
Panner (string name, Session&);
|
||||
virtual ~Panner ();
|
||||
|
||||
// FIXME: unify these two
|
||||
|
||||
/// The fundamental Panner function
|
||||
void distribute (BufferSet& src, BufferSet& dest, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff);
|
||||
|
||||
/// The other fundamental Panner function
|
||||
void distribute_automated (BufferSet& src, BufferSet& dest, jack_nframes_t start_frame, jack_nframes_t end_frames, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
|
||||
void set_name (string);
|
||||
|
||||
bool bypassed() const { return _bypassed; }
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ namespace ARDOUR {
|
|||
|
||||
class AudioEngine;
|
||||
class Session;
|
||||
class BufferSet;
|
||||
|
||||
class Plugin;
|
||||
|
||||
|
|
@ -120,7 +121,7 @@ class Plugin : public Stateful, public sigc::trackable
|
|||
virtual void deactivate () = 0;
|
||||
virtual void set_block_size (jack_nframes_t nframes) = 0;
|
||||
|
||||
virtual int connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset) = 0;
|
||||
virtual int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, jack_nframes_t nframes, jack_nframes_t offset) = 0;
|
||||
virtual std::set<uint32_t> automatable() const = 0;
|
||||
virtual void store_state (ARDOUR::PluginState&) = 0;
|
||||
virtual void restore_state (ARDOUR::PluginState&) = 0;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class Port : public sigc::trackable {
|
|||
virtual void silence (jack_nframes_t nframes, jack_nframes_t offset) = 0;
|
||||
|
||||
|
||||
std::string name() {
|
||||
std::string name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,11 @@ public:
|
|||
|
||||
void add_port(Port* port);
|
||||
|
||||
/** nth port */
|
||||
Port* port(size_t index) const;
|
||||
|
||||
Port* nth_port_of_type(DataType type, size_t n) const;
|
||||
/** nth port of type @a t, or nth port if t = NIL */
|
||||
Port* port(DataType t, size_t index) const;
|
||||
|
||||
AudioPort* nth_audio_port(size_t n) const;
|
||||
|
||||
|
|
@ -58,19 +60,19 @@ public:
|
|||
*/
|
||||
void clear() { _ports.clear(); }
|
||||
|
||||
const ChanCount& chan_count() const { return _chan_count; }
|
||||
const ChanCount& count() const { return _count; }
|
||||
|
||||
bool empty() const { return (_chan_count.get_total() == 0); }
|
||||
bool empty() const { return (_count.get_total() == 0); }
|
||||
|
||||
// ITERATORS
|
||||
|
||||
// obviously these iterators will need to get more clever
|
||||
// experimental phase, it's the interface that counts right now
|
||||
// FIXME: this is a filthy copy-and-paste mess
|
||||
|
||||
class iterator {
|
||||
public:
|
||||
|
||||
Port* operator*() { return _list.port(_index); }
|
||||
Port& operator*() { return *_set.port(_type, _index); }
|
||||
Port* operator->() { return _set.port(_type, _index); }
|
||||
iterator& operator++() { ++_index; return *this; } // yes, prefix only
|
||||
bool operator==(const iterator& other) { return (_index == other._index); }
|
||||
bool operator!=(const iterator& other) { return (_index != other._index); }
|
||||
|
|
@ -78,19 +80,29 @@ public:
|
|||
private:
|
||||
friend class PortSet;
|
||||
|
||||
iterator(PortSet& list, size_t index) : _list(list), _index(index) {}
|
||||
iterator(PortSet& list, DataType type, size_t index)
|
||||
: _set(list), _type(type), _index(index) {}
|
||||
|
||||
PortSet& _list;
|
||||
PortSet& _set;
|
||||
DataType _type; ///< Ignored if NIL (to iterator over entire set)
|
||||
size_t _index;
|
||||
};
|
||||
|
||||
iterator begin() { return iterator(*this, 0); }
|
||||
iterator end() { return iterator(*this, _chan_count.get_total()); }
|
||||
iterator begin(DataType type = DataType::NIL)
|
||||
{ return iterator(*this, type, 0); }
|
||||
|
||||
iterator end(DataType type = DataType::NIL)
|
||||
{
|
||||
return iterator(*this, type,
|
||||
(type == DataType::NIL) ? _count.get_total() : _count.get(type));
|
||||
}
|
||||
|
||||
// FIXME: typeify
|
||||
class const_iterator {
|
||||
public:
|
||||
|
||||
const Port* operator*() { return _list.port(_index); }
|
||||
const Port& operator*() { return *_set.port(_index); }
|
||||
const Port* operator->() { return _set.port(_index); }
|
||||
const_iterator& operator++() { ++_index; return *this; } // yes, prefix only
|
||||
bool operator==(const const_iterator& other) { return (_index == other._index); }
|
||||
bool operator!=(const const_iterator& other) { return (_index != other._index); }
|
||||
|
|
@ -98,21 +110,21 @@ public:
|
|||
private:
|
||||
friend class PortSet;
|
||||
|
||||
const_iterator(const PortSet& list, size_t index) : _list(list), _index(index) {}
|
||||
const_iterator(const PortSet& list, size_t index) : _set(list), _index(index) {}
|
||||
|
||||
const PortSet& _list;
|
||||
const PortSet& _set;
|
||||
size_t _index;
|
||||
};
|
||||
|
||||
const_iterator begin() const { return const_iterator(*this, 0); }
|
||||
const_iterator end() const { return const_iterator(*this, _chan_count.get_total()); }
|
||||
|
||||
const_iterator end() const { return const_iterator(*this, _count.get_total()); }
|
||||
|
||||
|
||||
class audio_iterator {
|
||||
public:
|
||||
|
||||
AudioPort* operator*() { return _list.nth_audio_port(_index); }
|
||||
AudioPort& operator*() { return *_set.nth_audio_port(_index); }
|
||||
AudioPort* operator->() { return _set.nth_audio_port(_index); }
|
||||
audio_iterator& operator++() { ++_index; return *this; } // yes, prefix only
|
||||
bool operator==(const audio_iterator& other) { return (_index == other._index); }
|
||||
bool operator!=(const audio_iterator& other) { return (_index != other._index); }
|
||||
|
|
@ -120,14 +132,14 @@ public:
|
|||
private:
|
||||
friend class PortSet;
|
||||
|
||||
audio_iterator(PortSet& list, size_t index) : _list(list), _index(index) {}
|
||||
audio_iterator(PortSet& list, size_t index) : _set(list), _index(index) {}
|
||||
|
||||
PortSet& _list;
|
||||
PortSet& _set;
|
||||
size_t _index;
|
||||
};
|
||||
|
||||
audio_iterator audio_begin() { return audio_iterator(*this, 0); }
|
||||
audio_iterator audio_end() { return audio_iterator(*this, _chan_count.get(DataType::AUDIO)); }
|
||||
audio_iterator audio_end() { return audio_iterator(*this, _count.get(DataType::AUDIO)); }
|
||||
|
||||
|
||||
|
||||
|
|
@ -142,7 +154,7 @@ private:
|
|||
// Vector of vectors, indexed by DataType::to_index()
|
||||
std::vector<PortVec> _ports;
|
||||
|
||||
ChanCount _chan_count;
|
||||
ChanCount _count;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ class Redirect : public IO
|
|||
bool active () const { return _active; }
|
||||
void set_active (bool yn, void *src);
|
||||
|
||||
virtual uint32_t output_streams() const { return n_outputs().get(_default_type); }
|
||||
virtual uint32_t input_streams () const { return n_inputs().get(_default_type); }
|
||||
virtual uint32_t natural_output_streams() const { return n_outputs().get(_default_type); }
|
||||
virtual uint32_t natural_input_streams () const { return n_inputs().get(_default_type); }
|
||||
virtual ChanCount output_streams() const { return n_outputs(); }
|
||||
virtual ChanCount input_streams () const { return n_inputs(); }
|
||||
virtual ChanCount natural_output_streams() const { return n_outputs(); }
|
||||
virtual ChanCount natural_input_streams () const { return n_inputs(); }
|
||||
|
||||
uint32_t sort_key() const { return _sort_key; }
|
||||
void set_sort_key (uint32_t key);
|
||||
|
|
@ -81,7 +81,7 @@ class Redirect : public IO
|
|||
Placement placement() const { return _placement; }
|
||||
void set_placement (Placement, void *src);
|
||||
|
||||
virtual void run (vector<Sample *>& ibufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset) = 0;
|
||||
virtual void run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset) = 0;
|
||||
virtual void activate () = 0;
|
||||
virtual void deactivate () = 0;
|
||||
virtual jack_nframes_t latency() { return 0; }
|
||||
|
|
|
|||
|
|
@ -161,8 +161,11 @@ class Route : public IO
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t max_redirect_outs () const { return redirect_max_outs; }
|
||||
ChanCount max_redirect_outs () const { return redirect_max_outs; }
|
||||
|
||||
// FIXME: remove/replace err_streams parameters with something appropriate
|
||||
// they are used by 'wierd_plugin_dialog'(sic) to display the number of input streams
|
||||
// at the insertion point if the insert fails
|
||||
int add_redirect (boost::shared_ptr<Redirect>, void *src, uint32_t* err_streams = 0);
|
||||
int add_redirects (const RedirectList&, void *src, uint32_t* err_streams = 0);
|
||||
int remove_redirect (boost::shared_ptr<Redirect>, void *src, uint32_t* err_streams = 0);
|
||||
|
|
@ -304,7 +307,7 @@ class Route : public IO
|
|||
void passthru (jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter_inputs);
|
||||
|
||||
virtual void process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
||||
virtual void process_output_buffers (BufferSet& bufs,
|
||||
jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick,
|
||||
bool meter);
|
||||
|
|
@ -318,11 +321,11 @@ class Route : public IO
|
|||
sigc::connection input_signal_connection;
|
||||
|
||||
state_id_t _current_state_id;
|
||||
uint32_t redirect_max_outs;
|
||||
ChanCount redirect_max_outs;
|
||||
uint32_t _remote_control_id;
|
||||
|
||||
uint32_t pans_required() const;
|
||||
uint32_t n_process_buffers ();
|
||||
ChanCount n_process_buffers ();
|
||||
|
||||
private:
|
||||
void init ();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class Send : public Redirect {
|
|||
Send (const Send&);
|
||||
~Send ();
|
||||
|
||||
void run (vector<Sample *> &bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset);
|
||||
void activate() {}
|
||||
void deactivate () {}
|
||||
|
||||
|
|
@ -50,12 +50,12 @@ class Send : public Redirect {
|
|||
XMLNode& get_state(void);
|
||||
int set_state(const XMLNode& node);
|
||||
|
||||
uint32_t pans_required() const { return expected_inputs; }
|
||||
void expect_inputs (uint32_t);
|
||||
uint32_t pans_required() const { return _expected_inputs.get(DataType::AUDIO); }
|
||||
void expect_inputs (const ChanCount&);
|
||||
|
||||
private:
|
||||
bool _metering;
|
||||
uint32_t expected_inputs;
|
||||
ChanCount _expected_inputs;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ class Route;
|
|||
class AuxInput;
|
||||
class Source;
|
||||
class AudioSource;
|
||||
class BufferSet;
|
||||
|
||||
class Diskstream;
|
||||
class AudioDiskstream;
|
||||
|
|
@ -280,9 +281,9 @@ class Session : public sigc::trackable, public Stateful
|
|||
|
||||
void process (jack_nframes_t nframes);
|
||||
|
||||
vector<Sample*>& get_passthru_buffers() { return _passthru_buffers; }
|
||||
vector<Sample*>& get_silent_buffers (uint32_t howmany);
|
||||
vector<Sample*>& get_send_buffers () { return _send_buffers; }
|
||||
BufferSet& get_silent_buffers (ChanCount count = ChanCount::ZERO);
|
||||
BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO);
|
||||
BufferSet& get_send_buffers (ChanCount count = ChanCount::ZERO);
|
||||
|
||||
Diskstream *diskstream_by_id (const PBD::ID& id);
|
||||
Diskstream *diskstream_by_name (string name);
|
||||
|
|
@ -1072,9 +1073,9 @@ class Session : public sigc::trackable, public Stateful
|
|||
jack_nframes_t _last_slave_transport_frame;
|
||||
jack_nframes_t maximum_output_latency;
|
||||
jack_nframes_t last_stop_frame;
|
||||
vector<Sample *> _passthru_buffers;
|
||||
vector<Sample *> _silent_buffers;
|
||||
vector<Sample *> _send_buffers;
|
||||
BufferSet* _scratch_buffers;
|
||||
BufferSet* _silent_buffers;
|
||||
BufferSet* _send_buffers;
|
||||
jack_nframes_t current_block_size;
|
||||
jack_nframes_t _worst_output_latency;
|
||||
jack_nframes_t _worst_input_latency;
|
||||
|
|
@ -1091,7 +1092,7 @@ class Session : public sigc::trackable, public Stateful
|
|||
|
||||
void update_latency_compensation_proxy (void* ignored);
|
||||
|
||||
void ensure_passthru_buffers (ChanCount howmany);
|
||||
void ensure_buffers (ChanCount howmany);
|
||||
|
||||
void process_scrub (jack_nframes_t);
|
||||
void process_without_events (jack_nframes_t);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class Track : public Route
|
|||
virtual void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) = 0;
|
||||
|
||||
virtual uint32_t n_process_buffers () = 0;
|
||||
virtual ChanCount n_process_buffers () = 0;
|
||||
|
||||
Diskstream *_diskstream;
|
||||
MeterPoint _saved_meter_point;
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ AudioDiskstream::init (Diskstream::Flag f)
|
|||
allocate_temporary_buffers ();
|
||||
|
||||
add_channel ();
|
||||
assert(_n_channels == 1);
|
||||
assert(_n_channels == ChanCount(DataType::AUDIO, 1));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -212,7 +212,7 @@ AudioDiskstream::non_realtime_input_change ()
|
|||
|
||||
if (input_change_pending & ConfigurationChanged) {
|
||||
|
||||
if (_io->n_inputs().get(DataType::AUDIO) > _n_channels) {
|
||||
if (_io->n_inputs().get(DataType::AUDIO) > _n_channels.get(DataType::AUDIO)) {
|
||||
|
||||
// we need to add new channel infos
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ AudioDiskstream::non_realtime_input_change ()
|
|||
add_channel ();
|
||||
}
|
||||
|
||||
} else if (_io->n_inputs().get(DataType::AUDIO) < _n_channels) {
|
||||
} else if (_io->n_inputs().get(DataType::AUDIO) < _n_channels.get(DataType::AUDIO)) {
|
||||
|
||||
// we need to get rid of channels
|
||||
|
||||
|
|
@ -1866,7 +1866,7 @@ AudioDiskstream::set_state (const XMLNode& node)
|
|||
// create necessary extra channels
|
||||
// we are always constructed with one and we always need one
|
||||
|
||||
if (nchans > _n_channels) {
|
||||
if (nchans > _n_channels.get(DataType::AUDIO)) {
|
||||
|
||||
// we need to add new channel infos
|
||||
//LockMonitor lm (state_lock, __LINE__, __FILE__);
|
||||
|
|
@ -1877,7 +1877,7 @@ AudioDiskstream::set_state (const XMLNode& node)
|
|||
add_channel ();
|
||||
}
|
||||
|
||||
} else if (nchans < _n_channels) {
|
||||
} else if (nchans < _n_channels.get(DataType::AUDIO)) {
|
||||
|
||||
// we need to get rid of channels
|
||||
//LockMonitor lm (state_lock, __LINE__, __FILE__);
|
||||
|
|
@ -1922,7 +1922,7 @@ AudioDiskstream::set_state (const XMLNode& node)
|
|||
}
|
||||
}
|
||||
|
||||
_n_channels = channels.size();
|
||||
_n_channels.set(DataType::AUDIO, channels.size());
|
||||
|
||||
in_set_state = false;
|
||||
|
||||
|
|
@ -2134,7 +2134,7 @@ AudioDiskstream::add_channel ()
|
|||
|
||||
channels.push_back (chan);
|
||||
|
||||
_n_channels = channels.size();
|
||||
_n_channels.set(DataType::AUDIO, channels.size());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2148,7 +2148,7 @@ AudioDiskstream::remove_channel ()
|
|||
destroy_channel (chan);
|
||||
channels.pop_back();
|
||||
|
||||
_n_channels = channels.size();
|
||||
_n_channels.set(DataType::AUDIO, channels.size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2224,7 +2224,7 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (pending_sources.size() != _n_channels) {
|
||||
if (pending_sources.size() != _n_channels.get(DataType::AUDIO)) {
|
||||
error << string_compose (_("%1: incorrect number of pending sources listed - ignoring them all"), _name)
|
||||
<< endmsg;
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ AudioPort::reset()
|
|||
{
|
||||
Port::reset();
|
||||
if (_flags & JackPortIsOutput) {
|
||||
if (_buffer.capacity() > 0) {
|
||||
_buffer.clear();
|
||||
}
|
||||
_silent = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include <ardour/audioplaylist.h>
|
||||
#include <ardour/panner.h>
|
||||
#include <ardour/utils.h>
|
||||
|
||||
#include <ardour/buffer_set.h>
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -400,17 +400,16 @@ AudioTrack::set_state_part_two ()
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ChanCount
|
||||
AudioTrack::n_process_buffers ()
|
||||
{
|
||||
return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
|
||||
return max (_diskstream->n_channels(), redirect_max_outs);
|
||||
}
|
||||
|
||||
void
|
||||
AudioTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter)
|
||||
{
|
||||
uint32_t nbufs = n_process_buffers ();
|
||||
process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
|
||||
process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, offset, true, declick, meter);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -568,16 +567,15 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
|
|||
|
||||
/* copy the diskstream data to all output buffers */
|
||||
|
||||
vector<Sample*>& bufs = _session.get_passthru_buffers ();
|
||||
uint32_t limit = n_process_buffers ();
|
||||
const size_t limit = n_process_buffers().get(DataType::AUDIO);
|
||||
BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
|
||||
|
||||
uint32_t n;
|
||||
uint32_t i;
|
||||
|
||||
|
||||
for (i = 0, n = 1; i < limit; ++i, ++n) {
|
||||
memcpy (bufs[i], b, sizeof (Sample) * nframes);
|
||||
if (n < diskstream.n_channels()) {
|
||||
memcpy (bufs.get_audio(i).data(nframes), b, sizeof (Sample) * nframes);
|
||||
if (n < diskstream.n_channels().get(DataType::AUDIO)) {
|
||||
tmpb = diskstream.playback_buffer(n);
|
||||
if (tmpb!=0) {
|
||||
b = tmpb;
|
||||
|
|
@ -595,7 +593,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
|
|||
}
|
||||
}
|
||||
|
||||
process_output_buffers (bufs, limit, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
|
||||
process_output_buffers (bufs, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
|
||||
|
||||
} else {
|
||||
/* problem with the diskstream; just be quiet for a bit */
|
||||
|
|
@ -627,7 +625,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac
|
|||
}
|
||||
|
||||
int
|
||||
AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
|
||||
AudioTrack::export_stuff (BufferSet& buffers, jack_nframes_t start, jack_nframes_t nframes)
|
||||
{
|
||||
gain_t gain_automation[nframes];
|
||||
gain_t gain_buffer[nframes];
|
||||
|
|
@ -635,8 +633,6 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
|
|||
RedirectList::iterator i;
|
||||
bool post_fader_work = false;
|
||||
gain_t this_gain = _gain;
|
||||
vector<Sample*>::iterator bi;
|
||||
Sample * b;
|
||||
AudioDiskstream& diskstream = audio_diskstream();
|
||||
|
||||
Glib::RWLock::ReaderLock rlock (redirect_lock);
|
||||
|
|
@ -645,24 +641,26 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
|
|||
AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream.playlist());
|
||||
assert(apl);
|
||||
|
||||
if (apl->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) {
|
||||
if (apl->read (buffers.get_audio(nframes).data(nframes),
|
||||
mix_buffer, gain_buffer, start, nframes) != nframes) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(buffers.count().get(DataType::AUDIO) >= 1);
|
||||
uint32_t n=1;
|
||||
bi = buffers.begin();
|
||||
b = buffers[0];
|
||||
Sample* b = buffers.get_audio(0).data(nframes);
|
||||
BufferSet::audio_iterator bi = buffers.audio_begin();
|
||||
++bi;
|
||||
for (; bi != buffers.end(); ++bi, ++n) {
|
||||
if (n < diskstream.n_channels()) {
|
||||
if (apl->read ((*bi), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
|
||||
for ( ; bi != buffers.audio_end(); ++bi, ++n) {
|
||||
if (n < diskstream.n_channels().get(DataType::AUDIO)) {
|
||||
if (apl->read (bi->data(nframes), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
|
||||
return -1;
|
||||
}
|
||||
b = (*bi);
|
||||
b = bi->data(nframes);
|
||||
}
|
||||
else {
|
||||
/* duplicate last across remaining buffers */
|
||||
memcpy ((*bi), b, sizeof (Sample) * nframes);
|
||||
memcpy (bi->data(nframes), b, sizeof (Sample) * nframes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -677,7 +675,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
|
|||
if ((insert = boost::dynamic_pointer_cast<Insert>(*i)) != 0) {
|
||||
switch (insert->placement()) {
|
||||
case PreFader:
|
||||
insert->run (buffers, nbufs, nframes, 0);
|
||||
insert->run (buffers, nframes, 0);
|
||||
break;
|
||||
case PostFader:
|
||||
post_fader_work = true;
|
||||
|
|
@ -690,8 +688,8 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
|
|||
|
||||
_gain_automation_curve.get_vector (start, start + nframes, gain_automation, nframes);
|
||||
|
||||
for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
|
||||
Sample *b = *bi;
|
||||
for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
|
||||
Sample *b = bi->data(nframes);
|
||||
for (jack_nframes_t n = 0; n < nframes; ++n) {
|
||||
b[n] *= gain_automation[n];
|
||||
}
|
||||
|
|
@ -699,8 +697,8 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
|
|||
|
||||
} else {
|
||||
|
||||
for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
|
||||
Sample *b = *bi;
|
||||
for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
|
||||
Sample *b = bi->data(nframes);
|
||||
for (jack_nframes_t n = 0; n < nframes; ++n) {
|
||||
b[n] *= this_gain;
|
||||
}
|
||||
|
|
@ -717,7 +715,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
|
|||
case PreFader:
|
||||
break;
|
||||
case PostFader:
|
||||
insert->run (buffers, nbufs, nframes, 0);
|
||||
insert->run (buffers, nframes, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ AudioEngine::register_output_port (DataType type, const string& portname)
|
|||
|
||||
|
||||
int
|
||||
AudioEngine::unregister_port (Port *port)
|
||||
AudioEngine::unregister_port (Port& port)
|
||||
{
|
||||
if (!_running) {
|
||||
/* probably happening when the engine has been halted by JACK,
|
||||
|
|
@ -481,14 +481,12 @@ AudioEngine::unregister_port (Port *port)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (port) {
|
||||
|
||||
int ret = jack_port_unregister (_jack, port->_port);
|
||||
int ret = jack_port_unregister (_jack, port._port);
|
||||
|
||||
if (ret == 0) {
|
||||
|
||||
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
|
||||
if ((*i) == port) {
|
||||
if (*i == &port) {
|
||||
ports.erase (i);
|
||||
break;
|
||||
}
|
||||
|
|
@ -499,9 +497,6 @@ AudioEngine::unregister_port (Port *port)
|
|||
|
||||
return ret;
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -563,7 +558,7 @@ AudioEngine::disconnect (const string& source, const string& destination)
|
|||
}
|
||||
|
||||
int
|
||||
AudioEngine::disconnect (Port *port)
|
||||
AudioEngine::disconnect (Port& port)
|
||||
{
|
||||
if (!_running) {
|
||||
if (!_has_run) {
|
||||
|
|
@ -574,7 +569,7 @@ AudioEngine::disconnect (Port *port)
|
|||
}
|
||||
}
|
||||
|
||||
int ret = jack_port_disconnect (_jack, port->_port);
|
||||
int ret = jack_port_disconnect (_jack, port._port);
|
||||
|
||||
if (ret == 0) {
|
||||
remove_connections_for (port);
|
||||
|
|
@ -851,7 +846,7 @@ AudioEngine::remove_all_ports ()
|
|||
}
|
||||
|
||||
void
|
||||
AudioEngine::remove_connections_for (Port* port)
|
||||
AudioEngine::remove_connections_for (Port& port)
|
||||
{
|
||||
for (PortConnections::iterator i = port_connections.begin(); i != port_connections.end(); ) {
|
||||
PortConnections::iterator tmp;
|
||||
|
|
@ -859,7 +854,7 @@ AudioEngine::remove_connections_for (Port* port)
|
|||
tmp = i;
|
||||
++tmp;
|
||||
|
||||
if ((*i).first == port->name()) {
|
||||
if ((*i).first == port.name()) {
|
||||
port_connections.erase (i);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ Auditioner::Auditioner (Session& s)
|
|||
|
||||
allow_pan_reset ();
|
||||
|
||||
reset_panner ();
|
||||
|
||||
IO::output_changed.connect (mem_fun (*this, &Auditioner::output_changed));
|
||||
|
||||
the_region = 0;
|
||||
|
|
@ -93,7 +95,7 @@ Auditioner::audition_current_playlist ()
|
|||
|
||||
/* force a panner reset now that we have all channels */
|
||||
|
||||
_panner->reset (n_outputs().get(DataType::AUDIO), _diskstream->n_channels());
|
||||
_panner->reset (n_outputs().get(DataType::AUDIO), _diskstream->n_channels().get(DataType::AUDIO));
|
||||
|
||||
g_atomic_int_set (&_active, 1);
|
||||
}
|
||||
|
|
@ -116,17 +118,17 @@ Auditioner::audition_region (AudioRegion& region)
|
|||
_diskstream->playlist()->clear (true, false);
|
||||
_diskstream->playlist()->add_region (*the_region, 0, 1, false);
|
||||
|
||||
while (_diskstream->n_channels() < the_region->n_channels()) {
|
||||
while (_diskstream->n_channels().get(DataType::AUDIO) < the_region->n_channels()) {
|
||||
audio_diskstream().add_channel ();
|
||||
}
|
||||
|
||||
while (_diskstream->n_channels() > the_region->n_channels()) {
|
||||
while (_diskstream->n_channels().get(DataType::AUDIO) > the_region->n_channels()) {
|
||||
audio_diskstream().remove_channel ();
|
||||
}
|
||||
|
||||
/* force a panner reset now that we have all channels */
|
||||
|
||||
_panner->reset (n_outputs().get(DataType::AUDIO), _diskstream->n_channels());
|
||||
reset_panner();
|
||||
|
||||
length = the_region->length();
|
||||
_diskstream->seek (0);
|
||||
|
|
|
|||
|
|
@ -83,11 +83,14 @@ MidiBuffer::~MidiBuffer()
|
|||
free(_data);
|
||||
}
|
||||
|
||||
|
||||
/** Note that offset and nframes refer to sample time, not actual buffer locations */
|
||||
void
|
||||
MidiBuffer::write(const Buffer& src, jack_nframes_t offset, jack_nframes_t nframes)
|
||||
MidiBuffer::read_from(const Buffer& src, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
assert(src.type() == DataType::MIDI);
|
||||
// FIXME: offsets? param semantics?
|
||||
throw;
|
||||
assert(src.type() == _type == DataType::MIDI);
|
||||
assert(offset == 0);
|
||||
MidiBuffer& msrc = (MidiBuffer&)src;
|
||||
_size = 0;
|
||||
|
|
|
|||
|
|
@ -18,26 +18,12 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/buffer.h>
|
||||
#include <ardour/port.h>
|
||||
#include <ardour/port_set.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
|
||||
/** Create a BufferSet to mirror a PortSet */
|
||||
BufferSet::BufferSet(const PortSet& ports)
|
||||
: _count(ports.chan_count())
|
||||
, _is_mirror(true)
|
||||
{
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
BufferVec v;
|
||||
|
||||
for (size_t j=0; j < ports.num_ports(*t); ++j) {
|
||||
v.push_back(&ports.nth_port_of_type(*t, j)->get_buffer());
|
||||
}
|
||||
|
||||
_buffers.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
/** Create a new, empty BufferSet */
|
||||
BufferSet::BufferSet()
|
||||
: _is_mirror(false)
|
||||
|
|
@ -46,36 +32,60 @@ BufferSet::BufferSet()
|
|||
_buffers.push_back( BufferVec() );
|
||||
|
||||
_count.reset();
|
||||
_available.reset();
|
||||
}
|
||||
|
||||
|
||||
BufferSet::~BufferSet()
|
||||
{
|
||||
if (!_is_mirror)
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
/** Destroy all contained buffers.
|
||||
*/
|
||||
void
|
||||
BufferSet::clear()
|
||||
{
|
||||
if (!_is_mirror) {
|
||||
for (std::vector<BufferVec>::iterator i = _buffers.begin(); i != _buffers.end(); ++i) {
|
||||
for (BufferVec::iterator j = (*i).begin(); j != (*i).end(); ++j) {
|
||||
delete *j;
|
||||
}
|
||||
(*i).clear();
|
||||
}
|
||||
}
|
||||
_buffers.clear();
|
||||
_count.reset();
|
||||
_available.reset();
|
||||
}
|
||||
|
||||
/** Make this BufferSet a direct mirror of a PortSet's buffers.
|
||||
*/
|
||||
void
|
||||
BufferSet::attach_buffers(PortSet& ports)
|
||||
{
|
||||
clear();
|
||||
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
_buffers.push_back(BufferVec());
|
||||
BufferVec& v = _buffers[(*t).to_index()];
|
||||
|
||||
for (PortSet::iterator p = ports.begin(*t); p != ports.end(*t); ++p) {
|
||||
assert(p->type() == *t);
|
||||
v.push_back(&(p->get_buffer()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_count = ports.count();
|
||||
|
||||
_is_mirror = true;
|
||||
}
|
||||
|
||||
void
|
||||
BufferSet::ensure_buffers(const ChanCount& chan_count, size_t buffer_capacity)
|
||||
BufferSet::ensure_buffers(const ChanCount& count, size_t buffer_capacity)
|
||||
{
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
ensure_buffers(chan_count.get(*t), *t, buffer_capacity);
|
||||
ensure_buffers(*t, count.get(*t), buffer_capacity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +94,7 @@ BufferSet::ensure_buffers(const ChanCount& chan_count, size_t buffer_capacity)
|
|||
* each of size at least @a buffer_size
|
||||
*/
|
||||
void
|
||||
BufferSet::ensure_buffers(size_t num_buffers, DataType type, size_t buffer_capacity)
|
||||
BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capacity)
|
||||
{
|
||||
assert(type != DataType::NIL);
|
||||
assert(type.to_index() < _buffers.size());
|
||||
|
|
@ -95,6 +105,13 @@ BufferSet::ensure_buffers(size_t num_buffers, DataType type, size_t buffer_capac
|
|||
// The vector of buffers of the type we care about
|
||||
BufferVec& bufs = _buffers[type.to_index()];
|
||||
|
||||
// If we're a mirror just make sure we're ok
|
||||
if (_is_mirror) {
|
||||
assert(_count.get(type) >= num_buffers);
|
||||
assert(bufs[0]->type() == type);
|
||||
return;
|
||||
}
|
||||
|
||||
// If there's not enough or they're too small, just nuke the whole thing and
|
||||
// rebuild it (so I'm lazy..)
|
||||
if (bufs.size() < num_buffers
|
||||
|
|
@ -110,21 +127,17 @@ BufferSet::ensure_buffers(size_t num_buffers, DataType type, size_t buffer_capac
|
|||
for (size_t i=0; i < num_buffers; ++i) {
|
||||
bufs.push_back(Buffer::create(type, buffer_capacity));
|
||||
}
|
||||
|
||||
_available.set(type, num_buffers);
|
||||
}
|
||||
|
||||
// Post-conditions
|
||||
assert(bufs[0]->type() == type);
|
||||
assert(bufs.size() >= num_buffers);
|
||||
assert((bufs[0])->type() == type);
|
||||
assert(bufs.size() == _available.get(type));
|
||||
assert(bufs[0]->capacity() >= buffer_capacity);
|
||||
}
|
||||
|
||||
size_t
|
||||
BufferSet::available_buffers(DataType type) const
|
||||
{
|
||||
return _buffers[type.to_symbol()-1].size();
|
||||
}
|
||||
|
||||
|
||||
/** Get the capacity (size) of the available buffers of the given type.
|
||||
*
|
||||
* All buffers of a certain type always have the same capacity.
|
||||
|
|
@ -132,7 +145,7 @@ BufferSet::available_buffers(DataType type) const
|
|||
size_t
|
||||
BufferSet::buffer_capacity(DataType type) const
|
||||
{
|
||||
assert(available_buffers(type) > 0);
|
||||
assert(_available.get(type) > 0);
|
||||
return _buffers[type.to_index()][0]->capacity();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ Curve::~Curve ()
|
|||
void
|
||||
Curve::solve ()
|
||||
{
|
||||
uint32_t npoints;
|
||||
size_t npoints;
|
||||
|
||||
if (!_dirty) {
|
||||
return;
|
||||
|
|
@ -83,7 +83,7 @@ Curve::solve ()
|
|||
|
||||
double x[npoints];
|
||||
double y[npoints];
|
||||
uint32_t i;
|
||||
size_t i;
|
||||
AutomationEventList::iterator xx;
|
||||
|
||||
for (i = 0, xx = events.begin(); xx != events.end(); ++xx, ++i) {
|
||||
|
|
@ -202,7 +202,7 @@ Curve::solve ()
|
|||
}
|
||||
|
||||
bool
|
||||
Curve::rt_safe_get_vector (double x0, double x1, float *vec, int32_t veclen)
|
||||
Curve::rt_safe_get_vector (double x0, double x1, float *vec, size_t veclen)
|
||||
{
|
||||
Glib::Mutex::Lock lm (lock, Glib::TRY_LOCK);
|
||||
|
||||
|
|
@ -215,19 +215,19 @@ Curve::rt_safe_get_vector (double x0, double x1, float *vec, int32_t veclen)
|
|||
}
|
||||
|
||||
void
|
||||
Curve::get_vector (double x0, double x1, float *vec, int32_t veclen)
|
||||
Curve::get_vector (double x0, double x1, float *vec, size_t veclen)
|
||||
{
|
||||
Glib::Mutex::Lock lm (lock);
|
||||
_get_vector (x0, x1, vec, veclen);
|
||||
}
|
||||
|
||||
void
|
||||
Curve::_get_vector (double x0, double x1, float *vec, int32_t veclen)
|
||||
Curve::_get_vector (double x0, double x1, float *vec, size_t veclen)
|
||||
{
|
||||
double rx, dx, lx, hx, max_x, min_x;
|
||||
int32_t i;
|
||||
int32_t original_veclen;
|
||||
int32_t npoints;
|
||||
size_t i;
|
||||
size_t original_veclen;
|
||||
size_t npoints;
|
||||
|
||||
if ((npoints = events.size()) == 0) {
|
||||
for (i = 0; i < veclen; ++i) {
|
||||
|
|
@ -258,7 +258,7 @@ Curve::_get_vector (double x0, double x1, float *vec, int32_t veclen)
|
|||
*/
|
||||
|
||||
double frac = (min_x - x0) / (x1 - x0);
|
||||
int32_t subveclen = (int32_t) floor (veclen * frac);
|
||||
size_t subveclen = (size_t) floor (veclen * frac);
|
||||
|
||||
subveclen = min (subveclen, veclen);
|
||||
|
||||
|
|
@ -276,7 +276,7 @@ Curve::_get_vector (double x0, double x1, float *vec, int32_t veclen)
|
|||
|
||||
double frac = (x1 - max_x) / (x1 - x0);
|
||||
|
||||
int32_t subveclen = (int32_t) floor (original_veclen * frac);
|
||||
size_t subveclen = lrintf (original_veclen * frac);
|
||||
|
||||
float val;
|
||||
|
||||
|
|
@ -441,7 +441,7 @@ Curve::restore_state (StateManager::State& state)
|
|||
extern "C" {
|
||||
|
||||
void
|
||||
curve_get_vector_from_c (void *arg, double x0, double x1, float* vec, int32_t vecsize)
|
||||
curve_get_vector_from_c (void *arg, double x0, double x1, float* vec, size_t vecsize)
|
||||
{
|
||||
static_cast<Curve*>(arg)->get_vector (x0, x1, vec, vecsize);
|
||||
}
|
||||
|
|
|
|||
85
libs/ardour/declicker.cc
Normal file
85
libs/ardour/declicker.cc
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Copyright (C) 2006 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 <ardour/declicker.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/buffer.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
|
||||
/** Apply a declick operation to the audio buffers of @a bufs */
|
||||
void
|
||||
Declicker::run (BufferSet& bufs, jack_nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity)
|
||||
{
|
||||
if (bufs.count().get(DataType::AUDIO) == 0)
|
||||
return;
|
||||
|
||||
assert(bufs.buffer_capacity(DataType::AUDIO) >= nframes);
|
||||
|
||||
const jack_nframes_t declick = std::min ((jack_nframes_t)4096, nframes);
|
||||
gain_t delta;
|
||||
double fractional_shift = -1.0/declick;
|
||||
double fractional_pos;
|
||||
gain_t polscale = invert_polarity ? -1.0f : 1.0f;
|
||||
|
||||
if (nframes == 0)
|
||||
return;
|
||||
|
||||
if (target < initial) {
|
||||
/* fade out: remove more and more of delta from initial */
|
||||
delta = -(initial - target);
|
||||
} else {
|
||||
/* fade in: add more and more of delta from initial */
|
||||
delta = target - initial;
|
||||
}
|
||||
|
||||
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
|
||||
Sample* const buffer = i->data(nframes);
|
||||
|
||||
fractional_pos = 1.0;
|
||||
|
||||
for (jack_nframes_t nx = 0; nx < declick; ++nx) {
|
||||
buffer[nx] *= polscale * (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
|
||||
fractional_pos += fractional_shift;
|
||||
}
|
||||
|
||||
/* now ensure the rest of the buffer has the target value applied, if necessary. */
|
||||
|
||||
if (declick != nframes) {
|
||||
|
||||
if (invert_polarity) {
|
||||
target = -target;
|
||||
}
|
||||
|
||||
if (target == 0.0) {
|
||||
memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
|
||||
} else if (target != 1.0) {
|
||||
for (jack_nframes_t nx = declick; nx < nframes; ++nx) {
|
||||
buffer[nx] *= target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
@ -124,8 +124,6 @@ Diskstream::init (Flag f)
|
|||
overwrite_frame = 0;
|
||||
overwrite_queued = false;
|
||||
input_change_pending = NoChange;
|
||||
|
||||
_n_channels = 0;
|
||||
}
|
||||
|
||||
Diskstream::~Diskstream ()
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <ardour/port.h>
|
||||
#include <ardour/route.h>
|
||||
#include <ardour/ladspa_plugin.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
|
||||
#ifdef VST_SUPPORT
|
||||
#include <ardour/vst_plugin.h>
|
||||
|
|
@ -49,6 +50,9 @@ using namespace std;
|
|||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
/* ********** FIXME: TYPE ************** */
|
||||
/* Inserts are still definitely audio only */
|
||||
|
||||
Insert::Insert(Session& s, Placement p)
|
||||
: Redirect (s, s.next_insert_name(), p)
|
||||
{
|
||||
|
|
@ -85,7 +89,7 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placemen
|
|||
|
||||
{
|
||||
Glib::Mutex::Lock em (_session.engine().process_lock());
|
||||
IO::MoreOutputs (ChanCount(_default_type, output_streams()));
|
||||
IO::MoreChannels (max(input_streams(), output_streams()));
|
||||
}
|
||||
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
|
|
@ -106,7 +110,7 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node)
|
|||
|
||||
{
|
||||
Glib::Mutex::Lock em (_session.engine().process_lock());
|
||||
IO::MoreOutputs (ChanCount(_default_type, output_streams()));
|
||||
IO::MoreChannels (max(input_streams(), output_streams()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -191,28 +195,32 @@ PluginInsert::auto_state_changed (uint32_t which)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ChanCount
|
||||
PluginInsert::output_streams() const
|
||||
{
|
||||
return _plugins[0]->get_info()->n_outputs * _plugins.size();
|
||||
// FIXME: TYPE
|
||||
return ChanCount(DataType::AUDIO, _plugins[0]->get_info()->n_outputs * _plugins.size());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ChanCount
|
||||
PluginInsert::input_streams() const
|
||||
{
|
||||
return _plugins[0]->get_info()->n_inputs * _plugins.size();
|
||||
// FIXME: TYPE
|
||||
return ChanCount(DataType::AUDIO, _plugins[0]->get_info()->n_inputs * _plugins.size());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ChanCount
|
||||
PluginInsert::natural_output_streams() const
|
||||
{
|
||||
return _plugins[0]->get_info()->n_outputs;
|
||||
// FIXME: TYPE
|
||||
return ChanCount(DataType::AUDIO, _plugins[0]->get_info()->n_outputs);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ChanCount
|
||||
PluginInsert::natural_input_streams() const
|
||||
{
|
||||
return _plugins[0]->get_info()->n_inputs;
|
||||
// FIXME: TYPE
|
||||
return ChanCount(DataType::AUDIO, _plugins[0]->get_info()->n_inputs);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -277,10 +285,10 @@ PluginInsert::deactivate ()
|
|||
}
|
||||
|
||||
void
|
||||
PluginInsert::connect_and_run (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, bool with_auto, jack_nframes_t now)
|
||||
PluginInsert::connect_and_run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset, bool with_auto, jack_nframes_t now)
|
||||
{
|
||||
int32_t in_index = 0;
|
||||
int32_t out_index = 0;
|
||||
uint32_t in_index = 0;
|
||||
uint32_t out_index = 0;
|
||||
|
||||
/* Note that we've already required that plugins
|
||||
be able to handle in-place processing.
|
||||
|
|
@ -310,7 +318,7 @@ PluginInsert::connect_and_run (vector<Sample*>& bufs, uint32_t nbufs, jack_nfram
|
|||
}
|
||||
|
||||
for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
||||
(*i)->connect_and_run (bufs, nbufs, in_index, out_index, nframes, offset);
|
||||
(*i)->connect_and_run (bufs, in_index, out_index, nframes, offset);
|
||||
}
|
||||
|
||||
/* leave remaining channel buffers alone */
|
||||
|
|
@ -351,28 +359,28 @@ PluginInsert::transport_stopped (jack_nframes_t now)
|
|||
void
|
||||
PluginInsert::silence (jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
int32_t in_index = 0;
|
||||
int32_t out_index = 0;
|
||||
uint32_t in_index = 0;
|
||||
uint32_t out_index = 0;
|
||||
|
||||
uint32_t n;
|
||||
|
||||
if (active()) {
|
||||
for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
||||
n = (*i) -> get_info()->n_inputs;
|
||||
(*i)->connect_and_run (_session.get_silent_buffers (n), n, in_index, out_index, nframes, offset);
|
||||
(*i)->connect_and_run (_session.get_silent_buffers (ChanCount(DataType::AUDIO, n)), in_index, out_index, nframes, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginInsert::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
PluginInsert::run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
if (active()) {
|
||||
|
||||
if (_session.transport_rolling()) {
|
||||
automation_run (bufs, nbufs, nframes, offset);
|
||||
automation_run (bufs, nframes, offset);
|
||||
} else {
|
||||
connect_and_run (bufs, nbufs, nframes, offset, false);
|
||||
connect_and_run (bufs, nframes, offset, false);
|
||||
}
|
||||
} else {
|
||||
uint32_t in = _plugins[0]->get_info()->n_inputs;
|
||||
|
|
@ -383,9 +391,11 @@ PluginInsert::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframe
|
|||
/* not active, but something has make up for any channel count increase */
|
||||
|
||||
for (uint32_t n = out - in; n < out; ++n) {
|
||||
memcpy (bufs[n], bufs[in - 1], sizeof (Sample) * nframes);
|
||||
memcpy (bufs.get_audio(n).data(nframes, offset), bufs.get_audio(in - 1).data(nframes, offset), sizeof (Sample) * nframes);
|
||||
}
|
||||
}
|
||||
|
||||
bufs.count().set(DataType::AUDIO, out);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -404,7 +414,7 @@ PluginInsert::set_parameter (uint32_t port, float val)
|
|||
}
|
||||
|
||||
void
|
||||
PluginInsert::automation_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
PluginInsert::automation_run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
ControlEvent next_event (0, 0.0f);
|
||||
jack_nframes_t now = _session.transport_frame ();
|
||||
|
|
@ -413,7 +423,7 @@ PluginInsert::automation_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nfram
|
|||
Glib::Mutex::Lock lm (_automation_lock, Glib::TRY_LOCK);
|
||||
|
||||
if (!lm.locked()) {
|
||||
connect_and_run (bufs, nbufs, nframes, offset, false);
|
||||
connect_and_run (bufs, nframes, offset, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -421,7 +431,7 @@ PluginInsert::automation_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nfram
|
|||
|
||||
/* no events have a time within the relevant range */
|
||||
|
||||
connect_and_run (bufs, nbufs, nframes, offset, true, now);
|
||||
connect_and_run (bufs, nframes, offset, true, now);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -429,7 +439,7 @@ PluginInsert::automation_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nfram
|
|||
|
||||
jack_nframes_t cnt = min (((jack_nframes_t) floor (next_event.when) - now), nframes);
|
||||
|
||||
connect_and_run (bufs, nbufs, cnt, offset, true, now);
|
||||
connect_and_run (bufs, cnt, offset, true, now);
|
||||
|
||||
nframes -= cnt;
|
||||
offset += cnt;
|
||||
|
|
@ -443,7 +453,7 @@ PluginInsert::automation_run (vector<Sample *>& bufs, uint32_t nbufs, jack_nfram
|
|||
/* cleanup anything that is left to do */
|
||||
|
||||
if (nframes) {
|
||||
connect_and_run (bufs, nbufs, nframes, offset, true, now);
|
||||
connect_and_run (bufs, nframes, offset, true, now);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -901,7 +911,7 @@ PortInsert::~PortInsert ()
|
|||
}
|
||||
|
||||
void
|
||||
PortInsert::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
PortInsert::run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
if (n_outputs().get(_default_type) == 0) {
|
||||
return;
|
||||
|
|
@ -1059,14 +1069,15 @@ PortInsert::compute_output_streams (int32_t cnt) const
|
|||
return n_inputs ().get(_default_type);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ChanCount
|
||||
PortInsert::output_streams() const
|
||||
{
|
||||
return n_inputs ().get(_default_type);
|
||||
return n_inputs ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ChanCount
|
||||
PortInsert::input_streams() const
|
||||
{
|
||||
return n_outputs ().get(_default_type);
|
||||
return n_outputs ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@
|
|||
#include <ardour/session.h>
|
||||
#include <ardour/cycle_timer.h>
|
||||
#include <ardour/panner.h>
|
||||
#include <ardour/dB.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/meter.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
|
@ -69,7 +70,7 @@ sigc::signal<void> IO::Meter;
|
|||
sigc::signal<int> IO::ConnectingLegal;
|
||||
sigc::signal<int> IO::PortsLegal;
|
||||
sigc::signal<int> IO::PannersLegal;
|
||||
sigc::signal<void,ChanCount> IO::MoreOutputs;
|
||||
sigc::signal<void,ChanCount> IO::MoreChannels;
|
||||
sigc::signal<int> IO::PortsCreated;
|
||||
|
||||
Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
|
||||
|
|
@ -91,13 +92,6 @@ static double direct_gain_to_control (gain_t gain) {
|
|||
return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
|
||||
}
|
||||
|
||||
/*
|
||||
static bool sort_ports_by_name (Port* a, Port* b)
|
||||
{
|
||||
return a->name() < b->name();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/** @param default_type The type of port that will be created by ensure_io
|
||||
* and friends if no type is explicitly requested (to avoid breakage).
|
||||
|
|
@ -106,6 +100,7 @@ IO::IO (Session& s, string name,
|
|||
int input_min, int input_max, int output_min, int output_max,
|
||||
DataType default_type)
|
||||
: _session (s),
|
||||
_output_buffers(new BufferSet()),
|
||||
_name (name),
|
||||
_default_type(default_type),
|
||||
_gain_control (*this),
|
||||
|
|
@ -116,6 +111,8 @@ IO::IO (Session& s, string name,
|
|||
_output_maximum (_default_type, output_max)
|
||||
{
|
||||
_panner = new Panner (name, _session);
|
||||
_meter = new PeakMeter (_session);
|
||||
|
||||
_gain = 1.0;
|
||||
_desired_gain = 1.0;
|
||||
_input_connection = 0;
|
||||
|
|
@ -137,11 +134,13 @@ IO::IO (Session& s, string name,
|
|||
Glib::Mutex::Lock guard (m_meter_signal_lock);
|
||||
m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
|
||||
}
|
||||
|
||||
// Connect to our own MoreChannels signal to connect output buffers
|
||||
IO::MoreChannels.connect (mem_fun (*this, &IO::attach_buffers));
|
||||
}
|
||||
|
||||
IO::~IO ()
|
||||
{
|
||||
|
||||
Glib::Mutex::Lock guard (m_meter_signal_lock);
|
||||
Glib::Mutex::Lock lm (io_lock);
|
||||
|
||||
|
|
@ -154,6 +153,10 @@ IO::~IO ()
|
|||
}
|
||||
|
||||
m_meter_connection.disconnect();
|
||||
|
||||
delete _meter;
|
||||
delete _panner;
|
||||
delete _output_buffers;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -162,216 +165,34 @@ IO::silence (jack_nframes_t nframes, jack_nframes_t offset)
|
|||
/* io_lock, not taken: function must be called from Session::process() calltree */
|
||||
|
||||
for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
|
||||
(*i)->silence (nframes, offset);
|
||||
i->silence (nframes, offset);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity)
|
||||
IO::pan_automated (BufferSet& bufs, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
jack_nframes_t declick = min ((jack_nframes_t)128, nframes);
|
||||
gain_t delta;
|
||||
Sample *buffer;
|
||||
double fractional_shift;
|
||||
double fractional_pos;
|
||||
gain_t polscale = invert_polarity ? -1.0f : 1.0f;
|
||||
|
||||
if (nframes == 0) return;
|
||||
|
||||
fractional_shift = -1.0/declick;
|
||||
|
||||
if (target < initial) {
|
||||
/* fade out: remove more and more of delta from initial */
|
||||
delta = -(initial - target);
|
||||
} else {
|
||||
/* fade in: add more and more of delta from initial */
|
||||
delta = target - initial;
|
||||
}
|
||||
|
||||
for (uint32_t n = 0; n < nbufs; ++n) {
|
||||
|
||||
buffer = bufs[n];
|
||||
fractional_pos = 1.0;
|
||||
|
||||
for (jack_nframes_t nx = 0; nx < declick; ++nx) {
|
||||
buffer[nx] *= polscale * (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
|
||||
fractional_pos += fractional_shift;
|
||||
}
|
||||
|
||||
/* now ensure the rest of the buffer has the target value
|
||||
applied, if necessary.
|
||||
*/
|
||||
|
||||
if (declick != nframes) {
|
||||
|
||||
if (invert_polarity) {
|
||||
target = -target;
|
||||
}
|
||||
|
||||
if (target == 0.0) {
|
||||
memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
|
||||
} else if (target != 1.0) {
|
||||
for (jack_nframes_t nx = declick; nx < nframes; ++nx) {
|
||||
buffer[nx] *= target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_panner->distribute_automated(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
|
||||
}
|
||||
|
||||
void
|
||||
IO::pan_automated (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
IO::pan (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff)
|
||||
{
|
||||
Sample* dst;
|
||||
|
||||
/* io_lock, not taken: function must be called from Session::process() calltree */
|
||||
|
||||
if (n_outputs().get(DataType::AUDIO) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (n_outputs().get(DataType::AUDIO) == 1) {
|
||||
|
||||
dst = audio_output(0)->get_audio_buffer().data (nframes, offset);
|
||||
|
||||
for (uint32_t n = 0; n < nbufs; ++n) {
|
||||
if (bufs[n] != dst) {
|
||||
memcpy (dst, bufs[n], sizeof (Sample) * nframes);
|
||||
}
|
||||
}
|
||||
|
||||
output(0)->mark_silence (false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t o = 0;
|
||||
vector<Sample *>::iterator in;
|
||||
Panner::iterator pan;
|
||||
Sample* obufs[n_outputs().get(DataType::AUDIO)];
|
||||
|
||||
/* the terrible silence ... */
|
||||
for (PortSet::audio_iterator out = _outputs.audio_begin(); out != _outputs.audio_end(); ++out, ++o) {
|
||||
(*out)->silence(nframes, offset);
|
||||
obufs[o] = (*out)->get_audio_buffer().data(nframes, offset);
|
||||
}
|
||||
|
||||
uint32_t n;
|
||||
|
||||
for (pan = _panner->begin(), n = 0; n < nbufs; ++n, ++pan) {
|
||||
(*pan)->distribute_automated (bufs[n], obufs, start, end, nframes, _session.pan_automation_buffer());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IO::pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff)
|
||||
{
|
||||
Sample* dst;
|
||||
Sample* src;
|
||||
|
||||
/* io_lock, not taken: function must be called from Session::process() calltree */
|
||||
|
||||
if (n_outputs().get(DataType::AUDIO) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* the panner can be empty if there are no inputs to the
|
||||
route, but still outputs
|
||||
*/
|
||||
|
||||
/* the panner can be empty if there are no inputs to the route, but still outputs */
|
||||
if (_panner->bypassed() || _panner->empty()) {
|
||||
deliver_output_no_pan (bufs, nbufs, nframes, offset);
|
||||
// FIXME: gain
|
||||
deliver_output_no_pan (bufs, nframes, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
if (n_outputs().get(DataType::AUDIO) == 1) {
|
||||
|
||||
dst = audio_output(0)->get_audio_buffer().data(nframes, offset);
|
||||
|
||||
if (gain_coeff == 0.0f) {
|
||||
|
||||
/* only one output, and gain was zero, so make it silent */
|
||||
|
||||
memset (dst, 0, sizeof (Sample) * nframes);
|
||||
|
||||
} else if (gain_coeff == 1.0f){
|
||||
|
||||
/* mix all buffers into the output */
|
||||
|
||||
uint32_t n;
|
||||
|
||||
memcpy (dst, bufs[0], sizeof (Sample) * nframes);
|
||||
|
||||
for (n = 1; n < nbufs; ++n) {
|
||||
src = bufs[n];
|
||||
|
||||
for (jack_nframes_t n = 0; n < nframes; ++n) {
|
||||
dst[n] += src[n];
|
||||
}
|
||||
}
|
||||
|
||||
audio_output(0)->mark_silence (false);
|
||||
|
||||
} else {
|
||||
|
||||
/* mix all buffers into the output, scaling them all by the gain */
|
||||
|
||||
uint32_t n;
|
||||
|
||||
src = bufs[0];
|
||||
|
||||
for (jack_nframes_t n = 0; n < nframes; ++n) {
|
||||
dst[n] = src[n] * gain_coeff;
|
||||
}
|
||||
|
||||
for (n = 1; n < nbufs; ++n) {
|
||||
src = bufs[n];
|
||||
|
||||
for (jack_nframes_t n = 0; n < nframes; ++n) {
|
||||
dst[n] += src[n] * gain_coeff;
|
||||
}
|
||||
}
|
||||
|
||||
audio_output(0)->mark_silence (false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t o = 0;
|
||||
vector<Sample *>::iterator in;
|
||||
Panner::iterator pan;
|
||||
Sample* obufs[n_outputs().get(DataType::AUDIO)];
|
||||
|
||||
/* the terrible silence ... */
|
||||
|
||||
/* XXX this is wasteful but i see no way to avoid it */
|
||||
|
||||
for (PortSet::audio_iterator out = _outputs.audio_begin(); out != _outputs.audio_end(); ++out, ++o) {
|
||||
obufs[o] = (*out)->get_audio_buffer().data (nframes, offset);
|
||||
memset (obufs[o], 0, sizeof (Sample) * nframes);
|
||||
(*out)->mark_silence (false);
|
||||
}
|
||||
|
||||
uint32_t n;
|
||||
|
||||
for (pan = _panner->begin(), n = 0; n < nbufs; ++n) {
|
||||
Panner::iterator tmp;
|
||||
|
||||
tmp = pan;
|
||||
++tmp;
|
||||
|
||||
(*pan)->distribute (bufs[n], obufs, gain_coeff, nframes);
|
||||
|
||||
if (tmp != _panner->end()) {
|
||||
pan = tmp;
|
||||
}
|
||||
_panner->distribute(bufs, output_buffers(), nframes, offset, gain_coeff);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
IO::deliver_output (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
throw;
|
||||
#if 0
|
||||
/* io_lock, not taken: function must be called from Session::process() calltree */
|
||||
|
||||
if (n_outputs().get(DataType::AUDIO) == 0) {
|
||||
|
|
@ -398,7 +219,7 @@ IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nfram
|
|||
}
|
||||
|
||||
if (dg != _gain) {
|
||||
apply_declick (bufs, nbufs, nframes, _gain, dg, false);
|
||||
Declicker::run (bufs, nbufs, nframes, _gain, dg, false);
|
||||
_gain = dg;
|
||||
pangain = 1.0f;
|
||||
}
|
||||
|
|
@ -410,11 +231,14 @@ IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nfram
|
|||
} else {
|
||||
pan (bufs, nbufs, nframes, offset, pangain);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
IO::deliver_output_no_pan (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
IO::deliver_output_no_pan (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
throw;
|
||||
#if 0
|
||||
/* io_lock, not taken: function must be called from Session::process() calltree */
|
||||
|
||||
if (n_outputs().get(DataType::AUDIO) == 0) {
|
||||
|
|
@ -488,51 +312,31 @@ IO::deliver_output_no_pan (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_
|
|||
}
|
||||
|
||||
if (dg != _gain) {
|
||||
apply_declick (outs, outs.size(), nframes, _gain, dg, false);
|
||||
Declicker::run (outs, outs.size(), nframes, _gain, dg, false);
|
||||
_gain = dg;
|
||||
}
|
||||
|
||||
if (apply_gain_automation) {
|
||||
_gain = old_gain;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
IO::collect_input (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
IO::collect_input (BufferSet& outs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
/* io_lock, not taken: function must be called from Session::process() calltree */
|
||||
outs.set_count(n_inputs());
|
||||
|
||||
uint32_t n = 0;
|
||||
Sample *last = 0;
|
||||
if (outs.count() == ChanCount::ZERO)
|
||||
return;
|
||||
|
||||
/* we require that bufs.size() >= 1 */
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
|
||||
for (PortSet::audio_iterator i = _inputs.audio_begin(); n < nbufs; ++i, ++n) {
|
||||
if (i == _inputs.audio_end()) {
|
||||
break;
|
||||
BufferSet::iterator o = outs.begin(*t);
|
||||
for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
|
||||
o->read_from(i->get_buffer(), nframes, offset);
|
||||
}
|
||||
|
||||
/* XXX always read the full extent of the port buffer that
|
||||
we need. One day, we may use jack_port_get_buffer_at_offset()
|
||||
or something similar. For now, this simple hack will
|
||||
have to do.
|
||||
|
||||
Hack? Why yes .. we only need to read nframes-worth of
|
||||
data, but the data we want is at 'offset' within the
|
||||
buffer.
|
||||
*/
|
||||
|
||||
last = (*i)->get_audio_buffer().data(nframes, offset);
|
||||
// the dest buffer's offset has already been applied
|
||||
memcpy (bufs[n], last, sizeof (Sample) * nframes);
|
||||
}
|
||||
|
||||
/* fill any excess outputs with the last input */
|
||||
|
||||
while (n < nbufs && last) {
|
||||
// the dest buffer's offset has already been applied
|
||||
memcpy (bufs[n], last, sizeof (Sample) * nframes);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -540,14 +344,12 @@ void
|
|||
IO::just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
vector<Sample*>& bufs = _session.get_passthru_buffers ();
|
||||
uint32_t nbufs = n_process_buffers ();
|
||||
BufferSet& bufs = _session.get_scratch_buffers ();
|
||||
ChanCount nbufs = n_process_buffers ();
|
||||
|
||||
collect_input (bufs, nbufs, nframes, offset);
|
||||
collect_input (bufs, nframes, offset);
|
||||
|
||||
for (uint32_t n = 0; n < nbufs; ++n) {
|
||||
_peak_power[n] = Session::compute_peak (bufs[n], nframes, _peak_power[n]);
|
||||
}
|
||||
_meter->run(bufs, nframes);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -829,7 +631,7 @@ IO::add_output_port (string destination, void* src, DataType type)
|
|||
reset_panner ();
|
||||
}
|
||||
|
||||
MoreOutputs (n_outputs()); /* EMIT SIGNAL */
|
||||
MoreChannels (n_outputs()); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
if (destination.length()) {
|
||||
|
|
@ -942,7 +744,7 @@ IO::add_input_port (string source, void* src, DataType type)
|
|||
reset_panner ();
|
||||
}
|
||||
|
||||
MoreOutputs (n_inputs()); /* EMIT SIGNAL */
|
||||
MoreChannels (n_inputs()); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
if (source.length()) {
|
||||
|
|
@ -1060,7 +862,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
|
|||
drop_input_connection ();
|
||||
setup_peak_meters ();
|
||||
reset_panner ();
|
||||
MoreOutputs (n_inputs()); /* EMIT SIGNAL */
|
||||
MoreChannels (n_inputs()); /* EMIT SIGNAL */
|
||||
_session.set_dirty ();
|
||||
}
|
||||
|
||||
|
|
@ -1075,6 +877,30 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
|
|||
return changed;
|
||||
}
|
||||
|
||||
/** Attach output_buffers to port buffers.
|
||||
*
|
||||
* Connected to IOs own MoreChannels signal.
|
||||
*/
|
||||
void
|
||||
IO::attach_buffers(ChanCount ignored)
|
||||
{
|
||||
_output_buffers->attach_buffers(_outputs);
|
||||
}
|
||||
|
||||
int
|
||||
IO::ensure_io (const ChanCount& in, const ChanCount& out, bool clear, void* src)
|
||||
{
|
||||
// FIXME: TYPE
|
||||
uint32_t nin = in.get(_default_type);
|
||||
uint32_t nout = out.get(_default_type);
|
||||
|
||||
// We only deal with one type still. Sorry about your luck.
|
||||
assert(nin == in.get_total());
|
||||
assert(nout == out.get_total());
|
||||
|
||||
return ensure_io(nin, nout, clear, src);
|
||||
}
|
||||
|
||||
int
|
||||
IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
|
||||
{
|
||||
|
|
@ -1217,7 +1043,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
|
|||
}
|
||||
|
||||
if (in_changed || out_changed) {
|
||||
MoreOutputs (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
|
||||
MoreChannels (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
|
||||
_session.set_dirty ();
|
||||
}
|
||||
|
||||
|
|
@ -1305,7 +1131,7 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src)
|
|||
|
||||
if (changed) {
|
||||
drop_output_connection ();
|
||||
MoreOutputs (n_outputs()); /* EMIT SIGNAL */
|
||||
MoreChannels (n_outputs()); /* EMIT SIGNAL */
|
||||
_session.set_dirty ();
|
||||
}
|
||||
|
||||
|
|
@ -1430,7 +1256,7 @@ IO::state (bool full_state)
|
|||
if (need_ins) {
|
||||
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
|
||||
|
||||
const char **connections = (*i)->get_connections();
|
||||
const char **connections = i->get_connections();
|
||||
|
||||
if (connections && connections[0]) {
|
||||
str += '{';
|
||||
|
|
@ -1467,7 +1293,7 @@ IO::state (bool full_state)
|
|||
|
||||
for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
|
||||
|
||||
const char **connections = (*i)->get_connections();
|
||||
const char **connections = i->get_connections();
|
||||
|
||||
if (connections && connections[0]) {
|
||||
|
||||
|
|
@ -1951,15 +1777,15 @@ IO::set_name (string name, void* src)
|
|||
}
|
||||
|
||||
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
|
||||
string current_name = (*i)->short_name();
|
||||
string current_name = i->short_name();
|
||||
current_name.replace (current_name.find (_name), _name.length(), name);
|
||||
(*i)->set_name (current_name);
|
||||
i->set_name (current_name);
|
||||
}
|
||||
|
||||
for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
|
||||
string current_name = (*i)->short_name();
|
||||
string current_name = i->short_name();
|
||||
current_name.replace (current_name.find (_name), _name.length(), name);
|
||||
(*i)->set_name (current_name);
|
||||
i->set_name (current_name);
|
||||
}
|
||||
|
||||
_name = name;
|
||||
|
|
@ -2034,7 +1860,7 @@ IO::set_port_latency (jack_nframes_t nframes)
|
|||
Glib::Mutex::Lock lm (io_lock);
|
||||
|
||||
for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
|
||||
(*i)->set_latency (nframes);
|
||||
i->set_latency (nframes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2049,7 +1875,7 @@ IO::output_latency () const
|
|||
/* io lock not taken - must be protected by other means */
|
||||
|
||||
for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
|
||||
if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
|
||||
if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
|
||||
max_latency = latency;
|
||||
}
|
||||
}
|
||||
|
|
@ -2068,7 +1894,7 @@ IO::input_latency () const
|
|||
/* io lock not taken - must be protected by other means */
|
||||
|
||||
for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
|
||||
if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
|
||||
if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
|
||||
max_latency = latency;
|
||||
}
|
||||
}
|
||||
|
|
@ -2106,7 +1932,7 @@ IO::use_input_connection (Connection& c, void* src)
|
|||
|
||||
/* clear any existing connections */
|
||||
|
||||
_session.engine().disconnect (_inputs.port(n));
|
||||
_session.engine().disconnect (*_inputs.port(n));
|
||||
|
||||
} else if (_inputs.port(n)->connected() > 1) {
|
||||
|
||||
|
|
@ -2119,7 +1945,7 @@ IO::use_input_connection (Connection& c, void* src)
|
|||
the one we want.
|
||||
*/
|
||||
|
||||
_session.engine().disconnect (_inputs.port(n));
|
||||
_session.engine().disconnect (*_inputs.port(n));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2185,7 +2011,7 @@ IO::use_output_connection (Connection& c, void* src)
|
|||
|
||||
/* clear any existing connections */
|
||||
|
||||
_session.engine().disconnect (_outputs.port(n));
|
||||
_session.engine().disconnect (*_outputs.port(n));
|
||||
|
||||
} else if (_outputs.port(n)->connected() > 1) {
|
||||
|
||||
|
|
@ -2198,7 +2024,7 @@ IO::use_output_connection (Connection& c, void* src)
|
|||
the one we want.
|
||||
*/
|
||||
|
||||
_session.engine().disconnect (_outputs.port(n));
|
||||
_session.engine().disconnect (*_outputs.port(n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2311,27 +2137,6 @@ IO::GainControllable::get_value (void) const
|
|||
return direct_gain_to_control (io.effective_gain());
|
||||
}
|
||||
|
||||
void
|
||||
IO::reset_peak_meters ()
|
||||
{
|
||||
uint32_t limit = max (n_inputs().get(DataType::AUDIO), n_outputs().get(DataType::AUDIO));
|
||||
|
||||
for (uint32_t i = 0; i < limit; ++i) {
|
||||
_peak_power[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IO::setup_peak_meters ()
|
||||
{
|
||||
uint32_t limit = max (n_inputs().get(DataType::AUDIO), n_outputs().get(DataType::AUDIO));
|
||||
|
||||
while (_peak_power.size() < limit) {
|
||||
_peak_power.push_back (0);
|
||||
_visible_peak_power.push_back (0);
|
||||
}
|
||||
}
|
||||
|
||||
UndoAction
|
||||
IO::get_memento() const
|
||||
{
|
||||
|
|
@ -2351,6 +2156,12 @@ IO::state_factory (std::string why) const
|
|||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
IO::setup_peak_meters()
|
||||
{
|
||||
_meter->setup(std::max(_inputs.count(), _outputs.count()));
|
||||
}
|
||||
|
||||
/**
|
||||
Update the peak meters.
|
||||
|
||||
|
|
@ -2364,40 +2175,16 @@ IO::update_meters()
|
|||
{
|
||||
Glib::Mutex::Lock guard (m_meter_signal_lock);
|
||||
|
||||
Meter();
|
||||
Meter(); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
IO::meter ()
|
||||
{
|
||||
// FIXME: Remove this function and just connect signal directly to PeakMeter::meter
|
||||
|
||||
Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
|
||||
uint32_t limit = max (n_inputs().get(DataType::AUDIO), n_outputs().get(DataType::AUDIO));
|
||||
|
||||
for (uint32_t n = 0; n < limit; ++n) {
|
||||
|
||||
/* XXX we should use atomic exchange here */
|
||||
|
||||
/* grab peak since last read */
|
||||
|
||||
float new_peak = _peak_power[n];
|
||||
_peak_power[n] = 0;
|
||||
|
||||
/* compute new visible value using falloff */
|
||||
|
||||
if (new_peak > 0.0) {
|
||||
new_peak = coefficient_to_dB (new_peak);
|
||||
} else {
|
||||
new_peak = minus_infinity();
|
||||
}
|
||||
|
||||
if (_session.meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
|
||||
_visible_peak_power[n] = new_peak;
|
||||
} else {
|
||||
// do falloff
|
||||
new_peak = _visible_peak_power[n] - _session.meter_falloff();
|
||||
_visible_peak_power[n] = max (new_peak, -INFINITY);
|
||||
}
|
||||
}
|
||||
_meter->meter();
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -2682,7 +2469,7 @@ IO::find_input_port_hole ()
|
|||
snprintf (buf, jack_port_name_size(), _("%s/in %u"), _name.c_str(), n);
|
||||
|
||||
for ( ; i != _inputs.end(); ++i) {
|
||||
if ((*i)->short_name() == buf) {
|
||||
if (i->short_name() == buf) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2712,7 +2499,7 @@ IO::find_output_port_hole ()
|
|||
snprintf (buf, jack_port_name_size(), _("%s/out %u"), _name.c_str(), n);
|
||||
|
||||
for ( ; i != _outputs.end(); ++i) {
|
||||
if ((*i)->short_name() == buf) {
|
||||
if (i->short_name() == buf) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include <ardour/session.h>
|
||||
#include <ardour/audioengine.h>
|
||||
#include <ardour/ladspa_plugin.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
|
||||
#include <pbd/stl_delete.h>
|
||||
|
||||
|
|
@ -516,26 +517,28 @@ LadspaPlugin::automatable () const
|
|||
}
|
||||
|
||||
int
|
||||
LadspaPlugin::connect_and_run (vector<Sample*>& bufs, uint32_t nbufs, int32_t& in_index, int32_t& out_index, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
LadspaPlugin::connect_and_run (BufferSet& bufs, uint32_t& in_index, uint32_t& out_index, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
uint32_t port_index;
|
||||
uint32_t port_index = 0;
|
||||
cycles_t then, now;
|
||||
|
||||
port_index = 0;
|
||||
|
||||
then = get_cycles ();
|
||||
|
||||
const uint32_t nbufs = bufs.count().get(DataType::AUDIO);
|
||||
|
||||
while (port_index < parameter_count()) {
|
||||
if (LADSPA_IS_PORT_AUDIO (port_descriptor(port_index))) {
|
||||
if (LADSPA_IS_PORT_INPUT (port_descriptor(port_index))) {
|
||||
connect_port (port_index, bufs[min((uint32_t) in_index,nbufs - 1)] + offset);
|
||||
const size_t index = min(in_index, nbufs - 1);
|
||||
connect_port (port_index, bufs.get_audio(index).data(nframes, offset));
|
||||
//cerr << this << ' ' << name() << " @ " << offset << " inport " << in_index << " = buf "
|
||||
// << min((uint32_t)in_index,nbufs) << " = " << &bufs[min((uint32_t)in_index,nbufs)][offset] << endl;
|
||||
in_index++;
|
||||
|
||||
|
||||
} else if (LADSPA_IS_PORT_OUTPUT (port_descriptor (port_index))) {
|
||||
connect_port (port_index, bufs[min((uint32_t) out_index,nbufs - 1)] + offset);
|
||||
const size_t index = min(out_index,nbufs - 1);
|
||||
connect_port (port_index, bufs.get_audio(index).data(nframes, offset));
|
||||
// cerr << this << ' ' << name() << " @ " << offset << " outport " << out_index << " = buf "
|
||||
// << min((uint32_t)out_index,nbufs) << " = " << &bufs[min((uint32_t)out_index,nbufs)][offset] << endl;
|
||||
out_index++;
|
||||
|
|
|
|||
110
libs/ardour/meter.cc
Normal file
110
libs/ardour/meter.cc
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright (C) 2006 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 <ardour/meter.h>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/peak.h>
|
||||
#include <ardour/dB.h>
|
||||
#include <ardour/session.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
|
||||
/** Get peaks from @a bufs
|
||||
* Input acceptance is lenient - the first n audio buffers from @a bufs will
|
||||
* be metered, where n was set by the last call to setup(), excess meters will
|
||||
* be set to 0.
|
||||
*/
|
||||
void
|
||||
PeakMeter::run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
size_t meterable = std::min(bufs.count().get(DataType::AUDIO), _peak_power.size());
|
||||
|
||||
// Meter what we have
|
||||
for (size_t n = 0; n < meterable; ++n) {
|
||||
_peak_power[n] = compute_peak (bufs.get_audio(n).data(nframes, offset), nframes, _peak_power[n]);
|
||||
}
|
||||
|
||||
// Zero any excess peaks
|
||||
for (size_t n = meterable; n < _peak_power.size(); ++n) {
|
||||
_peak_power[n] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PeakMeter::reset ()
|
||||
{
|
||||
for (size_t i = 0; i < _peak_power.size(); ++i) {
|
||||
_peak_power[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PeakMeter::setup (const ChanCount& in)
|
||||
{
|
||||
uint32_t limit = in.get(DataType::AUDIO);
|
||||
|
||||
while (_peak_power.size() < limit) {
|
||||
_peak_power.push_back (0);
|
||||
_visible_peak_power.push_back (0);
|
||||
}
|
||||
|
||||
assert(_peak_power.size() == limit);
|
||||
assert(_visible_peak_power.size() == limit);
|
||||
}
|
||||
|
||||
/** To be driven by the Meter signal from IO.
|
||||
* Caller MUST hold io_lock!
|
||||
*/
|
||||
void
|
||||
PeakMeter::meter ()
|
||||
{
|
||||
assert(_visible_peak_power.size() == _peak_power.size());
|
||||
|
||||
const size_t limit = _peak_power.size();
|
||||
|
||||
for (size_t n = 0; n < limit; ++n) {
|
||||
|
||||
/* XXX we should use atomic exchange here */
|
||||
|
||||
/* grab peak since last read */
|
||||
|
||||
float new_peak = _peak_power[n];
|
||||
_peak_power[n] = 0;
|
||||
|
||||
/* compute new visible value using falloff */
|
||||
|
||||
if (new_peak > 0.0) {
|
||||
new_peak = coefficient_to_dB (new_peak);
|
||||
} else {
|
||||
new_peak = minus_infinity();
|
||||
}
|
||||
|
||||
if (_session.meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
|
||||
_visible_peak_power[n] = new_peak;
|
||||
} else {
|
||||
// do falloff
|
||||
new_peak = _visible_peak_power[n] - _session.meter_falloff();
|
||||
_visible_peak_power[n] = std::max (new_peak, -INFINITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
@ -128,7 +128,7 @@ MidiDiskstream::init (Diskstream::Flag f)
|
|||
_capture_buf = new RingBufferNPT<RawMidi> (_session.diskstream_buffer_size());
|
||||
_capture_transition_buf = new RingBufferNPT<CaptureTransition> (128);
|
||||
|
||||
_n_channels = 1;
|
||||
_n_channels = ChanCount(DataType::MIDI, 1);
|
||||
}
|
||||
|
||||
MidiDiskstream::~MidiDiskstream ()
|
||||
|
|
@ -148,7 +148,7 @@ MidiDiskstream::non_realtime_input_change ()
|
|||
|
||||
if (input_change_pending & ConfigurationChanged) {
|
||||
|
||||
assert(_io->n_inputs().get(DataType::MIDI) == _n_channels);
|
||||
assert(_io->n_inputs() == _n_channels);
|
||||
}
|
||||
|
||||
get_input_sources ();
|
||||
|
|
|
|||
|
|
@ -386,17 +386,16 @@ MidiTrack::set_state_part_two ()
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ChanCount
|
||||
MidiTrack::n_process_buffers ()
|
||||
{
|
||||
return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
|
||||
return max (_diskstream->n_channels(), redirect_max_outs);
|
||||
}
|
||||
|
||||
void
|
||||
MidiTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter)
|
||||
{
|
||||
uint32_t nbufs = n_process_buffers ();
|
||||
process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
|
||||
process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, offset, true, declick, meter);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -508,7 +507,7 @@ MidiTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack
|
|||
}
|
||||
|
||||
void
|
||||
MidiTrack::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
||||
MidiTrack::process_output_buffers (BufferSet& bufs,
|
||||
jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick,
|
||||
bool meter)
|
||||
|
|
@ -539,9 +538,9 @@ MidiTrack::set_name (string str, void *src)
|
|||
}
|
||||
|
||||
int
|
||||
MidiTrack::export_stuff (vector<unsigned char*>& buffers, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
|
||||
MidiTrack::export_stuff (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t end_frame)
|
||||
{
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include <ardour/utils.h>
|
||||
|
||||
#include <ardour/mix.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
|
@ -292,8 +293,10 @@ BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt)
|
|||
}
|
||||
|
||||
void
|
||||
BaseStereoPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_nframes_t nframes)
|
||||
BaseStereoPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_coeff, jack_nframes_t nframes)
|
||||
{
|
||||
assert(obufs.count().get(DataType::AUDIO) == 2);
|
||||
|
||||
pan_t delta;
|
||||
Sample* dst;
|
||||
pan_t pan;
|
||||
|
|
@ -302,9 +305,11 @@ BaseStereoPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, ja
|
|||
return;
|
||||
}
|
||||
|
||||
Sample* const src = srcbuf.data(nframes);
|
||||
|
||||
/* LEFT */
|
||||
|
||||
dst = obufs[0];
|
||||
dst = obufs.get_audio(0).data(nframes);
|
||||
|
||||
if (fabsf ((delta = (left - desired_left))) > 0.002) { // about 1 degree of arc
|
||||
|
||||
|
|
@ -354,7 +359,7 @@ BaseStereoPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, ja
|
|||
|
||||
/* RIGHT */
|
||||
|
||||
dst = obufs[1];
|
||||
dst = obufs.get_audio(1).data(nframes);
|
||||
|
||||
if (fabsf ((delta = (right - desired_right))) > 0.002) { // about 1 degree of arc
|
||||
|
||||
|
|
@ -445,19 +450,22 @@ EqualPowerStereoPanner::update ()
|
|||
}
|
||||
|
||||
void
|
||||
EqualPowerStereoPanner::distribute_automated (Sample* src, Sample** obufs,
|
||||
EqualPowerStereoPanner::distribute_automated (AudioBuffer& srcbuf, BufferSet& obufs,
|
||||
jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes,
|
||||
pan_t** buffers)
|
||||
{
|
||||
assert(obufs.count().get(DataType::AUDIO) == 2);
|
||||
|
||||
Sample* dst;
|
||||
pan_t* pbuf;
|
||||
Sample* const src = srcbuf.data(nframes);
|
||||
|
||||
/* fetch positional data */
|
||||
|
||||
if (!_automation.rt_safe_get_vector (start, end, buffers[0], nframes)) {
|
||||
/* fallback */
|
||||
if (!_muted) {
|
||||
distribute (src, obufs, 1.0, nframes);
|
||||
distribute (srcbuf, obufs, 1.0, nframes);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -489,7 +497,7 @@ EqualPowerStereoPanner::distribute_automated (Sample* src, Sample** obufs,
|
|||
|
||||
/* LEFT */
|
||||
|
||||
dst = obufs[0];
|
||||
dst = obufs.get_audio(0).data(nframes);
|
||||
pbuf = buffers[0];
|
||||
|
||||
for (jack_nframes_t n = 0; n < nframes; ++n) {
|
||||
|
|
@ -500,7 +508,7 @@ EqualPowerStereoPanner::distribute_automated (Sample* src, Sample** obufs,
|
|||
|
||||
/* RIGHT */
|
||||
|
||||
dst = obufs[1];
|
||||
dst = obufs.get_audio(1).data(nframes);
|
||||
pbuf = buffers[1];
|
||||
|
||||
for (jack_nframes_t n = 0; n < nframes; ++n) {
|
||||
|
|
@ -648,7 +656,7 @@ Multi2dPanner::update ()
|
|||
}
|
||||
|
||||
void
|
||||
Multi2dPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_nframes_t nframes)
|
||||
Multi2dPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_coeff, jack_nframes_t nframes)
|
||||
{
|
||||
Sample* dst;
|
||||
pan_t pan;
|
||||
|
|
@ -659,10 +667,12 @@ Multi2dPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_
|
|||
return;
|
||||
}
|
||||
|
||||
Sample* const src = srcbuf.data(nframes);
|
||||
|
||||
|
||||
for (n = 0, o = parent.outputs.begin(); o != parent.outputs.end(); ++o, ++n) {
|
||||
|
||||
dst = obufs[n];
|
||||
dst = obufs.get_audio(n).data(nframes);
|
||||
|
||||
#ifdef CAN_INTERP
|
||||
if (fabsf ((delta = (left_interp - desired_left))) > 0.002) { // about 1 degree of arc
|
||||
|
|
@ -719,7 +729,7 @@ Multi2dPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, jack_
|
|||
}
|
||||
|
||||
void
|
||||
Multi2dPanner::distribute_automated (Sample* src, Sample** obufs,
|
||||
Multi2dPanner::distribute_automated (AudioBuffer& src, BufferSet& obufs,
|
||||
jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes,
|
||||
pan_t** buffers)
|
||||
{
|
||||
|
|
@ -1477,3 +1487,124 @@ Panner::set_position (float xpos, float ypos, float zpos, StreamPanner& orig)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Panner::distribute (BufferSet& inbufs, BufferSet& outbufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff)
|
||||
{
|
||||
if (outbufs.count().get(DataType::AUDIO) == 0) {
|
||||
// Don't want to lose audio...
|
||||
assert(inbufs.count().get(DataType::AUDIO) == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// We shouldn't be called in the first place...
|
||||
assert(!bypassed());
|
||||
assert(!empty());
|
||||
|
||||
|
||||
if (outbufs.count().get(DataType::AUDIO) == 1) {
|
||||
|
||||
AudioBuffer& dst = outbufs.get_audio(0);
|
||||
|
||||
if (gain_coeff == 0.0f) {
|
||||
|
||||
/* only one output, and gain was zero, so make it silent */
|
||||
|
||||
dst.silence(offset);
|
||||
|
||||
} else if (gain_coeff == 1.0f){
|
||||
|
||||
/* mix all buffers into the output */
|
||||
|
||||
// copy the first
|
||||
dst.read_from(inbufs.get_audio(0), nframes, offset);
|
||||
|
||||
// accumulate starting with the second
|
||||
BufferSet::audio_iterator i = inbufs.audio_begin();
|
||||
for (++i; i != inbufs.audio_end(); ++i) {
|
||||
dst.accumulate_from(*i, nframes, offset);
|
||||
}
|
||||
|
||||
//audio_output(0)->mark_silence (false); // FIXME
|
||||
|
||||
} else {
|
||||
|
||||
/* mix all buffers into the output, scaling them all by the gain */
|
||||
|
||||
// copy the first
|
||||
dst.read_from(inbufs.get_audio(0), nframes, offset);
|
||||
|
||||
// accumulate (with gain) starting with the second
|
||||
BufferSet::audio_iterator i = inbufs.audio_begin();
|
||||
for (++i; i != inbufs.audio_end(); ++i) {
|
||||
dst.accumulate_with_gain_from(*i, nframes, offset, gain_coeff);
|
||||
}
|
||||
|
||||
//audio_output(0)->mark_silence (false); // FIXME
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// More than 1 output, we should have 1 panner for each input
|
||||
assert(size() == inbufs.count().get(DataType::AUDIO));
|
||||
|
||||
/* the terrible silence ... */
|
||||
for (BufferSet::audio_iterator i = outbufs.audio_begin(); i != outbufs.audio_end(); ++i) {
|
||||
i->silence(nframes, offset);
|
||||
}
|
||||
|
||||
BufferSet::audio_iterator i = inbufs.audio_begin();
|
||||
for (iterator pan = begin(); pan != end(); ++pan, ++i) {
|
||||
(*pan)->distribute (*i, outbufs, gain_coeff, nframes);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Panner::distribute_automated (BufferSet& inbufs, BufferSet& outbufs, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
if (outbufs.count().get(DataType::AUDIO) == 0) {
|
||||
// Don't want to lose audio...
|
||||
assert(inbufs.count().get(DataType::AUDIO) == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// We shouldn't be called in the first place...
|
||||
assert(!bypassed());
|
||||
assert(!empty());
|
||||
|
||||
|
||||
if (outbufs.count().get(DataType::AUDIO) == 1) {
|
||||
|
||||
AudioBuffer& dst = outbufs.get_audio(0);
|
||||
|
||||
// FIXME: apply gain automation?
|
||||
|
||||
// copy the first
|
||||
dst.read_from(inbufs.get_audio(0), nframes, offset);
|
||||
|
||||
// accumulate starting with the second
|
||||
BufferSet::audio_iterator i = inbufs.audio_begin();
|
||||
for (++i; i != inbufs.audio_end(); ++i) {
|
||||
dst.accumulate_from(*i, nframes, offset);
|
||||
}
|
||||
|
||||
//audio_output(0)->mark_silence (false); // FIXME
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// More than 1 output, we should have 1 panner for each input
|
||||
assert(size() == inbufs.count().get(DataType::AUDIO));
|
||||
|
||||
/* the terrible silence ... */
|
||||
for (BufferSet::audio_iterator i = outbufs.audio_begin(); i != outbufs.audio_end(); ++i) {
|
||||
i->silence(nframes, offset);
|
||||
}
|
||||
|
||||
BufferSet::audio_iterator i = inbufs.audio_begin();
|
||||
for (iterator pan = begin(); pan != end(); ++pan, ++i) {
|
||||
(*pan)->distribute_automated (*i, outbufs, start_frame, end_frame, nframes, _session.pan_automation_buffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ PortSet::add_port(Port* port)
|
|||
v.push_back(port);
|
||||
sort(v.begin(), v.end(), sort_ports_by_name);
|
||||
|
||||
_chan_count.set(port->type(), _chan_count.get(port->type()) + 1);
|
||||
_count.set(port->type(), _count.get(port->type()) + 1);
|
||||
|
||||
assert(_chan_count.get(port->type()) == _ports[port->type().to_index()].size());
|
||||
assert(_count.get(port->type()) == _ports[port->type().to_index()].size());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -89,23 +89,27 @@ PortSet::port(size_t n) const
|
|||
}
|
||||
|
||||
Port*
|
||||
PortSet::nth_port_of_type(DataType type, size_t n) const
|
||||
PortSet::port(DataType type, size_t n) const
|
||||
{
|
||||
if (type == DataType::NIL) {
|
||||
return port(n);
|
||||
} else {
|
||||
const PortVec& v = _ports[type.to_index()];
|
||||
assert(n < v.size());
|
||||
return v[n];
|
||||
}
|
||||
}
|
||||
|
||||
AudioPort*
|
||||
PortSet::nth_audio_port(size_t n) const
|
||||
{
|
||||
return dynamic_cast<AudioPort*>(nth_port_of_type(DataType::AUDIO, n));
|
||||
return dynamic_cast<AudioPort*>(port(DataType::AUDIO, n));
|
||||
}
|
||||
|
||||
MidiPort*
|
||||
PortSet::nth_midi_port(size_t n) const
|
||||
{
|
||||
return dynamic_cast<MidiPort*>(nth_port_of_type(DataType::MIDI, n));
|
||||
return dynamic_cast<MidiPort*>(port(DataType::MIDI, n));
|
||||
}
|
||||
|
||||
} // namepace ARDOUR
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@
|
|||
#include <ardour/panner.h>
|
||||
#include <ardour/dB.h>
|
||||
#include <ardour/mix.h>
|
||||
|
||||
#include <ardour/declicker.h>
|
||||
#include <ardour/meter.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -74,7 +76,7 @@ Route::Route (Session& sess, const XMLNode& node)
|
|||
void
|
||||
Route::init ()
|
||||
{
|
||||
redirect_max_outs = 0;
|
||||
redirect_max_outs.reset();
|
||||
_muted = false;
|
||||
_soloed = false;
|
||||
_solo_safe = false;
|
||||
|
|
@ -215,8 +217,19 @@ Route::set_gain (gain_t val, void *src)
|
|||
IO::set_gain (val, src);
|
||||
}
|
||||
|
||||
/** Process this route for one (sub) cycle (process thread)
|
||||
*
|
||||
* @param bufs Scratch buffers to use for the signal path
|
||||
* @param start_frame Initial transport frame
|
||||
* @param end_frame Final transport frame
|
||||
* @param nframes Number of frames to output (to ports)
|
||||
* @param offset Output offset (of port buffers, for split cycles)
|
||||
*
|
||||
* Note that (end_frame - start_frame) may not be equal to nframes when the
|
||||
* transport speed isn't 1.0 (eg varispeed).
|
||||
*/
|
||||
void
|
||||
Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
||||
Route::process_output_buffers (BufferSet& bufs,
|
||||
jack_nframes_t start_frame, jack_nframes_t end_frame,
|
||||
jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick,
|
||||
bool meter)
|
||||
|
|
@ -224,7 +237,6 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
// This is definitely very audio-only for now
|
||||
assert(_default_type == DataType::AUDIO);
|
||||
|
||||
uint32_t n;
|
||||
RedirectList::iterator i;
|
||||
bool post_fader_work = false;
|
||||
bool mute_declick_applied = false;
|
||||
|
|
@ -267,17 +279,17 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
-------------------------------------------------------------------------------------------------- */
|
||||
|
||||
if (declick > 0) {
|
||||
apply_declick (bufs, nbufs, nframes, 0.0, 1.0, _phase_invert);
|
||||
Declicker::run (bufs, nframes, 0.0, 1.0, _phase_invert);
|
||||
_pending_declick = 0;
|
||||
} else if (declick < 0) {
|
||||
apply_declick (bufs, nbufs, nframes, 1.0, 0.0, _phase_invert);
|
||||
Declicker::run (bufs, nframes, 1.0, 0.0, _phase_invert);
|
||||
_pending_declick = 0;
|
||||
} else {
|
||||
|
||||
/* no global declick */
|
||||
|
||||
if (solo_gain != dsg) {
|
||||
apply_declick (bufs, nbufs, nframes, solo_gain, dsg, _phase_invert);
|
||||
Declicker::run (bufs, nframes, solo_gain, dsg, _phase_invert);
|
||||
solo_gain = dsg;
|
||||
}
|
||||
}
|
||||
|
|
@ -288,13 +300,11 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
-------------------------------------------------------------------------------------------------- */
|
||||
|
||||
if (meter && (_meter_point == MeterInput)) {
|
||||
for (n = 0; n < nbufs; ++n) {
|
||||
_peak_power[n] = Session::compute_peak (bufs[n], nframes, _peak_power[n]);
|
||||
}
|
||||
_meter->run(bufs, nframes);
|
||||
}
|
||||
|
||||
if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) {
|
||||
apply_declick (bufs, nbufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
Declicker::run (bufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
mute_gain = dmg;
|
||||
mute_declick_applied = true;
|
||||
}
|
||||
|
|
@ -324,7 +334,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
|
||||
} else {
|
||||
|
||||
co->deliver_output (bufs, nbufs, nframes, offset);
|
||||
co->deliver_output (bufs, nframes, offset);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -340,7 +350,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
for (i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
switch ((*i)->placement()) {
|
||||
case PreFader:
|
||||
(*i)->run (bufs, nbufs, nframes, offset);
|
||||
(*i)->run (bufs, nframes, offset);
|
||||
break;
|
||||
case PostFader:
|
||||
post_fader_work = true;
|
||||
|
|
@ -364,7 +374,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
|
||||
|
||||
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader) {
|
||||
apply_declick (bufs, nbufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
Declicker::run (bufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
mute_gain = dmg;
|
||||
mute_declick_applied = true;
|
||||
}
|
||||
|
|
@ -374,9 +384,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
-------------------------------------------------------------------------------------------------- */
|
||||
|
||||
if (meter && (_meter_point == MeterPreFader)) {
|
||||
for (n = 0; n < nbufs; ++n) {
|
||||
_peak_power[n] = Session::compute_peak (bufs[n], nframes, _peak_power[n]);
|
||||
}
|
||||
_meter->run(bufs, nframes);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -403,7 +411,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
|
||||
} else {
|
||||
|
||||
co->deliver_output (bufs, nbufs, nframes, offset);
|
||||
co->deliver_output (bufs, nframes, offset);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -431,16 +439,16 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
if (apply_gain_automation) {
|
||||
|
||||
if (_phase_invert) {
|
||||
for (n = 0; n < nbufs; ++n) {
|
||||
Sample *sp = bufs[n];
|
||||
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
|
||||
Sample* const sp = i->data(nframes);
|
||||
|
||||
for (jack_nframes_t nx = 0; nx < nframes; ++nx) {
|
||||
sp[nx] *= -gab[nx];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (n = 0; n < nbufs; ++n) {
|
||||
Sample *sp = bufs[n];
|
||||
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
|
||||
Sample* const sp = i->data(nframes);
|
||||
|
||||
for (jack_nframes_t nx = 0; nx < nframes; ++nx) {
|
||||
sp[nx] *= gab[nx];
|
||||
|
|
@ -458,7 +466,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
|
||||
if (_gain != dg) {
|
||||
|
||||
apply_declick (bufs, nbufs, nframes, _gain, dg, _phase_invert);
|
||||
Declicker::run (bufs, nframes, _gain, dg, _phase_invert);
|
||||
_gain = dg;
|
||||
|
||||
} else if (_gain != 0 && (_phase_invert || _gain != 1.0)) {
|
||||
|
|
@ -477,14 +485,14 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
this_gain = _gain;
|
||||
}
|
||||
|
||||
for (n = 0; n < nbufs; ++n) {
|
||||
Sample *sp = bufs[n];
|
||||
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
|
||||
Sample* const sp = i->data(nframes);
|
||||
apply_gain_to_buffer(sp,nframes,this_gain);
|
||||
}
|
||||
|
||||
} else if (_gain == 0) {
|
||||
for (n = 0; n < nbufs; ++n) {
|
||||
memset (bufs[n], 0, sizeof (Sample) * nframes);
|
||||
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
|
||||
i->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -511,7 +519,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
case PreFader:
|
||||
break;
|
||||
case PostFader:
|
||||
(*i)->run (bufs, nbufs, nframes, offset);
|
||||
(*i)->run (bufs, nframes, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -530,7 +538,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
}
|
||||
|
||||
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_control_outs) {
|
||||
apply_declick (bufs, nbufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
Declicker::run (bufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
mute_gain = dmg;
|
||||
mute_declick_applied = true;
|
||||
}
|
||||
|
|
@ -566,7 +574,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
|
||||
} else {
|
||||
|
||||
co->deliver_output_no_pan (bufs, nbufs, nframes, offset);
|
||||
co->deliver_output_no_pan (bufs, nframes, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -575,7 +583,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
----------------------------------------------------------------------*/
|
||||
|
||||
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) {
|
||||
apply_declick (bufs, nbufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
Declicker::run (bufs, nframes, mute_gain, dmg, _phase_invert);
|
||||
mute_gain = dmg;
|
||||
mute_declick_applied = true;
|
||||
}
|
||||
|
|
@ -616,7 +624,7 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
*/
|
||||
|
||||
if (_meter_point == MeterPostFader) {
|
||||
reset_peak_meters ();
|
||||
peak_meter().reset();
|
||||
}
|
||||
|
||||
IO::silence (nframes, offset);
|
||||
|
|
@ -624,15 +632,15 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
} else {
|
||||
|
||||
if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
|
||||
pan (bufs, nbufs, nframes, offset, speed_quietning);
|
||||
pan (bufs, nframes, offset, speed_quietning);
|
||||
} else {
|
||||
// cerr << _name << " panner state = " << _panner->automation_state() << endl;
|
||||
if (!_panner->empty() &&
|
||||
(_panner->automation_state() & Play ||
|
||||
((_panner->automation_state() & Touch) && !_panner->touching()))) {
|
||||
pan_automated (bufs, nbufs, start_frame, end_frame, nframes, offset);
|
||||
pan_automated (bufs, start_frame, end_frame, nframes, offset);
|
||||
} else {
|
||||
pan (bufs, nbufs, nframes, offset, 1.0);
|
||||
pan (bufs, nframes, offset, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -647,47 +655,38 @@ Route::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
|
|||
// cerr << "meter post" << endl;
|
||||
|
||||
if ((_gain == 0 && !apply_gain_automation) || dmg == 0) {
|
||||
uint32_t no = n_outputs().get(DataType::AUDIO);
|
||||
for (n = 0; n < no; ++n) {
|
||||
_peak_power[n] = 0;
|
||||
}
|
||||
_meter->reset();
|
||||
} else {
|
||||
uint32_t no = n_outputs().get(DataType::AUDIO);
|
||||
for (n = 0; n < no; ++n) {
|
||||
_peak_power[n] = Session::compute_peak (audio_output(n)->get_audio_buffer ().data(nframes, offset), nframes, _peak_power[n]);
|
||||
}
|
||||
_meter->run(output_buffers(), nframes, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ChanCount
|
||||
Route::n_process_buffers ()
|
||||
{
|
||||
return max (n_inputs().get(_default_type), static_cast<size_t>(redirect_max_outs));
|
||||
return max (n_inputs(), redirect_max_outs);
|
||||
}
|
||||
|
||||
void
|
||||
Route::passthru (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter_first)
|
||||
{
|
||||
vector<Sample*>& bufs = _session.get_passthru_buffers();
|
||||
uint32_t limit = n_process_buffers ();
|
||||
BufferSet& bufs = _session.get_scratch_buffers(n_process_buffers());
|
||||
|
||||
_silent = false;
|
||||
|
||||
collect_input (bufs, limit, nframes, offset);
|
||||
collect_input (bufs, nframes, offset);
|
||||
|
||||
#define meter_stream meter_first
|
||||
|
||||
if (meter_first) {
|
||||
for (uint32_t n = 0; n < limit; ++n) {
|
||||
_peak_power[n] = Session::compute_peak (bufs[n], nframes, _peak_power[n]);
|
||||
}
|
||||
_meter->run(bufs, nframes);
|
||||
meter_stream = false;
|
||||
} else {
|
||||
meter_stream = true;
|
||||
}
|
||||
|
||||
process_output_buffers (bufs, limit, start_frame, end_frame, nframes, offset, true, declick, meter_stream);
|
||||
process_output_buffers (bufs, start_frame, end_frame, nframes, offset, true, declick, meter_stream);
|
||||
|
||||
#undef meter_stream
|
||||
}
|
||||
|
|
@ -763,7 +762,7 @@ Route::set_mute (bool yn, void *src)
|
|||
int
|
||||
Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* err_streams)
|
||||
{
|
||||
uint32_t old_rmo = redirect_max_outs;
|
||||
ChanCount old_rmo = redirect_max_outs;
|
||||
|
||||
if (!_session.engine().connected()) {
|
||||
return 1;
|
||||
|
|
@ -775,13 +774,13 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t*
|
|||
boost::shared_ptr<PluginInsert> pi;
|
||||
boost::shared_ptr<PortInsert> porti;
|
||||
|
||||
uint32_t potential_max_streams = 0;
|
||||
ChanCount potential_max_streams;
|
||||
|
||||
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(redirect)) != 0) {
|
||||
pi->set_count (1);
|
||||
|
||||
if (pi->input_streams() == 0) {
|
||||
/* instrument plugin */
|
||||
if (pi->input_streams() == ChanCount::ZERO) {
|
||||
/* generator plugin */
|
||||
_have_internal_generator = true;
|
||||
}
|
||||
|
||||
|
|
@ -805,12 +804,7 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t*
|
|||
}
|
||||
|
||||
// Ensure peak vector sizes before the plugin is activated
|
||||
while (_peak_power.size() < potential_max_streams) {
|
||||
_peak_power.push_back(0);
|
||||
}
|
||||
while (_visible_peak_power.size() < potential_max_streams) {
|
||||
_visible_peak_power.push_back(0);
|
||||
}
|
||||
_meter->setup(potential_max_streams);
|
||||
|
||||
_redirects.push_back (redirect);
|
||||
|
||||
|
|
@ -824,7 +818,7 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t*
|
|||
redirect->active_changed.connect (mem_fun (*this, &Route::redirect_active_proxy));
|
||||
}
|
||||
|
||||
if (redirect_max_outs != old_rmo || old_rmo == 0) {
|
||||
if (redirect_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
|
||||
reset_panner ();
|
||||
}
|
||||
|
||||
|
|
@ -836,7 +830,7 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t*
|
|||
int
|
||||
Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_streams)
|
||||
{
|
||||
uint32_t old_rmo = redirect_max_outs;
|
||||
ChanCount old_rmo = redirect_max_outs;
|
||||
|
||||
if (!_session.engine().connected()) {
|
||||
return 1;
|
||||
|
|
@ -848,7 +842,7 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea
|
|||
RedirectList::iterator existing_end = _redirects.end();
|
||||
--existing_end;
|
||||
|
||||
uint32_t potential_max_streams = 0;
|
||||
ChanCount potential_max_streams;
|
||||
|
||||
for (RedirectList::const_iterator i = others.begin(); i != others.end(); ++i) {
|
||||
|
||||
|
|
@ -857,18 +851,13 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea
|
|||
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
|
||||
pi->set_count (1);
|
||||
|
||||
uint32_t m = max(pi->input_streams(), pi->output_streams());
|
||||
ChanCount m = max(pi->input_streams(), pi->output_streams());
|
||||
if (m > potential_max_streams)
|
||||
potential_max_streams = m;
|
||||
}
|
||||
|
||||
// Ensure peak vector sizes before the plugin is activated
|
||||
while (_peak_power.size() < potential_max_streams) {
|
||||
_peak_power.push_back(0);
|
||||
}
|
||||
while (_visible_peak_power.size() < potential_max_streams) {
|
||||
_visible_peak_power.push_back(0);
|
||||
}
|
||||
_meter->setup(potential_max_streams);
|
||||
|
||||
_redirects.push_back (*i);
|
||||
|
||||
|
|
@ -884,7 +873,7 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea
|
|||
}
|
||||
}
|
||||
|
||||
if (redirect_max_outs != old_rmo || old_rmo == 0) {
|
||||
if (redirect_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
|
||||
reset_panner ();
|
||||
}
|
||||
|
||||
|
|
@ -895,7 +884,7 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea
|
|||
void
|
||||
Route::clear_redirects (void *src)
|
||||
{
|
||||
uint32_t old_rmo = redirect_max_outs;
|
||||
ChanCount old_rmo = redirect_max_outs;
|
||||
|
||||
if (!_session.engine().connected()) {
|
||||
return;
|
||||
|
|
@ -910,7 +899,7 @@ Route::clear_redirects (void *src)
|
|||
reset_panner ();
|
||||
}
|
||||
|
||||
redirect_max_outs = 0;
|
||||
redirect_max_outs.reset();
|
||||
_have_internal_generator = false;
|
||||
redirects_changed (src); /* EMIT SIGNAL */
|
||||
}
|
||||
|
|
@ -918,13 +907,13 @@ Route::clear_redirects (void *src)
|
|||
int
|
||||
Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* err_streams)
|
||||
{
|
||||
uint32_t old_rmo = redirect_max_outs;
|
||||
ChanCount old_rmo = redirect_max_outs;
|
||||
|
||||
if (!_session.engine().connected()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
redirect_max_outs = 0;
|
||||
redirect_max_outs.reset();
|
||||
|
||||
{
|
||||
Glib::RWLock::WriterLock lm (redirect_lock);
|
||||
|
|
@ -1020,7 +1009,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams)
|
|||
map<Placement,list<InsertCount> > insert_map;
|
||||
jack_nframes_t initial_streams;
|
||||
|
||||
redirect_max_outs = 0;
|
||||
redirect_max_outs.reset();
|
||||
i_cnt = 0;
|
||||
s_cnt = 0;
|
||||
|
||||
|
|
@ -1102,7 +1091,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams)
|
|||
|
||||
recompute:
|
||||
|
||||
redirect_max_outs = 0;
|
||||
redirect_max_outs.reset();
|
||||
RedirectList::iterator prev = _redirects.end();
|
||||
|
||||
for (r = _redirects.begin(); r != _redirects.end(); prev = r, ++r) {
|
||||
|
|
@ -1110,7 +1099,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams)
|
|||
|
||||
if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
|
||||
if (r == _redirects.begin()) {
|
||||
s->expect_inputs (n_inputs().get(_default_type));
|
||||
s->expect_inputs (n_inputs());
|
||||
} else {
|
||||
s->expect_inputs ((*prev)->output_streams());
|
||||
}
|
||||
|
|
@ -1167,7 +1156,7 @@ Route::check_some_plugin_counts (list<InsertCount>& iclist, int32_t required_inp
|
|||
int
|
||||
Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_streams)
|
||||
{
|
||||
uint32_t old_rmo = redirect_max_outs;
|
||||
ChanCount old_rmo = redirect_max_outs;
|
||||
|
||||
if (err_streams) {
|
||||
*err_streams = 0;
|
||||
|
|
@ -1240,7 +1229,7 @@ Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_st
|
|||
}
|
||||
}
|
||||
|
||||
if (redirect_max_outs != old_rmo || old_rmo == 0) {
|
||||
if (redirect_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
|
||||
reset_panner ();
|
||||
}
|
||||
|
||||
|
|
@ -1290,7 +1279,7 @@ Route::sort_redirects (uint32_t* err_streams)
|
|||
{
|
||||
RedirectSorter comparator;
|
||||
Glib::RWLock::WriterLock lm (redirect_lock);
|
||||
uint32_t old_rmo = redirect_max_outs;
|
||||
ChanCount old_rmo = redirect_max_outs;
|
||||
|
||||
/* the sweet power of C++ ... */
|
||||
|
||||
|
|
@ -1706,8 +1695,6 @@ Route::silence (jack_nframes_t nframes, jack_nframes_t offset)
|
|||
{
|
||||
if (!_silent) {
|
||||
|
||||
// reset_peak_meters ();
|
||||
|
||||
IO::silence (nframes, offset);
|
||||
|
||||
if (_control_outs) {
|
||||
|
|
@ -2004,14 +1991,14 @@ Route::pans_required () const
|
|||
return 0;
|
||||
}
|
||||
|
||||
return max (n_inputs ().get(DataType::AUDIO), static_cast<size_t>(redirect_max_outs));
|
||||
return max (n_inputs ().get(DataType::AUDIO), static_cast<size_t>(redirect_max_outs.get(DataType::AUDIO)));
|
||||
}
|
||||
|
||||
int
|
||||
Route::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset,
|
||||
bool session_state_changing, bool can_record, bool rec_monitors_input)
|
||||
{
|
||||
if (n_outputs().get(_default_type) == 0) {
|
||||
if (n_outputs().get_total() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2022,7 +2009,7 @@ Route::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes
|
|||
|
||||
apply_gain_automation = false;
|
||||
|
||||
if (n_inputs().get(_default_type)) {
|
||||
if (n_inputs().get_total()) {
|
||||
passthru (start_frame, end_frame, nframes, offset, 0, false);
|
||||
} else {
|
||||
silence (nframes, offset);
|
||||
|
|
@ -2089,8 +2076,6 @@ Route::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t
|
|||
|
||||
if (am.locked() && _session.transport_rolling()) {
|
||||
|
||||
jack_nframes_t start_frame = end_frame - nframes;
|
||||
|
||||
if (gain_automation_playback()) {
|
||||
apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
|
||||
}
|
||||
|
|
@ -2114,7 +2099,7 @@ void
|
|||
Route::toggle_monitor_input ()
|
||||
{
|
||||
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
|
||||
(*i)->request_monitor_input(!(*i)->monitoring_input());
|
||||
i->request_monitor_input( ! i->monitoring_input());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2126,11 +2111,10 @@ Route::has_external_redirects () const
|
|||
for (RedirectList::const_iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
|
||||
if ((pi = boost::dynamic_pointer_cast<const PortInsert>(*i)) != 0) {
|
||||
|
||||
uint32_t no = pi->n_outputs().get(_default_type);
|
||||
for (PortSet::const_iterator port = pi->outputs().begin();
|
||||
port != pi->outputs().end(); ++port) {
|
||||
|
||||
for (uint32_t n = 0; n < no; ++n) {
|
||||
|
||||
string port_name = pi->output(n)->name();
|
||||
string port_name = port->name();
|
||||
string client_name = port_name.substr (0, port_name.find(':'));
|
||||
|
||||
/* only say "yes" if the redirect is actually in use */
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@
|
|||
#include <ardour/session.h>
|
||||
#include <ardour/port.h>
|
||||
#include <ardour/audio_port.h>
|
||||
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/meter.h>
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
|
@ -36,7 +37,6 @@ Send::Send (Session& s, Placement p)
|
|||
: Redirect (s, s.next_send_name(), p)
|
||||
{
|
||||
_metering = false;
|
||||
expected_inputs = 0;
|
||||
save_state (_("initial state"));
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
|
@ -45,7 +45,6 @@ Send::Send (Session& s, const XMLNode& node)
|
|||
: Redirect (s, "send", PreFader)
|
||||
{
|
||||
_metering = false;
|
||||
expected_inputs = 0;
|
||||
|
||||
if (set_state (node)) {
|
||||
throw failed_constructor();
|
||||
|
|
@ -59,7 +58,6 @@ Send::Send (const Send& other)
|
|||
: Redirect (other._session, other._session.next_send_name(), other.placement())
|
||||
{
|
||||
_metering = false;
|
||||
expected_inputs = 0;
|
||||
save_state (_("initial state"));
|
||||
RedirectCreated (this); /* EMIT SIGNAL */
|
||||
}
|
||||
|
|
@ -105,37 +103,26 @@ Send::set_state(const XMLNode& node)
|
|||
}
|
||||
|
||||
void
|
||||
Send::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
Send::run (BufferSet& bufs, jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
if (active()) {
|
||||
|
||||
// we have to copy the input, because IO::deliver_output may alter the buffers
|
||||
// in-place, which a send must never do.
|
||||
|
||||
vector<Sample*>& sendbufs = _session.get_send_buffers();
|
||||
BufferSet& sendbufs = _session.get_send_buffers(bufs.count());
|
||||
|
||||
for (size_t i=0; i < nbufs; ++i) {
|
||||
memcpy (sendbufs[i], bufs[i], sizeof (Sample) * nframes);
|
||||
}
|
||||
sendbufs.read_from(bufs, nframes);
|
||||
assert(sendbufs.count() == bufs.count());
|
||||
assert(sendbufs.count() == _outputs.count());
|
||||
|
||||
|
||||
IO::deliver_output (sendbufs, nbufs, nframes, offset);
|
||||
IO::deliver_output (sendbufs, nframes, offset);
|
||||
|
||||
if (_metering) {
|
||||
uint32_t n;
|
||||
uint32_t no = n_outputs().get(DataType::AUDIO);
|
||||
|
||||
if (_gain == 0) {
|
||||
|
||||
for (n = 0; n < no; ++n) {
|
||||
_peak_power[n] = 0;
|
||||
}
|
||||
|
||||
_meter->reset();
|
||||
} else {
|
||||
|
||||
for (n = 0; n < no; ++n) {
|
||||
_peak_power[n] = Session::compute_peak (audio_output(n)->get_audio_buffer().data(nframes, offset), nframes, _peak_power[n]);
|
||||
}
|
||||
_meter->run(output_buffers(), nframes, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,12 +130,7 @@ Send::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_
|
|||
silence (nframes, offset);
|
||||
|
||||
if (_metering) {
|
||||
uint32_t n;
|
||||
uint32_t no = n_outputs().get(DataType::AUDIO);
|
||||
|
||||
for (n = 0; n < no; ++n) {
|
||||
_peak_power[n] = 0;
|
||||
}
|
||||
_meter->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -160,15 +142,15 @@ Send::set_metering (bool yn)
|
|||
|
||||
if (!_metering) {
|
||||
/* XXX possible thread hazard here */
|
||||
reset_peak_meters ();
|
||||
peak_meter().reset();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Send::expect_inputs (uint32_t expected)
|
||||
Send::expect_inputs (const ChanCount& expected)
|
||||
{
|
||||
if (expected != expected_inputs) {
|
||||
expected_inputs = expected;
|
||||
if (expected != _expected_inputs) {
|
||||
_expected_inputs = expected;
|
||||
reset_panner ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@
|
|||
#include <ardour/playlist.h>
|
||||
#include <ardour/click.h>
|
||||
#include <ardour/data_type.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
|
||||
#ifdef HAVE_LIBLO
|
||||
#include <ardour/osc.h>
|
||||
|
|
@ -256,6 +257,9 @@ Session::Session (AudioEngine &eng,
|
|||
string* mix_template)
|
||||
|
||||
: _engine (eng),
|
||||
_scratch_buffers(new BufferSet()),
|
||||
_silent_buffers(new BufferSet()),
|
||||
_send_buffers(new BufferSet()),
|
||||
_mmc_port (default_mmc_port),
|
||||
_mtc_port (default_mtc_port),
|
||||
_midi_port (default_midi_port),
|
||||
|
|
@ -307,6 +311,9 @@ Session::Session (AudioEngine &eng,
|
|||
jack_nframes_t initial_length)
|
||||
|
||||
: _engine (eng),
|
||||
_scratch_buffers(new BufferSet()),
|
||||
_silent_buffers(new BufferSet()),
|
||||
_send_buffers(new BufferSet()),
|
||||
_mmc_port (default_mmc_port),
|
||||
_mtc_port (default_mtc_port),
|
||||
_midi_port (default_midi_port),
|
||||
|
|
@ -389,17 +396,9 @@ Session::~Session ()
|
|||
|
||||
clear_clicks ();
|
||||
|
||||
for (vector<Sample*>::iterator i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i) {
|
||||
free(*i);
|
||||
}
|
||||
|
||||
for (vector<Sample*>::iterator i = _silent_buffers.begin(); i != _silent_buffers.end(); ++i) {
|
||||
free(*i);
|
||||
}
|
||||
|
||||
for (vector<Sample*>::iterator i = _send_buffers.begin(); i != _send_buffers.end(); ++i) {
|
||||
free(*i);
|
||||
}
|
||||
delete _scratch_buffers;
|
||||
delete _silent_buffers;
|
||||
delete _send_buffers;
|
||||
|
||||
AudioDiskstream::free_working_buffers();
|
||||
|
||||
|
|
@ -1444,38 +1443,10 @@ Session::set_block_size (jack_nframes_t nframes)
|
|||
|
||||
{
|
||||
Glib::RWLock::ReaderLock dsm (diskstream_lock);
|
||||
vector<Sample*>::iterator i;
|
||||
uint32_t np;
|
||||
|
||||
current_block_size = nframes;
|
||||
|
||||
for (np = 0, i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i, ++np) {
|
||||
free (*i);
|
||||
}
|
||||
|
||||
for (vector<Sample*>::iterator i = _silent_buffers.begin(); i != _silent_buffers.end(); ++i) {
|
||||
free (*i);
|
||||
}
|
||||
|
||||
_passthru_buffers.clear ();
|
||||
_silent_buffers.clear ();
|
||||
|
||||
ensure_passthru_buffers (ChanCount(DataType::AUDIO, np));
|
||||
|
||||
for (vector<Sample*>::iterator i = _send_buffers.begin(); i != _send_buffers.end(); ++i) {
|
||||
free(*i);
|
||||
|
||||
Sample *buf;
|
||||
#ifdef NO_POSIX_MEMALIGN
|
||||
buf = (Sample *) malloc(current_block_size * sizeof(Sample));
|
||||
#else
|
||||
posix_memalign((void **)&buf,16,current_block_size * 4);
|
||||
#endif
|
||||
*i = buf;
|
||||
|
||||
memset (*i, 0, sizeof (Sample) * current_block_size);
|
||||
}
|
||||
|
||||
ensure_buffers(_scratch_buffers->available());
|
||||
|
||||
if (_gain_automation_buffer) {
|
||||
delete [] _gain_automation_buffer;
|
||||
|
|
@ -3138,7 +3109,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
|
|||
AudioFileSource *
|
||||
Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
|
||||
{
|
||||
string spath = audio_path_from_name (ds.name(), ds.n_channels(), chan, destructive);
|
||||
string spath = audio_path_from_name (ds.name(), ds.n_channels().get(DataType::AUDIO), chan, destructive);
|
||||
|
||||
/* this might throw failed_constructor(), which is OK */
|
||||
|
||||
|
|
@ -3657,41 +3628,17 @@ Session::tempo_map_changed (Change ignored)
|
|||
set_dirty ();
|
||||
}
|
||||
|
||||
/** Ensures that all buffers (scratch, send, silent, etc) are allocated for
|
||||
* the given count with the current block size.
|
||||
*/
|
||||
void
|
||||
Session::ensure_passthru_buffers (ChanCount howmany)
|
||||
Session::ensure_buffers (ChanCount howmany)
|
||||
{
|
||||
// FIXME: temporary hack
|
||||
// FIXME: NASTY assumption (midi block size == audio block size)
|
||||
_scratch_buffers->ensure_buffers(howmany, current_block_size);
|
||||
_send_buffers->ensure_buffers(howmany, current_block_size);
|
||||
_silent_buffers->ensure_buffers(howmany, current_block_size);
|
||||
|
||||
while (howmany.get(DataType::AUDIO) > _passthru_buffers.size()) {
|
||||
Sample *p;
|
||||
#ifdef NO_POSIX_MEMALIGN
|
||||
p = (Sample *) malloc(current_block_size * sizeof(Sample));
|
||||
#else
|
||||
posix_memalign((void **)&p,16,current_block_size * 4);
|
||||
#endif
|
||||
_passthru_buffers.push_back (p);
|
||||
|
||||
*p = 0;
|
||||
|
||||
#ifdef NO_POSIX_MEMALIGN
|
||||
p = (Sample *) malloc(current_block_size * sizeof(Sample));
|
||||
#else
|
||||
posix_memalign((void **)&p,16,current_block_size * 4);
|
||||
#endif
|
||||
memset (p, 0, sizeof (Sample) * current_block_size);
|
||||
_silent_buffers.push_back (p);
|
||||
|
||||
*p = 0;
|
||||
|
||||
#ifdef NO_POSIX_MEMALIGN
|
||||
p = (Sample *) malloc(current_block_size * sizeof(Sample));
|
||||
#else
|
||||
posix_memalign((void **)&p,16,current_block_size * 4);
|
||||
#endif
|
||||
memset (p, 0, sizeof (Sample) * current_block_size);
|
||||
_send_buffers.push_back (p);
|
||||
|
||||
}
|
||||
allocate_pan_automation_buffers (current_block_size, howmany.get(DataType::AUDIO), false);
|
||||
}
|
||||
|
||||
|
|
@ -3860,16 +3807,16 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
|
|||
bool overwrite, vector<Source*>& srcs, InterThreadInfo& itt)
|
||||
{
|
||||
int ret = -1;
|
||||
Playlist* playlist;
|
||||
AudioFileSource* fsource;
|
||||
Playlist* playlist = 0;
|
||||
AudioFileSource* fsource = 0;
|
||||
uint32_t x;
|
||||
char buf[PATH_MAX+1];
|
||||
string dir;
|
||||
uint32_t nchans;
|
||||
ChanCount nchans(track.audio_diskstream().n_channels());
|
||||
jack_nframes_t position;
|
||||
jack_nframes_t this_chunk;
|
||||
jack_nframes_t to_do;
|
||||
vector<Sample*> buffers;
|
||||
BufferSet buffers;
|
||||
|
||||
// any bigger than this seems to cause stack overflows in called functions
|
||||
const jack_nframes_t chunk_size = (128 * 1024)/4;
|
||||
|
|
@ -3888,11 +3835,9 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
|
|||
goto out;
|
||||
}
|
||||
|
||||
nchans = track.audio_diskstream().n_channels();
|
||||
|
||||
dir = discover_best_sound_dir ();
|
||||
|
||||
for (uint32_t chan_n=0; chan_n < nchans; ++chan_n) {
|
||||
for (uint32_t chan_n=0; chan_n < nchans.get(DataType::AUDIO); ++chan_n) {
|
||||
|
||||
for (x = 0; x < 99999; ++x) {
|
||||
snprintf (buf, sizeof(buf), "%s/%s-%d-bounce-%" PRIu32 ".wav", dir.c_str(), playlist->name().c_str(), chan_n, x+1);
|
||||
|
|
@ -3928,22 +3873,14 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
|
|||
to_do = len;
|
||||
|
||||
/* create a set of reasonably-sized buffers */
|
||||
|
||||
for (vector<Sample*>::iterator i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i) {
|
||||
Sample* b;
|
||||
#ifdef NO_POSIX_MEMALIGN
|
||||
b = (Sample *) malloc(chunk_size * sizeof(Sample));
|
||||
#else
|
||||
posix_memalign((void **)&b,16,chunk_size * 4);
|
||||
#endif
|
||||
buffers.push_back (b);
|
||||
}
|
||||
buffers.ensure_buffers(nchans, chunk_size);
|
||||
buffers.set_count(nchans);
|
||||
|
||||
while (to_do && !itt.cancel) {
|
||||
|
||||
this_chunk = min (to_do, chunk_size);
|
||||
|
||||
if (track.export_stuff (buffers, nchans, start, this_chunk)) {
|
||||
if (track.export_stuff (buffers, start, this_chunk)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -3952,7 +3889,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
|
|||
AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*src);
|
||||
|
||||
if (afs) {
|
||||
if (afs->write (buffers[n], this_chunk) != this_chunk) {
|
||||
if (afs->write (buffers.get_audio(n).data(this_chunk), this_chunk) != this_chunk) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
@ -4002,10 +3939,6 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
|
|||
}
|
||||
}
|
||||
|
||||
for (vector<Sample*>::iterator i = buffers.begin(); i != buffers.end(); ++i) {
|
||||
free(*i);
|
||||
}
|
||||
|
||||
g_atomic_int_set (&processing_prohibited, 0);
|
||||
|
||||
itt.done = true;
|
||||
|
|
@ -4013,13 +3946,35 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
|
|||
return ret;
|
||||
}
|
||||
|
||||
vector<Sample*>&
|
||||
Session::get_silent_buffers (uint32_t howmany)
|
||||
BufferSet&
|
||||
Session::get_silent_buffers (ChanCount count)
|
||||
{
|
||||
for (uint32_t i = 0; i < howmany; ++i) {
|
||||
memset (_silent_buffers[i], 0, sizeof (Sample) * current_block_size);
|
||||
assert(_silent_buffers->available() >= count);
|
||||
_silent_buffers->set_count(count);
|
||||
|
||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||
for (size_t i=0; i < count.get(*t); ++i) {
|
||||
_silent_buffers->get(*t, i).clear();
|
||||
}
|
||||
return _silent_buffers;
|
||||
}
|
||||
|
||||
return *_silent_buffers;
|
||||
}
|
||||
|
||||
BufferSet&
|
||||
Session::get_scratch_buffers (ChanCount count)
|
||||
{
|
||||
assert(_scratch_buffers->available() >= count);
|
||||
_scratch_buffers->set_count(count);
|
||||
return *_scratch_buffers;
|
||||
}
|
||||
|
||||
BufferSet&
|
||||
Session::get_send_buffers (ChanCount count)
|
||||
{
|
||||
assert(_send_buffers->available() >= count);
|
||||
_send_buffers->set_count(count);
|
||||
return *_send_buffers;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <ardour/session.h>
|
||||
#include <ardour/tempo.h>
|
||||
#include <ardour/io.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
|
|
@ -42,7 +43,6 @@ Session::click (jack_nframes_t start, jack_nframes_t nframes, jack_nframes_t off
|
|||
TempoMap::BBTPointList *points;
|
||||
jack_nframes_t end;
|
||||
Sample *buf;
|
||||
vector<Sample*> bufs;
|
||||
|
||||
if (_click_io == 0) {
|
||||
return;
|
||||
|
|
@ -57,7 +57,8 @@ Session::click (jack_nframes_t start, jack_nframes_t nframes, jack_nframes_t off
|
|||
|
||||
end = start + nframes;
|
||||
|
||||
buf = _passthru_buffers[0];
|
||||
BufferSet& bufs = get_scratch_buffers(ChanCount(DataType::AUDIO, 1));
|
||||
buf = bufs.get_audio(0).data(nframes);
|
||||
points = _tempo_map->get_points (start, end);
|
||||
|
||||
if (points == 0) {
|
||||
|
|
@ -127,7 +128,7 @@ Session::click (jack_nframes_t start, jack_nframes_t nframes, jack_nframes_t off
|
|||
i = next;
|
||||
}
|
||||
|
||||
_click_io->deliver_output (_passthru_buffers, 1, nframes, offset);
|
||||
_click_io->deliver_output (bufs, nframes, offset);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ Session::prepare_diskstreams ()
|
|||
int
|
||||
Session::no_roll (jack_nframes_t nframes, jack_nframes_t offset)
|
||||
{
|
||||
jack_nframes_t end_frame = _transport_frame + nframes;
|
||||
jack_nframes_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
|
||||
int ret = 0;
|
||||
bool declick = get_transport_declick_required();
|
||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
|
|
@ -130,6 +130,9 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
|
|||
|
||||
record_active = actively_recording(); // || (get_record_enabled() && get_punch_in());
|
||||
|
||||
const jack_nframes_t start_frame = _transport_frame;
|
||||
const jack_nframes_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
|
||||
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
|
||||
int ret;
|
||||
|
|
@ -140,7 +143,7 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
|
|||
|
||||
(*i)->set_pending_declick (declick);
|
||||
|
||||
if ((ret = (*i)->roll (nframes, _transport_frame, _transport_frame + nframes, offset, declick, record_active, rec_monitors)) < 0) {
|
||||
if ((ret = (*i)->roll (nframes, start_frame, end_frame, offset, declick, record_active, rec_monitors)) < 0) {
|
||||
|
||||
/* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
|
||||
and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
|
||||
|
|
@ -172,6 +175,9 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset)
|
|||
declick = -1;
|
||||
}
|
||||
|
||||
const jack_nframes_t start_frame = _transport_frame;
|
||||
const jack_nframes_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
|
||||
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
|
||||
int ret;
|
||||
|
|
@ -180,7 +186,7 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset)
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((ret = (*i)->silent_roll (nframes, _transport_frame, _transport_frame + nframes, offset, record_active, rec_monitors)) < 0) {
|
||||
if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, offset, record_active, rec_monitors)) < 0) {
|
||||
|
||||
/* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
|
||||
and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
|||
Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
|
||||
Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
|
||||
|
||||
IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
|
||||
IO::MoreChannels.connect (mem_fun (*this, &Session::ensure_buffers));
|
||||
|
||||
/* stop IO objects from doing stuff until we're ready for them */
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ void
|
|||
Track::toggle_monitor_input ()
|
||||
{
|
||||
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
|
||||
(*i)->request_monitor_input(!(*i)->monitoring_input());
|
||||
i->request_monitor_input(!i->monitoring_input());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ Track::can_record()
|
|||
{
|
||||
bool will_record = true;
|
||||
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end() && will_record; ++i) {
|
||||
if (!(*i)->connected())
|
||||
if (!i->connected())
|
||||
will_record = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <ardour/session.h>
|
||||
#include <ardour/route.h>
|
||||
#include <ardour/audio_track.h>
|
||||
|
||||
#include <ardour/meter.h>
|
||||
#include <control_protocol/control_protocol.h>
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
|
@ -253,7 +253,7 @@ ControlProtocol::route_get_peak_input_power (uint32_t table_index, uint32_t whic
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
return r->peak_input_power (which_input);
|
||||
return r->peak_meter().peak_power (which_input);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue