summaryrefslogtreecommitdiffstats
path: root/src/server/InputPort.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2014-08-31 01:24:57 +0000
committerDavid Robillard <d@drobilla.net>2014-08-31 01:24:57 +0000
commita2792bd09212eed55bba1aa30dc09043a6955486 (patch)
treed4262f760d4522bc6f1c99778987aada332b9e7e /src/server/InputPort.cpp
parente3ecb2b439bd03d27b5e11efe430c24f0ebe6283 (diff)
downloadingen-a2792bd09212eed55bba1aa30dc09043a6955486.tar.gz
ingen-a2792bd09212eed55bba1aa30dc09043a6955486.tar.bz2
ingen-a2792bd09212eed55bba1aa30dc09043a6955486.zip
Use float sequences for sample-accurate control ports.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5462 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/server/InputPort.cpp')
-rw-r--r--src/server/InputPort.cpp103
1 files changed, 67 insertions, 36 deletions
diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp
index e0406f05..3e345f8d 100644
--- a/src/server/InputPort.cpp
+++ b/src/server/InputPort.cpp
@@ -75,6 +75,10 @@ InputPort::get_buffers(BufferFactory& bufs,
{
const size_t num_arcs = real_time ? _arcs.size() : _num_arcs;
+ if (is_a(PortType::ATOM) && !_value.is_valid()) {
+ poly = 1;
+ }
+
if (is_a(PortType::AUDIO) && num_arcs == 0) {
// Audio input with no arcs, use shared zero buffer
for (uint32_t v = 0; v < poly; ++v) {
@@ -97,7 +101,8 @@ InputPort::get_buffers(BufferFactory& bufs,
// Otherwise, allocate local buffers
for (uint32_t v = 0; v < poly; ++v) {
voices->at(v).buffer.reset();
- voices->at(v).buffer = bufs.get_buffer(buffer_type(), _buffer_size, real_time);
+ voices->at(v).buffer = bufs.get_buffer(
+ buffer_type(), _value.type(), _buffer_size, real_time);
voices->at(v).buffer->clear();
}
return true;
@@ -135,34 +140,16 @@ InputPort::max_tail_poly(Context& context) const
return parent_block()->parent_graph()->internal_poly_process();
}
-static void
-get_sources(const Context& context,
- const ArcImpl& arc,
- uint32_t voice,
- const Buffer** srcs,
- uint32_t max_num_srcs,
- uint32_t& num_srcs)
-{
- if (arc.must_mix()) {
- // Mixing down voices: all tail voices => one head voice
- for (uint32_t v = 0; v < arc.tail()->poly(); ++v) {
- assert(num_srcs < max_num_srcs);
- srcs[num_srcs++] = arc.tail()->buffer(v).get();
- }
- } else {
- // Matching polyphony: each tail voice => corresponding head voice
- assert(arc.tail()->poly() == arc.head()->poly());
- assert(num_srcs < max_num_srcs);
- srcs[num_srcs++] = arc.tail()->buffer(voice).get();
- }
-}
-
void
InputPort::pre_process(Context& context)
{
- // If value has been set (e.g. events pushed) by the user, don't smash it
- if (_set_by_user)
+ if (_set_by_user) {
+ // Value has been set (e.g. events pushed) by the user, don't smash it
+ for (uint32_t v = 0; v < _poly; ++v) {
+ buffer(v)->update_value_buffer(context.offset());
+ }
return;
+ }
if (_arcs.empty()) {
for (uint32_t v = 0; v < _poly; ++v) {
@@ -173,30 +160,74 @@ InputPort::pre_process(Context& context)
_voices->at(v).buffer = _arcs.front().buffer(v);
}
} else {
- const uint32_t src_poly = max_tail_poly(context);
- const uint32_t max_num_srcs = _arcs.size() * src_poly;
+ // Mix down to local buffers in pre_run()
+ for (uint32_t v = 0; v < _poly; ++v) {
+ buffer(v)->prepare_write(context);
+ }
+ }
+}
+
+void
+InputPort::pre_run(Context& context)
+{
+ if (!_set_by_user && !_arcs.empty() && !direct_connect()) {
+ const uint32_t src_poly = max_tail_poly(context);
+ const uint32_t max_n_srcs = _arcs.size() * src_poly;
- const Buffer* srcs[max_num_srcs];
for (uint32_t v = 0; v < _poly; ++v) {
- // Get all the sources for this voice
- uint32_t num_srcs = 0;
- for (const auto& a : _arcs) {
- get_sources(context, a, v, srcs, max_num_srcs, num_srcs);
+ // Get all sources for this voice
+ const Buffer* srcs[max_n_srcs];
+ uint32_t n_srcs = 0;
+ for (const auto& arc : _arcs) {
+ if (_poly == 1) {
+ // P -> 1 or 1 -> 1: all tail voices => each head voice
+ for (uint32_t w = 0; w < arc.tail()->poly(); ++w) {
+ assert(n_srcs < max_n_srcs);
+ srcs[n_srcs++] = arc.buffer(w, context.offset()).get();
+ assert(srcs[n_srcs - 1]);
+ }
+ } else {
+ // P -> P or 1 -> P: tail voice => corresponding head voice
+ assert(n_srcs < max_n_srcs);
+ srcs[n_srcs++] = arc.buffer(v, context.offset()).get();
+ assert(srcs[n_srcs - 1]);
+ }
}
- // Then mix them into out buffer for this voice
- mix(context, buffer(v).get(), srcs, num_srcs);
+ // Then mix them into our buffer for this voice
+ mix(context, buffer(v).get(), srcs, n_srcs);
}
}
+}
- if (!_arcs.empty()) {
- monitor(context);
+SampleCount
+InputPort::next_value_offset(SampleCount offset, SampleCount end) const
+{
+ SampleCount earliest = end;
+ for (const auto& arc : _arcs) {
+ if (arc.tail()->type() != this->type()) {
+ const SampleCount o = arc.tail()->next_value_offset(offset, end);
+ if (o < earliest) {
+ earliest = o;
+ }
+ }
}
+ return earliest;
+}
+
+void
+InputPort::update_values(SampleCount offset)
+{
}
void
InputPort::post_process(Context& context)
{
+ if (!_arcs.empty() || _force_monitor_update) {
+ monitor(context, _force_monitor_update);
+ _force_monitor_update = false;
+ }
+
if (_set_by_user) {
if (_buffer_type == _bufs.uris().atom_Sequence) {
// Clear events received via a SetPortValue