Skip to content

Commit

Permalink
Merge branch 'develop' into quality-api
Browse files Browse the repository at this point in the history
  • Loading branch information
paulfd authored Jun 14, 2020
2 parents 4dfbf54 + 3994089 commit c9a8245
Show file tree
Hide file tree
Showing 30 changed files with 1,171 additions and 81 deletions.
2 changes: 1 addition & 1 deletion .travis/script_osx.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ cmake -DCMAKE_BUILD_TYPE=Release \
-DSFIZZ_VST=ON \
-DSFIZZ_AU=ON \
-DSFIZZ_TESTS=OFF \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_CXX_STANDARD=14 \
-DLV2PLUGIN_INSTALL_DIR=/Library/Audio/Plug-Ins/LV2 \
-DVSTPLUGIN_INSTALL_DIR=/Library/Audio/Plug-Ins/VST3 \
-DAUPLUGIN_INSTALL_DIR=/Library/Audio/Plug-Ins/Components \
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/BM_ADSR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class EnvelopeFixture : public benchmark::Fixture
}

sfz::MidiState midiState;
sfz::Region region{midiState};
sfz::Region region{0, midiState};
sfz::ADSREnvelope<float> envelope;
std::vector<float> output;
};
Expand Down
2 changes: 1 addition & 1 deletion lv2/manifest.ttl.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

<@LV2PLUGIN_URI@>
a lv2:Plugin ;
lv2:binary <@PROJECT_NAME@@CMAKE_SHARED_LIBRARY_SUFFIX@> ;
lv2:binary <@PROJECT_NAME@@CMAKE_SHARED_MODULE_SUFFIX@> ;
rdfs:seeAlso <@[email protected]> .
78 changes: 53 additions & 25 deletions lv2/sfizz.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,11 @@ typedef struct
const float *freewheel_port;
const float *scala_root_key_port;
const float *tuning_frequency_port;
const float *stretch_tuning_port;

// Atom forge
LV2_Atom_Forge forge; ///< Forge for writing atoms in run thread
LV2_Atom_Forge_Frame notify_frame; ///< Cached for worker replies
LV2_Atom_Forge forge_secondary; ///< Forge for writing into other buffers

// Logger
LV2_Log_Logger logger;
Expand Down Expand Up @@ -150,6 +151,7 @@ typedef struct
int num_voices;
unsigned int preload_size;
sfizz_oversampling_factor_t oversampling;
float stretch_tuning;
volatile bool check_modification;
int max_block_size;
int sample_counter;
Expand All @@ -170,6 +172,7 @@ enum
SFIZZ_FREEWHEELING = 8,
SFIZZ_SCALA_ROOT_KEY = 9,
SFIZZ_TUNING_FREQUENCY = 10,
SFIZZ_STRETCH_TUNING = 11,
};

