commit f36ff7247556ddeb733edaee0397505f2b077940
parent bc5e0eebd7077a69ae3a6eefe1baf8f7c318f663
Author: Johannes Lorenz <[email protected]>
Date: Thu, 6 Jul 2017 23:39:45 +0200
Merge branch 'master' into default_values
Diffstat:
16 files changed, 666 insertions(+), 190 deletions(-)
diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp
@@ -114,6 +114,201 @@ static const Ports sysefsendto =
}}
};
+#define rBegin [](const char *msg, RtData &d) { rtosc::AutomationMgr &a = *(AutomationMgr*)d.obj
+#define rEnd }
+
+static int extract_num(const char *&msg)
+{
+ while(*msg && !isdigit(*msg)) msg++;
+ int num = atoi(msg);
+ while(isdigit(*msg)) msg++;
+ return num;
+}
+
+static int get_next_int(const char *msg)
+{
+ return extract_num(msg);
+}
+
+static const Ports mapping_ports = {
+ {"offset::f", rProp(parameter) rShort("off") rLinear(-50, 50) rMap(unit, percent), 0,
+ rBegin;
+ int slot = d.idx[1];
+ int param = d.idx[0];
+ if(!strcmp("f",rtosc_argument_string(msg))) {
+ a.setSlotSubOffset(slot, param, rtosc_argument(msg, 0).f);
+ a.updateMapping(slot, param);
+ d.broadcast(d.loc, "f", a.getSlotSubOffset(slot, param));
+ } else
+ d.reply(d.loc, "f", a.getSlotSubOffset(slot, param));
+ rEnd},
+ {"gain::f", rProp(parameter) rShort("gain") rLinear(-200, 200) rMap(unit, percent), 0,
+ rBegin;
+ int slot = d.idx[1];
+ int param = d.idx[0];
+ if(!strcmp("f",rtosc_argument_string(msg))) {
+ a.setSlotSubGain(slot, param, rtosc_argument(msg, 0).f);
+ a.updateMapping(slot, param);
+ d.broadcast(d.loc, "f", a.getSlotSubGain(slot, param));
+ } else
+ d.reply(d.loc, "f", a.getSlotSubGain(slot, param));
+ rEnd},
+};
+
+static const Ports auto_param_ports = {
+ {"used:", rProp(parameter) rProp(read-only) rDoc("If automation is assigned to anything"), 0,
+ rBegin;
+ int slot = d.idx[1];
+ int param = d.idx[0];
+
+ d.reply(d.loc, a.slots[slot].automations[param].used ? "T" : "F");
+ rEnd},
+ {"active::T:F", rProp(parameter) rDoc("If automation is being actively used"), 0,
+ rBegin;
+ int slot = d.idx[1];
+ int param = d.idx[0];
+ if(rtosc_narguments(msg))
+ a.slots[slot].automations[param].active = rtosc_argument(msg, 0).T;
+ else
+ d.reply(d.loc, a.slots[slot].automations[param].active ? "T" : "F");
+ rEnd},
+ {"path:", rProp(parameter) rProp(read-only) rDoc("Path of parameter"), 0,
+ rBegin;
+ int slot = d.idx[1];
+ int param = d.idx[0];
+ d.reply(d.loc, "s", a.slots[slot].automations[param].param_path);
+ rEnd},
+ {"clear:", 0, 0,
+ rBegin;
+ int slot = d.idx[1];
+ int param = d.idx[0];
+ a.clearSlotSub(slot, param);
+ rEnd},
+ {"mapping/", 0, &mapping_ports,
+ rBegin;
+ SNIP;
+ mapping_ports.dispatch(msg, d);
+ rEnd},
+
+ //{"mapping", rDoc("Parameter mapping control"), 0,
+ // rBegin;
+ // int slot = d.idx[1];
+ // int param = d.idx[0];
+ // if(!strcmp("b", rtosc_argument_string(msg))) {
+ // int len = rtosc_argument(msg, 0).b.len / sizeof(float);
+ // float *data = (float*)rtosc_argument(msg, 0).b.data;
+ // } else {
+ // d.reply(d.loc, "b",
+ // a.slots[slot].automations[param].map.npoints*sizeof(float),
+ // a.slots[slot].automations[param].map.control_points);
+ // }
+ // rEnd},
+};
+
+static const Ports slot_ports = {
+ //{"learn-binding:s", rDoc("Create binding for automation path with midi-learn"), 0,
+ // rBegin;
+ // (void) m;
+ // //m->automate.createBinding(rtosc_argument(msg, 0).i,
+ // // rtosc_argument(msg, 1).s,
+ // // rtosc_argument(msg, 2).T);
+ // rEnd},
+ //{"create-binding:s", rDoc("Create binding for automation path"), 0,
+ // rBegin;
+ // m->automate.createBinding(rtosc_argument(msg, 0).i,
+ // rtosc_argument(msg, 1).s,
+ // rtosc_argument(msg, 2).T);
+ // rEnd},
+ {"value::f", rProp(parameter) rMap(default, 0.5) rLinear(0, 1) rDoc("Access current value in slot 'i' (0..1)"), 0,
+ rBegin;
+ int num = d.idx[0];
+ if(!strcmp("f",rtosc_argument_string(msg))) {
+ a.setSlot(num, rtosc_argument(msg, 0).f);
+ d.broadcast(d.loc, "f", a.getSlot(num));
+ } else
+ d.reply(d.loc, "f", a.getSlot(num));
+ rEnd},
+
+ {"name::s", rProp(parameter) rDoc("Access name of automation slot"), 0,
+ rBegin;
+ int num = d.idx[0];
+ if(!strcmp("s",rtosc_argument_string(msg))) {
+ a.setName(num, rtosc_argument(msg, 0).s);
+ d.broadcast(d.loc, "s", a.getName(num));
+ } else
+ d.reply(d.loc, "s", a.getName(num));
+ rEnd},
+ {"midi-cc::i", rProp(parameter) rMap(default, -1) rDoc("Access assigned midi CC slot") , 0,
+ rBegin;
+ int slot = d.idx[0];
+ if(rtosc_narguments(msg))
+ a.slots[slot].midi_cc = rtosc_argument(msg, 0).i;
+ else
+ d.reply(d.loc, "i", a.slots[slot].midi_cc);
+
+ rEnd},
+ {"active::T:F", rProp(parameter) rMap(default, F) rDoc("If Slot is enabled"), 0,
+ rBegin;
+ int slot = d.idx[0];
+ if(rtosc_narguments(msg))
+ a.slots[slot].active = rtosc_argument(msg, 0).T;
+ else
+ d.reply(d.loc, a.slots[slot].active ? "T" : "F");
+ rEnd},
+ {"learning:", rProp(parameter) rMap(default, -1) rDoc("If slot is trying to find a midi learn binding"), 0,
+ rBegin;
+ int slot = d.idx[0];
+ d.reply(d.loc, "i", a.slots[slot].learning);
+ rEnd},
+ {"clear:", 0, 0,
+ rBegin;
+ int slot = d.idx[0];
+ a.clearSlot(slot);
+ rEnd},
+ {"param#4/", rDoc("Info on individual param mappings"), &auto_param_ports,
+ rBegin;
+ (void)a;
+ d.push_index(get_next_int(msg));
+ SNIP;
+ auto_param_ports.dispatch(msg, d);
+ d.pop_index();
+ rEnd},
+};
+
+static const Ports automate_ports = {
+ {"active-slot::i", rProp(parameter) rMap(min, -1) rMap(max, 16) rDoc("Active Slot for macro learning"), 0,
+ rBegin;
+ if(!strcmp("i",rtosc_argument_string(msg))) {
+ a.active_slot = rtosc_argument(msg, 0).i;
+ d.broadcast(d.loc, "i", a.active_slot);
+ } else
+ d.reply(d.loc, "i", a.active_slot);
+ rEnd},
+ {"learn-binding-new-slot:s", rDoc("Learn a parameter assigned to a new slot"), 0,
+ rBegin;
+ int free_slot = a.free_slot();
+ if(free_slot >= 0) {
+ a.createBinding(free_slot, rtosc_argument(msg, 0).s, true);
+ a.active_slot = free_slot;
+ }
+ rEnd},
+ {"learn-binding-same-slot:s", rDoc("Learn a parameter appending to the active-slot"), 0,
+ rBegin;
+ if(a.active_slot >= 0)
+ a.createBinding(a.active_slot, rtosc_argument(msg, 0).s, true);
+ rEnd},
+ {"slot#16/", rDoc("Parameters of individual automation slots"), &slot_ports,
+ rBegin;
+ (void)a;
+ d.push_index(get_next_int(msg));
+ SNIP;
+ slot_ports.dispatch(msg, d);
+ d.pop_index();
+ rEnd},
+};
+
+#undef rBegin
+#undef rEnd
#define rBegin [](const char *msg, RtData &d) { Master *m = (Master*)d.obj
#define rEnd }
@@ -124,6 +319,7 @@ static const Ports watchPorts = {
rEnd},
};
+
extern const Ports bankPorts;
static const Ports master_ports = {
rString(last_xmz, XMZ_PATH_MAX, "File name for last name loaded if any."),
@@ -250,13 +446,12 @@ static const Ports master_ports = {
[](const char *,RtData &d) {
Master *M = (Master*)d.obj;
M->frozenState = false;}},
- {"midi-learn/", 0, &rtosc::MidiMapperRT::ports,
+ {"automate/", rDoc("MIDI Learn/Plugin Automation support"), &automate_ports,
[](const char *msg, RtData &d) {
- Master *M = (Master*)d.obj;
SNIP;
- printf("residue message = <%s>\n", msg);
- d.obj = &M->midi;
- rtosc::MidiMapperRT::ports.dispatch(msg,d);}},
+ d.obj = (void*)&((Master*)d.obj)->automate;
+ automate_ports.dispatch(msg, d);
+ }},
{"close-ui:", rDoc("Request to close any connection named \"GUI\""), 0,
[](const char *, RtData &d) {
d.reply("/close-ui", "");}},
@@ -307,6 +502,14 @@ static const Ports master_ports = {
rBOIL_END},
{"bank/", rDoc("Controls for instrument banks"), &bankPorts,
[](const char*,RtData&) {}},
+ {"learn:s", rProp(depricated) rDoc("MIDI Learn"), 0,
+ rBegin;
+ int free_slot = m->automate.free_slot();
+ if(free_slot >= 0) {
+ m->automate.createBinding(free_slot, rtosc_argument(msg, 0).s, true);
+ m->automate.active_slot = free_slot;
+ }
+ rEnd},
};
#undef rBegin
@@ -383,15 +586,18 @@ vuData::vuData(void)
Master::Master(const SYNTH_T &synth_, Config* config)
:HDDRecorder(synth_), time(synth_), ctl(synth_, &time),
microtonal(config->cfg.GzipCompression), bank(config),
+ automate(16,4,8),
frozenState(false), pendingMemory(false),
synth(synth_), gzip_compression(config->cfg.GzipCompression)
{
bToU = NULL;
uToB = NULL;
- //Setup MIDI
- midi.frontend = [this](const char *msg) {bToU->raw_write(msg);};
- midi.backend = [this](const char *msg) {applyOscEvent(msg);};
+ //Setup MIDI Learn
+ automate.set_ports(master_ports);
+ automate.set_instance(this);
+ //midi.frontend = [this](const char *msg) {bToU->raw_write(msg);};
+ automate.backend = [this](const char *msg) {applyOscEvent(msg);};
memory = new AllocatorClass();
swaplr = 0;
@@ -541,8 +747,7 @@ void Master::setController(char chan, int type, int par)
{
if(frozenState)
return;
- //TODO add chan back
- midi.handleCC(type,par);
+ automate.handleMidi(chan, type, par);
if((type == C_dataentryhi) || (type == C_dataentrylo)
|| (type == C_nrpnhi) || (type == C_nrpnlo)) { //Process RPN and NRPN by the Master (ignore the chan)
ctl.setparameternumber(type, par);
@@ -746,13 +951,19 @@ bool Master::runOSC(float *outl, float *outr, bool offline)
}
if(!d.matches) {// && !ports.apropos(msg)) {
fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40);
- fprintf(stderr, "Unknown address<BACKEND:%s> '%s:%s'\n",
+ fprintf(stderr, "Unknown address<BACKEND:%s> '%s:%s'\n",
offline ? "offline" : "online",
uToB->peak(),
rtosc_argument_string(uToB->peak()));
fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
}
}
+
+ if(automate.damaged) {
+ d.broadcast("/damage", "s", "/automate/");
+ automate.damaged = 0;
+ }
+
if(events>1 && false)
fprintf(stderr, "backend: %d events per cycle\n",events);
diff --git a/src/Misc/Master.h b/src/Misc/Master.h
@@ -16,7 +16,7 @@
#define MASTER_H
#include "../globals.h"
#include "Microtonal.h"
-#include <rtosc/miditable.h>
+#include <rtosc/automations.h>
#include <rtosc/ports.h>
#include "Time.h"
@@ -179,7 +179,7 @@ class Master
WatchManager watcher;
//Midi Learn
- rtosc::MidiMapperRT midi;
+ rtosc::AutomationMgr automate;
bool frozenState;//read-only parameters for threadsafe actions
Allocator *memory;
diff --git a/src/Misc/Microtonal.cpp b/src/Misc/Microtonal.cpp
@@ -863,7 +863,7 @@ void Microtonal::apply(void)
{
char buf[100*MAX_OCTAVE_SIZE] = {0};
char tmpbuf[100] = {0};
- for (int i=0;i<getoctavesize();i++){
+ for (int i=0;i<octavesize;i++){
if (i!=0)
strncat(buf, "\n", sizeof(buf)-1);
tuningtoline(i,tmpbuf,100);
diff --git a/src/Misc/MiddleWare.cpp b/src/Misc/MiddleWare.cpp
@@ -227,50 +227,50 @@ void preparePadSynth(string path, PADnoteParameters *p, rtosc::RtData &d)
* MIDI Serialization *
* *
******************************************************************************/
-void saveMidiLearn(XMLwrapper &xml, const rtosc::MidiMappernRT &midi)
-{
- xml.beginbranch("midi-learn");
- for(auto value:midi.inv_map) {
- XmlNode binding("midi-binding");
- auto biject = std::get<3>(value.second);
- binding["osc-path"] = value.first;
- binding["coarse-CC"] = to_s(std::get<1>(value.second));
- binding["fine-CC"] = to_s(std::get<2>(value.second));
- binding["type"] = "i";
- binding["minimum"] = to_s(biject.min);
- binding["maximum"] = to_s(biject.max);
- xml.add(binding);
- }
- xml.endbranch();
-}
-
-void loadMidiLearn(XMLwrapper &xml, rtosc::MidiMappernRT &midi)
-{
- using rtosc::Port;
- if(xml.enterbranch("midi-learn")) {
- auto nodes = xml.getBranch();
-
- //TODO clear mapper
-
- for(auto node:nodes) {
- if(node.name != "midi-binding" ||
- !node.has("osc-path") ||
- !node.has("coarse-CC"))
- continue;
- const string path = node["osc-path"];
- const int CC = atoi(node["coarse-CC"].c_str());
- const Port *p = Master::ports.apropos(path.c_str());
- if(p) {
- printf("loading midi port...\n");
- midi.addNewMapper(CC, *p, path);
- } else {
- printf("unknown midi bindable <%s>\n", path.c_str());
- }
- }
- xml.exitbranch();
- } else
- printf("cannot find 'midi-learn' branch...\n");
-}
+//void saveMidiLearn(XMLwrapper &xml, const rtosc::MidiMappernRT &midi)
+//{
+// xml.beginbranch("midi-learn");
+// for(auto value:midi.inv_map) {
+// XmlNode binding("midi-binding");
+// auto biject = std::get<3>(value.second);
+// binding["osc-path"] = value.first;
+// binding["coarse-CC"] = to_s(std::get<1>(value.second));
+// binding["fine-CC"] = to_s(std::get<2>(value.second));
+// binding["type"] = "i";
+// binding["minimum"] = to_s(biject.min);
+// binding["maximum"] = to_s(biject.max);
+// xml.add(binding);
+// }
+// xml.endbranch();
+//}
+//
+//void loadMidiLearn(XMLwrapper &xml, rtosc::MidiMappernRT &midi)
+//{
+// using rtosc::Port;
+// if(xml.enterbranch("midi-learn")) {
+// auto nodes = xml.getBranch();
+//
+// //TODO clear mapper
+//
+// for(auto node:nodes) {
+// if(node.name != "midi-binding" ||
+// !node.has("osc-path") ||
+// !node.has("coarse-CC"))
+// continue;
+// const string path = node["osc-path"];
+// const int CC = atoi(node["coarse-CC"].c_str());
+// const Port *p = Master::ports.apropos(path.c_str());
+// if(p) {
+// printf("loading midi port...\n");
+// midi.addNewMapper(CC, *p, path);
+// } else {
+// printf("unknown midi bindable <%s>\n", path.c_str());
+// }
+// }
+// xml.exitbranch();
+// } else
+// printf("cannot find 'midi-learn' branch...\n");
+//}
/******************************************************************************
* Non-RealTime Object Store *
@@ -747,7 +747,7 @@ public:
rtosc::UndoHistory undo;
//MIDI Learn
- rtosc::MidiMappernRT midi_mapper;
+ //rtosc::MidiMappernRT midi_mapper;
//Link To the Realtime
rtosc::ThreadLink *bToU;
@@ -1202,24 +1202,24 @@ static rtosc::Ports middwareSnoopPorts = {
impl.kitEnable(msg);
d.forward();
rEnd},
- {"save_xlz:s", 0, 0,
- rBegin;
- const char *file = rtosc_argument(msg, 0).s;
- XMLwrapper xml;
- saveMidiLearn(xml, impl.midi_mapper);
- xml.saveXMLfile(file, impl.master->gzip_compression);
- rEnd},
- {"load_xlz:s", 0, 0,
- rBegin;
- const char *file = rtosc_argument(msg, 0).s;
- XMLwrapper xml;
- xml.loadXMLfile(file);
- loadMidiLearn(xml, impl.midi_mapper);
- rEnd},
- {"clear_xlz:", 0, 0,
- rBegin;
- impl.midi_mapper.clear();
- rEnd},
+ //{"save_xlz:s", 0, 0,
+ // rBegin;
+ // const char *file = rtosc_argument(msg, 0).s;
+ // XMLwrapper xml;
+ // saveMidiLearn(xml, impl.midi_mapper);
+ // xml.saveXMLfile(file, impl.master->gzip_compression);
+ // rEnd},
+ //{"load_xlz:s", 0, 0,
+ // rBegin;
+ // const char *file = rtosc_argument(msg, 0).s;
+ // XMLwrapper xml;
+ // xml.loadXMLfile(file);
+ // loadMidiLearn(xml, impl.midi_mapper);
+ // rEnd},
+ //{"clear_xlz:", 0, 0,
+ // rBegin;
+ // impl.midi_mapper.clear();
+ // rEnd},
//scale file stuff
{"load_xsz:s", 0, 0,
rBegin;
@@ -1391,51 +1391,51 @@ static rtosc::Ports middwareSnoopPorts = {
impl.undo.seekHistory(+1);
rEnd},
//port to observe the midi mappings
- {"midi-learn-values:", 0, 0,
- rBegin;
- auto &midi = impl.midi_mapper;
- auto key = keys(midi.inv_map);
- //cc-id, path, min, max
-#define MAX_MIDI 32
- rtosc_arg_t args[MAX_MIDI*4];
- char argt[MAX_MIDI*4+1] = {0};
- int j=0;
- for(unsigned i=0; i<key.size() && i<MAX_MIDI; ++i) {
- auto val = midi.inv_map[key[i]];
- if(std::get<1>(val) == -1)
- continue;
- argt[4*j+0] = 'i';
- args[4*j+0].i = std::get<1>(val);
- argt[4*j+1] = 's';
- args[4*j+1].s = key[i].c_str();
- argt[4*j+2] = 'i';
- args[4*j+2].i = 0;
- argt[4*j+3] = 'i';
- args[4*j+3].i = 127;
- j++;
-
- }
- d.replyArray(d.loc, argt, args);
-#undef MAX_MIDI
- rEnd},
- {"learn:s", 0, 0,
- rBegin;
- string addr = rtosc_argument(msg, 0).s;
- auto &midi = impl.midi_mapper;
- auto map = midi.getMidiMappingStrings();
- if(map.find(addr) != map.end())
- midi.map(addr.c_str(), false);
- else
- midi.map(addr.c_str(), true);
- rEnd},
- {"unlearn:s", 0, 0,
- rBegin;
- string addr = rtosc_argument(msg, 0).s;
- auto &midi = impl.midi_mapper;
- auto map = midi.getMidiMappingStrings();
- midi.unMap(addr.c_str(), false);
- midi.unMap(addr.c_str(), true);
- rEnd},
+ //{"midi-learn-values:", 0, 0,
+ // rBegin;
+ // auto &midi = impl.midi_mapper;
+ // auto key = keys(midi.inv_map);
+ // //cc-id, path, min, max
+//#define MAX_MIDI 32
+ // rtosc_arg_t args[MAX_MIDI*4];
+ // char argt[MAX_MIDI*4+1] = {0};
+ // int j=0;
+ // for(unsigned i=0; i<key.size() && i<MAX_MIDI; ++i) {
+ // auto val = midi.inv_map[key[i]];
+ // if(std::get<1>(val) == -1)
+ // continue;
+ // argt[4*j+0] = 'i';
+ // args[4*j+0].i = std::get<1>(val);
+ // argt[4*j+1] = 's';
+ // args[4*j+1].s = key[i].c_str();
+ // argt[4*j+2] = 'i';
+ // args[4*j+2].i = 0;
+ // argt[4*j+3] = 'i';
+ // args[4*j+3].i = 127;
+ // j++;
+
+ // }
+ // d.replyArray(d.loc, argt, args);
+//#undef MAX_MIDI
+ // rEnd},
+ //{"learn:s", 0, 0,
+ // rBegin;
+ // string addr = rtosc_argument(msg, 0).s;
+ // auto &midi = impl.midi_mapper;
+ // auto map = midi.getMidiMappingStrings();
+ // if(map.find(addr) != map.end())
+ // midi.map(addr.c_str(), false);
+ // else
+ // midi.map(addr.c_str(), true);
+ // rEnd},
+ //{"unlearn:s", 0, 0,
+ // rBegin;
+ // string addr = rtosc_argument(msg, 0).s;
+ // auto &midi = impl.midi_mapper;
+ // auto map = midi.getMidiMappingStrings();
+ // midi.unMap(addr.c_str(), false);
+ // midi.unMap(addr.c_str(), true);
+ // rEnd},
//drop this message into the abyss
{"ui/title:", 0, 0, [](const char *msg, RtData &d) {}},
{"quit:", 0, 0, [](const char *, RtData&) {Pexitprogram = 1;}},
@@ -1482,10 +1482,10 @@ static rtosc::Ports middlewareReplyPorts = {
if(impl.recording_undo)
impl.undo.recordEvent(msg);
rEnd},
- {"midi-use-CC:i", 0, 0,
- rBegin;
- impl.midi_mapper.useFreeID(rtosc_argument(msg, 0).i);
- rEnd},
+ //{"midi-use-CC:i", 0, 0,
+ // rBegin;
+ // impl.midi_mapper.useFreeID(rtosc_argument(msg, 0).i);
+ // rEnd},
{"broadcast:", 0, 0, rBegin; impl.broadcast = true; rEnd},
{"forward:", 0, 0, rBegin; impl.forward = true; rEnd},
};
@@ -1510,8 +1510,8 @@ MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, SYNTH_T synth_,
{
bToU = new rtosc::ThreadLink(4096*2*16,1024/16);
uToB = new rtosc::ThreadLink(4096*2*16,1024/16);
- midi_mapper.base_ports = &Master::ports;
- midi_mapper.rt_cb = [this](const char *msg){handleMsg(msg);};
+ //midi_mapper.base_ports = &Master::ports;
+ //midi_mapper.rt_cb = [this](const char *msg){handleMsg(msg);};
if(preferrred_port != -1)
server = lo_server_new_with_proto(to_s(preferrred_port).c_str(),
LO_UDP, liblo_error_cb);
diff --git a/src/Misc/Schema.cpp b/src/Misc/Schema.cpp
@@ -21,6 +21,8 @@ namespace zyn {
* - 'shortname' : string [OPTIONAL]
* - 'tooltip' : string [OPTIONAL]
* - 'type' : type
+ * - 'units' : unit-type
+ * - 'scale' : scale-type
* - 'domain' : range [OPTIONAL]
* - 'options' : [option...] [OPTIONAL]
* type : {'int', 'float', 'boolean'}
@@ -115,6 +117,9 @@ void dump_param_cb(const rtosc::Port *p, const char *full_name, const char*,
auto mparameter = meta.find("parameter");
auto mdoc = meta.find("documentation");
auto msname = meta.find("shortname");
+ auto units = meta.find("unit");
+ auto scale = meta.find("scale");
+
opts options;
string doc;
string name = p->name;;
@@ -190,6 +195,10 @@ void dump_param_cb(const rtosc::Port *p, const char *full_name, const char*,
o << " \"shortname\": \"" << msname.value << "\",\n";
o << " \"name\" : \"" << name << "\",\n";
o << " \"tooltip\" : \"" << doc << "\",\n";
+ if(units != meta.end())
+ o << " \"units\" : \"" << units.value << "\",\n";
+ if(scale != meta.end())
+ o << " \"scale\" : \"" << scale.value << "\",\n";
o << " \"type\" : \"" << type << "\"";
if(min && max)
o << ",\n \"range\" : [" << min << "," << max << "]";
diff --git a/src/Misc/Util.h b/src/Misc/Util.h
@@ -179,4 +179,6 @@ rPresetType, \
}
+#define rUnit(x) rMap(unit, x)
+
#endif
diff --git a/src/Misc/XMLwrapper.cpp b/src/Misc/XMLwrapper.cpp
@@ -253,7 +253,7 @@ void XMLwrapper::addparreal(const string &name, float val)
union { float in; uint32_t out; } convert;
char buf[11];
convert.in = val;
- sprintf(buf, "0x%8X", convert.out);
+ sprintf(buf, "0x%0.8X", convert.out);
addparams("par_real", 3, "name", name.c_str(), "value",
stringFrom<float>(val).c_str(), "exact_value", buf);
}
diff --git a/src/Params/FilterParams.cpp b/src/Params/FilterParams.cpp
@@ -3,7 +3,9 @@
FilterParams.cpp - Parameters for filter
Copyright (C) 2002-2005 Nasca Octavian Paul
+ Copyright (C) 2017 Mark McCurry
Author: Nasca Octavian Paul
+ Mark McCurry
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -66,14 +68,16 @@ const rtosc::Ports FilterParams::ports = {
rOption(Ptype, rShort("type"),
rOptions(LP1, HP1, LP2, HP2, BP, notch, peak,
l.shelf, h.shelf), "Filter Type"),
- rParamZyn(Pfreq, rShort("cutoff"), "Center Freq"),
- rParamZyn(Pq, rShort("q"),
- "Quality Factor (resonance/bandwidth)"),
rParamI(Pstages, rShort("stages"),
rLinear(0,5), "Filter Stages"),
- rParamZyn(Pfreqtrack, rShort("f.track"),
+ rParamF(baseq, rShort("q"), rUnit(none), rLog(0.1, 1000),
+ "Quality Factor (resonance/bandwidth)"),
+ rParamF(basefreq, rShort("cutoff"), rUnit(Hz), rLog(31.25, 32000),
+ "Base cutoff frequency"),
+ rParamF(freqtracking, rShort("f.track"), rUnit(%), rLinear(-100, 100),
"Frequency Tracking amount"),
- rParamZyn(Pgain, rShort("gain"), "Output Gain"),
+ rParamF(gain, rShort("gain"), rUnit(dB), rLinear(-30, 30),
+ "Output Gain"),
rParamI(Pnumformants, rShort("formants"),
rLinear(1,12), "Number of formants to be used"),
rParamZyn(Pformantslowness, rShort("slew"),
@@ -223,6 +227,65 @@ const rtosc::Ports FilterParams::ports = {
}
d.replyArray(d.loc, type, args);
}},
+
+ //Old 0..127 parameter mappings
+ {"Pfreq::i", rLinear(0, 127) rShort("cutoff") rProp(deprecated) rDoc("Center Freq"), 0,
+ [](const char *msg, RtData &d) {
+ FilterParams *obj = (FilterParams*)d.obj;
+ if(rtosc_narguments(msg)) {
+ int Pfreq = rtosc_argument(msg, 0).i;
+ obj->basefreq = (Pfreq / 64.0f - 1.0f) * 5.0f;
+ obj->basefreq = powf(2.0f, obj->basefreq + 9.96578428f);
+ rChangeCb;
+ d.broadcast(d.loc, "i", Pfreq);
+ } else {
+ float tmp = obj->basefreq;
+ tmp = log2f(tmp) - 9.96578428f;
+ tmp = (tmp / 5.0 + 1.0) * 64.0f;
+ int Pfreq = roundf(tmp);
+ d.reply(d.loc, "i", Pfreq);
+ }
+ }},
+ {"Pfreqtrack::i", rLinear(0, 127) rShort("f.track") rProp(deprecated) rDoc("Frequency Tracking amount"), 0,
+ [](const char *msg, RtData &d) {
+ FilterParams *obj = (FilterParams*)d.obj;
+ if(rtosc_narguments(msg)) {
+ int Pfreqtracking = rtosc_argument(msg, 0).i;
+ obj->freqtracking = 100 * (Pfreqtracking - 64.0f) / (64.0f);
+ rChangeCb;
+ d.broadcast(d.loc, "i", Pfreqtracking);
+ } else {
+ int Pfreqtracking = obj->freqtracking/100.0*64.0 + 64.0;
+ d.reply(d.loc, "i", Pfreqtracking);
+ }
+ }},
+ {"Pgain::i", rLinear(0, 127) rShort("gain") rProp(deprecated) rDoc("Output Gain"), 0,
+ [](const char *msg, RtData &d) {
+ FilterParams *obj = (FilterParams*)d.obj;
+ if(rtosc_narguments(msg)) {
+ int Pgain = rtosc_argument(msg, 0).i;
+ obj->gain = (Pgain / 64.0f - 1.0f) * 30.0f; //-30..30dB
+ rChangeCb;
+ d.broadcast(d.loc, "i", Pgain);
+ } else {
+ int Pgain = roundf((obj->gain/30.0f + 1.0f) * 64.0f);
+ d.reply(d.loc, "i", Pgain);
+ }
+ }},
+ {"Pq::i", rLinear(0,127) rShort("q") rProp(deprecated)
+ rDoc("Quality Factor (resonance/bandwidth)"), 0,
+ [](const char *msg, RtData &d) {
+ FilterParams *obj = (FilterParams*)d.obj;
+ if(rtosc_narguments(msg)) {
+ int Pq = rtosc_argument(msg, 0).i;
+ obj->baseq = expf(powf((float) Pq / 127.0f, 2) * logf(1000.0f)) - 0.9f;
+ rChangeCb;
+ d.broadcast(d.loc, "i", Pq);
+ } else {
+ int Pq = roundf(127.0f * sqrtf(logf(0.9f + obj->baseq)/logf(1000.0f)));
+ d.reply(d.loc, "i", Pq);
+ }
+ }},
};
#undef rChangeCb
#define rChangeCb
@@ -258,16 +321,21 @@ void FilterParams::defaults()
Pfreq = Dfreq;
Pq = Dq;
- Pstages = 0;
- Pfreqtrack = 64;
- Pgain = 64;
- Pcategory = 0;
+ Pstages = 0;
+ basefreq = (Pfreq / 64.0f - 1.0f) * 5.0f;
+ basefreq = powf(2.0f, basefreq + 9.96578428f);
+ baseq = expf(powf((float) Pq / 127.0f, 2) * logf(1000.0f)) - 0.9f;
+
+ gain = 0.0f;
+ freqtracking = 0.0f;
+
+ Pcategory = 0;
Pnumformants = 3;
Pformantslowness = 64;
for(int j = 0; j < FF_MAX_VOWELS; ++j)
defaults(j);
- ;
+
Psequencesize = 3;
for(int i = 0; i < FF_MAX_SEQUENCE; ++i)
@@ -307,10 +375,10 @@ void FilterParams::getfromFilterParams(FilterParams *pars)
Pfreq = pars->Pfreq;
Pq = pars->Pq;
- Pstages = pars->Pstages;
- Pfreqtrack = pars->Pfreqtrack;
- Pgain = pars->Pgain;
- Pcategory = pars->Pcategory;
+ Pstages = pars->Pstages;
+ freqtracking = pars->freqtracking;
+ gain = pars->gain;
+ Pcategory = pars->Pcategory;
Pnumformants = pars->Pnumformants;
Pformantslowness = pars->Pformantslowness;
@@ -338,21 +406,21 @@ void FilterParams::getfromFilterParams(FilterParams *pars)
*/
float FilterParams::getfreq() const
{
- return (Pfreq / 64.0f - 1.0f) * 5.0f;
+ return log2(basefreq) - log2f(1000.0f);
}
float FilterParams::getq() const
{
- return expf(powf((float) Pq / 127.0f, 2) * logf(1000.0f)) - 0.9f;
+ return baseq;
}
float FilterParams::getfreqtracking(float notefreq) const
{
- return logf(notefreq / 440.0f) * (Pfreqtrack - 64.0f) / (64.0f * LOG_2);
+ return log2f(notefreq / 440.0f) * (freqtracking / 100.0);
}
float FilterParams::getgain() const
{
- return (Pgain / 64.0f - 1.0f) * 30.0f; //-30..30dB
+ return gain;
}
/*
@@ -428,11 +496,11 @@ void FilterParams::add2XML(XMLwrapper& xml)
//filter parameters
xml.addpar("category", Pcategory);
xml.addpar("type", Ptype);
- xml.addpar("freq", Pfreq);
- xml.addpar("q", Pq);
+ xml.addparreal("basefreq", basefreq);
+ xml.addparreal("baseq", baseq);
xml.addpar("stages", Pstages);
- xml.addpar("freq_track", Pfreqtrack);
- xml.addpar("gain", Pgain);
+ xml.addparreal("freq_tracking", freqtracking);
+ xml.addparreal("gain", gain);
//formant filter parameters
if((Pcategory == 1) || (!xml.minimal)) {
@@ -482,14 +550,28 @@ void FilterParams::getfromXMLsection(XMLwrapper& xml, int n)
void FilterParams::getfromXML(XMLwrapper& xml)
{
+ const bool upgrade_3_0_2 = (xml.fileversion() < version_type(3,0,2)) && (xml.getparreal("basefreq", -1) < 0);
+
//filter parameters
- Pcategory = xml.getpar127("category", Pcategory);
- Ptype = xml.getpar127("type", Ptype);
- Pfreq = xml.getpar127("freq", Pfreq);
- Pq = xml.getpar127("q", Pq);
- Pstages = xml.getpar127("stages", Pstages);
- Pfreqtrack = xml.getpar127("freq_track", Pfreqtrack);
- Pgain = xml.getpar127("gain", Pgain);
+ Pcategory = xml.getpar127("category", Pcategory);
+ Ptype = xml.getpar127("type", Ptype);
+ Pstages = xml.getpar127("stages", Pstages);
+ if(upgrade_3_0_2) {
+ int Pfreq = xml.getpar127("freq", 0);
+ basefreq = (Pfreq / 64.0f - 1.0f) * 5.0f;
+ basefreq = powf(2.0f, basefreq + 9.96578428f);
+ int Pq = xml.getpar127("q", 0);
+ baseq = expf(powf((float) Pq / 127.0f, 2) * logf(1000.0f)) - 0.9f;
+ int Pgain = xml.getpar127("gain", 0);
+ gain = (Pgain / 64.0f - 1.0f) * 30.0f; //-30..30dB
+ int Pfreqtracking = xml.getpar127("freq_track", 0);
+ freqtracking = 100 * (Pfreqtracking - 64.0f) / (64.0f);
+ } else {
+ basefreq = xml.getparreal("basefreq", 1000);
+ baseq = xml.getparreal("baseq", 10);
+ gain = xml.getparreal("gain", 0);
+ freqtracking = xml.getparreal("freq_track", 0);
+ }
//formant filter parameters
if(xml.enterbranch("FORMANT_FILTER")) {
@@ -527,11 +609,11 @@ void FilterParams::paste(FilterParams &x)
{
COPY(Pcategory);
COPY(Ptype);
- COPY(Pfreq);
+ COPY(basefreq);
COPY(Pq);
COPY(Pstages);
- COPY(Pfreqtrack);
- COPY(Pgain);
+ COPY(freqtracking);
+ COPY(gain);
COPY(Pnumformants);
COPY(Pformantslowness);
@@ -566,7 +648,6 @@ void FilterParams::paste(FilterParams &x)
void FilterParams::pasteArray(FilterParams &x, int nvowel)
{
- printf("FilterParameters::pasting-an-array<%d>\n", nvowel);
for(int nformant = 0; nformant < FF_MAX_FORMANTS; ++nformant) {
auto &self = Pvowels[nvowel].formants[nformant];
auto &update = x.Pvowels[nvowel].formants[nformant];
diff --git a/src/Params/FilterParams.h b/src/Params/FilterParams.h
@@ -46,13 +46,18 @@ class FilterParams:public PresetsArray
float getfreqtracking(float notefreq) const ;
float getgain() const ;
- unsigned char Pcategory; //Filter category (Analog/Formant/StVar)
- unsigned char Ptype; // Filter type (for analog lpf,hpf,bpf..)
- unsigned char Pfreq; // Frequency (64-central frequency)
- unsigned char Pq; // Q parameters (resonance or bandwidth)
- unsigned char Pstages; //filter stages+1
- unsigned char Pfreqtrack; //how the filter frequency is changing according the note frequency
- unsigned char Pgain; //filter's output gain
+ unsigned Pcategory:2; //< Filter category (Analog/Formant/StVar)
+ unsigned Ptype:8; //< Filter type (for analog lpf,hpf,bpf..)
+ unsigned Pstages:8; //< filter stages+1
+ float basefreq; //< Base cutoff frequency (Hz)
+ float baseq; //< Q parameters (resonance or bandwidth)
+ float freqtracking; //< Tracking of center frequency with note frequency (percentage)
+ float gain; //< filter's output gain (dB)
+
+ int Pq; //dummy
+ int Pfreq; //dummy
+ int Pfreqtrack; //dummy
+ int Pgain; //dummy
//Formant filter parameters
unsigned char Pnumformants; //how many formants are used
diff --git a/src/Plugin/ZynAddSubFX/DistrhoPluginInfo.h b/src/Plugin/ZynAddSubFX/DistrhoPluginInfo.h
@@ -41,6 +41,22 @@
#define DISTRHO_PLUGIN_WANT_FULL_STATE 1
enum Parameters {
+ kParamSlot1,
+ kParamSlot2,
+ kParamSlot3,
+ kParamSlot4,
+ kParamSlot5,
+ kParamSlot6,
+ kParamSlot7,
+ kParamSlot8,
+ kParamSlot9,
+ kParamSlot10,
+ kParamSlot11,
+ kParamSlot12,
+ kParamSlot13,
+ kParamSlot14,
+ kParamSlot15,
+ kParamSlot16,
kParamOscPort,
kParamCount
};
diff --git a/src/Plugin/ZynAddSubFX/ZynAddSubFX.cpp b/src/Plugin/ZynAddSubFX/ZynAddSubFX.cpp
@@ -224,6 +224,15 @@ protected:
parameter.ranges.def = 0.0f;
break;
}
+ if(kParamSlot1 <= index && index <= kParamSlot16) {
+ parameter.hints = kParameterIsAutomable;
+ parameter.name = ("Slot " + zyn::to_s(index-kParamSlot1 + 1)).c_str();
+ parameter.symbol = ("slot" + zyn::to_s(index-kParamSlot1 + 1)).c_str();
+ parameter.unit = "";
+ parameter.ranges.min = 0.0f;
+ parameter.ranges.max = 1.0f;
+ parameter.ranges.def = 0.5f;
+ }
}
/**
@@ -236,9 +245,11 @@ protected:
{
case kParamOscPort:
return oscPort;
- default:
- return 0.0f;
}
+ if(kParamSlot1 <= index && index <= kParamSlot16) {
+ return master->automate.getSlot(index - kParamSlot1);
+ }
+ return 0.0f;
}
/**
@@ -247,9 +258,12 @@ protected:
When a parameter is marked as automable, you must ensure no non-realtime operations are performed.
@note This function will only be called for parameter inputs.
*/
- void setParameterValue(uint32_t /*index*/, float /*value*/) noexcept override
+ void setParameterValue(uint32_t index, float value) noexcept override
{
// only an output port for now
+ if(kParamSlot1 <= index && index <= kParamSlot16) {
+ master->automate.setSlot(index - kParamSlot1, value);
+ }
}
/* --------------------------------------------------------------------------------------------------------
diff --git a/src/Tests/MessageTest.h b/src/Tests/MessageTest.h
@@ -243,6 +243,53 @@ class MessageTest:public CxxTest::TestSuite
TS_ASSERT_EQUALS(field2, 35);
}
+ void testFilterDepricated(void)
+ {
+ vector<string> v = {"Pfreq", "Pfreqtrack", "Pgain", "Pq"};
+ for(int i=0; i<v.size(); ++i) {
+ string path = "/part0/kit0/adpars/GlobalPar/GlobalFilter/"+v[i];
+ for(int j=0; j<128; ++j) {
+ mw->transmitMsg(path.c_str(), "i", j); //Set
+ mw->transmitMsg(path.c_str(), ""); //Get
+ }
+
+ }
+ while(ms->uToB->hasNext()) {
+ const char *msg = ms->uToB->read();
+ //printf("RT: handling <%s>\n", msg);
+ ms->applyOscEvent(msg);
+ }
+
+ int id = 0;
+ int state = 0;
+ int value = 0;
+ // 0 - broadcast
+ // 1 - true value (set)
+ // 2 - expected value (get)
+ while(ms->bToU->hasNext()) {
+ const char *msg = ms->bToU->read();
+ if(state == 0) {
+ TS_ASSERT_EQUALS(rtosc_narguments(msg), 0);
+ state = 1;
+ } else if(state == 1) {
+ TS_ASSERT_EQUALS(rtosc_narguments(msg), 1);
+ value = rtosc_argument(msg, 0).i;
+ state = 2;
+ } else if(state == 2) {
+ int val = rtosc_argument(msg, 0).i;
+ if(value != val) {
+ printf("%s - %d should equal %d\n", msg, value, val);
+ TS_ASSERT(0);
+ }
+ state = 0;
+ }
+
+ //printf("Message #%d %s:%s\n", id++, msg, rtosc_argument_string(msg));
+ //if(rtosc_narguments(msg))
+ // printf(" %d\n", rtosc_argument(msg, 0).i);
+ }
+ }
+
private:
SYNTH_T *synth;
diff --git a/src/Tests/PluginTest.h b/src/Tests/PluginTest.h
@@ -33,6 +33,95 @@ NSM_Client *nsm = 0;
char *instance_name=(char*)"";
MiddleWare *middleware;
+void fill_vec_with_lines(std::vector<string> &v, string s)
+{
+ std::istringstream stream(s);
+ std::string line;
+ while(std::getline(stream, line))
+ v.push_back(line);
+}
+void print_string_differences(string orig, string next)
+{
+ std::vector<string> a, b;
+ fill_vec_with_lines(a, orig);
+ fill_vec_with_lines(b, next);
+ int N = a.size();
+ int M = b.size();
+ printf("%d vs %d\n", N, M);
+
+ //Original String by New String
+ //Each step is either an insertion, deletion, or match
+ //Match is 0 cost and moves +1 State (if symbols are the same)
+ //Replace is 3 cost and moves +1 State (if symbols are different)
+ //Insertion is 2 cost and moves +2 State (+2 if symbols are different)
+ //Deletion is 1 cost and moves +0 State (+2 if symbols are different)
+ char *transition = new char[N*M];
+ int *cost = new int[N*M];
+
+ const int match = 1;
+ const int insert = 2;
+ const int del = 3;
+ for(int i=0; i<N; ++i) {
+ for(int j=0; j<M; ++j) {
+ transition[i*M + j] = 0;
+ cost[i*M + j] = 0xffff;
+ }
+ }
+
+ //Just assume the -1 line is the same
+ cost[0*M + 0] = (a[0] == b[0])*3;
+ cost[0*M + 1] = (a[1] == b[0])*2 + 2;
+ for(int i=1; i<N; ++i) {
+ for(int j=0; j<M; ++j) {
+ int cost_match = 0xffffff;
+ int cost_ins = 0xffffff;
+ int cost_del = 0xffffff;
+ cost_del = cost[(i-1)*M + j] + 2 + (a[i] != b[j])*2;
+ if(j > 1)
+ cost_ins = cost[(i-1)*M + (j-2)] + 1 + 2*(a[i] != b[j]);
+ if(j > 0)
+ cost_match = cost[(i-1)*M + (j-1)] + 2*(a[i] != b[j]);
+
+ if(cost_match >= 0xffff && cost_ins >= 0xffff && cost_del >= 0xffff) {
+ ;
+ } else if(cost_match < cost_ins && cost_match < cost_del) {
+ cost[i*M+j] = cost_match;
+ transition[i*M+j] = match;
+ } else if(cost_ins < cost_del) {
+ cost[i*M+j] = cost_ins;
+ transition[i*M+j] = insert;
+ } else {
+ cost[i*M+j] = cost_del;
+ transition[i*M+j] = del;
+ }
+ }
+ }
+
+ int total_cost = cost[(N-1)*M + (M-1)];
+ if(total_cost < 500) {
+ printf("total cost = %d\n", cost[(N-1)*M + (M-1)]);
+
+ //int b_pos = b.size()-1;
+ int a_pos = a.size()-1;
+ for(int i=(M-1); i >= 0; --i) {
+ if(a[a_pos] != b[i]) {
+ printf("- %s\n", a[a_pos].c_str());
+ printf("+ %s\n", b[i].c_str());
+ }
+ if(transition[i*M+a_pos] == match) {
+ //printf("R");
+ a_pos -= 1;
+ } else if(transition[i*M+a_pos] == del) {
+ //printf("D");
+ } else if(transition[i*M+a_pos] == insert) {
+ //printf("I");
+ a_pos -= 2;
+ }
+ }
+ //printf("%d vs %d\n", N, M);
+ }
+}
+
class PluginTest:public CxxTest::TestSuite
{
public:
@@ -104,6 +193,8 @@ class PluginTest:public CxxTest::TestSuite
TS_ASSERT_EQUALS((int)(fdata.length()+1), res);
TS_ASSERT(fdata == result);
+ if(fdata != result)
+ print_string_differences(fdata, result);
}
diff --git a/src/Tests/guitar-adnote.xmz b/src/Tests/guitar-adnote.xmz
@@ -137,11 +137,11 @@ version-revision="1" ZynAddSubFX-author="Nasca Octavian Paul">
<FILTER>
<par name="category" value="0" />
<par name="type" value="2" />
-<par name="freq" value="70" />
-<par name="q" value="40" />
+<par_real name="basefreq" value="1383.91" exact_value="0x44ACFD1C" />
+<par_real name="baseq" value="1.08427" exact_value="0x3F8AC956" />
<par name="stages" value="0" />
-<par name="freq_track" value="64" />
-<par name="gain" value="64" />
+<par_real name="freq_tracking" value="0" exact_value="0x00000000" />
+<par_real name="gain" value="0" exact_value="0x00000000" />
</FILTER>
<FILTER_ENVELOPE>
<par_bool name="free_mode" value="no" />
@@ -309,11 +309,11 @@ version-revision="1" ZynAddSubFX-author="Nasca Octavian Paul">
<FILTER>
<par name="category" value="0" />
<par name="type" value="2" />
-<par name="freq" value="65" />
-<par name="q" value="68" />
+<par_real name="basefreq" value="1055.65" exact_value="0x4483F4A4" />
+<par_real name="baseq" value="6.34546" exact_value="0x40CB0DF9" />
<par name="stages" value="0" />
-<par name="freq_track" value="64" />
-<par name="gain" value="64" />
+<par_real name="freq_tracking" value="0" exact_value="0x00000000" />
+<par_real name="gain" value="0" exact_value="0x00000000" />
</FILTER>
<par_bool name="filter_envelope_enabled" value="yes" />
<FILTER_ENVELOPE>
@@ -1060,11 +1060,11 @@ version-revision="1" ZynAddSubFX-author="Nasca Octavian Paul">
<FILTER>
<par name="category" value="0" />
<par name="type" value="4" />
-<par name="freq" value="80" />
-<par name="q" value="40" />
+<par_real name="basefreq" value="2378.41" exact_value="0x4514A69F" />
+<par_real name="baseq" value="1.08427" exact_value="0x3F8AC956" />
<par name="stages" value="0" />
-<par name="freq_track" value="64" />
-<par name="gain" value="64" />
+<par_real name="freq_tracking" value="0" exact_value="0x00000000" />
+<par_real name="gain" value="0" exact_value="0x00000000" />
</FILTER>
<par name="filter_velocity_sensing" value="64" />
<par name="filter_velocity_sensing_amplitude" value="64" />
@@ -3411,11 +3411,11 @@ version-revision="1" ZynAddSubFX-author="Nasca Octavian Paul">
<FILTER>
<par name="category" value="0" />
<par name="type" value="2" />
-<par name="freq" value="111" />
-<par name="q" value="95" />
+<par_real name="basefreq" value="12745.1" exact_value="0x4647248B" />
+<par_real name="baseq" value="46.8148" exact_value="0x423B4262" />
<par name="stages" value="0" />
-<par name="freq_track" value="64" />
-<par name="gain" value="64" />
+<par_real name="freq_tracking" value="0" exact_value="0x00000000" />
+<par_real name="gain" value="0" exact_value="0x00000000" />
</FILTER>
<FILTER_ENVELOPE>
<par_bool name="free_mode" value="no" />
diff --git a/src/UI/MasterUI.fl b/src/UI/MasterUI.fl
@@ -2,7 +2,7 @@
version 1.0302
header_name {.h}
code_name {.cc}
-decl {//Copyright (c) 2002-2009 Nasca Octavian Paul - (c) 2009-2016 Mark McCurry} {private local
+decl {//Copyright (c) 2002-2009 Nasca Octavian Paul - (c) 2009-2017 Mark McCurry} {private local
}
decl {//License: GNU GPL version 2 or later} {private local
diff --git a/src/main.cpp b/src/main.cpp
@@ -220,7 +220,7 @@ int main(int argc, char *argv[])
<< "\nZynAddSubFX - Copyright (c) 2002-2013 Nasca Octavian Paul and others"
<< endl;
cerr
- << " Copyright (c) 2009-2016 Mark McCurry [active maintainer]"
+ << " Copyright (c) 2009-2017 Mark McCurry [active maintainer]"
<< endl;
cerr << "Compiled: " << __DATE__ << " " << __TIME__ << endl;
cerr << "This program is free software (GNU GPL v2 or later) and \n";