- Oscillator - VCA - Noise - Step Sequencer - MIDI CC to CV Also added the infrastructure to use Faust for creating new processors (used by the Oscillator, VCA and Noise nodes).looper
parent
1a4435dd71
commit
5ca602b9e4
@ -0,0 +1,169 @@
|
||||
# @begin:license
|
||||
#
|
||||
# Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
|
||||
#
|
||||
# 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.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# @end:license
|
||||
|
||||
from distutils import core
|
||||
from distutils.command.build import build
|
||||
from distutils.command.install import install
|
||||
import urllib.request
|
||||
import os
|
||||
import os.path
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import zipfile
|
||||
|
||||
VERSION = '2.15.11'
|
||||
DOWNLOAD_URL = 'https://github.com/grame-cncm/faust/archive/%s.zip' % VERSION
|
||||
|
||||
assert os.getenv('VIRTUAL_ENV'), "Not running in a virtualenv."
|
||||
|
||||
|
||||
class FaustMixin(object):
|
||||
user_options = [
|
||||
('build-base=', 'b',
|
||||
"base directory for build library"),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_base = os.path.join(os.getenv('VIRTUAL_ENV'), 'build', 'faust')
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def zip_path(self):
|
||||
return os.path.join(self.build_base, 'faust-%s.zip' % VERSION)
|
||||
|
||||
@property
|
||||
def src_dir(self):
|
||||
return os.path.join(self.build_base, 'src-%s' % VERSION)
|
||||
|
||||
|
||||
class BuildFaust(FaustMixin, core.Command):
|
||||
def run(self):
|
||||
if not os.path.isdir(self.build_base):
|
||||
os.makedirs(self.build_base)
|
||||
|
||||
self._download_zip(self.zip_path)
|
||||
self._unpack_zip(self.zip_path, self.src_dir)
|
||||
self._make(self.src_dir)
|
||||
|
||||
def _download_zip(self, zip_path):
|
||||
if os.path.exists(zip_path):
|
||||
return
|
||||
|
||||
total_bytes = 0
|
||||
with urllib.request.urlopen(DOWNLOAD_URL) as fp_in:
|
||||
with open(zip_path + '.partial', 'wb') as fp_out:
|
||||
last_report = time.time()
|
||||
try:
|
||||
while True:
|
||||
dat = fp_in.read(10240)
|
||||
if not dat:
|
||||
break
|
||||
fp_out.write(dat)
|
||||
total_bytes += len(dat)
|
||||
if time.time() - last_report > 1:
|
||||
sys.stderr.write(
|
||||
'Downloading %s: %d bytes\r'
|
||||
% (DOWNLOAD_URL, total_bytes))
|
||||
sys.stderr.flush()
|
||||
last_report = time.time()
|
||||
finally:
|
||||
sys.stderr.write('\033[K')
|
||||
sys.stderr.flush()
|
||||
|
||||
os.rename(zip_path + '.partial', zip_path)
|
||||
print('Downloaded %s: %d bytes' % (DOWNLOAD_URL, total_bytes))
|
||||
|
||||
def _unpack_zip(self, zip_path, src_dir):
|
||||
if os.path.isdir(src_dir):
|
||||
return
|
||||
|
||||
print("Extracting...")
|
||||
|
||||
base_dir = None
|
||||
with zipfile.ZipFile(zip_path) as fp:
|
||||
for path in fp.namelist():
|
||||
while path:
|
||||
path, b = os.path.split(path)
|
||||
if not path:
|
||||
if base_dir is None:
|
||||
base_dir = b
|
||||
elif b != base_dir:
|
||||
raise RuntimeError(
|
||||
"No common base dir (%s)" % b)
|
||||
|
||||
fp.extractall(self.build_base)
|
||||
|
||||
os.rename(os.path.join(self.build_base, base_dir), src_dir)
|
||||
print("Extracted to %s" % src_dir)
|
||||
return src_dir
|
||||
|
||||
def _make(self, make_dir):
|
||||
if os.path.exists(os.path.join(make_dir, '.build.complete')):
|
||||
return
|
||||
|
||||
print("Running make...")
|
||||
subprocess.run(
|
||||
['make',
|
||||
'-j8',
|
||||
'PREFIX=' + os.getenv('VIRTUAL_ENV'),
|
||||
'compiler'],
|
||||
cwd=make_dir,
|
||||
check=True)
|
||||
open(os.path.join(make_dir, '.build.complete'), 'w').close()
|
||||
|
||||
|
||||
class InstallFaust(FaustMixin, core.Command):
|
||||
@property
|
||||
def sentinel_path(self):
|
||||
return os.path.join(
|
||||
os.getenv('VIRTUAL_ENV'), '.faust-%s-installed' % VERSION)
|
||||
|
||||
def run(self):
|
||||
if os.path.exists(self.sentinel_path):
|
||||
return
|
||||
|
||||
print("Running make install...")
|
||||
subprocess.run(
|
||||
['make',
|
||||
'PREFIX=' + os.getenv('VIRTUAL_ENV'),
|
||||
'install'],
|
||||
cwd=self.src_dir,
|
||||
check=True)
|
||||
open(self.sentinel_path, 'w').close()
|
||||
|
||||
def get_outputs(self):
|
||||
return [self.sentinel_path]
|
||||
|
||||
|
||||
build.sub_commands.append(('build_faust', None))
|
||||
install.sub_commands.insert(0, ('install_faust', None))
|
||||
|
||||
|
||||
core.setup(
|
||||
name = 'faust',
|
||||
version = VERSION,
|
||||
cmdclass = {
|
||||
'build_faust': BuildFaust,
|
||||
'install_faust': InstallFaust,
|
||||
},
|
||||
)
|
@ -0,0 +1,157 @@
|
||||
# @begin:license
|
||||
#
|
||||
# Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
|
||||
#
|
||||
# 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.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# @end:license
|
||||
|
||||
from distutils import core
|
||||
from distutils.command.build import build
|
||||
from distutils.command.install import install
|
||||
import urllib.request
|
||||
import os
|
||||
import os.path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import zipfile
|
||||
|
||||
VERSION = '0.20190330'
|
||||
COMMIT_ID = '64a57f5693573ed73409f16c0d7ba420cde6111e'
|
||||
DOWNLOAD_URL = 'https://github.com/grame-cncm/faustlibraries/archive/%s.zip' % COMMIT_ID
|
||||
|
||||
assert os.getenv('VIRTUAL_ENV'), "Not running in a virtualenv."
|
||||
|
||||
|
||||
class FaustLibrariesMixin(object):
|
||||
user_options = [
|
||||
('build-base=', 'b',
|
||||
"base directory for build library"),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_base = os.path.join(os.getenv('VIRTUAL_ENV'), 'build', 'faustlibraries')
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def zip_path(self):
|
||||
return os.path.join(self.build_base, 'faustlibraries-%s.zip' % VERSION)
|
||||
|
||||
@property
|
||||
def src_dir(self):
|
||||
return os.path.join(self.build_base, 'src-%s' % VERSION)
|
||||
|
||||
|
||||
class BuildFaustLibraries(FaustLibrariesMixin, core.Command):
|
||||
def run(self):
|
||||
if not os.path.isdir(self.build_base):
|
||||
os.makedirs(self.build_base)
|
||||
|
||||
self._download_zip(self.zip_path)
|
||||
self._unpack_zip(self.zip_path, self.src_dir)
|
||||
|
||||
def _download_zip(self, zip_path):
|
||||
if os.path.exists(zip_path):
|
||||
return
|
||||
|
||||
total_bytes = 0
|
||||
with urllib.request.urlopen(DOWNLOAD_URL) as fp_in:
|
||||
with open(zip_path + '.partial', 'wb') as fp_out:
|
||||
last_report = time.time()
|
||||
try:
|
||||
while True:
|
||||
dat = fp_in.read(10240)
|
||||
if not dat:
|
||||
break
|
||||
fp_out.write(dat)
|
||||
total_bytes += len(dat)
|
||||
if time.time() - last_report > 1:
|
||||
sys.stderr.write(
|
||||
'Downloading %s: %d bytes\r'
|
||||
% (DOWNLOAD_URL, total_bytes))
|
||||
sys.stderr.flush()
|
||||
last_report = time.time()
|
||||
finally:
|
||||
sys.stderr.write('\033[K')
|
||||
sys.stderr.flush()
|
||||
|
||||
os.rename(zip_path + '.partial', zip_path)
|
||||
print('Downloaded %s: %d bytes' % (DOWNLOAD_URL, total_bytes))
|
||||
|
||||
def _unpack_zip(self, zip_path, src_dir):
|
||||
if os.path.isdir(src_dir):
|
||||
return
|
||||
|
||||
print("Extracting...")
|
||||
|
||||
base_dir = None
|
||||
with zipfile.ZipFile(zip_path) as fp:
|
||||
for path in fp.namelist():
|
||||
while path:
|
||||
path, b = os.path.split(path)
|
||||
if not path:
|
||||
if base_dir is None:
|
||||
base_dir = b
|
||||
elif b != base_dir:
|
||||
raise RuntimeError(
|
||||
"No common base dir (%s)" % b)
|
||||
|
||||
fp.extractall(self.build_base)
|
||||
|
||||
os.rename(os.path.join(self.build_base, base_dir), src_dir)
|
||||
print("Extracted to %s" % src_dir)
|
||||
return src_dir
|
||||
|
||||
|
||||
class InstallFaustLibraries(FaustLibrariesMixin, core.Command):
|
||||
@property
|
||||
def sentinel_path(self):
|
||||
return os.path.join(
|
||||
os.getenv('VIRTUAL_ENV'), '.faustlibraries-%s-installed' % VERSION)
|
||||
|
||||
@property
|
||||
def install_dir(self):
|
||||
return os.path.join(
|
||||
os.getenv('VIRTUAL_ENV'), 'share', 'faustlibraries')
|
||||
|
||||
def run(self):
|
||||
if os.path.exists(self.sentinel_path):
|
||||
return
|
||||
|
||||
print("Copy files...")
|
||||
shutil.rmtree(self.install_dir)
|
||||
shutil.copytree(self.src_dir, self.install_dir)
|
||||
open(self.sentinel_path, 'w').close()
|
||||
|
||||
def get_outputs(self):
|
||||
return [self.sentinel_path]
|
||||
|
||||
|
||||
build.sub_commands.append(('build_faustlibraries', None))
|
||||
install.sub_commands.insert(0, ('install_faustlibraries', None))
|
||||
|
||||
|
||||
core.setup(
|
||||
name = 'faustlibraries',
|
||||
version = VERSION,
|
||||
cmdclass = {
|
||||
'build_faustlibraries': BuildFaustLibraries,
|
||||
'install_faustlibraries': InstallFaustLibraries,
|
||||
},
|
||||
)
|
@ -0,0 +1,2 @@
|
||||
from typing import Any
|
||||
def __getattr__(arrr: str) -> Any: ...
|
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
CLASSNAME=$1
|
||||
SRC=$2
|
||||
DESTDIR=$3
|
||||
|
||||
CLASSNAME_UPPER=$(echo ${CLASSNAME} | tr '[a-z]' '[A-Z]')
|
||||
SRCDIR=$(realpath --relative-to=$(pwd) $(dirname ${SRC}))
|
||||
BASE=$(basename ${SRC%.dsp})
|
||||
|
||||
LD_LIBRARY_PATH=${VIRTUAL_ENV}/lib ${VIRTUAL_ENV}/bin/faust \
|
||||
--import-dir ${VIRTUAL_ENV}/share/faustlibraries/ \
|
||||
--language cpp \
|
||||
--class-name Processor${CLASSNAME}DSP \
|
||||
--super-class-name noisicaa::FaustDSP \
|
||||
-a noisicaa/audioproc/engine/processor_faust.cpp.tmpl \
|
||||
-o ${DESTDIR}/${BASE}.cpp.tmp \
|
||||
${SRC}
|
||||
|
||||
sed <${DESTDIR}/${BASE}.cpp.tmp >${DESTDIR}/${BASE}.cpp \
|
||||
-e '1,9d'\
|
||||
-e '$d' \
|
||||
-e "s#<<srcDir>>#${SRCDIR}#g" \
|
||||
-e "s#<<base>>#${BASE}#g" \
|
||||
-e "s#<<className>>#${CLASSNAME}#g" \
|
||||
-e "s#<<classNameUpper>>#${CLASSNAME_UPPER}#g"
|
||||
|
||||
sed <noisicaa/audioproc/engine/processor_faust.h.tmpl >${DESTDIR}/${BASE}.h \
|
||||
-e "s#<<srcDir>>#${SRCDIR}#g" \
|
||||
-e "s#<<base>>#${BASE}#g" \
|
||||
-e "s#<<className>>#${CLASSNAME}#g" \
|
||||
-e "s#<<classNameUpper>>#${CLASSNAME_UPPER}#g"
|
||||
|
||||
LD_LIBRARY_PATH=${VIRTUAL_ENV}/lib ${VIRTUAL_ENV}/bin/faust \
|
||||
--import-dir ${VIRTUAL_ENV}/share/faustlibraries/ \
|
||||
--language cpp \
|
||||
-a gen-json.cpp \
|
||||
-o ${DESTDIR}/${BASE}.json_dumper.cpp \
|
||||
${SRC}
|
||||
|
||||
g++ -I${VIRTUAL_ENV}/include -o${DESTDIR}/${BASE}.json_dumper ${DESTDIR}/${BASE}.json_dumper.cpp
|
||||
${DESTDIR}/${BASE}.json_dumper >${DESTDIR}/${BASE}.json
|
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 6.6 KiB |
@ -0,0 +1,3 @@
|
||||
Source: http://lv2plug.in/git/cgit.cgi/lv2site.git/tree/content/images/logo.svg
|
||||
Author: David Robillard <http://drobilla.net/>
|
||||
Licence: https://opensource.org/licenses/ISC
|
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.5 KiB |
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* @begin:license
|
||||
*
|
||||
* Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* @end:license
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "faust/dsp/dsp.h"
|
||||
#include "faust/gui/meta.h"
|
||||
#include "faust/gui/UI.h"
|
||||
|
||||
#include "noisicaa/core/perf_stats.h"
|
||||
#include "noisicaa/host_system/host_system.h"
|
||||
#include "noisicaa/audioproc/engine/processor_faust.h"
|
||||
|
||||
namespace noisicaa {
|
||||
|
||||
class FaustControls : public UI {
|
||||
public:
|
||||
int num_controls() const {
|
||||
return _control_map.size();
|
||||
}
|
||||
|
||||
float* get_control_ptr(const string& name) {
|
||||
return _control_map[name];
|
||||
}
|
||||
|
||||
void openTabBox(const char* label) override {}
|
||||
void openHorizontalBox(const char* label) override {}
|
||||
void openVerticalBox(const char* label) override {}
|
||||
void closeBox() override {}
|
||||
|
||||
void addButton(const char* label, float* zone) override {
|
||||
_control_map[label] = zone;
|
||||
}
|
||||
void addCheckButton(const char* label, float* zone) override {
|
||||
_control_map[label] = zone;
|
||||
}
|
||||
void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) override {
|
||||
_control_map[label] = zone;
|
||||
}
|
||||
void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) override {
|
||||
_control_map[label] = zone;
|
||||
}
|
||||
void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) override {
|
||||
_control_map[label] = zone;
|
||||
}
|
||||
|
||||
void addHorizontalBargraph(const char* label, float* zone, float min, float max) override {
|
||||
_control_map[label] = zone;
|
||||
}
|
||||
void addVerticalBargraph(const char* label, float* zone, float min, float max) override {
|
||||
_control_map[label] = zone;
|
||||
}
|
||||
|
||||
void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) override {}
|
||||
void declare(float* zone, const char* key, const char* val) override {}
|
||||
|
||||
private:
|
||||
map<string, float*> _control_map;
|
||||
};
|
||||
|
||||
ProcessorFaust::ProcessorFaust(
|
||||
const string& realm_name, const string& node_id, HostSystem *host_system,
|
||||
const pb::NodeDescription& desc)
|
||||
: Processor(
|
||||
realm_name, node_id, "noisicaa.audioproc.engine.processor.faust", host_system, desc) {}
|
||||
|
||||
Status ProcessorFaust::setup_internal() {
|
||||
RETURN_IF_ERROR(Processor::setup_internal());
|
||||
|
||||
_dsp.reset(create_dsp());
|
||||
_dsp->init(_host_system->sample_rate());
|
||||
|
||||
FaustControls controls;
|
||||
_dsp->buildUserInterface(&controls);
|
||||
|
||||
int dsp_ports = _dsp->getNumInputs() + _dsp->getNumOutputs() + controls.num_controls();
|
||||
if (dsp_ports != _desc.ports_size()) {
|
||||
return ERROR_STATUS("Port mismatch (desc=%d, dsp=%d)", _desc.ports_size(), dsp_ports);
|
||||
}
|
||||
|
||||
_buffers.reset(new BufferPtr[_desc.ports_size()]);
|
||||
_inputs.reset(new float*[_dsp->getNumInputs()]);
|
||||
_outputs.reset(new float*[_dsp->getNumOutputs()]);
|
||||
_controls.reset(new float*[controls.num_controls()]);
|
||||
|
||||
int control_idx = 0;
|
||||
for (int port_idx = 0 ; port_idx < _desc.ports_size() ; ++port_idx) {
|
||||
const auto& port_desc = _desc.ports(port_idx);
|
||||
if (port_idx < _dsp->getNumInputs()) {
|
||||
if (port_desc.direction() != pb::PortDescription::INPUT) {
|
||||
return ERROR_STATUS(
|
||||
"Port %d: Expected INPUT port, got %s",
|
||||
port_idx, pb::PortDescription::Direction_Name(port_desc.direction()).c_str());
|
||||
}
|
||||
if (port_desc.type() != pb::PortDescription::AUDIO
|
||||
&& port_desc.type() != pb::PortDescription::ARATE_CONTROL) {
|
||||
return ERROR_STATUS(
|
||||
"Port %d: Expected AUDIO/ARATE_CONTROL port, got %s",
|
||||
port_idx, pb::PortDescription::Type_Name(port_desc.type()).c_str());
|
||||
}
|
||||
} else if (port_idx < _dsp->getNumInputs() + _dsp->getNumOutputs()) {
|
||||
if (port_desc.direction() != pb::PortDescription::OUTPUT) {
|
||||
return ERROR_STATUS(
|
||||
"Port %d: Expected OUTPUT port, got %s",
|
||||
port_idx, pb::PortDescription::Direction_Name(port_desc.direction()).c_str());
|
||||
}
|
||||
if (port_desc.type() != pb::PortDescription::AUDIO
|
||||
&& port_desc.type() != pb::PortDescription::ARATE_CONTROL) {
|
||||
return ERROR_STATUS(
|
||||
"Port %d: Expected AUDIO/ARATE_CONTROL port, got %s",
|
||||
port_idx, pb::PortDescription::Type_Name(port_desc.type()).c_str());
|
||||
}
|
||||
} else {
|
||||
if (port_desc.direction() != pb::PortDescription::INPUT) {
|
||||
return ERROR_STATUS(
|
||||
"Port %d: Expected INPUT port, got %s",
|
||||
port_idx, pb::PortDescription::Direction_Name(port_desc.direction()).c_str());
|
||||
}
|
||||
if (port_desc.type() != pb::PortDescription::KRATE_CONTROL) {
|
||||
return ERROR_STATUS(
|
||||
"Port %d: Expected KRATE_CONTROL port, got %s",
|
||||
port_idx, pb::PortDescription::Type_Name(port_desc.type()).c_str());
|
||||
}
|
||||
|
||||
float* control_ptr = controls.get_control_ptr(port_desc.name());
|
||||
if (control_ptr == nullptr) {
|
||||
return ERROR_STATUS(
|
||||
"Port %d: Control '%s' not declared by DSP",
|
||||
port_idx, port_desc.name().c_str());
|
||||
}
|
||||
_controls.get()[control_idx] = control_ptr;
|
||||
++control_idx;
|
||||
}
|
||||
}
|
||||
|
||||
return Status::Ok();
|
||||
}
|
||||
|
||||
void ProcessorFaust::cleanup_internal() {
|
||||
_dsp.reset();
|
||||
_buffers.reset();
|
||||
_inputs.reset();
|
||||
_outputs.reset();
|
||||
_controls.reset();
|
||||
|
||||
Processor::cleanup_internal();
|
||||
}
|
||||
|
||||
Status ProcessorFaust::connect_port_internal(
|
||||
BlockContext* ctxt, uint32_t port_idx, BufferPtr buf) {
|
||||
if (port_idx >= (uint32_t)_desc.ports_size()) {
|
||||
return ERROR_STATUS("Invalid port index %d", port_idx);
|
||||
}
|
||||
|
||||
_buffers.get()[port_idx] = buf;
|
||||
return Status::Ok();
|
||||
}
|
||||
|
||||
Status ProcessorFaust::process_block_internal(BlockContext* ctxt, TimeMapper* time_mapper) {
|
||||
PerfTracker tracker(ctxt->perf.get(), "faust");
|
||||
|
||||
float** inputs = _inputs.get();
|
||||
float** outputs = _outputs.get();
|
||||
|
||||
int input_idx = 0;
|
||||
int output_idx = 0;
|
||||
int control_idx = 0;
|
||||
for (int port_idx = 0 ; port_idx < _desc.ports_size() ; ++port_idx) {
|
||||
BufferPtr buf = _buffers.get()[port_idx];
|
||||
if (buf == nullptr) {
|
||||
return ERROR_STATUS("Port %d not connected.", port_idx);
|
||||
}
|
||||
|
||||
if (port_idx < _dsp->getNumInputs()) {
|
||||
inputs[input_idx] = (float*)buf;
|
||||
++input_idx;
|
||||
} else if (port_idx < _dsp->getNumInputs() + _dsp->getNumOutputs()) {
|
||||
outputs[output_idx] = (float*)buf;
|
||||
++output_idx;
|
||||
} else {
|
||||
*(_controls.get()[control_idx]) = *((float*)buf);
|
||||
++control_idx;
|
||||
}
|
||||
}
|
||||
|
||||
_dsp->compute(_host_system->block_size(), inputs, outputs);
|
||||
|
||||
return Status::Ok();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* @begin:license
|
||||
*
|
||||
* Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* @end:license
|
||||
*/
|
||||
|
||||
#include "<<srcDir>>/<<base>>.h"
|
||||
|
||||
<<includeIntrinsic>>
|
||||
|
||||
<<includeclass>>
|
||||
|
||||
namespace noisicaa {
|
||||
|
||||
Processor<<className>>::Processor<<className>>(
|
||||
const string& realm_name, const string& node_id, HostSystem* host_system,
|
||||
const pb::NodeDescription& desc)
|
||||
: ProcessorFaust(realm_name, node_id, host_system, desc) {}
|
||||
|
||||
FaustDSP* Processor<<className>>::create_dsp() {
|
||||
return new ::Processor<<className>>DSP();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
// -*- mode: c++ -*-
|
||||
|
||||
/*
|
||||
* @begin:license
|
||||
*
|
||||
* Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* @end:license
|
||||
*/
|
||||
|
||||
#ifndef _NOISICAA_AUDIOPROC_ENGINE_PROCESSOR_FAUST_H
|
||||
#define _NOISICAA_AUDIOPROC_ENGINE_PROCESSOR_FAUST_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "faust/dsp/dsp.h"
|
||||
#include "faust/gui/meta.h"
|
||||
#include "faust/gui/UI.h"
|
||||
|
||||
#include "noisicaa/core/status.h"
|
||||
#include "noisicaa/audioproc/engine/processor.h"
|
||||
|
||||
namespace noisicaa {
|
||||
|
||||
using namespace std;
|
||||
|
||||
class FaustDSP : public dsp {
|
||||
};
|
||||
|
||||
class ProcessorFaust : public Processor {
|
||||
protected:
|
||||
ProcessorFaust(
|
||||
const string& realm_name, const string& node_id, HostSystem* host_system,
|
||||
const pb::NodeDescription& desc);
|
||||
|
||||
Status setup_internal() override;
|
||||
void cleanup_internal() override;
|
||||
Status connect_port_internal(BlockContext* ctxt, uint32_t port_idx, BufferPtr buf) override;
|
||||
Status process_block_internal(BlockContext* ctxt, TimeMapper* time_mapper) override;
|
||||
|
||||
virtual FaustDSP* create_dsp() = 0;
|
||||
|
||||
private:
|
||||
unique_ptr<FaustDSP> _dsp;
|
||||
unique_ptr<BufferPtr> _buffers;
|
||||
unique_ptr<float*> _controls;
|
||||
unique_ptr<float*> _inputs;
|
||||
unique_ptr<float*> _outputs;
|
||||
};
|
||||
|
||||
} // namespace noisicaa
|
||||
|
||||
#endif
|
@ -0,0 +1,44 @@
|
||||
// -*- mode: c++ -*-
|
||||
|
||||
/*
|
||||
* @begin:license
|
||||
*
|
||||
* Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* @end:license
|
||||
*/
|
||||
|
||||
#ifndef _NOISICAA_BUILTIN_NODES_<<classNameUpper>>_PROCESSOR_H
|
||||
#define _NOISICAA_BUILTIN_NODES_<<classNameUpper>>_PROCESSOR_H
|
||||
|
||||
#include "noisicaa/audioproc/engine/processor_faust.h"
|
||||
|
||||
namespace noisicaa {
|
||||
|
||||
class Processor<<className>> : public ProcessorFaust {
|
||||
public:
|
||||
Processor<<className>>(
|
||||
const string& realm_name, const string& node_id, HostSystem* host_system,
|
||||
const pb::NodeDescription& desc);
|
||||
|
||||
protected:
|
||||
FaustDSP* create_dsp() override;
|
||||
};
|
||||
|
||||
} // namespace noisicaa
|
||||
|
||||
#endif
|