summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-01-05 02:31:33 +0000
committerDavid Robillard <d@drobilla.net>2010-01-05 02:31:33 +0000
commitf1a8e02f49de5545b69af7afeaff376a1c47f1f8 (patch)
tree721e3f53786c7dd1579c1f72b396cf11e62bcc5e /src
parent13eaacac207abce0b99159b29ea06df47c4c0e15 (diff)
downloadingen-f1a8e02f49de5545b69af7afeaff376a1c47f1f8.tar.gz
ingen-f1a8e02f49de5545b69af7afeaff376a1c47f1f8.tar.bz2
ingen-f1a8e02f49de5545b69af7afeaff376a1c47f1f8.zip
Event mixing.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2337 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/engine/BufferFactory.cpp21
-rw-r--r--src/engine/BufferFactory.hpp2
-rw-r--r--src/engine/ConnectionImpl.cpp2
-rw-r--r--src/engine/InputPort.cpp2
-rw-r--r--src/engine/mix.hpp84
5 files changed, 99 insertions, 12 deletions
diff --git a/src/engine/BufferFactory.cpp b/src/engine/BufferFactory.cpp
index d84cf658..aff44254 100644
--- a/src/engine/BufferFactory.cpp
+++ b/src/engine/BufferFactory.cpp
@@ -46,17 +46,20 @@ struct BufferDeleter {
SharedPtr<Buffer>
-BufferFactory::get(Shared::PortType type, size_t size)
+BufferFactory::get(Shared::PortType type, size_t size, bool force_create)
{
Raul::AtomicPtr<Buffer>& head_ptr = free_list(type);
- Buffer* try_head;
- Buffer* next;
- do {
- try_head = head_ptr.get();
- if (!try_head)
- break;
- next = try_head->_next;
- } while (!head_ptr.compare_and_exchange(try_head, next));
+ Buffer* try_head = NULL;
+
+ if (!force_create) {
+ Buffer* next;
+ do {
+ try_head = head_ptr.get();
+ if (!try_head)
+ break;
+ next = try_head->_next;
+ } while (!head_ptr.compare_and_exchange(try_head, next));
+ }
if (!try_head) {
if (ThreadManager::current_thread_id() != THREAD_PROCESS) {
diff --git a/src/engine/BufferFactory.hpp b/src/engine/BufferFactory.hpp
index 25164db9..d6e0b70c 100644
--- a/src/engine/BufferFactory.hpp
+++ b/src/engine/BufferFactory.hpp
@@ -36,7 +36,7 @@ class BufferFactory {
public:
BufferFactory(Engine& engine, SharedPtr<Shared::LV2URIMap> map);
- SharedPtr<Buffer> get(Shared::PortType type, size_t size=0);
+ SharedPtr<Buffer> get(Shared::PortType type, size_t size=0, bool force_create=false);
private:
friend class BufferDeleter;
diff --git a/src/engine/ConnectionImpl.cpp b/src/engine/ConnectionImpl.cpp
index b64875c2..f934fc21 100644
--- a/src/engine/ConnectionImpl.cpp
+++ b/src/engine/ConnectionImpl.cpp
@@ -51,7 +51,7 @@ ConnectionImpl::ConnectionImpl(BufferFactory& bufs, PortImpl* src_port, PortImpl
assert(src_port->path() != dst_port->path());
if (must_mix() || must_queue())
- _local_buffer = bufs.get(dst_port->type(), dst_port->buffer_size());
+ _local_buffer = bufs.get(dst_port->type(), dst_port->buffer_size(), true);
if (must_queue())
diff --git a/src/engine/InputPort.cpp b/src/engine/InputPort.cpp
index b980f2e6..4a1a8136 100644
--- a/src/engine/InputPort.cpp
+++ b/src/engine/InputPort.cpp
@@ -124,7 +124,7 @@ InputPort::connect_buffers()
// Use local buffers
} else {
for (uint32_t v = 0; v < _poly; ++v)
- _buffers->at(v) = _bufs.get(type()); // Use local buffer
+ _buffers->at(v) = _bufs.get(_type, _buffer_size); // Use local buffer
}
// Connect node to buffers
diff --git a/src/engine/mix.hpp b/src/engine/mix.hpp
new file mode 100644
index 00000000..a4cd16d8
--- /dev/null
+++ b/src/engine/mix.hpp
@@ -0,0 +1,84 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen 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.
+ *
+ * Ingen 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 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MIX_HPP
+#define MIX_HPP
+
+#include <iostream>
+#include "interface/PortType.hpp"
+#include "Buffer.hpp"
+#include "Context.hpp"
+
+namespace Ingen {
+
+inline void
+mix(Context& context, Buffer* dst, const Buffer*const* srcs, uint32_t num_srcs)
+{
+ using Shared::PortType;
+ switch (dst->type().symbol()) {
+ case PortType::AUDIO:
+ case PortType::CONTROL:
+ // Copy the first source
+ dst->copy(context, srcs[0]);
+
+ // Mix in the rest
+ for (uint32_t i = 1; i < num_srcs; ++i) {
+ assert(srcs[i]->type() == PortType::AUDIO || srcs[i]->type() == PortType::CONTROL);
+ ((AudioBuffer*)dst)->accumulate(context, (AudioBuffer*)srcs[i]);
+ }
+
+ break;
+
+ case PortType::EVENTS:
+ dst->clear();
+ for (uint32_t i = 0; i < num_srcs; ++i) {
+ assert(srcs[i]->type() == PortType::EVENTS);
+ srcs[i]->rewind();
+ }
+
+ while (true) {
+ const EventBuffer* first = NULL;
+ for (uint32_t i = 0; i < num_srcs; ++i) {
+ const EventBuffer* const src = (const EventBuffer*)srcs[i];
+ if (src->is_valid()) {
+ if (!first || src->get_event()->frames < first->get_event()->frames)
+ first = src;
+ }
+ }
+ if (first) {
+ const LV2_Event* const ev = first->get_event();
+ ((EventBuffer*)dst)->append(
+ ev->frames, ev->subframes, ev->type, ev->size,
+ (const uint8_t*)ev + sizeof(LV2_Event));
+ first->increment();
+ } else {
+ break;
+ }
+ }
+
+ dst->rewind();
+ break;
+
+ default:
+ std::cerr << "ERROR: Mix of unsupported buffer types" << std::endl;
+ return;
+ }
+}
+
+} // namespace Ingen
+
+#endif // MIX_HPP