CC as parameters for LV2

This commit is contained in:
Jean Pierre Cimalando 2021-04-04 16:28:08 +02:00
parent 55fe026143
commit 1c3104800a
7 changed files with 139 additions and 3 deletions

View file

@ -40,3 +40,46 @@ else()
set(LV2PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/lv2" CACHE STRING
"Install destination for LV2 bundle [default: ${CMAKE_INSTALL_PREFIX}/lib/lv2]")
endif()
include(StringUtility)
function(sfizz_lv2_generate_controllers_ttl FILE)
file(WRITE "${FILE}" "# LV2 parameters for SFZ controllers
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sfizz: <${LV2PLUGIN_URI}#> .
")
math(EXPR _j "${SFIZZ_NUM_CCS}-1")
foreach(_i RANGE "${_j}")
string_left_pad(_i "${_i}" 3 0)
file(APPEND "${FILE}" "
sfizz:cc${_i}
a lv2:Parameter ;
rdfs:label \"Controller ${_i}\" ;
rdfs:range atom:Float .
")
endforeach()
file(APPEND "${FILE}" "
<${LV2PLUGIN_URI}>
a lv2:Plugin ;
")
file(APPEND "${FILE}" " patch:readable sfizz:cc000")
foreach(_i RANGE 1 "${_j}")
string_left_pad(_i "${_i}" 3 0)
file(APPEND "${FILE}" ", sfizz:cc${_i}")
endforeach()
file(APPEND "${FILE}" " ;
")
file(APPEND "${FILE}" " patch:writable sfizz:cc000")
foreach(_i RANGE 1 "${_j}")
string_left_pad(_i "${_i}" 3 0)
file(APPEND "${FILE}" ", sfizz:cc${_i}")
endforeach()
file(APPEND "${FILE}" " .
")
endfunction()

11
cmake/StringUtility.cmake Normal file
View file

@ -0,0 +1,11 @@
# SPDX-License-Identifier: BSD-2-Clause
function(string_left_pad VAR INPUT LENGTH FILLCHAR)
set(_output "${INPUT}")
string(LENGTH "${_output}" _length)
while(_length LESS "${LENGTH}")
string(PREPEND _output "${FILLCHAR}")
string(LENGTH "${_output}" _length)
endwhile()
set("${VAR}" "${_output}" PARENT_SCOPE)
endfunction()

View file

@ -82,6 +82,9 @@ if(SFIZZ_USE_VCPKG OR SFIZZ_STATIC_DEPENDENCIES OR CMAKE_CXX_COMPILER_ID MATCHES
file(COPY "lgpl-3.0.txt" DESTINATION ${PROJECT_BINARY_DIR})
endif()
# Generate controllers.ttl
sfizz_lv2_generate_controllers_ttl("${PROJECT_BINARY_DIR}/controllers.ttl")
# Copy resource files into the bundle
set(LV2_RESOURCES
DefaultInstrument.sfz

View file

@ -5,7 +5,7 @@
<@LV2PLUGIN_URI@>
a lv2:Plugin ;
lv2:binary <Contents/Binary/@PROJECT_NAME@@CMAKE_SHARED_MODULE_SUFFIX@> ;
rdfs:seeAlso <@PROJECT_NAME@.ttl> .
rdfs:seeAlso <@PROJECT_NAME@.ttl>, <controllers.ttl> .
@LV2PLUGIN_IF_ENABLE_UI@<@LV2PLUGIN_URI@#ui>
@LV2PLUGIN_IF_ENABLE_UI@ a ui:@LV2_UI_TYPE@ ;

View file

@ -329,6 +329,65 @@ sfizz_lv2_receive_message(void* data, int delay, const char* path, const char* s
(void)write_ok;
}
static void
sfizz_lv2_setup_cc_parameters(sfizz_plugin_t* self)
{
// store the associations between CC number and parameter URID
// construct it trivially in the form of a tabulated perfect hash function
LV2_URID* cc_to_urid = new LV2_URID[sfz::config::numCCs];
int* urid_to_cc;
int urid_to_cc_size;
LV2_URID min_cc_urid {};
LV2_URID max_cc_urid {};
for (int cc = 0; cc < sfz::config::numCCs; ++cc) {
char name[256];
sprintf(name, SFIZZ_URI "#cc%03d", cc);
LV2_URID urid = self->map->map(self->map->handle, name);
if (cc == 0) {
min_cc_urid = urid;
max_cc_urid = urid;
}
else {
min_cc_urid = (urid < min_cc_urid) ? urid : min_cc_urid;
max_cc_urid = (urid > max_cc_urid) ? urid : max_cc_urid;
}
cc_to_urid[cc] = urid;
}
urid_to_cc_size = max_cc_urid - min_cc_urid + 1;
urid_to_cc = new int[urid_to_cc_size];
for (int i = 0; i < urid_to_cc_size; ++i)
urid_to_cc[i] = -1;
for (int cc = 0; cc < sfz::config::numCCs; ++cc) {
LV2_URID urid = cc_to_urid[cc];
urid_to_cc[urid - min_cc_urid] = cc;
}
self->cc_to_urid = cc_to_urid;
self->urid_to_cc = urid_to_cc;
self->min_cc_urid = min_cc_urid;
self->max_cc_urid = max_cc_urid;
}
static int
sfizz_lv2_get_cc_from_parameter_urid(const sfizz_plugin_t* self, LV2_URID urid)
{
int cc = -1;
if (urid >= self->min_cc_urid && urid <= self->max_cc_urid)
cc = self->urid_to_cc[urid - self->min_cc_urid];
return cc;
}
static LV2_URID
sfizz_lv2_get_parameter_urid_from_cc(const sfizz_plugin_t* self, int cc)
{
return self->cc_to_urid[cc];
}
static LV2_Handle
instantiate(const LV2_Descriptor *descriptor,
double rate,
@ -476,6 +535,8 @@ instantiate(const LV2_Descriptor *descriptor,
return NULL;
}
sfizz_lv2_setup_cc_parameters(self);
self->synth = sfizz_create_synth();
self->client = sfizz_create_client(self);
self->synth_mutex = spin_mutex_create();
@ -501,6 +562,8 @@ cleanup(LV2_Handle instance)
spin_mutex_destroy(self->synth_mutex);
sfizz_delete_client(self->client);
sfizz_free(self->synth);
delete[] self->cc_to_urid;
delete[] self->urid_to_cc;
delete self;
}
@ -575,7 +638,14 @@ sfizz_lv2_handle_atom_object(sfizz_plugin_t *self, const LV2_Atom_Object *obj)
char body[MAX_PATH_SIZE];
} sfizz_path_atom_buffer_t;
if (key == self->sfizz_sfz_file_uri)
int cc = sfizz_lv2_get_cc_from_parameter_urid(self, key);
if (cc != -1) {
if (atom->type == self->atom_float_uri && atom->size == sizeof(float)) {
float value = *(const float *)LV2_ATOM_BODY_CONST(atom);
// TODO: CC parameter arrived
}
}
else if (key == self->sfizz_sfz_file_uri)
{
LV2_Atom_Forge *forge = &self->forge_secondary;
sfizz_path_atom_buffer_t buffer;
@ -796,6 +866,7 @@ run(LV2_Handle instance, uint32_t sample_count)
if (ev->body.type == self->atom_object_uri || ev->body.type == self->atom_blank_uri)
{
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
if (obj->body.otype == self->patch_set_uri)
{
sfizz_lv2_handle_atom_object(self, obj);

View file

@ -371,4 +371,6 @@ midnam:update a lv2:Feature .
lv2:default 0 ;
lv2:minimum 0 ;
lv2:maximum 65535 ;
] .
] ;
rdfs:seeAlso <controllers.ttl> .

View file

@ -92,6 +92,12 @@ struct sfizz_plugin_t
LV2_URID time_beats_per_minute_uri {};
LV2_URID time_speed_uri {};
// CC parameters
LV2_URID* cc_to_urid {};
int* urid_to_cc {};
LV2_URID min_cc_urid {};
LV2_URID max_cc_urid {};
// Sfizz related data
sfizz_synth_t *synth {};
sfizz_client_t *client {};