From b23071e5ac85ab88db623835995b0738b7bea3e7 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sat, 4 Jul 2020 11:34:31 +0200 Subject: [PATCH 1/6] lv2: default files for sfz and scala --- lv2/CMakeLists.txt | 11 +++++++ lv2/resources/DefaultInstrument.sfz | 3 ++ lv2/resources/DefaultScale.scl | 14 +++++++++ lv2/sfizz.c | 47 ++++++++++++++++++----------- 4 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 lv2/resources/DefaultInstrument.sfz create mode 100644 lv2/resources/DefaultScale.scl diff --git a/lv2/CMakeLists.txt b/lv2/CMakeLists.txt index 17e1dcfb..d28c8f85 100644 --- a/lv2/CMakeLists.txt +++ b/lv2/CMakeLists.txt @@ -43,6 +43,17 @@ if (SFIZZ_USE_VCPKG OR SFIZZ_STATIC_LIBSNDFILE OR CMAKE_CXX_COMPILER_ID MATCHES file(COPY "lgpl-3.0.txt" DESTINATION ${PROJECT_BINARY_DIR}) endif() +# Copy resource files into the bundle +set(LV2_RESOURCES + DefaultInstrument.sfz + DefaultScale.scl) +execute_process( + COMMAND "${CMAKE_COMMAND}" -E make_directory "${PROJECT_BINARY_DIR}/Resources") +foreach(res ${LV2_RESOURCES}) + file (COPY "${CMAKE_CURRENT_SOURCE_DIR}/resources/${res}" + DESTINATION "${PROJECT_BINARY_DIR}/Resources") +endforeach() + # Installation if (NOT MSVC) install (DIRECTORY ${PROJECT_BINARY_DIR} DESTINATION ${LV2PLUGIN_INSTALL_DIR} diff --git a/lv2/resources/DefaultInstrument.sfz b/lv2/resources/DefaultInstrument.sfz new file mode 100644 index 00000000..5f82f9c2 --- /dev/null +++ b/lv2/resources/DefaultInstrument.sfz @@ -0,0 +1,3 @@ + +sample=*sine +ampeg_attack=0.02 ampeg_release=0.1 diff --git a/lv2/resources/DefaultScale.scl b/lv2/resources/DefaultScale.scl new file mode 100644 index 00000000..081422f0 --- /dev/null +++ b/lv2/resources/DefaultScale.scl @@ -0,0 +1,14 @@ +Equal temperament +12 +100.0 +200.0 +300.0 +400.0 +500.0 +600.0 +700.0 +800.0 +900.0 +1000.0 +1100.0 +1200.0 diff --git a/lv2/sfizz.c b/lv2/sfizz.c index e779a72b..4f9fab1e 100644 --- a/lv2/sfizz.c +++ b/lv2/sfizz.c @@ -88,12 +88,11 @@ #define LV2_DEBUG(...) #endif -static const char default_sfz_text[] = - "sample=*sine" "\n" - "ampeg_attack=0.02 ampeg_release=0.1" "\n"; - typedef struct { + // Paths + const char *bundle_path; + // Features LV2_URID_Map *map; LV2_URID_Unmap *unmap; @@ -299,14 +298,27 @@ sfizz_lv2_parse_sample_rate(sfizz_plugin_t* self, const LV2_Options_Option* opt) } } +static void +sfizz_lv2_get_default_sfz_path(LV2_Handle instance, char *path, size_t size) +{ + sfizz_plugin_t *self = (sfizz_plugin_t *)instance; + snprintf(path, size, "%s/%s", self->bundle_path, "Resources/DefaultInstrument.sfz"); +} + +static void +sfizz_lv2_get_default_scala_path(LV2_Handle instance, char *path, size_t size) +{ + sfizz_plugin_t *self = (sfizz_plugin_t *)instance; + snprintf(path, size, "%s/%s", self->bundle_path, "Resources/DefaultScale.scl"); +} + static LV2_Handle instantiate(const LV2_Descriptor *descriptor, double rate, - const char *path, + const char *bundle_path, const LV2_Feature *const *features) { UNUSED(descriptor); - UNUSED(path); LV2_Options_Option *options = NULL; bool supports_bounded_block_size = false; bool options_has_block_size = false; @@ -317,6 +329,10 @@ instantiate(const LV2_Descriptor *descriptor, if (!self) return NULL; + LV2_Handle instance = (LV2_Handle)self; + + self->bundle_path = bundle_path; + // Set defaults self->max_block_size = MAX_BLOCK_SIZE; self->sample_rate = (float)rate; @@ -434,7 +450,12 @@ instantiate(const LV2_Descriptor *descriptor, } self->synth = sfizz_create_synth(); - sfizz_load_string(self->synth, "default.sfz", default_sfz_text); + + sfizz_lv2_get_default_sfz_path(instance, self->sfz_file_path, MAX_PATH_SIZE); + sfizz_lv2_get_default_scala_path(instance, self->scala_file_path, MAX_PATH_SIZE); + + sfizz_load_file(self->synth, self->sfz_file_path); + sfizz_load_scala_file(self->synth, self->scala_file_path); return (LV2_Handle)self; } @@ -902,16 +923,8 @@ sfizz_lv2_load_file(LV2_Handle instance, const char *file_path) { sfizz_plugin_t *self = (sfizz_plugin_t *)instance; - if (file_path[0] == '\0') - { - if (!sfizz_load_string(self->synth, "default.sfz", default_sfz_text)) - return false; - } - else - { - if (!sfizz_load_file(self->synth, file_path)) - return false; - } + if (!sfizz_load_file(self->synth, file_path)) + return false; sfizz_lv2_update_file_info(self, file_path); return true; From 5b298f10bab31ea2d64e72894f75904ee1233008 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Sat, 4 Jul 2020 13:55:07 +0200 Subject: [PATCH 2/6] "Clear" the synth by loading an empty instrument For instruments saved without the default sine, this should keep them from sounding --- lv2/resources/EmptyInstrument.sfz | 0 lv2/sfizz.c | 13 +++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 lv2/resources/EmptyInstrument.sfz diff --git a/lv2/resources/EmptyInstrument.sfz b/lv2/resources/EmptyInstrument.sfz new file mode 100644 index 00000000..e69de29b diff --git a/lv2/sfizz.c b/lv2/sfizz.c index 4f9fab1e..ffe1d3e1 100644 --- a/lv2/sfizz.c +++ b/lv2/sfizz.c @@ -305,6 +305,13 @@ sfizz_lv2_get_default_sfz_path(LV2_Handle instance, char *path, size_t size) snprintf(path, size, "%s/%s", self->bundle_path, "Resources/DefaultInstrument.sfz"); } +static void +sfizz_lv2_get_empty_sfz_path(LV2_Handle instance, char *path, size_t size) +{ + sfizz_plugin_t *self = (sfizz_plugin_t *)instance; + snprintf(path, size, "%s/%s", self->bundle_path, "Resources/EmptyInstrument.sfz"); +} + static void sfizz_lv2_get_default_scala_path(LV2_Handle instance, char *path, size_t size) { @@ -967,6 +974,11 @@ restore(LV2_Handle instance, } lv2_log_note(&self->logger, "[sfizz] Restoring the file %s\n", path); + // Load an empty file to remove the default sine + sfizz_lv2_get_empty_sfz_path(instance, self->sfz_file_path, MAX_PATH_SIZE); + sfizz_lv2_load_file(instance, self->sfz_file_path); + + // Try loading the new file sfizz_lv2_load_file(instance, path); if (map_path) @@ -1144,6 +1156,7 @@ work(LV2_Handle instance, uint32_t size, const void *data) { + UNUSED(size); sfizz_plugin_t *self = (sfizz_plugin_t *)instance; if (!data) { lv2_log_error(&self->logger, "[sfizz] Ignoring empty data in the worker thread\n"); From abf22c3546b4c7fa8e323fffa02ed4c760554ed0 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Sat, 4 Jul 2020 14:26:44 +0200 Subject: [PATCH 3/6] Use a string rather than a file --- lv2/resources/EmptyInstrument.sfz | 0 lv2/sfizz.c | 11 ++--------- 2 files changed, 2 insertions(+), 9 deletions(-) delete mode 100644 lv2/resources/EmptyInstrument.sfz diff --git a/lv2/resources/EmptyInstrument.sfz b/lv2/resources/EmptyInstrument.sfz deleted file mode 100644 index e69de29b..00000000 diff --git a/lv2/sfizz.c b/lv2/sfizz.c index ffe1d3e1..95e84a35 100644 --- a/lv2/sfizz.c +++ b/lv2/sfizz.c @@ -305,13 +305,6 @@ sfizz_lv2_get_default_sfz_path(LV2_Handle instance, char *path, size_t size) snprintf(path, size, "%s/%s", self->bundle_path, "Resources/DefaultInstrument.sfz"); } -static void -sfizz_lv2_get_empty_sfz_path(LV2_Handle instance, char *path, size_t size) -{ - sfizz_plugin_t *self = (sfizz_plugin_t *)instance; - snprintf(path, size, "%s/%s", self->bundle_path, "Resources/EmptyInstrument.sfz"); -} - static void sfizz_lv2_get_default_scala_path(LV2_Handle instance, char *path, size_t size) { @@ -975,8 +968,8 @@ restore(LV2_Handle instance, lv2_log_note(&self->logger, "[sfizz] Restoring the file %s\n", path); // Load an empty file to remove the default sine - sfizz_lv2_get_empty_sfz_path(instance, self->sfz_file_path, MAX_PATH_SIZE); - sfizz_lv2_load_file(instance, self->sfz_file_path); + strcpy(self->sfz_file_path, ""); + sfizz_load_string(self->synth, "empty.sfz", ""); // Try loading the new file sfizz_lv2_load_file(instance, path); From a29b04eb867f87df9116401c003b148a35291586 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sun, 5 Jul 2020 06:11:18 +0200 Subject: [PATCH 4/6] Update the restore mechanism, keep the path in case of load failure --- lv2/sfizz.c | 129 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 76 insertions(+), 53 deletions(-) diff --git a/lv2/sfizz.c b/lv2/sfizz.c index 95e84a35..930c8380 100644 --- a/lv2/sfizz.c +++ b/lv2/sfizz.c @@ -90,9 +90,6 @@ typedef struct { - // Paths - const char *bundle_path; - // Features LV2_URID_Map *map; LV2_URID_Unmap *unmap; @@ -160,6 +157,9 @@ typedef struct int sample_counter; float sample_rate; atomic_int must_update_midnam; + + // Paths + char bundle_path[MAX_PATH_SIZE]; } sfizz_plugin_t; enum @@ -331,7 +331,8 @@ instantiate(const LV2_Descriptor *descriptor, LV2_Handle instance = (LV2_Handle)self; - self->bundle_path = bundle_path; + strncpy(self->bundle_path, bundle_path, MAX_PATH_SIZE); + self->bundle_path[MAX_PATH_SIZE - 1] = '\0'; // Set defaults self->max_block_size = MAX_BLOCK_SIZE; @@ -900,10 +901,10 @@ lv2_set_options(LV2_Handle instance, const LV2_Options_Option *options) static void sfizz_lv2_update_file_info(sfizz_plugin_t* self, const char *file_path) { - strcpy(self->sfz_file_path, file_path); + if (file_path != self->sfz_file_path) + strcpy(self->sfz_file_path, file_path); - const char *display_path = (file_path[0] != '\0') ? file_path : "(default)"; - lv2_log_note(&self->logger, "[sfizz] File changed to: %s\n", display_path); + lv2_log_note(&self->logger, "[sfizz] File changed to: %s\n", file_path); char *unknown_opcodes = sfizz_get_unknown_opcodes(self->synth); if (unknown_opcodes) @@ -922,12 +923,19 @@ static bool sfizz_lv2_load_file(LV2_Handle instance, const char *file_path) { sfizz_plugin_t *self = (sfizz_plugin_t *)instance; - - if (!sfizz_load_file(self->synth, file_path)) - return false; - + bool status = sfizz_load_file(self->synth, file_path); sfizz_lv2_update_file_info(self, file_path); - return true; + return status; +} + +static bool +sfizz_lv2_load_scala_file(LV2_Handle instance, const char *file_path) +{ + sfizz_plugin_t *self = (sfizz_plugin_t *)instance; + bool status = sfizz_load_scala_file(self->synth, file_path); + if (file_path != self->scala_file_path) + strcpy(self->scala_file_path, file_path); + return status; } static LV2_State_Status @@ -938,6 +946,7 @@ restore(LV2_Handle instance, const LV2_Feature *const *features) { UNUSED(flags); + LV2_State_Status status = LV2_STATE_SUCCESS; sfizz_plugin_t *self = (sfizz_plugin_t *)instance; LV2_State_Map_Path *map_path = NULL; @@ -950,6 +959,13 @@ restore(LV2_Handle instance, free_path = (LV2_State_Free_Path *)(**f).data; } + // Set default values + sfizz_lv2_get_default_sfz_path(instance, self->sfz_file_path, MAX_PATH_SIZE); + sfizz_lv2_get_default_scala_path(instance, self->scala_file_path, MAX_PATH_SIZE); + self->num_voices = DEFAULT_VOICES; + self->preload_size = DEFAULT_PRELOAD; + self->oversampling = DEFAULT_OVERSAMPLING; + // Fetch back the saved file path, if any size_t size; uint32_t type; @@ -963,16 +979,11 @@ restore(LV2_Handle instance, { path = map_path->absolute_path(map_path->handle, path); if (!path) - return LV2_STATE_ERR_UNKNOWN; + status = LV2_STATE_ERR_UNKNOWN; } - lv2_log_note(&self->logger, "[sfizz] Restoring the file %s\n", path); - // Load an empty file to remove the default sine - strcpy(self->sfz_file_path, ""); - sfizz_load_string(self->synth, "empty.sfz", ""); - - // Try loading the new file - sfizz_lv2_load_file(instance, path); + strncpy(self->sfz_file_path, path, MAX_PATH_SIZE); + self->sfz_file_path[MAX_PATH_SIZE - 1] = '\0'; if (map_path) free_path->free_path(free_path->handle, (char *)path); @@ -986,20 +997,11 @@ restore(LV2_Handle instance, { path = map_path->absolute_path(map_path->handle, path); if (!path) - return LV2_STATE_ERR_UNKNOWN; + status = LV2_STATE_ERR_UNKNOWN; } - if (sfizz_load_scala_file(self->synth, path)) - { - lv2_log_note(&self->logger, - "[sfizz] Restoring the scale %s\n", path); - strcpy(self->scala_file_path, path); - } - else - { - lv2_log_error(&self->logger, - "[sfizz] Error while restoring the scale %s\n", path); - } + strncpy(self->scala_file_path, path, MAX_PATH_SIZE); + self->scala_file_path[MAX_PATH_SIZE - 1] = '\0'; if (map_path) free_path->free_path(free_path->handle, (char *)path); @@ -1009,38 +1011,60 @@ restore(LV2_Handle instance, if (value) { int num_voices = *(const int *)value; - if (num_voices > 0 && num_voices <= MAX_VOICES && num_voices != self->num_voices) - { - lv2_log_note(&self->logger, "[sfizz] Restoring the number of voices to %d\n", num_voices); - sfizz_set_num_voices(self->synth, num_voices); + if (num_voices > 0 && num_voices <= MAX_VOICES) self->num_voices = num_voices; - } } value = retrieve(handle, self->sfizz_preload_size_uri, &size, &type, &val_flags); if (value) { unsigned int preload_size = *(const unsigned int *)value; - if (preload_size != self->preload_size) - { - lv2_log_note(&self->logger, "[sfizz] Restoring the preload size to %d\n", preload_size); - sfizz_set_preload_size(self->synth, preload_size); - self->preload_size = preload_size; - } + self->preload_size = preload_size; } value = retrieve(handle, self->sfizz_oversampling_uri, &size, &type, &val_flags); if (value) { sfizz_oversampling_factor_t oversampling = *(const sfizz_oversampling_factor_t *)value; - if (oversampling != self->oversampling) - { - lv2_log_note(&self->logger, "[sfizz] Restoring the oversampling to %d\n", oversampling); - sfizz_set_oversampling_factor(self->synth, oversampling); - self->oversampling = oversampling; - } + self->oversampling = oversampling; } - return LV2_STATE_SUCCESS; + + // Sync the parameters to the synth + + // Load an empty file to remove the default sine, and then the new file. + sfizz_load_string(self->synth, "empty.sfz", ""); + if (sfizz_lv2_load_file(instance, self->sfz_file_path)) + { + lv2_log_note(&self->logger, + "[sfizz] Restoring the file %s\n", self->sfz_file_path); + } + else + { + lv2_log_error(&self->logger, + "[sfizz] Error while restoring the file %s\n", self->sfz_file_path); + } + + if (sfizz_load_scala_file(self->synth, self->scala_file_path)) + { + lv2_log_note(&self->logger, + "[sfizz] Restoring the scale %s\n", self->scala_file_path); + } + else + { + lv2_log_error(&self->logger, + "[sfizz] Error while restoring the scale %s\n", self->scala_file_path); + } + + lv2_log_note(&self->logger, "[sfizz] Restoring the number of voices to %d\n", self->num_voices); + sfizz_set_num_voices(self->synth, self->num_voices); + + lv2_log_note(&self->logger, "[sfizz] Restoring the preload size to %d\n", self->preload_size); + sfizz_set_preload_size(self->synth, self->preload_size); + + lv2_log_note(&self->logger, "[sfizz] Restoring the oversampling to %d\n", self->oversampling); + sfizz_set_oversampling_factor(self->synth, self->oversampling); + + return status; } static LV2_State_Status @@ -1171,8 +1195,7 @@ work(LV2_Handle instance, else if (atom->type == self->sfizz_scala_file_uri) { const char *scala_file_path = LV2_ATOM_BODY_CONST(atom); - if (sfizz_load_scala_file(self->synth, scala_file_path)) { - strcpy(self->scala_file_path, scala_file_path); + if (sfizz_lv2_load_scala_file(self->synth, scala_file_path)) { lv2_log_note(&self->logger, "[sfizz] Scala file loaded: %s\n", scala_file_path); } else { lv2_log_error(&self->logger, @@ -1235,7 +1258,7 @@ work(LV2_Handle instance, lv2_log_note(&self->logger, "[sfizz] Scala file %s seems to have been updated, reloading\n", self->scala_file_path); - if (sfizz_load_scala_file(self->synth, self->scala_file_path)) { + if (sfizz_lv2_load_scala_file(self->synth, self->scala_file_path)) { lv2_log_note(&self->logger, "[sfizz] Scala file loaded: %s\n", self->scala_file_path); } else { lv2_log_error(&self->logger, From 8e4c3dfbb3eac170551ddf4b828535d0e725d28c Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Sun, 5 Jul 2020 11:53:41 +0200 Subject: [PATCH 5/6] Disable modification checks for the default file and upon restoring Reenabled if the file was properly restored --- lv2/sfizz.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lv2/sfizz.c b/lv2/sfizz.c index 930c8380..03cf1785 100644 --- a/lv2/sfizz.c +++ b/lv2/sfizz.c @@ -344,7 +344,7 @@ instantiate(const LV2_Descriptor *descriptor, self->oversampling = DEFAULT_OVERSAMPLING; self->preload_size = DEFAULT_PRELOAD; self->stretch_tuning = 0.0f; - self->check_modification = true; + self->check_modification = false; self->sample_counter = 0; // Get the features from the host and populate the structure @@ -1033,10 +1033,12 @@ restore(LV2_Handle instance, // Load an empty file to remove the default sine, and then the new file. sfizz_load_string(self->synth, "empty.sfz", ""); + self->check_modification = false; if (sfizz_lv2_load_file(instance, self->sfz_file_path)) { lv2_log_note(&self->logger, "[sfizz] Restoring the file %s\n", self->sfz_file_path); + self->check_modification = true; } else { From 74e53ca70d617b8ab34f4099c00a72d3470b1bea Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Sun, 5 Jul 2020 11:54:31 +0200 Subject: [PATCH 6/6] Set the max bundle path size lower than the max path size This silences a GCC warning for snprintf --- lv2/sfizz.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lv2/sfizz.c b/lv2/sfizz.c index 03cf1785..3ad3579e 100644 --- a/lv2/sfizz.c +++ b/lv2/sfizz.c @@ -57,7 +57,6 @@ #include "atomic_compat.h" -#define DEFAULT_SFZ_FILE "/home/paul/Documents/AVL_Percussions/AVL_Drumkits_Percussion-1.0-Alt.sfz" #define SFIZZ_URI "http://sfztools.github.io/sfizz" #define SFIZZ_PREFIX SFIZZ_URI "#" #define SFIZZ__sfzFile "http://sfztools.github.io/sfizz:sfzfile" @@ -82,6 +81,11 @@ #define LOG_SAMPLE_COUNT 48000 #define UNUSED(x) (void)(x) +#define DEFAULT_SCALA_FILE "Resources/DefaultScale.scl" +#define DEFAULT_SFZ_FILE "Resources/DefaultInstrument.sfz" +// This assumes that the longest path is the default sfz file; if not, change it +#define MAX_BUNDLE_PATH_SIZE (MAX_PATH_SIZE - sizeof(DEFAULT_SFZ_FILE)) + #ifndef NDEBUG #define LV2_DEBUG(...) lv2_log_note(&self->logger, "[DEBUG] " __VA_ARGS__) #else @@ -159,7 +163,7 @@ typedef struct atomic_int must_update_midnam; // Paths - char bundle_path[MAX_PATH_SIZE]; + char bundle_path[MAX_BUNDLE_PATH_SIZE]; } sfizz_plugin_t; enum @@ -302,14 +306,14 @@ static void sfizz_lv2_get_default_sfz_path(LV2_Handle instance, char *path, size_t size) { sfizz_plugin_t *self = (sfizz_plugin_t *)instance; - snprintf(path, size, "%s/%s", self->bundle_path, "Resources/DefaultInstrument.sfz"); + snprintf(path, size, "%s/%s", self->bundle_path, DEFAULT_SFZ_FILE); } static void sfizz_lv2_get_default_scala_path(LV2_Handle instance, char *path, size_t size) { sfizz_plugin_t *self = (sfizz_plugin_t *)instance; - snprintf(path, size, "%s/%s", self->bundle_path, "Resources/DefaultScale.scl"); + snprintf(path, size, "%s/%s", self->bundle_path, DEFAULT_SCALA_FILE); } static LV2_Handle @@ -331,8 +335,8 @@ instantiate(const LV2_Descriptor *descriptor, LV2_Handle instance = (LV2_Handle)self; - strncpy(self->bundle_path, bundle_path, MAX_PATH_SIZE); - self->bundle_path[MAX_PATH_SIZE - 1] = '\0'; + strncpy(self->bundle_path, bundle_path, MAX_BUNDLE_PATH_SIZE); + self->bundle_path[MAX_BUNDLE_PATH_SIZE - 1] = '\0'; // Set defaults self->max_block_size = MAX_BLOCK_SIZE;