static void
Expand Down Expand Up @@ -242,6 +245,9 @@ connect_port(LV2_Handle instance,
case SFIZZ_TUNING_FREQUENCY:
self->tuning_frequency_port = (const float *)data;
break;
case SFIZZ_STRETCH_TUNING:
self->stretch_tuning_port = (const float *)data;
break;
default:
break;
}
Expand Down Expand Up @@ -302,6 +308,7 @@ instantiate(const LV2_Descriptor *descriptor,
self->num_voices = DEFAULT_VOICES;
self->oversampling = DEFAULT_OVERSAMPLING;
self->preload_size = DEFAULT_PRELOAD;
self->stretch_tuning = 0.0f;
self->check_modification = true;
self->sample_counter = 0;

Expand Down Expand Up @@ -359,6 +366,7 @@ instantiate(const LV2_Descriptor *descriptor,

// Initialize the forge
lv2_atom_forge_init(&self->forge, self->map);
lv2_atom_forge_init(&self->forge_secondary, self->map);

// Check the options for the block size and sample rate parameters
if (options)
Expand Down Expand Up @@ -438,13 +446,17 @@ static void
sfizz_lv2_send_file_path(sfizz_plugin_t *self, LV2_URID urid, const char *path)
{
LV2_Atom_Forge_Frame frame;
lv2_atom_forge_frame_time(&self->forge, 0);
lv2_atom_forge_object(&self->forge, &frame, 0, self->patch_set_uri);
lv2_atom_forge_key(&self->forge, self->patch_property_uri);
lv2_atom_forge_urid(&self->forge, urid);
lv2_atom_forge_key(&self->forge, self->patch_value_uri);
lv2_atom_forge_path(&self->forge, path, (uint32_t)strlen(path));
lv2_atom_forge_pop(&self->forge, &frame);

bool write_ok =
lv2_atom_forge_frame_time(&self->forge, 0) &&
lv2_atom_forge_object(&self->forge, &frame, 0, self->patch_set_uri) &&
lv2_atom_forge_key(&self->forge, self->patch_property_uri) &&
lv2_atom_forge_urid(&self->forge, urid) &&
lv2_atom_forge_key(&self->forge, self->patch_value_uri) &&
lv2_atom_forge_path(&self->forge, path, (uint32_t)strlen(path));

if (write_ok)
lv2_atom_forge_pop(&self->forge, &frame);
}


Expand Down Expand Up @@ -480,28 +492,28 @@ sfizz_lv2_handle_atom_object(sfizz_plugin_t *self, const LV2_Atom_Object *obj)
return;
}

typedef struct
{
LV2_Atom atom;
char body[MAX_PATH_SIZE];
} sfizz_path_atom_buffer_t;

if (key == self->sfizz_sfz_file_uri)
{
const uint32_t original_atom_size = lv2_atom_total_size((const LV2_Atom *)atom);
const uint32_t null_terminated_atom_size = original_atom_size + 1;
char atom_buffer[MAX_PATH_SIZE];
memcpy(&atom_buffer, atom, original_atom_size);
atom_buffer[original_atom_size] = 0; // Null terminate the string for safety
LV2_Atom *sfz_file_path = (LV2_Atom *)&atom_buffer;
sfz_file_path->type = self->sfizz_sfz_file_uri;
self->worker->schedule_work(self->worker->handle, null_terminated_atom_size, sfz_file_path);
LV2_Atom_Forge *forge = &self->forge_secondary;
sfizz_path_atom_buffer_t buffer;
lv2_atom_forge_set_buffer(forge, (uint8_t *)&buffer, sizeof(buffer));
if (lv2_atom_forge_typed_string(forge, self->sfizz_sfz_file_uri, LV2_ATOM_BODY_CONST(atom), strnlen(LV2_ATOM_BODY_CONST(atom), atom->size)))
self->worker->schedule_work(self->worker->handle, lv2_atom_total_size(&buffer.atom), &buffer.atom);
self->check_modification = false;
}
else if (key == self->sfizz_scala_file_uri)
{
const uint32_t original_atom_size = lv2_atom_total_size((const LV2_Atom *)atom);
const uint32_t null_terminated_atom_size = original_atom_size + 1;
char atom_buffer[MAX_PATH_SIZE];
memcpy(&atom_buffer, atom, original_atom_size);
atom_buffer[original_atom_size] = 0; // Null terminate the string for safety
LV2_Atom *scala_file_path = (LV2_Atom *)&atom_buffer;
scala_file_path->type = self->sfizz_scala_file_uri;
self->worker->schedule_work(self->worker->handle, null_terminated_atom_size, scala_file_path);
LV2_Atom_Forge *forge = &self->forge_secondary;
sfizz_path_atom_buffer_t buffer;
lv2_atom_forge_set_buffer(forge, (uint8_t *)&buffer, sizeof(buffer));
if (lv2_atom_forge_typed_string(forge, self->sfizz_scala_file_uri, LV2_ATOM_BODY_CONST(atom), strnlen(LV2_ATOM_BODY_CONST(atom), atom->size)))
self->worker->schedule_work(self->worker->handle, lv2_atom_total_size(&buffer.atom), &buffer.atom);
self->check_modification = false;
}
else
Expand Down Expand Up @@ -654,6 +666,17 @@ sfizz_lv2_check_freewheeling(sfizz_plugin_t* self)
}
}

static void
sfizz_lv2_check_stretch_tuning(sfizz_plugin_t* self)
{
float stretch_tuning = (float)*self->stretch_tuning_port;
if (stretch_tuning != self->stretch_tuning)
{
sfizz_load_stretch_tuning_by_ratio(self->synth, stretch_tuning);
self->stretch_tuning = stretch_tuning;
}
}

