Merge pull request #304 from jpcima/default-files

lv2: default files for sfz and scala
This commit is contained in:
Paul Ferrand 2020-07-06 13:25:33 +02:00 committed by GitHub
commit e38af66e0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 137 additions and 61 deletions

View file

@ -49,6 +49,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}) file(COPY "lgpl-3.0.txt" DESTINATION ${PROJECT_BINARY_DIR})
endif() 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 # Installation
if (NOT MSVC) if (NOT MSVC)
install (DIRECTORY ${PROJECT_BINARY_DIR} DESTINATION ${LV2PLUGIN_INSTALL_DIR} install (DIRECTORY ${PROJECT_BINARY_DIR} DESTINATION ${LV2PLUGIN_INSTALL_DIR}

View file

@ -0,0 +1,3 @@
<region>
sample=*sine
ampeg_attack=0.02 ampeg_release=0.1

View file

@ -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

View file

@ -58,7 +58,6 @@
#include "atomic_compat.h" #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_URI "http://sfztools.github.io/sfizz"
#define SFIZZ_PREFIX SFIZZ_URI "#" #define SFIZZ_PREFIX SFIZZ_URI "#"
#define SFIZZ__sfzFile "http://sfztools.github.io/sfizz:sfzfile" #define SFIZZ__sfzFile "http://sfztools.github.io/sfizz:sfzfile"
@ -83,16 +82,17 @@
#define LOG_SAMPLE_COUNT 48000 #define LOG_SAMPLE_COUNT 48000
#define UNUSED(x) (void)(x) #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 #ifndef NDEBUG
#define LV2_DEBUG(...) lv2_log_note(&self->logger, "[DEBUG] " __VA_ARGS__) #define LV2_DEBUG(...) lv2_log_note(&self->logger, "[DEBUG] " __VA_ARGS__)
#else #else
#define LV2_DEBUG(...) #define LV2_DEBUG(...)
#endif #endif
static const char default_sfz_text[] =
"<region>sample=*sine" "\n"
"ampeg_attack=0.02 ampeg_release=0.1" "\n";
typedef struct typedef struct
{ {
// Features // Features
@ -163,6 +163,9 @@ typedef struct
int sample_counter; int sample_counter;
float sample_rate; float sample_rate;
atomic_int must_update_midnam; atomic_int must_update_midnam;
// Paths
char bundle_path[MAX_BUNDLE_PATH_SIZE];
} sfizz_plugin_t; } sfizz_plugin_t;
enum enum
@ -302,14 +305,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, 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, DEFAULT_SCALA_FILE);
}
static LV2_Handle static LV2_Handle
instantiate(const LV2_Descriptor *descriptor, instantiate(const LV2_Descriptor *descriptor,
double rate, double rate,
const char *path, const char *bundle_path,
const LV2_Feature *const *features) const LV2_Feature *const *features)
{ {
UNUSED(descriptor); UNUSED(descriptor);
UNUSED(path);
LV2_Options_Option *options = NULL; LV2_Options_Option *options = NULL;
bool supports_bounded_block_size = false; bool supports_bounded_block_size = false;
bool options_has_block_size = false; bool options_has_block_size = false;
@ -320,6 +336,11 @@ instantiate(const LV2_Descriptor *descriptor,
if (!self) if (!self)
return NULL; return NULL;
LV2_Handle instance = (LV2_Handle)self;
strncpy(self->bundle_path, bundle_path, MAX_BUNDLE_PATH_SIZE);
self->bundle_path[MAX_BUNDLE_PATH_SIZE - 1] = '\0';
// Set defaults // Set defaults
self->max_block_size = MAX_BLOCK_SIZE; self->max_block_size = MAX_BLOCK_SIZE;
self->sample_rate = (float)rate; self->sample_rate = (float)rate;
@ -330,7 +351,7 @@ instantiate(const LV2_Descriptor *descriptor,
self->oversampling = DEFAULT_OVERSAMPLING; self->oversampling = DEFAULT_OVERSAMPLING;
self->preload_size = DEFAULT_PRELOAD; self->preload_size = DEFAULT_PRELOAD;
self->stretch_tuning = 0.0f; self->stretch_tuning = 0.0f;
self->check_modification = true; self->check_modification = false;
self->sample_counter = 0; self->sample_counter = 0;
// Get the features from the host and populate the structure // Get the features from the host and populate the structure
@ -437,7 +458,12 @@ instantiate(const LV2_Descriptor *descriptor,
} }
self->synth = sfizz_create_synth(); 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; return (LV2_Handle)self;
} }
@ -886,10 +912,10 @@ lv2_set_options(LV2_Handle instance, const LV2_Options_Option *options)
static void static void
sfizz_lv2_update_file_info(sfizz_plugin_t* self, const char *file_path) 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", file_path);
lv2_log_note(&self->logger, "[sfizz] File changed to: %s\n", display_path);
char *unknown_opcodes = sfizz_get_unknown_opcodes(self->synth); char *unknown_opcodes = sfizz_get_unknown_opcodes(self->synth);
if (unknown_opcodes) if (unknown_opcodes)
@ -908,20 +934,19 @@ static bool
sfizz_lv2_load_file(LV2_Handle instance, const char *file_path) sfizz_lv2_load_file(LV2_Handle instance, const char *file_path)
{ {
sfizz_plugin_t *self = (sfizz_plugin_t *)instance; sfizz_plugin_t *self = (sfizz_plugin_t *)instance;
bool status = sfizz_load_file(self->synth, file_path);
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;
}
sfizz_lv2_update_file_info(self, 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 static LV2_State_Status
@ -932,6 +957,7 @@ restore(LV2_Handle instance,
const LV2_Feature *const *features) const LV2_Feature *const *features)
{ {
UNUSED(flags); UNUSED(flags);
LV2_State_Status status = LV2_STATE_SUCCESS;
sfizz_plugin_t *self = (sfizz_plugin_t *)instance; sfizz_plugin_t *self = (sfizz_plugin_t *)instance;
LV2_State_Map_Path *map_path = NULL; LV2_State_Map_Path *map_path = NULL;
@ -944,6 +970,13 @@ restore(LV2_Handle instance,
free_path = (LV2_State_Free_Path *)(**f).data; 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 // Fetch back the saved file path, if any
size_t size; size_t size;
uint32_t type; uint32_t type;
@ -957,11 +990,11 @@ restore(LV2_Handle instance,
{ {
path = map_path->absolute_path(map_path->handle, path); path = map_path->absolute_path(map_path->handle, path);
if (!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); strncpy(self->sfz_file_path, path, MAX_PATH_SIZE);
sfizz_lv2_load_file(instance, path); self->sfz_file_path[MAX_PATH_SIZE - 1] = '\0';
if (map_path) if (map_path)
free_path->free_path(free_path->handle, (char *)path); free_path->free_path(free_path->handle, (char *)path);
@ -975,20 +1008,11 @@ restore(LV2_Handle instance,
{ {
path = map_path->absolute_path(map_path->handle, path); path = map_path->absolute_path(map_path->handle, path);
if (!path) if (!path)
return LV2_STATE_ERR_UNKNOWN; status = LV2_STATE_ERR_UNKNOWN;
} }
if (sfizz_load_scala_file(self->synth, path)) strncpy(self->scala_file_path, path, MAX_PATH_SIZE);
{ self->scala_file_path[MAX_PATH_SIZE - 1] = '\0';
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);
}
if (map_path) if (map_path)
free_path->free_path(free_path->handle, (char *)path); free_path->free_path(free_path->handle, (char *)path);
@ -998,38 +1022,62 @@ restore(LV2_Handle instance,
if (value) if (value)
{ {
int num_voices = *(const int *)value; int num_voices = *(const int *)value;
if (num_voices > 0 && num_voices <= MAX_VOICES && num_voices != self->num_voices) if (num_voices > 0 && num_voices <= MAX_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);
self->num_voices = num_voices; self->num_voices = num_voices;
}
} }
value = retrieve(handle, self->sfizz_preload_size_uri, &size, &type, &val_flags); value = retrieve(handle, self->sfizz_preload_size_uri, &size, &type, &val_flags);
if (value) if (value)
{ {
unsigned int preload_size = *(const unsigned int *)value; unsigned int preload_size = *(const unsigned int *)value;
if (preload_size != self->preload_size) self->preload_size = 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;
}
} }
value = retrieve(handle, self->sfizz_oversampling_uri, &size, &type, &val_flags); value = retrieve(handle, self->sfizz_oversampling_uri, &size, &type, &val_flags);
if (value) if (value)
{ {
sfizz_oversampling_factor_t oversampling = *(const sfizz_oversampling_factor_t *)value; sfizz_oversampling_factor_t oversampling = *(const sfizz_oversampling_factor_t *)value;
if (oversampling != self->oversampling) self->oversampling = oversampling;
{
lv2_log_note(&self->logger, "[sfizz] Restoring the oversampling to %d\n", oversampling);
sfizz_set_oversampling_factor(self->synth, 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", "");
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
{
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 static LV2_State_Status
@ -1138,6 +1186,7 @@ work(LV2_Handle instance,
uint32_t size, uint32_t size,
const void *data) const void *data)
{ {
UNUSED(size);
sfizz_plugin_t *self = (sfizz_plugin_t *)instance; sfizz_plugin_t *self = (sfizz_plugin_t *)instance;
if (!data) { if (!data) {
lv2_log_error(&self->logger, "[sfizz] Ignoring empty data in the worker thread\n"); lv2_log_error(&self->logger, "[sfizz] Ignoring empty data in the worker thread\n");
@ -1159,8 +1208,7 @@ work(LV2_Handle instance,
else if (atom->type == self->sfizz_scala_file_uri) else if (atom->type == self->sfizz_scala_file_uri)
{ {
const char *scala_file_path = LV2_ATOM_BODY_CONST(atom); const char *scala_file_path = LV2_ATOM_BODY_CONST(atom);
if (sfizz_load_scala_file(self->synth, scala_file_path)) { if (sfizz_lv2_load_scala_file(self->synth, scala_file_path)) {
strcpy(self->scala_file_path, scala_file_path);
lv2_log_note(&self->logger, "[sfizz] Scala file loaded: %s\n", scala_file_path); lv2_log_note(&self->logger, "[sfizz] Scala file loaded: %s\n", scala_file_path);
} else { } else {
lv2_log_error(&self->logger, lv2_log_error(&self->logger,
@ -1223,7 +1271,7 @@ work(LV2_Handle instance,
lv2_log_note(&self->logger, lv2_log_note(&self->logger,
"[sfizz] Scala file %s seems to have been updated, reloading\n", "[sfizz] Scala file %s seems to have been updated, reloading\n",
self->scala_file_path); 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); lv2_log_note(&self->logger, "[sfizz] Scala file loaded: %s\n", self->scala_file_path);
} else { } else {
lv2_log_error(&self->logger, lv2_log_error(&self->logger,