beginning of midi + fixes
This commit is contained in:
parent
85e2c1ef14
commit
d8379dcb6d
1
TODO
1
TODO
@ -12,3 +12,4 @@
|
||||
* #if > 0 -> dotjs
|
||||
* 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
|
||||
* 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
|
||||
map:
|
||||
"linear" vs "logarithmic"
|
||||
VST3:
|
||||
VST3: many places (requires libm)
|
||||
LV2: manifest.ttl lv2:port lv2:portProperty pprops:logarithmic
|
||||
}
|
||||
]
|
||||
|
@ -54,7 +54,7 @@
|
||||
lv2:portProperty lv2:integer ;
|
||||
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{{?}} ;
|
||||
lv2:name "{{=p.name}}" ;
|
||||
{{?"shortName" in p}}
|
||||
@ -65,10 +65,16 @@
|
||||
lv2:minimum {{=p.minimum.toExponential()}} ;
|
||||
lv2:maximum {{=p.maximum.toExponential()}} ;
|
||||
lv2:default {{=p.defaultValue.toExponential()}} ;
|
||||
{{??p.type == "midi"}}
|
||||
atom:bufferType atom:Sequence ;
|
||||
atom:supports midi:MidiEvent ;
|
||||
{{?}}
|
||||
{{?p.sidechain}}
|
||||
lv2:portProperty lv2:isSideChain ;
|
||||
{{?}}
|
||||
{{?p.control}}
|
||||
lv2:designation lv2:control ;
|
||||
{{?}}
|
||||
{{?p.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_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_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;
|
||||
#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
|
||||
i->c[port] = data_location;
|
||||
#endif
|
||||
|
@ -4,9 +4,11 @@ var sep = path.sep;
|
||||
module.exports = function (data, api) {
|
||||
data.tibia.lv2 = {
|
||||
prefixes: [
|
||||
{ id: "atom", uri: "http://lv2plug.in/ns/ext/atom#" },
|
||||
{ id: "doap", uri: "http://usefulinc.com/ns/doap#" },
|
||||
{ id: "foaf", uri: "http://xmlns.com/foaf/0.1/" },
|
||||
{ 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: "rdf", uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" },
|
||||
{ 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)
|
||||
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++) {
|
||||
var p = data.product.parameters[i];
|
||||
var e = Object.create(p);
|
||||
e.type = "control";
|
||||
e.symbol = data.lv2.parameterSymbols[i];
|
||||
e.paramIndex = i;
|
||||
data.tibia.lv2.ports.push(e);
|
||||
ports.push(e);
|
||||
}
|
||||
|
||||
var audioBuses = data.product.buses.filter(x => x.type == "audio");
|
||||
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));
|
||||
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);
|
||||
|
||||
api.generateFileFromTemplateFile(`data${sep}manifest.ttl`, `data${sep}manifest.ttl`, data);
|
||||
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_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_EVENT_OUTPUT_N {{=it.product.buses.filter(x => x.type == "event" && x.direction == "output").length}}
|
||||
#define DATA_PRODUCT_BUSES_MIDI_INPUT_N {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").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_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
|
||||
|
||||
#if DATA_PRODUCT_BUSES_EVENT_INPUT_N > 0
|
||||
static struct Steinberg_Vst_BusInfo busInfoEventInput[DATA_PRODUCT_BUSES_EVENT_INPUT_N] = {
|
||||
{{~it.product.buses.filter(x => x.type == "event" && x.direction == "input") :b}}
|
||||
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||
static struct Steinberg_Vst_BusInfo busInfoMidiInput[DATA_PRODUCT_BUSES_MIDI_INPUT_N] = {
|
||||
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "input") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kInput,
|
||||
/* .channelCount = */ 1,
|
||||
/* .channelCount = */ 16,
|
||||
/* .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{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if DATA_PRODUCT_BUSES_EVENT_OUTPUT_N > 0
|
||||
static struct Steinberg_Vst_BusInfo busInfoAudioInput[DATA_PRODUCT_BUSES_EVENT_OUTPUT_N] = {
|
||||
{{~it.product.buses.filter(x => x.type == "event" && x.direction == "output") :b}}
|
||||
#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
||||
static struct Steinberg_Vst_BusInfo busInfoMidiOutput[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N] = {
|
||||
{{~it.product.buses.filter(x => x.type == "midi" && x.direction == "output") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kOutput,
|
||||
/* .channelCount = */ 1,
|
||||
/* .channelCount = */ 16,
|
||||
/* .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{{?}}
|
||||
},
|
||||
{{~}}
|
||||
@ -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}}
|
||||
|
||||
#if DATA_PRODUCT_PARAMETERS_N > 0
|
||||
static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PRODUCT_PARAMETERS_N] = {
|
||||
#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 + 2 * (DATA_PRODUCT_BUSES_MIDI_INPUT_N + DATA_PRODUCT_BUSES_MIDI_OUTPUT_N)] = {
|
||||
{{~it.product.parameters.filter(x => !x.isLatency) :p: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
|
||||
|
@ -168,9 +168,9 @@ static Steinberg_int32 pluginGetBusCount(void *thisInterface, Steinberg_Vst_Medi
|
||||
return DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N;
|
||||
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
||||
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)
|
||||
return DATA_PRODUCT_BUSES_EVENT_OUTPUT_N;
|
||||
return DATA_PRODUCT_BUSES_MIDI_OUTPUT_N;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -197,17 +197,17 @@ static Steinberg_tresult pluginGetBusInfo(void* thisInterface, Steinberg_Vst_Med
|
||||
}
|
||||
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
||||
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
||||
#if DATA_PRODUCT_BUSES_EVENT_INPUT_N > 0
|
||||
if (index >= DATA_PRODUCT_BUSES_AUDIO_INPUT_N)
|
||||
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||
if (index >= DATA_PRODUCT_BUSES_MIDI_INPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
*bus = busInfoEventInput[index];
|
||||
*bus = busInfoMidiInput[index];
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
||||
#if DATA_PRODUCT_BUSES_EVENT_OUTPUT_N > 0
|
||||
if (index >= DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N)
|
||||
#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
||||
if (index >= DATA_PRODUCT_BUSES_MIDI_OUTPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
*bus = busInfoEventOutput[index];
|
||||
*bus = busInfoMidiOutput[index];
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
}
|
||||
@ -240,14 +240,14 @@ static Steinberg_tresult pluginActivateBus(void* thisInterface, Steinberg_Vst_Me
|
||||
}
|
||||
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
||||
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
||||
#if DATA_PRODUCT_BUSES_EVENT_INPUT_N > 0
|
||||
if (index >= DATA_PRODUCT_BUSES_AUDIO_INPUT_N)
|
||||
#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0
|
||||
if (index >= DATA_PRODUCT_BUSES_MIDI_INPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
||||
#if DATA_PRODUCT_BUSES_EVENT_OUTPUT_N > 0
|
||||
if (index >= DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N)
|
||||
#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0
|
||||
if (index >= DATA_PRODUCT_BUSES_MIDI_OUTPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
@ -704,12 +704,12 @@ static Steinberg_tresult controllerGetState(void* thisInterface, struct Steinber
|
||||
|
||||
static Steinberg_int32 controllerGetParameterCount(void* thisInterface) {
|
||||
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) {
|
||||
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;
|
||||
*info = parameterInfo[paramIndex];
|
||||
return Steinberg_kResultTrue;
|
||||
|
@ -7,7 +7,7 @@
|
||||
"project": "@example:project",
|
||||
"types": [ "@lv2:AmplifierPlugin" ],
|
||||
"version": "1.0",
|
||||
"busSymbols": [ "input", "output" ],
|
||||
"parameterSymbols": [ "gain", "enabled" ]
|
||||
"busSymbols": [ "input", "output", "midi_in", "midi_out" ],
|
||||
"parameterSymbols": [ "gain", "delay", "cutoff", "enabled" ]
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,12 @@ typedef struct plugin {
|
||||
|
||||
float gain;
|
||||
float delay;
|
||||
float cutoff;
|
||||
char bypass;
|
||||
|
||||
float * delay_line;
|
||||
size_t delay_line_cur;
|
||||
float z1;
|
||||
} plugin;
|
||||
|
||||
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) {
|
||||
memset(instance->delay_line, 0, instance->delay_line_length * sizeof(float));
|
||||
instance->delay_line_cur = 0;
|
||||
instance->z1 = 0.f;
|
||||
}
|
||||
|
||||
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;
|
||||
break;
|
||||
case 2:
|
||||
instance->cutoff = value;
|
||||
break;
|
||||
case 3:
|
||||
instance->bypass = value >= 0.5f;
|
||||
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) {
|
||||
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++) {
|
||||
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++;
|
||||
if (instance->delay_line_cur == instance->delay_line_length)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,24 @@
|
||||
"sidechain": false,
|
||||
"cv": 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": [
|
||||
@ -64,6 +82,22 @@
|
||||
"unit": "ms",
|
||||
"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",
|
||||
"shortName": "Bypass",
|
||||
|
Loading…
Reference in New Issue
Block a user