static void
run(LV2_Handle instance, uint32_t sample_count)
{
Expand All @@ -666,7 +689,9 @@ run(LV2_Handle instance, uint32_t sample_count)
lv2_atom_forge_set_buffer(&self->forge, (uint8_t *)self->notify_port, notify_capacity);

// Start a sequence in the notify output port.
lv2_atom_forge_sequence_head(&self->forge, &self->notify_frame, 0);
LV2_Atom_Forge_Frame notify_frame;
if (!lv2_atom_forge_sequence_head(&self->forge, &notify_frame, 0))
assert(false);

LV2_ATOM_SEQUENCE_FOREACH(self->control_port, ev)
{
Expand Down Expand Up @@ -719,6 +744,7 @@ run(LV2_Handle instance, uint32_t sample_count)
sfizz_set_volume(self->synth, *(self->volume_port));
sfizz_set_scala_root_key(self->synth, *(self->scala_root_key_port));
sfizz_set_tuning_frequency(self->synth, *(self->tuning_frequency_port));
sfizz_lv2_check_stretch_tuning(self);
sfizz_lv2_check_preload_size(self);
sfizz_lv2_check_oversampling(self);
sfizz_lv2_check_num_voices(self);
Expand Down Expand Up @@ -756,6 +782,8 @@ run(LV2_Handle instance, uint32_t sample_count)
{
self->midnam->update(self->midnam->handle);
}

lv2_atom_forge_pop(&self->forge, &notify_frame);
}

static uint32_t
Expand Down
11 changes: 11 additions & 0 deletions lv2/sfizz.ttl.in
Original file line number Diff line number Diff line change
Expand Up @@ -280,4 +280,15 @@ midnam:update a lv2:Feature .
lv2:minimum 300.0 ;
lv2:maximum 500.0 ;
units:unit units:hz
] , [
a lv2:InputPort, lv2:ControlPort ;
lv2:index 11 ;
lv2:symbol "stretched_tuning" ;
lv2:name "Stretched tuning",
"Accordage étiré"@fr ;
pg:group <@LV2PLUGIN_URI@#tuning> ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
units:unit units:coef
] .
9 changes: 9 additions & 0 deletions src/sfizz.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ SFIZZ_EXPORTED_API void sfizz_set_tuning_frequency(sfizz_synth_t* synth, float f
*/
SFIZZ_EXPORTED_API float sfizz_get_tuning_frequency(sfizz_synth_t* synth);

/**
* @brief Configure stretch tuning using a predefined parametric Railsback curve.
* A ratio 1/2 is supposed to match the average piano; 0 disables (the default).
*
* @param synth The sfizz synth.
* @param ratio The parameter in domain 0-1.
*/
SFIZZ_EXPORTED_API void sfizz_load_stretch_tuning_by_ratio(sfizz_synth_t* synth, float ratio);

/**
* @brief Return the number of regions in the currently loaded SFZ file.
*
Expand Down
8 changes: 8 additions & 0 deletions src/sfizz.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ class SFIZZ_EXPORTED_API Sfizz
*/
float getTuningFrequency() const;

/**
* @brief Configure stretch tuning using a predefined parametric Railsback curve.
* A ratio 1/2 is supposed to match the average piano; 0 disables (the default).
*
* @param ratio The parameter in domain 0-1.
*/
void loadStretchTuningByRatio(float ratio);

/**
* @brief Return the current number of regions loaded.
*/
Expand Down
41 changes: 41 additions & 0 deletions src/sfizz/NumericId.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: BSD-2-Clause

// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz

#pragma once

/**
* @brief Numeric identifier
*
* It is a generic numeric identifier. The template wrapper serves to enforce a
* stronger compile-time check, such that one kind of identifier can't be
* mistaken for another kind, or for an unrelated integer such as an index.
*/
template <class T>
struct NumericId {
constexpr NumericId() = default;

explicit constexpr NumericId(int number)
: number(number)
{
}

constexpr bool valid() const noexcept
{
return number != -1;
}

constexpr bool operator==(NumericId other) const noexcept
{
return number == other.number;
}

constexpr bool operator!=(NumericId other) const noexcept
{
return number != other.number;
}

const int number = -1;
};
15 changes: 13 additions & 2 deletions src/sfizz/Region.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "AudioBuffer.h"
#include "MidiState.h"
#include "FileId.h"
#include "NumericId.h"
#include "absl/types/optional.h"
#include <bitset>
#include <string>
Expand All @@ -35,8 +36,8 @@ namespace sfz {
*
*/
struct Region {
Region(const MidiState& midiState, absl::string_view defaultPath = "")
: midiState(midiState), defaultPath(std::move(defaultPath))
Region(int regionNumber, const MidiState& midiState, absl::string_view defaultPath = "")
: id{regionNumber}, midiState(midiState), defaultPath(std::move(defaultPath))
{
ccSwitched.set();

Expand All @@ -46,6 +47,14 @@ struct Region {
Region(const Region&) = default;
~Region() = default;

/**
* @brief Get the number which identifies this region
*/
NumericId<Region> getId() const noexcept
{
return id;
}

/**
* @brief Triggers on release?
*
Expand Down Expand Up @@ -238,6 +247,8 @@ struct Region {
*/
float getGainToEffectBus(unsigned number) const noexcept;

const NumericId<Region> id;

// Sound source: sample playback
FileId sampleId {}; // Sample
absl::optional<int> sampleQuality {};
Expand Down
2 changes: 2 additions & 0 deletions src/sfizz/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "Wavetables.h"
#include "Curve.h"
#include "Tuning.h"
#include "absl/types/optional.h"

namespace sfz
{
Expand All @@ -31,6 +32,7 @@ struct Resources
EQPool eqPool { midiState };
WavetablePool wavePool;
Tuning tuning;
absl::optional<StretchTuning> stretch;

void setSampleRate(float samplerate)
{
Expand Down
Loading

0 comments on commit c9a8245

Please sign in to comment.