Plugin-level support for host time
This commit is contained in:
parent
95bf4fc480
commit
36f5a62f04
9 changed files with 343 additions and 11 deletions
168
lv2/sfizz.c
168
lv2/sfizz.c
|
|
@ -131,7 +131,9 @@ typedef struct
|
||||||
LV2_URID sample_rate_uri;
|
LV2_URID sample_rate_uri;
|
||||||
LV2_URID atom_object_uri;
|
LV2_URID atom_object_uri;
|
||||||
LV2_URID atom_float_uri;
|
LV2_URID atom_float_uri;
|
||||||
|
LV2_URID atom_double_uri;
|
||||||
LV2_URID atom_int_uri;
|
LV2_URID atom_int_uri;
|
||||||
|
LV2_URID atom_long_uri;
|
||||||
LV2_URID atom_urid_uri;
|
LV2_URID atom_urid_uri;
|
||||||
LV2_URID atom_path_uri;
|
LV2_URID atom_path_uri;
|
||||||
LV2_URID patch_set_uri;
|
LV2_URID patch_set_uri;
|
||||||
|
|
@ -150,6 +152,12 @@ typedef struct
|
||||||
LV2_URID sfizz_check_modification_uri;
|
LV2_URID sfizz_check_modification_uri;
|
||||||
LV2_URID sfizz_active_voices_uri;
|
LV2_URID sfizz_active_voices_uri;
|
||||||
LV2_URID time_position_uri;
|
LV2_URID time_position_uri;
|
||||||
|
LV2_URID time_bar_uri;
|
||||||
|
LV2_URID time_bar_beat_uri;
|
||||||
|
LV2_URID time_beat_unit_uri;
|
||||||
|
LV2_URID time_beats_per_bar_uri;
|
||||||
|
LV2_URID time_beats_per_minute_uri;
|
||||||
|
LV2_URID time_speed_uri;
|
||||||
|
|
||||||
// Sfizz related data
|
// Sfizz related data
|
||||||
sfizz_synth_t *synth;
|
sfizz_synth_t *synth;
|
||||||
|
|
@ -166,6 +174,14 @@ typedef struct
|
||||||
float sample_rate;
|
float sample_rate;
|
||||||
atomic_int must_update_midnam;
|
atomic_int must_update_midnam;
|
||||||
|
|
||||||
|
// Timing data
|
||||||
|
int bar;
|
||||||
|
float bar_beat;
|
||||||
|
int beats_per_bar;
|
||||||
|
int beat_unit;
|
||||||
|
float bpm_tempo;
|
||||||
|
float speed;
|
||||||
|
|
||||||
// Paths
|
// Paths
|
||||||
char bundle_path[MAX_BUNDLE_PATH_SIZE];
|
char bundle_path[MAX_BUNDLE_PATH_SIZE];
|
||||||
} sfizz_plugin_t;
|
} sfizz_plugin_t;
|
||||||
|
|
@ -187,6 +203,14 @@ enum
|
||||||
SFIZZ_ACTIVE_VOICES = 12,
|
SFIZZ_ACTIVE_VOICES = 12,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SFIZZ_TIMEINFO_POSITION = 1 << 0,
|
||||||
|
SFIZZ_TIMEINFO_SIGNATURE = 1 << 1,
|
||||||
|
SFIZZ_TIMEINFO_TEMPO = 1 << 2,
|
||||||
|
SFIZZ_TIMEINFO_SPEED = 1 << 3,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sfizz_lv2_state_free_path(LV2_State_Free_Path_Handle handle,
|
sfizz_lv2_state_free_path(LV2_State_Free_Path_Handle handle,
|
||||||
char *path)
|
char *path)
|
||||||
|
|
@ -210,7 +234,9 @@ sfizz_lv2_map_required_uris(sfizz_plugin_t *self)
|
||||||
self->nominal_block_length_uri = map->map(map->handle, LV2_BUF_SIZE__nominalBlockLength);
|
self->nominal_block_length_uri = map->map(map->handle, LV2_BUF_SIZE__nominalBlockLength);
|
||||||
self->sample_rate_uri = map->map(map->handle, LV2_PARAMETERS__sampleRate);
|
self->sample_rate_uri = map->map(map->handle, LV2_PARAMETERS__sampleRate);
|
||||||
self->atom_float_uri = map->map(map->handle, LV2_ATOM__Float);
|
self->atom_float_uri = map->map(map->handle, LV2_ATOM__Float);
|
||||||
|
self->atom_double_uri = map->map(map->handle, LV2_ATOM__Double);
|
||||||
self->atom_int_uri = map->map(map->handle, LV2_ATOM__Int);
|
self->atom_int_uri = map->map(map->handle, LV2_ATOM__Int);
|
||||||
|
self->atom_long_uri = map->map(map->handle, LV2_ATOM__Long);
|
||||||
self->atom_path_uri = map->map(map->handle, LV2_ATOM__Path);
|
self->atom_path_uri = map->map(map->handle, LV2_ATOM__Path);
|
||||||
self->atom_urid_uri = map->map(map->handle, LV2_ATOM__URID);
|
self->atom_urid_uri = map->map(map->handle, LV2_ATOM__URID);
|
||||||
self->atom_object_uri = map->map(map->handle, LV2_ATOM__Object);
|
self->atom_object_uri = map->map(map->handle, LV2_ATOM__Object);
|
||||||
|
|
@ -230,6 +256,68 @@ sfizz_lv2_map_required_uris(sfizz_plugin_t *self)
|
||||||
self->sfizz_log_status_uri = map->map(map->handle, SFIZZ__logStatus);
|
self->sfizz_log_status_uri = map->map(map->handle, SFIZZ__logStatus);
|
||||||
self->sfizz_check_modification_uri = map->map(map->handle, SFIZZ__checkModification);
|
self->sfizz_check_modification_uri = map->map(map->handle, SFIZZ__checkModification);
|
||||||
self->time_position_uri = map->map(map->handle, LV2_TIME__Position);
|
self->time_position_uri = map->map(map->handle, LV2_TIME__Position);
|
||||||
|
self->time_bar_uri = map->map(map->handle, LV2_TIME__bar);
|
||||||
|
self->time_bar_beat_uri = map->map(map->handle, LV2_TIME__barBeat);
|
||||||
|
self->time_beat_unit_uri = map->map(map->handle, LV2_TIME__beatUnit);
|
||||||
|
self->time_beats_per_bar_uri = map->map(map->handle, LV2_TIME__beatsPerBar);
|
||||||
|
self->time_beats_per_minute_uri = map->map(map->handle, LV2_TIME__beatsPerMinute);
|
||||||
|
self->time_speed_uri = map->map(map->handle, LV2_TIME__speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
sfizz_atom_extract_real(sfizz_plugin_t *self, const LV2_Atom *atom, double *real)
|
||||||
|
{
|
||||||
|
if (!atom)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const LV2_URID type = atom->type;
|
||||||
|
|
||||||
|
if (type == self->atom_int_uri && atom->size >= sizeof(int32_t)) {
|
||||||
|
*real = ((const LV2_Atom_Int *)atom)->body;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (type == self->atom_long_uri && atom->size >= sizeof(int64_t)) {
|
||||||
|
*real = ((const LV2_Atom_Long *)atom)->body;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (type == self->atom_float_uri && atom->size >= sizeof(float)) {
|
||||||
|
*real = ((const LV2_Atom_Float *)atom)->body;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (type == self->atom_double_uri && atom->size >= sizeof(double)) {
|
||||||
|
*real = ((const LV2_Atom_Double *)atom)->body;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
sfizz_atom_extract_integer(sfizz_plugin_t *self, const LV2_Atom *atom, int64_t *integer)
|
||||||
|
{
|
||||||
|
if (!atom)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const LV2_URID type = atom->type;
|
||||||
|
|
||||||
|
if (type == self->atom_int_uri && atom->size >= sizeof(int32_t)) {
|
||||||
|
*integer = ((const LV2_Atom_Int *)atom)->body;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (type == self->atom_long_uri && atom->size >= sizeof(int64_t)) {
|
||||||
|
*integer = ((const LV2_Atom_Long *)atom)->body;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (type == self->atom_float_uri && atom->size >= sizeof(float)) {
|
||||||
|
*integer = (int64_t)((const LV2_Atom_Float *)atom)->body;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (type == self->atom_double_uri && atom->size >= sizeof(double)) {
|
||||||
|
*integer = (int64_t)((const LV2_Atom_Double *)atom)->body;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -326,6 +414,19 @@ sfizz_lv2_get_default_scala_path(LV2_Handle instance, char *path, size_t size)
|
||||||
snprintf(path, size, "%s/%s", self->bundle_path, DEFAULT_SCALA_FILE);
|
snprintf(path, size, "%s/%s", self->bundle_path, DEFAULT_SCALA_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sfizz_lv2_update_timeinfo(sfizz_plugin_t *self, int delay, int updates)
|
||||||
|
{
|
||||||
|
if (updates & SFIZZ_TIMEINFO_POSITION)
|
||||||
|
sfizz_send_time_position(self->synth, delay, self->bar, self->bar_beat);
|
||||||
|
if (updates & SFIZZ_TIMEINFO_SIGNATURE)
|
||||||
|
sfizz_send_time_signature(self->synth, delay, self->beats_per_bar, self->beat_unit);
|
||||||
|
if (updates & SFIZZ_TIMEINFO_TEMPO)
|
||||||
|
sfizz_send_tempo(self->synth, delay, 60.0f / self->bpm_tempo);
|
||||||
|
if (updates & SFIZZ_TIMEINFO_SPEED)
|
||||||
|
sfizz_send_playback_state(self->synth, delay, self->speed > 0);
|
||||||
|
}
|
||||||
|
|
||||||
static LV2_Handle
|
static LV2_Handle
|
||||||
instantiate(const LV2_Descriptor *descriptor,
|
instantiate(const LV2_Descriptor *descriptor,
|
||||||
double rate,
|
double rate,
|
||||||
|
|
@ -361,6 +462,14 @@ instantiate(const LV2_Descriptor *descriptor,
|
||||||
self->check_modification = false;
|
self->check_modification = false;
|
||||||
self->sample_counter = 0;
|
self->sample_counter = 0;
|
||||||
|
|
||||||
|
// Initial timing
|
||||||
|
self->bar = 0;
|
||||||
|
self->bar_beat = 0;
|
||||||
|
self->beats_per_bar = 4;
|
||||||
|
self->beat_unit = 4;
|
||||||
|
self->bpm_tempo = 120;
|
||||||
|
self->speed = 1;
|
||||||
|
|
||||||
// Get the features from the host and populate the structure
|
// Get the features from the host and populate the structure
|
||||||
for (const LV2_Feature *const *f = features; *f; f++)
|
for (const LV2_Feature *const *f = features; *f; f++)
|
||||||
{
|
{
|
||||||
|
|
@ -472,6 +581,8 @@ instantiate(const LV2_Descriptor *descriptor,
|
||||||
sfizz_load_file(self->synth, self->sfz_file_path);
|
sfizz_load_file(self->synth, self->sfz_file_path);
|
||||||
sfizz_load_scala_file(self->synth, self->scala_file_path);
|
sfizz_load_scala_file(self->synth, self->scala_file_path);
|
||||||
|
|
||||||
|
sfizz_lv2_update_timeinfo(self, 0, ~0);
|
||||||
|
|
||||||
return (LV2_Handle)self;
|
return (LV2_Handle)self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -751,6 +862,8 @@ run(LV2_Handle instance, uint32_t sample_count)
|
||||||
|
|
||||||
LV2_ATOM_SEQUENCE_FOREACH(self->control_port, ev)
|
LV2_ATOM_SEQUENCE_FOREACH(self->control_port, ev)
|
||||||
{
|
{
|
||||||
|
const int delay = (int)ev->time.frames;
|
||||||
|
|
||||||
// If the received atom is an object/patch message
|
// If the received atom is an object/patch message
|
||||||
if (ev->body.type == self->atom_object_uri)
|
if (ev->body.type == self->atom_object_uri)
|
||||||
{
|
{
|
||||||
|
|
@ -779,7 +892,60 @@ run(LV2_Handle instance, uint32_t sample_count)
|
||||||
}
|
}
|
||||||
else if (obj->body.otype == self->time_position_uri)
|
else if (obj->body.otype == self->time_position_uri)
|
||||||
{
|
{
|
||||||
// TODO: Handle time position atom
|
const LV2_Atom *bar_atom = NULL;
|
||||||
|
const LV2_Atom *bar_beat_atom = NULL;
|
||||||
|
const LV2_Atom *beat_unit_atom = NULL;
|
||||||
|
const LV2_Atom *beats_per_bar_atom = NULL;
|
||||||
|
const LV2_Atom *beats_per_minute_atom = NULL;
|
||||||
|
const LV2_Atom *speed_atom = NULL;
|
||||||
|
|
||||||
|
lv2_atom_object_get(
|
||||||
|
obj,
|
||||||
|
self->time_bar_uri, &bar_atom,
|
||||||
|
self->time_bar_beat_uri, &bar_beat_atom,
|
||||||
|
self->time_beats_per_bar_uri, &beats_per_bar_atom,
|
||||||
|
self->time_beats_per_minute_uri, &beats_per_minute_atom,
|
||||||
|
self->time_beat_unit_uri, &beat_unit_atom,
|
||||||
|
self->time_speed_uri, &speed_atom,
|
||||||
|
0);
|
||||||
|
|
||||||
|
int updates = 0;
|
||||||
|
|
||||||
|
int64_t bar;
|
||||||
|
double bar_beat;
|
||||||
|
if (sfizz_atom_extract_integer(self, bar_atom, &bar)) {
|
||||||
|
self->bar = (int)bar;
|
||||||
|
updates |= SFIZZ_TIMEINFO_POSITION;
|
||||||
|
}
|
||||||
|
if (sfizz_atom_extract_real(self, bar_beat_atom, &bar_beat)) {
|
||||||
|
self->bar_beat = (float)bar_beat;
|
||||||
|
updates |= SFIZZ_TIMEINFO_POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
double beats_per_bar;
|
||||||
|
int64_t beat_unit;
|
||||||
|
if (sfizz_atom_extract_real(self, beats_per_bar_atom, &beats_per_bar)) {
|
||||||
|
self->beats_per_bar = (int)beats_per_bar;
|
||||||
|
updates |= SFIZZ_TIMEINFO_SIGNATURE;
|
||||||
|
}
|
||||||
|
if (sfizz_atom_extract_integer(self, beat_unit_atom, &beat_unit)) {
|
||||||
|
self->beat_unit = (int)beat_unit;
|
||||||
|
updates |= SFIZZ_TIMEINFO_SIGNATURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
double tempo;
|
||||||
|
if (sfizz_atom_extract_real(self, beats_per_minute_atom, &tempo)) {
|
||||||
|
self->bpm_tempo = (float)tempo;
|
||||||
|
updates |= SFIZZ_TIMEINFO_TEMPO;
|
||||||
|
}
|
||||||
|
|
||||||
|
double speed;
|
||||||
|
if (sfizz_atom_extract_real(self, speed_atom, &speed)) {
|
||||||
|
self->speed = (float)speed;
|
||||||
|
updates |= SFIZZ_TIMEINFO_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
sfizz_lv2_update_timeinfo(self, delay, updates);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
36
src/sfizz.h
36
src/sfizz.h
|
|
@ -302,13 +302,43 @@ SFIZZ_EXPORTED_API void sfizz_send_pitch_wheel(sfizz_synth_t* synth, int delay,
|
||||||
SFIZZ_EXPORTED_API void sfizz_send_aftertouch(sfizz_synth_t* synth, int delay, char aftertouch);
|
SFIZZ_EXPORTED_API void sfizz_send_aftertouch(sfizz_synth_t* synth, int delay, char aftertouch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a tempo event. (CURRENTLY UNIMPLEMENTED)
|
* @brief Send a tempo event.
|
||||||
*
|
*
|
||||||
* @param synth The synth.
|
* @param synth The synth.
|
||||||
* @param delay The delay.
|
* @param delay The delay.
|
||||||
* @param seconds_per_quarter The seconds per quarter.
|
* @param seconds_per_beat The seconds per beat.
|
||||||
*/
|
*/
|
||||||
SFIZZ_EXPORTED_API void sfizz_send_tempo(sfizz_synth_t* synth, int delay, float seconds_per_quarter);
|
SFIZZ_EXPORTED_API void sfizz_send_tempo(sfizz_synth_t* synth, int delay, float seconds_per_beat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the time signature.
|
||||||
|
*
|
||||||
|
* @param synth The synth.
|
||||||
|
* @param delay The delay.
|
||||||
|
* @param beats_per_bar The number of beats per bar, or time signature numerator.
|
||||||
|
* @param beat_unit The note corresponding to one beat, or time signature denominator.
|
||||||
|
*/
|
||||||
|
SFIZZ_EXPORTED_API void sfizz_send_time_signature(sfizz_synth_t* synth, int delay, int beats_per_bar, int beat_unit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the time position.
|
||||||
|
*
|
||||||
|
* @param synth The synth.
|
||||||
|
* @param delay The delay.
|
||||||
|
* @param bar The current bar.
|
||||||
|
* @param bar_beat The fractional position of the current beat within the bar.
|
||||||
|
*/
|
||||||
|
SFIZZ_EXPORTED_API void sfizz_send_time_position(sfizz_synth_t* synth, int delay, int bar, float bar_beat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the playback state.
|
||||||
|
*
|
||||||
|
* @param synth The synth.
|
||||||
|
* @param delay The delay.
|
||||||
|
* @param playback_state The playback state, 1 if playing, 0 if stopped.
|
||||||
|
*/
|
||||||
|
SFIZZ_EXPORTED_API void sfizz_send_playback_state(sfizz_synth_t* synth, int delay, int playback_state);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Render a block audio data into a stereo channel. No other channel
|
* @brief Render a block audio data into a stereo channel. No other channel
|
||||||
|
|
|
||||||
|
|
@ -291,13 +291,39 @@ public:
|
||||||
void aftertouch(int delay, uint8_t aftertouch) noexcept;
|
void aftertouch(int delay, uint8_t aftertouch) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a tempo event to the synth. (CURRENTLY UNIMPLEMENTED)
|
* @brief Send a tempo event to the synth.
|
||||||
*
|
*
|
||||||
* @param delay the delay at which the event occurs; this should be lower than the size of
|
* @param delay the delay at which the event occurs; this should be lower than the size of
|
||||||
* the block in the next call to renderBlock().
|
* the block in the next call to renderBlock().
|
||||||
* @param secondsPerQuarter the new period of the quarter note.
|
* @param secondsPerBeat the new period of the beat.
|
||||||
*/
|
*/
|
||||||
void tempo(int delay, float secondsPerQuarter) noexcept;
|
void tempo(int delay, float secondsPerBeat) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the time signature.
|
||||||
|
*
|
||||||
|
* @param delay The delay.
|
||||||
|
* @param beats_per_bar The number of beats per bar, or time signature numerator.
|
||||||
|
* @param beat_unit The note corresponding to one beat, or time signature denominator.
|
||||||
|
*/
|
||||||
|
void timeSignature(int delay, int beatsPerBar, int beatUnit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the time position.
|
||||||
|
*
|
||||||
|
* @param delay The delay.
|
||||||
|
* @param bar The current bar.
|
||||||
|
* @param bar_beat The fractional position of the current beat within the bar.
|
||||||
|
*/
|
||||||
|
void timePosition(int delay, int bar, float barBeat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the playback state.
|
||||||
|
*
|
||||||
|
* @param delay The delay.
|
||||||
|
* @param playback_state The playback state, 1 if playing, 0 if stopped.
|
||||||
|
*/
|
||||||
|
void playbackState(int delay, int playbackState);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Render an block of audio data in the buffer. This call will reset
|
* @brief Render an block of audio data in the buffer. This call will reset
|
||||||
|
|
|
||||||
|
|
@ -1116,6 +1116,29 @@ void sfz::Synth::tempo(int /* delay */, float /* secondsPerQuarter */) noexcept
|
||||||
{
|
{
|
||||||
ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration };
|
ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration };
|
||||||
}
|
}
|
||||||
|
void sfz::Synth::timeSignature(int delay, int beatsPerBar, int beatUnit)
|
||||||
|
{
|
||||||
|
ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration };
|
||||||
|
|
||||||
|
(void)delay;
|
||||||
|
(void)beatsPerBar;
|
||||||
|
(void)beatUnit;
|
||||||
|
}
|
||||||
|
void sfz::Synth::timePosition(int delay, int bar, float barBeat)
|
||||||
|
{
|
||||||
|
ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration };
|
||||||
|
|
||||||
|
(void)delay;
|
||||||
|
(void)bar;
|
||||||
|
(void)barBeat;
|
||||||
|
}
|
||||||
|
void sfz::Synth::playbackState(int delay, int playbackState)
|
||||||
|
{
|
||||||
|
ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration };
|
||||||
|
|
||||||
|
(void)delay;
|
||||||
|
(void)playbackState;
|
||||||
|
}
|
||||||
|
|
||||||
int sfz::Synth::getNumRegions() const noexcept
|
int sfz::Synth::getNumRegions() const noexcept
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -392,6 +392,29 @@ public:
|
||||||
* @param secondsPerQuarter the new period of the quarter note
|
* @param secondsPerQuarter the new period of the quarter note
|
||||||
*/
|
*/
|
||||||
void tempo(int delay, float secondsPerQuarter) noexcept;
|
void tempo(int delay, float secondsPerQuarter) noexcept;
|
||||||
|
/**
|
||||||
|
* @brief Send the time signature.
|
||||||
|
*
|
||||||
|
* @param delay The delay.
|
||||||
|
* @param beats_per_bar The number of beats per bar, or time signature numerator.
|
||||||
|
* @param beat_unit The note corresponding to one beat, or time signature denominator.
|
||||||
|
*/
|
||||||
|
void timeSignature(int delay, int beatsPerBar, int beatUnit);
|
||||||
|
/**
|
||||||
|
* @brief Send the time position.
|
||||||
|
*
|
||||||
|
* @param delay The delay.
|
||||||
|
* @param bar The current bar.
|
||||||
|
* @param bar_beat The fractional position of the current beat within the bar.
|
||||||
|
*/
|
||||||
|
void timePosition(int delay, int bar, float barBeat);
|
||||||
|
/**
|
||||||
|
* @brief Send the playback state.
|
||||||
|
*
|
||||||
|
* @param delay The delay.
|
||||||
|
* @param playback_state The playback state, 1 if playing, 0 if stopped.
|
||||||
|
*/
|
||||||
|
void playbackState(int delay, int playbackState);
|
||||||
/**
|
/**
|
||||||
* @brief Render an block of audio data in the buffer. This call will reset
|
* @brief Render an block of audio data in the buffer. This call will reset
|
||||||
* the synth in its waiting state for the next batch of events. The size of
|
* the synth in its waiting state for the next batch of events. The size of
|
||||||
|
|
|
||||||
|
|
@ -153,9 +153,24 @@ void sfz::Sfizz::aftertouch(int delay, uint8_t aftertouch) noexcept
|
||||||
synth->aftertouch(delay, aftertouch);
|
synth->aftertouch(delay, aftertouch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Sfizz::tempo(int delay, float secondsPerQuarter) noexcept
|
void sfz::Sfizz::tempo(int delay, float secondsPerBeat) noexcept
|
||||||
{
|
{
|
||||||
synth->tempo(delay, secondsPerQuarter);
|
synth->tempo(delay, secondsPerBeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfz::Sfizz::timeSignature(int delay, int beatsPerBar, int beatUnit)
|
||||||
|
{
|
||||||
|
synth->timeSignature(delay, beatsPerBar, beatUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfz::Sfizz::timePosition(int delay, int bar, float barBeat)
|
||||||
|
{
|
||||||
|
synth->timePosition(delay, bar, barBeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfz::Sfizz::playbackState(int delay, int playbackState)
|
||||||
|
{
|
||||||
|
synth->playbackState(delay, playbackState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Sfizz::renderBlock(float** buffers, size_t numSamples, int /*numOutputs*/) noexcept
|
void sfz::Sfizz::renderBlock(float** buffers, size_t numSamples, int /*numOutputs*/) noexcept
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,21 @@ void sfizz_send_tempo(sfizz_synth_t* synth, int delay, float seconds_per_quarter
|
||||||
auto self = reinterpret_cast<sfz::Synth*>(synth);
|
auto self = reinterpret_cast<sfz::Synth*>(synth);
|
||||||
self->tempo(delay, seconds_per_quarter);
|
self->tempo(delay, seconds_per_quarter);
|
||||||
}
|
}
|
||||||
|
void sfizz_send_time_signature(sfizz_synth_t* synth, int delay, int beats_per_bar, int beat_unit)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<sfz::Synth*>(synth);
|
||||||
|
self->timeSignature(delay, beats_per_bar, beat_unit);
|
||||||
|
}
|
||||||
|
void sfizz_send_time_position(sfizz_synth_t* synth, int delay, int bar, float bar_beat)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<sfz::Synth*>(synth);
|
||||||
|
self->timePosition(delay, bar, bar_beat);
|
||||||
|
}
|
||||||
|
void sfizz_send_playback_state(sfizz_synth_t* synth, int delay, int playback_state)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<sfz::Synth*>(synth);
|
||||||
|
self->playbackState(delay, playback_state);
|
||||||
|
}
|
||||||
|
|
||||||
void sfizz_render_block(sfizz_synth_t* synth, float** channels, int num_channels, int num_frames)
|
void sfizz_render_block(sfizz_synth_t* synth, float** channels, int num_channels, int num_frames)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
#include "pluginterfaces/vst/ivstparameterchanges.h"
|
#include "pluginterfaces/vst/ivstparameterchanges.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#pragma message("TODO: send tempo") // NOLINT
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
constexpr int fastRound(T x)
|
constexpr int fastRound(T x)
|
||||||
{
|
{
|
||||||
|
|
@ -55,6 +53,13 @@ tresult PLUGIN_API SfizzVstProcessor::initialize(FUnknown* context)
|
||||||
_currentStretchedTuning = 0.0;
|
_currentStretchedTuning = 0.0;
|
||||||
loadSfzFileOrDefault(*_synth, {});
|
loadSfzFileOrDefault(*_synth, {});
|
||||||
|
|
||||||
|
_synth->tempo(0, 0.5);
|
||||||
|
_timeSigNumerator = 4;
|
||||||
|
_timeSigDenominator = 4;
|
||||||
|
_synth->timeSignature(0, _timeSigNumerator, _timeSigDenominator);
|
||||||
|
_synth->timePosition(0, 0, 0);
|
||||||
|
_synth->playbackState(0, 0);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,6 +148,9 @@ tresult PLUGIN_API SfizzVstProcessor::process(Vst::ProcessData& data)
|
||||||
{
|
{
|
||||||
sfz::Sfizz& synth = *_synth;
|
sfz::Sfizz& synth = *_synth;
|
||||||
|
|
||||||
|
if (data.processContext)
|
||||||
|
updateTimeInfo(*data.processContext);
|
||||||
|
|
||||||
if (Vst::IParameterChanges* pc = data.inputParameterChanges)
|
if (Vst::IParameterChanges* pc = data.inputParameterChanges)
|
||||||
processParameterChanges(*pc);
|
processParameterChanges(*pc);
|
||||||
|
|
||||||
|
|
@ -198,6 +206,27 @@ tresult PLUGIN_API SfizzVstProcessor::process(Vst::ProcessData& data)
|
||||||
return kResultTrue;
|
return kResultTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SfizzVstProcessor::updateTimeInfo(const Vst::ProcessContext& context)
|
||||||
|
{
|
||||||
|
sfz::Sfizz& synth = *_synth;
|
||||||
|
|
||||||
|
if (context.state & context.kTempoValid)
|
||||||
|
synth.tempo(0, 60.0f / context.tempo);
|
||||||
|
|
||||||
|
if (context.state & context.kTimeSigValid) {
|
||||||
|
_timeSigNumerator = context.timeSigNumerator;
|
||||||
|
_timeSigDenominator = context.timeSigDenominator;
|
||||||
|
synth.timeSignature(0, _timeSigNumerator, _timeSigDenominator);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.state & context.kProjectTimeMusicValid) {
|
||||||
|
double beats = context.projectTimeMusic * 0.25 * _timeSigDenominator;
|
||||||
|
double bars = beats / _timeSigNumerator;
|
||||||
|
beats -= int(bars) * _timeSigNumerator;
|
||||||
|
synth.timePosition(0, int(bars), float(beats));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SfizzVstProcessor::processParameterChanges(Vst::IParameterChanges& pc)
|
void SfizzVstProcessor::processParameterChanges(Vst::IParameterChanges& pc)
|
||||||
{
|
{
|
||||||
uint32 paramCount = pc.getParameterCount();
|
uint32 paramCount = pc.getParameterCount();
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,11 @@ private:
|
||||||
uint32 _fileChangeCounter = 0;
|
uint32 _fileChangeCounter = 0;
|
||||||
uint32 _fileChangePeriod = 0;
|
uint32 _fileChangePeriod = 0;
|
||||||
|
|
||||||
|
// time info
|
||||||
|
int _timeSigNumerator = 0;
|
||||||
|
int _timeSigDenominator = 0;
|
||||||
|
void updateTimeInfo(const Vst::ProcessContext& context);
|
||||||
|
|
||||||
// messaging
|
// messaging
|
||||||
struct RTMessage {
|
struct RTMessage {
|
||||||
const char* type;
|
const char* type;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue