beginning of midi + fixes
This commit is contained in:
parent
85e2c1ef14
commit
d8379dcb6d
1
TODO
1
TODO
@ -12,3 +12,4 @@
|
|||||||
* #if > 0 -> dotjs
|
* #if > 0 -> dotjs
|
||||||
* more mappings, lv2 port props
|
* more mappings, lv2 port props
|
||||||
* latency mechanism, see https://steinbergmedia.github.io/vst3_dev_portal/pages/Technical+Documentation/Workflow+Diagrams/Get+Latency+Call+Sequence.html, https://steinbergmedia.github.io/vst3_doc/vstinterfaces/classSteinberg_1_1Vst_1_1IAudioProcessor.html#af8884671ccefe68e0a86e72413a0fcf8, https://steinbergmedia.github.io/vst3_dev_portal/pages/Technical+Documentation/Workflow+Diagrams/Audio+Processor+Call+Sequence.html
|
* latency mechanism, see https://steinbergmedia.github.io/vst3_dev_portal/pages/Technical+Documentation/Workflow+Diagrams/Get+Latency+Call+Sequence.html, https://steinbergmedia.github.io/vst3_doc/vstinterfaces/classSteinberg_1_1Vst_1_1IAudioProcessor.html#af8884671ccefe68e0a86e72413a0fcf8, https://steinbergmedia.github.io/vst3_dev_portal/pages/Technical+Documentation/Workflow+Diagrams/Audio+Processor+Call+Sequence.html
|
||||||
|
* vst3 don't include/link libm if not needed, etc. (reduce to minimum reqs)
|
||||||
|
2
notes
2
notes
@ -86,7 +86,7 @@ product {
|
|||||||
LV2: manifest.ttl lv2:port units:unit
|
LV2: manifest.ttl lv2:port units:unit
|
||||||
map:
|
map:
|
||||||
"linear" vs "logarithmic"
|
"linear" vs "logarithmic"
|
||||||
VST3:
|
VST3: many places (requires libm)
|
||||||
LV2: manifest.ttl lv2:port lv2:portProperty pprops:logarithmic
|
LV2: manifest.ttl lv2:port lv2:portProperty pprops:logarithmic
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
lv2:portProperty lv2:integer ;
|
lv2:portProperty lv2:integer ;
|
||||||
lv2:portProperty lv2:reportsLatency ;
|
lv2:portProperty lv2:reportsLatency ;
|
||||||
{{??}}
|
{{??}}
|
||||||
a {{?p.type == "control"}}lv2:ControlPort{{??}}{{?p.cv}}lv2:CVPort{{??}}lv2:AudioPort{{?}}{{?}} ,
|
a {{?p.type == "control"}}lv2:ControlPort{{??p.type == "midi"}}atom:AtomPort{{??}}{{?p.cv}}lv2:CVPort{{??}}lv2:AudioPort{{?}}{{?}} ,
|
||||||
{{?p.direction == "input"}}lv2:InputPort{{??}}lv2:OutputPort{{?}} ;
|
{{?p.direction == "input"}}lv2:InputPort{{??}}lv2:OutputPort{{?}} ;
|
||||||
lv2:name "{{=p.name}}" ;
|
lv2:name "{{=p.name}}" ;
|
||||||
{{?"shortName" in p}}
|
{{?"shortName" in p}}
|
||||||
@ -65,10 +65,16 @@
|
|||||||
lv2:minimum {{=p.minimum.toExponential()}} ;
|
lv2:minimum {{=p.minimum.toExponential()}} ;
|
||||||
lv2:maximum {{=p.maximum.toExponential()}} ;
|
lv2:maximum {{=p.maximum.toExponential()}} ;
|
||||||
lv2:default {{=p.defaultValue.toExponential()}} ;
|
lv2:default {{=p.defaultValue.toExponential()}} ;
|
||||||
|
{{??p.type == "midi"}}
|
||||||
|
atom:bufferType atom:Sequence ;
|
||||||
|
atom:supports midi:MidiEvent ;
|
||||||
{{?}}
|
{{?}}
|
||||||
{{?p.sidechain}}
|
{{?p.sidechain}}
|
||||||
lv2:portProperty lv2:isSideChain ;
|
lv2:portProperty lv2:isSideChain ;
|
||||||
{{?}}
|
{{?}}
|
||||||
|
{{?p.control}}
|
||||||
|
lv2:designation lv2:control ;
|
||||||
|
{{?}}
|
||||||
{{?p.toggled}}
|
{{?p.toggled}}
|
||||||
lv2:portProperty lv2:toggled ;
|
lv2:portProperty lv2:toggled ;
|
||||||
{{?}}
|
{{?}}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#define DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
#define DATA_PRODUCT_AUDIO_INPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
||||||
#define DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
#define DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((s, x) => s += x.channels == "mono" ? 1 : 2, 0)}}
|
||||||
|
#define DATA_PRODUCT_MIDI_INPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||||
|
#define DATA_PRODUCT_MIDI_OUTPUTS_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}}
|
||||||
#define DATA_PRODUCT_CONTROL_INPUTS_N {{=it.product.parameters.filter(x => x.direction == "input").length}}
|
#define DATA_PRODUCT_CONTROL_INPUTS_N {{=it.product.parameters.filter(x => x.direction == "input").length}}
|
||||||
#define DATA_PRODUCT_CONTROL_OUTPUTS_N {{=it.product.parameters.filter(x => x.direction == "output").length}}
|
#define DATA_PRODUCT_CONTROL_OUTPUTS_N {{=it.product.parameters.filter(x => x.direction == "output").length}}
|
||||||
|
|
||||||
|
@ -73,6 +73,20 @@ static void connect_port(LV2_Handle instance, uint32_t port, void * data_locatio
|
|||||||
}
|
}
|
||||||
port -= DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N;
|
port -= DATA_PRODUCT_AUDIO_OUTPUT_CHANNELS_N;
|
||||||
#endif
|
#endif
|
||||||
|
#if DATA_PRODUCT_MIDI_INPUTS_N > 0
|
||||||
|
if (port < DATA_PRODUCT_MIDI_INPUTS_N) {
|
||||||
|
// TBD
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
port -= DATA_PRODUCT_MIDI_INPUTS_N;
|
||||||
|
#endif
|
||||||
|
#if DATA_PRODUCT_MIDI_OUTPUTS_N > 0
|
||||||
|
if (port < DATA_PRODUCT_MIDI_OUTPUTS_N) {
|
||||||
|
// TBD
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
port -= DATA_PRODUCT_MIDI_OUTPUTS_N;
|
||||||
|
#endif
|
||||||
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
#if (DATA_PRODUCT_CONTROL_INPUTS_N + DATA_PRODUCT_CONTROL_OUTPUTS_N) > 0
|
||||||
i->c[port] = data_location;
|
i->c[port] = data_location;
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,9 +4,11 @@ var sep = path.sep;
|
|||||||
module.exports = function (data, api) {
|
module.exports = function (data, api) {
|
||||||
data.tibia.lv2 = {
|
data.tibia.lv2 = {
|
||||||
prefixes: [
|
prefixes: [
|
||||||
|
{ id: "atom", uri: "http://lv2plug.in/ns/ext/atom#" },
|
||||||
{ id: "doap", uri: "http://usefulinc.com/ns/doap#" },
|
{ id: "doap", uri: "http://usefulinc.com/ns/doap#" },
|
||||||
{ id: "foaf", uri: "http://xmlns.com/foaf/0.1/" },
|
{ id: "foaf", uri: "http://xmlns.com/foaf/0.1/" },
|
||||||
{ id: "lv2", uri: "http://lv2plug.in/ns/lv2core#" },
|
{ id: "lv2", uri: "http://lv2plug.in/ns/lv2core#" },
|
||||||
|
{ id: "midi", uri: "http://lv2plug.in/ns/ext/midi#" },
|
||||||
{ id: "pprops", uri: "http://lv2plug.in/ns/ext/port-props#" },
|
{ id: "pprops", uri: "http://lv2plug.in/ns/ext/port-props#" },
|
||||||
{ id: "rdf", uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
|
{ id: "rdf", uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
|
||||||
{ id: "rdfs", uri: "http://www.w3.org/2000/01/rdf-schema#" },
|
{ id: "rdfs", uri: "http://www.w3.org/2000/01/rdf-schema#" },
|
||||||
@ -56,33 +58,49 @@ module.exports = function (data, api) {
|
|||||||
for (var id in data.lv2.prefixes)
|
for (var id in data.lv2.prefixes)
|
||||||
data.tibia.lv2.prefixes.push({ id: id, uri: data.lv2.prefixes[id] });
|
data.tibia.lv2.prefixes.push({ id: id, uri: data.lv2.prefixes[id] });
|
||||||
|
|
||||||
|
var audioBuses = data.product.buses.filter(x => x.type == "audio");
|
||||||
|
var ports = [];
|
||||||
|
var bi = 0;
|
||||||
|
for (; bi < audioBuses.length; bi++) {
|
||||||
|
var b = audioBuses[bi];
|
||||||
|
if (b.channels == "mono") {
|
||||||
|
var e = { type: "audio", direction: b.direction, name: b.name, sidechain: b.sidechain, cv: b.cv, optional: b.optional };
|
||||||
|
e.symbol = data.lv2.busSymbols[bi];
|
||||||
|
ports.push(e);
|
||||||
|
} else {
|
||||||
|
var e = { type: "audio", direction: b.direction, name: b.name + " Left", shortName: b.shortName + " L", sidechain: b.sidechain, cv: b.cv };
|
||||||
|
e.symbol = data.lv2.busSymbols[bi] + "_L";
|
||||||
|
data.tibia.lv2.ports.push(e);
|
||||||
|
var e = { type: "audio", direction: b.direction, name: b.name + " Right", shortName: b.shortName + " R", sidechain: b.sidechain, cv: b.cv };
|
||||||
|
e.symbol = data.lv2.busSymbols[bi] + "_R";
|
||||||
|
ports.push(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ports.sort((a, b) => a.direction != b.direction ? (a.direction == "input" ? -1 : 1) : 0);
|
||||||
|
data.tibia.lv2.ports.push.apply(data.tibia.lv2.ports, ports);
|
||||||
|
|
||||||
|
var midiBuses = data.product.buses.filter(x => x.type == "midi");
|
||||||
|
var ports = [];
|
||||||
|
for (var i = 0; i < midiBuses.length; i++, bi++) {
|
||||||
|
var b = midiBuses[i];
|
||||||
|
var e = { type: "midi", direction: b.direction, name: b.name, sidechain: b.sidechain, control: b.control, optional: b.optional };
|
||||||
|
e.symbol = data.lv2.busSymbols[bi];
|
||||||
|
ports.push(e);
|
||||||
|
}
|
||||||
|
ports.sort((a, b) => a.direction != b.direction ? (a.direction == "input" ? -1 : 1) : 0);
|
||||||
|
data.tibia.lv2.ports.push.apply(data.tibia.lv2.ports, ports);
|
||||||
|
|
||||||
|
var ports = [];
|
||||||
for (var i = 0; i < data.product.parameters.length; i++) {
|
for (var i = 0; i < data.product.parameters.length; i++) {
|
||||||
var p = data.product.parameters[i];
|
var p = data.product.parameters[i];
|
||||||
var e = Object.create(p);
|
var e = Object.create(p);
|
||||||
e.type = "control";
|
e.type = "control";
|
||||||
e.symbol = data.lv2.parameterSymbols[i];
|
e.symbol = data.lv2.parameterSymbols[i];
|
||||||
e.paramIndex = i;
|
e.paramIndex = i;
|
||||||
data.tibia.lv2.ports.push(e);
|
ports.push(e);
|
||||||
}
|
}
|
||||||
|
ports.sort((a, b) => a.direction != b.direction ? (a.direction == "input" ? -1 : 1) : 0);
|
||||||
var audioBuses = data.product.buses.filter(x => x.type == "audio");
|
data.tibia.lv2.ports.push.apply(data.tibia.lv2.ports, ports);
|
||||||
for (var i = 0; i < audioBuses.length; i++) {
|
|
||||||
var b = audioBuses[i];
|
|
||||||
if (b.channels == "mono") {
|
|
||||||
var e = { type: "audio", direction: b.direction, name: b.name, sidechain: b.sidechain, cv: b.cv };
|
|
||||||
e.symbol = data.lv2.busSymbols[i];
|
|
||||||
data.tibia.lv2.ports.push(e);
|
|
||||||
} else {
|
|
||||||
var e = { type: "audio", direction: b.direction, name: b.name + " Left", shortName: b.shortName + " L", sidechain: b.sidechain, cv: b.cv };
|
|
||||||
e.symbol = data.lv2.busSymbols[i] + "_L";
|
|
||||||
data.tibia.lv2.ports.push(e);
|
|
||||||
var e = { type: "audio", direction: b.direction, name: b.name + " Right", shortName: b.shortName + " R", sidechain: b.sidechain, cv: b.cv };
|
|
||||||
e.symbol = data.lv2.busSymbols[i] + "_R";
|
|
||||||
data.tibia.lv2.ports.push(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.tibia.lv2.ports.sort((a, b) => a.type != b.type ? (a.type == "audio" ? -1 : 1) : (a.direction != b.direction ? (a.direction == "input" ? -1 : 1) : 0));
|
|
||||||
|
|
||||||
api.generateFileFromTemplateFile(`data${sep}manifest.ttl`, `data${sep}manifest.ttl`, data);
|
api.generateFileFromTemplateFile(`data${sep}manifest.ttl`, `data${sep}manifest.ttl`, data);
|
||||||
api.copyFile(`src${sep}lv2.c`, `src${sep}lv2.c`);
|
api.copyFile(`src${sep}lv2.c`, `src${sep}lv2.c`);
|
||||||
|
@ -30,8 +30,8 @@ static const Steinberg_TUID dataControllerCID = SMTG_INLINE_UID(DATA_VST3_CONTRO
|
|||||||
|
|
||||||
#define DATA_PRODUCT_BUSES_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}}
|
#define DATA_PRODUCT_BUSES_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").length}}
|
||||||
#define DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}}
|
#define DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").length}}
|
||||||
#define DATA_PRODUCT_BUSES_EVENT_INPUT_N {{=it.product.buses.filter(x => x.type == "event" && x.direction == "input").length}}
|
#define DATA_PRODUCT_BUSES_MIDI_INPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length}}
|
||||||
#define DATA_PRODUCT_BUSES_EVENT_OUTPUT_N {{=it.product.buses.filter(x => x.type == "event" && x.direction == "output").length}}
|
#define DATA_PRODUCT_BUSES_MIDI_OUTPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "output").length}}
|
||||||
|
|
||||||
#define DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
#define DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "input").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||||
#define DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
#define DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N {{=it.product.buses.filter(x => x.type == "audio" && x.direction == "output").reduce((a, x) => a + (x.channels == "mono" ? 1 : 2), 0)}}
|
||||||
@ -66,30 +66,30 @@ static struct Steinberg_Vst_BusInfo busInfoAudioOutput[DATA_PRODUCT_BUSES_AUDIO_
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DATA_PRODUCT_BUSES_EVENT_INPUT_N > 0
|
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
static struct Steinberg_Vst_BusInfo busInfoEventInput[DATA_PRODUCT_BUSES_EVENT_INPUT_N] = {
|
static struct Steinberg_Vst_BusInfo busInfoMidiInput[DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
||||||
{{~it.product.buses.filter(x => x.type == "event" && x.direction == "input") :b}}
|
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b}}
|
||||||
{
|
{
|
||||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||||
/* .direction = */ Steinberg_Vst_BusDirections_kInput,
|
/* .direction = */ Steinberg_Vst_BusDirections_kInput,
|
||||||
/* .channelCount = */ 1,
|
/* .channelCount = */ 16,
|
||||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .busType = */ Steinberg_Vst_BusTypes_kMain,
|
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||||
/* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
/* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||||
},
|
},
|
||||||
{{~}}
|
{{~}}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DATA_PRODUCT_BUSES_EVENT_OUTPUT_N > 0
|
#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
||||||
static struct Steinberg_Vst_BusInfo busInfoAudioInput[DATA_PRODUCT_BUSES_EVENT_OUTPUT_N] = {
|
static struct Steinberg_Vst_BusInfo busInfoMidiOutput[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N] = {
|
||||||
{{~it.product.buses.filter(x => x.type == "event" && x.direction == "output") :b}}
|
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "output") :b}}
|
||||||
{
|
{
|
||||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||||
/* .direction = */ Steinberg_Vst_BusDirections_kOutput,
|
/* .direction = */ Steinberg_Vst_BusDirections_kOutput,
|
||||||
/* .channelCount = */ 1,
|
/* .channelCount = */ 16,
|
||||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
/* .busType = */ Steinberg_Vst_BusTypes_kMain,
|
/* .busType = */ {{?b.sidechain}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||||
/* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
/* .flags = */ 0{{?!b.optional}} | Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||||
},
|
},
|
||||||
{{~}}
|
{{~}}
|
||||||
@ -98,8 +98,8 @@ static struct Steinberg_Vst_BusInfo busInfoAudioInput[DATA_PRODUCT_BUSES_EVENT_O
|
|||||||
|
|
||||||
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}}
|
#define DATA_PRODUCT_PARAMETERS_N {{=it.product.parameters.filter(x => !x.isLatency).length}}
|
||||||
|
|
||||||
#if DATA_PRODUCT_PARAMETERS_N > 0
|
#if DATA_PRODUCT_PARAMETERS_N + DATA_PRODUCT_BUSES_MIDI_INPUT_N + DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
||||||
static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_N] = {
|
static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_N + 2 * (DATA_PRODUCT_BUSES_MIDI_INPUT_N + DATA_PRODUCT_BUSES_MIDI_OUTPUT_N)] = {
|
||||||
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
{{~it.product.parameters.filter(x => !x.isLatency) :p:i}}
|
||||||
{
|
{
|
||||||
/* .id = */ {{=i}},
|
/* .id = */ {{=i}},
|
||||||
@ -122,6 +122,50 @@ static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_
|
|||||||
{{?}}
|
{{?}}
|
||||||
},
|
},
|
||||||
{{~}}
|
{{~}}
|
||||||
|
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b:i}}
|
||||||
|
{
|
||||||
|
/* .id = */ {{=it.product.parameters.filter(x => !x.isLatency).length + 2 * i}},
|
||||||
|
/* .title = */ { {{~Array.from(b.name + " CP") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " CP") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
|
/* .units = */ { 0 },
|
||||||
|
/* .stepCount = */ 0,
|
||||||
|
/* .defaultNormalizedValue = */ 0.0,
|
||||||
|
/* .unitId = */ 0,
|
||||||
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* .id = */ {{=it.product.parameters.filter(x => !x.isLatency).length + 2 * i + 1}},
|
||||||
|
/* .title = */ { {{~Array.from(b.name + " PB") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " PB") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
|
/* .units = */ { 0 },
|
||||||
|
/* .stepCount = */ 0,
|
||||||
|
/* .defaultNormalizedValue = */ 0.0,
|
||||||
|
/* .unitId = */ 0,
|
||||||
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly
|
||||||
|
},
|
||||||
|
{{~}}
|
||||||
|
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "output") :b:i}}
|
||||||
|
{
|
||||||
|
/* .id = */ {{=it.product.parameters.filter(x => !x.isLatency).length + 2 * it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length + 2 * i}},
|
||||||
|
/* .title = */ { {{~Array.from(b.name + " CP") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " CP") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
|
/* .units = */ { 0 },
|
||||||
|
/* .stepCount = */ 0,
|
||||||
|
/* .defaultNormalizedValue = */ 0.0,
|
||||||
|
/* .unitId = */ 0,
|
||||||
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* .id = */ {{=it.product.parameters.filter(x => !x.isLatency).length + 2 * it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length + 2 * i + 1}},
|
||||||
|
/* .title = */ { {{~Array.from(b.name + " PB") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
|
/* .shortTitle = */ { {{~Array.from(b.shortName + " PB") :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||||
|
/* .units = */ { 0 },
|
||||||
|
/* .stepCount = */ 0,
|
||||||
|
/* .defaultNormalizedValue = */ 0.0,
|
||||||
|
/* .unitId = */ 0,
|
||||||
|
/* .flags = */ Steinberg_Vst_ParameterInfo_ParameterFlags_kIsHidden | Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly
|
||||||
|
},
|
||||||
|
{{~}}
|
||||||
};
|
};
|
||||||
|
|
||||||
# define DATA_PARAM_BYPASS 1
|
# define DATA_PARAM_BYPASS 1
|
||||||
|
@ -168,9 +168,9 @@ static Steinberg_int32 pluginGetBusCount(void *thisInterface, Steinberg_Vst_Medi
|
|||||||
return DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N;
|
return DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N;
|
||||||
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
||||||
if (dir == Steinberg_Vst_BusDirections_kInput)
|
if (dir == Steinberg_Vst_BusDirections_kInput)
|
||||||
return DATA_PRODUCT_BUSES_EVENT_INPUT_N;
|
return DATA_PRODUCT_BUSES_MIDI_INPUT_N;
|
||||||
else if (dir == Steinberg_Vst_BusDirections_kOutput)
|
else if (dir == Steinberg_Vst_BusDirections_kOutput)
|
||||||
return DATA_PRODUCT_BUSES_EVENT_OUTPUT_N;
|
return DATA_PRODUCT_BUSES_MIDI_OUTPUT_N;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -197,17 +197,17 @@ static Steinberg_tresult pluginGetBusInfo(void* thisInterface, Steinberg_Vst_Med
|
|||||||
}
|
}
|
||||||
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
||||||
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
||||||
#if DATA_PRODUCT_BUSES_EVENT_INPUT_N > 0
|
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
if (index >= DATA_PRODUCT_BUSES_AUDIO_INPUT_N)
|
if (index >= DATA_PRODUCT_BUSES_MIDI_INPUT_N)
|
||||||
return Steinberg_kInvalidArgument;
|
return Steinberg_kInvalidArgument;
|
||||||
*bus = busInfoEventInput[index];
|
*bus = busInfoMidiInput[index];
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
#endif
|
#endif
|
||||||
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
||||||
#if DATA_PRODUCT_BUSES_EVENT_OUTPUT_N > 0
|
#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
||||||
if (index >= DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N)
|
if (index >= DATA_PRODUCT_BUSES_MIDI_OUTPUT_N)
|
||||||
return Steinberg_kInvalidArgument;
|
return Steinberg_kInvalidArgument;
|
||||||
*bus = busInfoEventOutput[index];
|
*bus = busInfoMidiOutput[index];
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -240,14 +240,14 @@ static Steinberg_tresult pluginActivateBus(void* thisInterface, Steinberg_Vst_Me
|
|||||||
}
|
}
|
||||||
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
||||||
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
||||||
#if DATA_PRODUCT_BUSES_EVENT_INPUT_N > 0
|
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||||
if (index >= DATA_PRODUCT_BUSES_AUDIO_INPUT_N)
|
if (index >= DATA_PRODUCT_BUSES_MIDI_INPUT_N)
|
||||||
return Steinberg_kInvalidArgument;
|
return Steinberg_kInvalidArgument;
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
#endif
|
#endif
|
||||||
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
||||||
#if DATA_PRODUCT_BUSES_EVENT_OUTPUT_N > 0
|
#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
||||||
if (index >= DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N)
|
if (index >= DATA_PRODUCT_BUSES_MIDI_OUTPUT_N)
|
||||||
return Steinberg_kInvalidArgument;
|
return Steinberg_kInvalidArgument;
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
#endif
|
#endif
|
||||||
@ -704,12 +704,12 @@ static Steinberg_tresult controllerGetState(void* thisInterface, struct Steinber
|
|||||||
|
|
||||||
static Steinberg_int32 controllerGetParameterCount(void* thisInterface) {
|
static Steinberg_int32 controllerGetParameterCount(void* thisInterface) {
|
||||||
TRACE("controller get parameter count\n");
|
TRACE("controller get parameter count\n");
|
||||||
return DATA_PRODUCT_PARAMETERS_N;
|
return DATA_PRODUCT_PARAMETERS_N + 2 * (DATA_PRODUCT_BUSES_MIDI_INPUT_N + DATA_PRODUCT_BUSES_MIDI_OUTPUT_N);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Steinberg_tresult controllerGetParameterInfo(void* thisInterface, Steinberg_int32 paramIndex, struct Steinberg_Vst_ParameterInfo* info) {
|
static Steinberg_tresult controllerGetParameterInfo(void* thisInterface, Steinberg_int32 paramIndex, struct Steinberg_Vst_ParameterInfo* info) {
|
||||||
TRACE("controller get parameter info\n");
|
TRACE("controller get parameter info\n");
|
||||||
if (paramIndex < 0 || paramIndex >= DATA_PRODUCT_PARAMETERS_N)
|
if (paramIndex < 0 || paramIndex >= DATA_PRODUCT_PARAMETERS_N + 2 * (DATA_PRODUCT_BUSES_MIDI_INPUT_N + DATA_PRODUCT_BUSES_MIDI_OUTPUT_N))
|
||||||
return Steinberg_kResultFalse;
|
return Steinberg_kResultFalse;
|
||||||
*info = parameterInfo[paramIndex];
|
*info = parameterInfo[paramIndex];
|
||||||
return Steinberg_kResultTrue;
|
return Steinberg_kResultTrue;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"project": "@example:project",
|
"project": "@example:project",
|
||||||
"types": [ "@lv2:AmplifierPlugin" ],
|
"types": [ "@lv2:AmplifierPlugin" ],
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"busSymbols": [ "input", "output" ],
|
"busSymbols": [ "input", "output", "midi_in", "midi_out" ],
|
||||||
"parameterSymbols": [ "gain", "enabled" ]
|
"parameterSymbols": [ "gain", "delay", "cutoff", "enabled" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,12 @@ typedef struct plugin {
|
|||||||
|
|
||||||
float gain;
|
float gain;
|
||||||
float delay;
|
float delay;
|
||||||
|
float cutoff;
|
||||||
char bypass;
|
char bypass;
|
||||||
|
|
||||||
float * delay_line;
|
float * delay_line;
|
||||||
size_t delay_line_cur;
|
size_t delay_line_cur;
|
||||||
|
float z1;
|
||||||
} plugin;
|
} plugin;
|
||||||
|
|
||||||
static void plugin_init(plugin *instance) {
|
static void plugin_init(plugin *instance) {
|
||||||
@ -35,6 +37,7 @@ static void plugin_mem_set(plugin *instance, void *mem) {
|
|||||||
static void plugin_reset(plugin *instance) {
|
static void plugin_reset(plugin *instance) {
|
||||||
memset(instance->delay_line, 0, instance->delay_line_length * sizeof(float));
|
memset(instance->delay_line, 0, instance->delay_line_length * sizeof(float));
|
||||||
instance->delay_line_cur = 0;
|
instance->delay_line_cur = 0;
|
||||||
|
instance->z1 = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_set_parameter(plugin *instance, size_t index, float value) {
|
static void plugin_set_parameter(plugin *instance, size_t index, float value) {
|
||||||
@ -46,6 +49,9 @@ static void plugin_set_parameter(plugin *instance, size_t index, float value) {
|
|||||||
instance->delay = 0.001f * value;
|
instance->delay = 0.001f * value;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
instance->cutoff = value;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
instance->bypass = value >= 0.5f;
|
instance->bypass = value >= 0.5f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -62,12 +68,15 @@ static size_t calc_index(size_t cur, size_t delay, size_t len) {
|
|||||||
|
|
||||||
static void plugin_process(plugin *instance, const float **inputs, float **outputs, size_t n_samples) {
|
static void plugin_process(plugin *instance, const float **inputs, float **outputs, size_t n_samples) {
|
||||||
size_t delay = roundf(instance->sample_rate * instance->delay);
|
size_t delay = roundf(instance->sample_rate * instance->delay);
|
||||||
|
const float mA1 = instance->sample_rate / (instance->sample_rate + 6.283185307179586f * instance->cutoff);
|
||||||
for (size_t i = 0; i < n_samples; i++) {
|
for (size_t i = 0; i < n_samples; i++) {
|
||||||
instance->delay_line[instance->delay_line_cur] = inputs[0][i];
|
instance->delay_line[instance->delay_line_cur] = inputs[0][i];
|
||||||
const float y = instance->delay_line[calc_index(instance->delay_line_cur, delay, instance->delay_line_length)];
|
const float x = instance->delay_line[calc_index(instance->delay_line_cur, delay, instance->delay_line_length)];
|
||||||
instance->delay_line_cur++;
|
instance->delay_line_cur++;
|
||||||
if (instance->delay_line_cur == instance->delay_line_length)
|
if (instance->delay_line_cur == instance->delay_line_length)
|
||||||
instance->delay_line_cur = 0;
|
instance->delay_line_cur = 0;
|
||||||
|
const float y = x + mA1 * (instance->z1 - x);
|
||||||
|
instance->z1 = y;
|
||||||
outputs[0][i] = instance->bypass ? inputs[0][i] : instance->gain * y;
|
outputs[0][i] = instance->bypass ? inputs[0][i] : instance->gain * y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,24 @@
|
|||||||
"sidechain": false,
|
"sidechain": false,
|
||||||
"cv": false,
|
"cv": false,
|
||||||
"optional": false
|
"optional": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "midi",
|
||||||
|
"direction": "input",
|
||||||
|
"name": "MIDI input",
|
||||||
|
"shortName": "MIDI input",
|
||||||
|
"sidechain": true,
|
||||||
|
"control": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "midi",
|
||||||
|
"direction": "output",
|
||||||
|
"name": "MIDI output",
|
||||||
|
"shortName": "MIDI output",
|
||||||
|
"sidechain": true,
|
||||||
|
"control": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -64,6 +82,22 @@
|
|||||||
"unit": "ms",
|
"unit": "ms",
|
||||||
"map": "linear"
|
"map": "linear"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Cutoff",
|
||||||
|
"shortName": "Cutoff",
|
||||||
|
"direction": "input",
|
||||||
|
"isBypass": false,
|
||||||
|
"isLatency": false,
|
||||||
|
"defaultValue": 1000.0,
|
||||||
|
"minimum": 20.0,
|
||||||
|
"maximum": 20e3,
|
||||||
|
"toggled": false,
|
||||||
|
"optional": false,
|
||||||
|
"integer": false,
|
||||||
|
"list": false,
|
||||||
|
"unit": "hz",
|
||||||
|
"map": "logarithmic"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Bypass",
|
"name": "Bypass",
|
||||||
"shortName": "Bypass",
|
"shortName": "Bypass",
|
||||||
|
Loading…
Reference in New Issue
Block a user