Reduce overhead of multi-type-ness (last Summer's SoC):

Use uint32_t instead of size_t counts (halves size of ChanCount on 64-bit).
	Shift DataType values down to eliminate subtraction every index of a ChanCount or *Set.

Allow using DataType directly as an array index (prettier/terser).
Fix some mixed spaces/tabs in file comment headers.


git-svn-id: svn://localhost/ardour2/trunk@2082 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2007-06-29 06:58:07 +00:00
parent 44867662a3
commit eb296b2c95
18 changed files with 76 additions and 66 deletions

View file

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2007 Paul Davis Copyright (C) 2007 Paul Davis
Author: Dave Robillard Author: Dave Robillard
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2007 Paul Davis Copyright (C) 2007 Paul Davis
Author: Dave Robillard Author: Dave Robillard
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -270,8 +270,8 @@ PluginSelector::input_refiller ()
// Insert into GTK list // Insert into GTK list
for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) { for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
snprintf (ibuf, sizeof(ibuf)-1, "%zu", (*i)->n_inputs.n_total()); snprintf (ibuf, sizeof(ibuf)-1, "%u", (*i)->n_inputs.n_total());
snprintf (obuf, sizeof(obuf)-1, "%zu", (*i)->n_outputs.n_total()); snprintf (obuf, sizeof(obuf)-1, "%u", (*i)->n_outputs.n_total());
Gtk::TreeModel::Row newrow = *(lmodel->append()); Gtk::TreeModel::Row newrow = *(lmodel->append());
newrow[lcols.name] = (*i)->name.c_str(); newrow[lcols.name] = (*i)->name.c_str();

View file

@ -48,7 +48,7 @@ public:
void read_from(const Buffer& src, nframes_t len, nframes_t offset) void read_from(const Buffer& src, nframes_t len, nframes_t offset)
{ {
assert(_capacity > 0); assert(_capacity > 0);
assert(src.type() == _type == DataType::AUDIO); assert(src.type() == DataType::AUDIO);
assert(offset + len <= _capacity); assert(offset + len <= _capacity);
memcpy(_data + offset, ((AudioBuffer&)src).data(), sizeof(Sample) * len); memcpy(_data + offset, ((AudioBuffer&)src).data(), sizeof(Sample) * len);
_silent = src.silent(); _silent = src.silent();

View file

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2007 Paul Davis Copyright (C) 2007 Paul Davis
Author: Dave Robillard Author: Dave Robillard
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -71,7 +71,7 @@ public:
Buffer& get(DataType type, size_t i) Buffer& get(DataType type, size_t i)
{ {
assert(i <= _count.get(type)); assert(i <= _count.get(type));
return *_buffers[type.to_index()][i]; return *_buffers[type][i];
} }
AudioBuffer& get_audio(size_t i) AudioBuffer& get_audio(size_t i)
@ -140,7 +140,7 @@ public:
private: private:
typedef std::vector<Buffer*> BufferVec; typedef std::vector<Buffer*> BufferVec;
/// Vector of vectors, indexed by DataType::to_index() /// Vector of vectors, indexed by DataType
std::vector<BufferVec> _buffers; std::vector<BufferVec> _buffers;
/// Use counts (there may be more actual buffers than this) /// Use counts (there may be more actual buffers than this)

View file

@ -1,5 +1,6 @@
/* /*
Copyright (C) 2006 Paul Davis Copyright (C) 2006 Paul Davis
Author: Dave Robillard
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -14,24 +15,28 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: insert.cc 712 2006-07-28 01:08:57Z drobilla $
*/ */
#ifndef __ardour_chan_count_h__ #ifndef __ardour_chan_count_h__
#define __ardour_chan_count_h__ #define __ardour_chan_count_h__
#include <ardour/data_type.h> #include <ardour/data_type.h>
#include <cassert>
namespace ARDOUR { namespace ARDOUR {
/** A count of channels, possibly with many types.
*
* Operators are defined so this may safely be used as if it were a simple
* (single-typed) integer count of channels.
*/
class ChanCount { class ChanCount {
public: public:
ChanCount() { reset(); } ChanCount() { reset(); }
// Convenience constructor for making single-typed streams (stereo, mono, etc) // Convenience constructor for making single-typed streams (stereo, mono, etc)
ChanCount(DataType type, size_t channels) ChanCount(DataType type, uint32_t channels)
{ {
reset(); reset();
set(type, channels); set(type, channels);
@ -40,31 +45,31 @@ public:
void reset() void reset()
{ {
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
_counts[(*t).to_index()] = 0; _counts[*t] = 0;
} }
} }
// -1 is what to_index does. inlined for speed. this should maybe be changed.. void set(DataType t, uint32_t count) { assert(t != DataType::NIL); _counts[t] = count; }
inline size_t n_audio() const { return _counts[DataType::AUDIO-1]; } uint32_t get(DataType t) const { assert(t != DataType::NIL); return _counts[t]; }
inline size_t n_midi() const { return _counts[DataType::MIDI-1]; }
inline void set_audio(size_t a) { _counts[DataType::AUDIO-1] = a; }
inline void set_midi(size_t m) { _counts[DataType::MIDI-1] = m; }
size_t n_total() const inline uint32_t n_audio() const { return _counts[DataType::AUDIO]; }
inline void set_audio(uint32_t a) { _counts[DataType::AUDIO] = a; }
inline uint32_t n_midi() const { return _counts[DataType::MIDI]; }
inline void set_midi(uint32_t m) { _counts[DataType::MIDI] = m; }
uint32_t n_total() const
{ {
size_t ret = 0; uint32_t ret = 0;
for (size_t i=0; i < DataType::num_types; ++i) for (uint32_t i=0; i < DataType::num_types; ++i)
ret += _counts[i]; ret += _counts[i];
return ret; return ret;
} }
void set(DataType type, size_t count) { _counts[type.to_index()] = count; }
size_t get(DataType type) const { return _counts[type.to_index()]; }
bool operator==(const ChanCount& other) const bool operator==(const ChanCount& other) const
{ {
for (size_t i=0; i < DataType::num_types; ++i) for (uint32_t i=0; i < DataType::num_types; ++i)
if (_counts[i] != other._counts[i]) if (_counts[i] != other._counts[i])
return false; return false;
@ -79,7 +84,7 @@ public:
bool operator<(const ChanCount& other) const bool operator<(const ChanCount& other) const
{ {
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
if (_counts[(*t).to_index()] > other._counts[(*t).to_index()]) { if (_counts[*t] > other._counts[*t]) {
return false; return false;
} }
} }
@ -94,7 +99,7 @@ public:
bool operator>(const ChanCount& other) const bool operator>(const ChanCount& other) const
{ {
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
if (_counts[(*t).to_index()] < other._counts[(*t).to_index()]) { if (_counts[*t] < other._counts[*t]) {
return false; return false;
} }
} }
@ -111,7 +116,7 @@ public:
private: private:
size_t _counts[DataType::num_types]; uint32_t _counts[DataType::num_types];
}; };

View file

@ -1,5 +1,6 @@
/* /*
Copyright (C) 2006 Paul Davis Copyright (C) 2006 Paul Davis
Author: Dave Robillard
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free
@ -35,17 +36,25 @@ namespace ARDOUR {
class DataType class DataType
{ {
public: public:
/// WARNING: make REALLY sure you don't mess up indexes if you change this /** Numeric symbol for this DataType.
*
* Castable to int for use as an array index (e.g. by ChanCount).
* Note this means NIL is (ntypes-1) and guaranteed to change when
* types are added, so this number is NOT suitable for serialization,
* network, or binary anything.
*
* WARNING: The number of non-NIL entries here must match num_types.
*/
enum Symbol { enum Symbol {
NIL = 0, AUDIO = 0,
AUDIO, MIDI = 1,
MIDI NIL = 2,
}; };
/** Number of types (not including NIL). /** Number of types (not including NIL).
* WARNING: make sure this matches Symbol! * WARNING: make sure this matches Symbol!
*/ */
static const size_t num_types = 2; static const uint32_t num_types = 2;
DataType(const Symbol& symbol) DataType(const Symbol& symbol)
: _symbol(symbol) : _symbol(symbol)
@ -54,17 +63,12 @@ public:
/** Construct from a string (Used for loading from XML and Ports) /** Construct from a string (Used for loading from XML and Ports)
* The string can be as in an XML file (eg "audio" or "midi"), or a * The string can be as in an XML file (eg "audio" or "midi"), or a
* Jack type string (from jack_port_type) */ * Jack type string (from jack_port_type) */
DataType(const std::string& str) { DataType(const std::string& str)
if (str == "audio") : _symbol(NIL) {
if (str == "audio" || str == JACK_DEFAULT_AUDIO_TYPE)
_symbol = AUDIO; _symbol = AUDIO;
else if (str == JACK_DEFAULT_AUDIO_TYPE) else if (str == "midi" || str == JACK_DEFAULT_MIDI_TYPE)
_symbol = AUDIO;
else if (str == "midi")
_symbol = MIDI; _symbol = MIDI;
else if (str == JACK_DEFAULT_MIDI_TYPE)
_symbol = MIDI;
else
_symbol = NIL;
} }
/** Get the Jack type this DataType corresponds to */ /** Get the Jack type this DataType corresponds to */
@ -85,8 +89,7 @@ public:
} }
} }
//Symbol to_symbol() const { return _symbol; } inline operator uint32_t() const { return (uint32_t)_symbol; }
inline size_t to_index() const { return (size_t)_symbol - 1; }
/** DataType iterator, for writing generic loops that iterate over all /** DataType iterator, for writing generic loops that iterate over all
* available types. * available types.
@ -94,7 +97,7 @@ public:
class iterator { class iterator {
public: public:
iterator(size_t index) : _index(index) {} iterator(uint32_t index) : _index(index) {}
DataType operator*() { return DataType((Symbol)_index); } DataType operator*() { return DataType((Symbol)_index); }
iterator& operator++() { ++_index; return *this; } // yes, prefix only iterator& operator++() { ++_index; return *this; } // yes, prefix only
@ -104,11 +107,11 @@ public:
private: private:
friend class DataType; friend class DataType;
size_t _index; uint32_t _index;
}; };
static iterator begin() { return iterator(1); } static iterator begin() { return iterator(0); }
static iterator end() { return iterator(num_types+1); } static iterator end() { return iterator(num_types); }
bool operator==(const Symbol symbol) { return (_symbol == symbol); } bool operator==(const Symbol symbol) { return (_symbol == symbol); }
bool operator!=(const Symbol symbol) { return (_symbol != symbol); } bool operator!=(const Symbol symbol) { return (_symbol != symbol); }
@ -117,7 +120,7 @@ public:
bool operator!=(const DataType other) { return (_symbol != other._symbol); } bool operator!=(const DataType other) { return (_symbol != other._symbol); }
private: private:
Symbol _symbol; Symbol _symbol; // could be const if not for the string constructor
}; };

View file

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2006 Paul Davis Copyright (C) 2006 Paul Davis
Author: Dave Robillard Author: Dave Robillard
This program is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the Free

View file

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2006 Paul Davis Copyright (C) 2006 Paul Davis
Author: Dave Robillard Author: Dave Robillard
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -39,7 +39,7 @@ public:
PortSet(); PortSet();
size_t num_ports() const; size_t num_ports() const;
size_t num_ports(DataType type) const { return _ports[type.to_index()].size(); } size_t num_ports(DataType type) const { return _ports[type].size(); }
void add(Port* port); void add(Port* port);
bool remove(Port* port); bool remove(Port* port);

View file

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2007 Paul Davis Copyright (C) 2007 Paul Davis
Author: Dave Robillard Author: Dave Robillard
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View file

@ -67,7 +67,7 @@ BufferSet::attach_buffers(PortSet& ports)
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
_buffers.push_back(BufferVec()); _buffers.push_back(BufferVec());
BufferVec& v = _buffers[(*t).to_index()]; BufferVec& v = _buffers[*t];
for (PortSet::iterator p = ports.begin(*t); p != ports.end(*t); ++p) { for (PortSet::iterator p = ports.begin(*t); p != ports.end(*t); ++p) {
assert(p->type() == *t); assert(p->type() == *t);
@ -97,13 +97,13 @@ void
BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capacity) BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capacity)
{ {
assert(type != DataType::NIL); assert(type != DataType::NIL);
assert(type.to_index() < _buffers.size()); assert(type < _buffers.size());
if (num_buffers == 0) if (num_buffers == 0)
return; return;
// The vector of buffers of the type we care about // The vector of buffers of the type we care about
BufferVec& bufs = _buffers[type.to_index()]; BufferVec& bufs = _buffers[type];
// If we're a mirror just make sure we're ok // If we're a mirror just make sure we're ok
if (_is_mirror) { if (_is_mirror) {
@ -146,7 +146,7 @@ size_t
BufferSet::buffer_capacity(DataType type) const BufferSet::buffer_capacity(DataType type) const
{ {
assert(_available.get(type) > 0); assert(_available.get(type) > 0);
return _buffers[type.to_index()][0]->capacity(); return _buffers[type][0]->capacity();
} }
// FIXME: make 'in' const // FIXME: make 'in' const

View file

@ -33,7 +33,7 @@ infinity_factory()
ChanCount ret; ChanCount ret;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
ret.set(*t, SIZE_MAX); ret.set(*t, UINT32_MAX);
} }
return ret; return ret;

View file

@ -36,7 +36,7 @@ namespace ARDOUR {
void void
PeakMeter::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) PeakMeter::run (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
{ {
size_t meterable = std::min(bufs.count().n_total(), _peak_power.size()); size_t meterable = std::min((size_t)bufs.count().n_total(), _peak_power.size());
size_t n = 0; size_t n = 0;

View file

@ -34,17 +34,14 @@ static bool sort_ports_by_name (Port* a, Port* b)
void void
PortSet::add(Port* port) PortSet::add(Port* port)
{ {
const size_t list_index = port->type().to_index(); PortVec& v = _ports[port->type()];
assert(list_index < _ports.size());
PortVec& v = _ports[list_index];
v.push_back(port); v.push_back(port);
sort(v.begin(), v.end(), sort_ports_by_name); sort(v.begin(), v.end(), sort_ports_by_name);
_count.set(port->type(), _count.get(port->type()) + 1); _count.set(port->type(), _count.get(port->type()) + 1);
assert(_count.get(port->type()) == _ports[port->type().to_index()].size()); assert(_count.get(port->type()) == _ports[port->type()].size());
} }
bool bool
@ -108,7 +105,7 @@ PortSet::port(DataType type, size_t n) const
if (type == DataType::NIL) { if (type == DataType::NIL) {
return port(n); return port(n);
} else { } else {
const PortVec& v = _ports[type.to_index()]; const PortVec& v = _ports[type];
assert(n < v.size()); assert(n < v.size());
return v[n]; return v[n];
} }

View file

@ -2308,7 +2308,7 @@ Route::pans_required () const
return 0; return 0;
} }
return max (n_inputs ().n_audio(), static_cast<size_t>(processor_max_outs.n_audio())); return max (n_inputs ().n_audio(), processor_max_outs.n_audio());
} }
int int

View file

@ -3678,7 +3678,12 @@ Session::tempo_map_changed (Change ignored)
void void
Session::ensure_buffers (ChanCount howmany) Session::ensure_buffers (ChanCount howmany)
{ {
// FIXME: NASTY assumption (midi block size == audio block size) // We need at least 1 MIDI scratch buffer to mix/merge
if (howmany.n_midi() < 1)
howmany.set_midi(1);
// FIXME: JACK needs to tell us maximum MIDI buffer size
// Using nasty assumption (max # events == nframes) for now
_scratch_buffers->ensure_buffers(howmany, current_block_size); _scratch_buffers->ensure_buffers(howmany, current_block_size);
_send_buffers->ensure_buffers(howmany, current_block_size); _send_buffers->ensure_buffers(howmany, current_block_size);
_silent_buffers->ensure_buffers(howmany, current_block_size); _silent_buffers->ensure_buffers(howmany, current_block_size);