summaryrefslogtreecommitdiff
path: root/libs/plugins
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-08-24 05:33:18 +0200
committerRobin Gareus <robin@gareus.org>2016-08-24 05:33:18 +0200
commitaa349d3f8c112b407d19bf09fb50a20940331295 (patch)
tree3b2f8d1cd47bf088c6a2ed6a79551349f20b29fd /libs/plugins
parent8da58c3da02d48adbb6bdd9f2d1489c33a603299 (diff)
add support for reverb & chorus in a-fluidsynth
Diffstat (limited to 'libs/plugins')
-rw-r--r--libs/plugins/a-fluidsynth.lv2/a-fluidsynth.c113
-rw-r--r--libs/plugins/a-fluidsynth.lv2/a-fluidsynth.ttl.in149
2 files changed, 221 insertions, 41 deletions
diff --git a/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.c b/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.c
index c6b743ed84..11015b5ba1 100644
--- a/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.c
+++ b/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.c
@@ -23,6 +23,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#define AFS_URN "urn:ardour:a-fluidsynth"
@@ -49,7 +50,20 @@ enum {
FS_PORT_CONTROL = 0,
FS_PORT_NOTIFY,
FS_PORT_OUT_L,
- FS_PORT_OUT_R
+ FS_PORT_OUT_R,
+ FS_OUT_GAIN,
+ FS_REV_ENABLE,
+ FS_REV_ROOMSIZE,
+ FS_REV_DAMPING,
+ FS_REV_WIDTH,
+ FS_REV_LEVEL,
+ FS_CHR_ENABLE,
+ FS_CHR_N,
+ FS_CHR_SPEED,
+ FS_CHR_DEPTH,
+ FS_CHR_LEVEL,
+ FS_CHR_TYPE,
+ FS_PORT_LAST
};
enum {
@@ -61,7 +75,9 @@ typedef struct {
/* ports */
const LV2_Atom_Sequence* control;
LV2_Atom_Sequence* notify;
- float* output[2];
+
+ float* p_ports[FS_PORT_LAST];
+ float v_ports[FS_PORT_LAST];
/* fluid synth */
fluid_settings_t* settings;
@@ -104,6 +120,7 @@ typedef struct {
/* *****************************************************************************
* helpers
*/
+
static bool
load_sf2 (AFluidSynth* self, const char* fn)
{
@@ -150,7 +167,7 @@ parse_patch_msg (AFluidSynth* self, const LV2_Atom_Object* obj)
return NULL;
}
- lv2_atom_object_get(obj, self->patch_value, &file_path, 0);
+ lv2_atom_object_get (obj, self->patch_value, &file_path, 0);
if (!file_path || file_path->type != self->atom_Path) {
return NULL;
}
@@ -158,7 +175,6 @@ parse_patch_msg (AFluidSynth* self, const LV2_Atom_Object* obj)
return file_path;
}
-
static void
inform_ui (AFluidSynth* self)
{
@@ -168,15 +184,23 @@ inform_ui (AFluidSynth* self)
LV2_Atom_Forge_Frame frame;
lv2_atom_forge_frame_time (&self->forge, 0);
- x_forge_object(&self->forge, &frame, 1, self->patch_Set);
+ x_forge_object (&self->forge, &frame, 1, self->patch_Set);
lv2_atom_forge_property_head (&self->forge, self->patch_property, 0);
lv2_atom_forge_urid (&self->forge, self->afs_sf2file);
lv2_atom_forge_property_head (&self->forge, self->patch_value, 0);
- lv2_atom_forge_path( &self->forge, self->current_sf2_file_path, strlen(self->current_sf2_file_path));
+ lv2_atom_forge_path (&self->forge, self->current_sf2_file_path, strlen (self->current_sf2_file_path));
lv2_atom_forge_pop (&self->forge, &frame);
}
+static float
+db_to_coeff (float db)
+{
+ if (db <= -80) { return 0; }
+ else if (db >= 20) { return 10; }
+ return powf (10.f, .05f * db);
+}
+
/* *****************************************************************************
* LV2 Plugin
*/
@@ -294,11 +318,10 @@ connect_port (LV2_Handle instance,
case FS_PORT_NOTIFY:
self->notify = (LV2_Atom_Sequence*)data;
break;
- case FS_PORT_OUT_L:
- self->output[0] = (float*)data;
- break;
- case FS_PORT_OUT_R:
- self->output[1] = (float*)data;
+ default:
+ if (port < FS_PORT_LAST) {
+ self->p_ports[port] = (float*)data;
+ }
break;
}
}
@@ -324,14 +347,64 @@ run (LV2_Handle instance, uint32_t n_samples)
lv2_atom_forge_sequence_head (&self->forge, &self->frame, 0);
if (!self->initialized || self->reinit_in_progress) {
- memset (self->output[0], 0, n_samples * sizeof (float));
- memset (self->output[1], 0, n_samples * sizeof (float));
+ memset (self->p_ports[FS_PORT_OUT_L], 0, n_samples * sizeof (float));
+ memset (self->p_ports[FS_PORT_OUT_R], 0, n_samples * sizeof (float));
} else if (self->panic) {
fluid_synth_all_notes_off (self->synth, -1);
fluid_synth_all_sounds_off (self->synth, -1);
+ //fluid_synth_reset_reverb (self->synth);
+ //fluid_synth_reset_chorus (self->synth);
self->panic = false;
}
+ if (self->initialized && !self->reinit_in_progress) {
+ bool rev_change = false;
+ bool chr_change = false;
+ // TODO clamp values to ranges
+ if (self->v_ports[FS_OUT_GAIN] != *self->p_ports[FS_OUT_GAIN]) {
+ fluid_synth_set_gain (self->synth, db_to_coeff (*self->p_ports[FS_OUT_GAIN]));
+ }
+ if (self->v_ports[FS_REV_ENABLE] != *self->p_ports[FS_REV_ENABLE]) {
+ fluid_synth_set_reverb_on (self->synth, *self->p_ports[FS_REV_ENABLE] > 0 ? 1 : 0);
+ rev_change = true;
+ }
+ if (self->v_ports[FS_CHR_ENABLE] != *self->p_ports[FS_CHR_ENABLE]) {
+ fluid_synth_set_chorus_on (self->synth, *self->p_ports[FS_CHR_ENABLE] > 0 ? 1 : 0);
+ chr_change = true;
+ }
+
+ for (uint32_t p = FS_REV_ROOMSIZE; p <= FS_REV_LEVEL && !rev_change; ++p) {
+ if (self->v_ports[p] != *self->p_ports[p]) {
+ rev_change = true;
+ }
+ }
+ for (uint32_t p = FS_CHR_N; p <= FS_CHR_TYPE && !chr_change; ++p) {
+ if (self->v_ports[p] != *self->p_ports[p]) {
+ chr_change = true;
+ }
+ }
+
+ if (rev_change) {
+ fluid_synth_set_reverb (self->synth,
+ *self->p_ports[FS_REV_ROOMSIZE],
+ *self->p_ports[FS_REV_DAMPING],
+ *self->p_ports[FS_REV_WIDTH],
+ *self->p_ports[FS_REV_LEVEL]);
+ }
+
+ if (chr_change) {
+ fluid_synth_set_chorus (self->synth,
+ rintf (*self->p_ports[FS_CHR_N]),
+ db_to_coeff (*self->p_ports[FS_CHR_LEVEL]),
+ *self->p_ports[FS_CHR_SPEED],
+ *self->p_ports[FS_CHR_DEPTH],
+ (*self->p_ports[FS_CHR_TYPE] > 0) ? FLUID_CHORUS_MOD_SINE : FLUID_CHORUS_MOD_TRIANGLE);
+ }
+ for (uint32_t p = FS_OUT_GAIN; p < FS_PORT_LAST; ++p) {
+ self->v_ports[p] = *self->p_ports[p];
+ }
+ }
+
uint32_t offset = 0;
LV2_ATOM_SEQUENCE_FOREACH (self->control, ev) {
@@ -349,7 +422,7 @@ run (LV2_Handle instance, uint32_t n_samples)
self->queue_sf2_file_path[1023] = '\0';
self->reinit_in_progress = true;
int magic = 0x4711;
- self->schedule->schedule_work (self->schedule->handle, sizeof(int), &magic);
+ self->schedule->schedule_work (self->schedule->handle, sizeof (int), &magic);
}
}
}
@@ -362,8 +435,8 @@ run (LV2_Handle instance, uint32_t n_samples)
fluid_synth_write_float (
self->synth,
ev->time.frames - offset,
- &self->output[0][offset], 0, 1,
- &self->output[1][offset], 0, 1);
+ &self->p_ports[FS_PORT_OUT_L][offset], 0, 1,
+ &self->p_ports[FS_PORT_OUT_R][offset], 0, 1);
}
offset = ev->time.frames;
@@ -384,7 +457,7 @@ run (LV2_Handle instance, uint32_t n_samples)
if (self->queue_reinit && !self->reinit_in_progress) {
self->reinit_in_progress = true;
int magic = 0x4711;
- self->schedule->schedule_work (self->schedule->handle, sizeof(int), &magic);
+ self->schedule->schedule_work (self->schedule->handle, sizeof (int), &magic);
}
/* inform the GUI */
@@ -397,8 +470,8 @@ run (LV2_Handle instance, uint32_t n_samples)
fluid_synth_write_float (
self->synth,
n_samples - offset,
- &self->output[0][offset], 0, 1,
- &self->output[1][offset], 0, 1);
+ &self->p_ports[FS_PORT_OUT_L][offset], 0, 1,
+ &self->p_ports[FS_PORT_OUT_R][offset], 0, 1);
}
}
@@ -424,7 +497,7 @@ work (LV2_Handle instance,
{
AFluidSynth* self = (AFluidSynth*)instance;
- if (size != sizeof(int)) {
+ if (size != sizeof (int)) {
return LV2_WORKER_ERR_UNKNOWN;
}
int magic = *((const int*)data);
diff --git a/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.ttl.in b/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.ttl.in
index 3363d18a6d..ca9b3ca39a 100644
--- a/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.ttl.in
+++ b/libs/plugins/a-fluidsynth.lv2/a-fluidsynth.ttl.in
@@ -4,53 +4,54 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
+@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix state: <http://lv2plug.in/ns/ext/state#> .
-@prefix unit: <http://lv2plug.in/ns/extensions/units#> .
+@prefix units: <http://lv2plug.in/ns/extensions/units#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
<http://ardour.org/credits.html>
- a foaf:Person ;
- foaf:name "Ardour Team" ;
- foaf:homepage <http://ardour.org/> .
+ a foaf:Person ;
+ foaf:name "Ardour Team" ;
+ foaf:homepage <http://ardour.org/> .
<urn:ardour:a-fluidsynth:sf2file>
- a lv2:Parameter ;
- rdfs:label "SF2 File" ;
- rdfs:range atom:Path .
+ a lv2:Parameter ;
+ rdfs:label "SF2 File" ;
+ rdfs:range atom:Path .
<urn:ardour:a-fluidsynth>
- a doap:Project, lv2:InstrumentPlugin, lv2:Plugin ;
+ a doap:Project, lv2:InstrumentPlugin, lv2:Plugin ;
- doap:name "a-Fluid Synth" ;
- rdfs:comment "SF2 Synthesizer using Fluidsynth" ;
+ doap:name "a-Fluid Synth" ;
+ rdfs:comment "SF2 Synthesizer using Fluidsynth" ;
- doap:maintainer <http://ardour.org/credits.html> ;
- doap:license <http://usefulinc.com/doap/licenses/gpl> ;
+ doap:maintainer <http://ardour.org/credits.html> ;
+ doap:license <http://usefulinc.com/doap/licenses/gpl> ;
- lv2:microVersion 2 ; lv2:minorVersion 0 ;
+ lv2:microVersion 2 ; lv2:minorVersion 0 ;
- lv2:requiredFeature urid:map, work:schedule ;
- lv2:extensionData work:interface, state:interface ;
- lv2:optionalFeature lv2:hardRTCapable;
+ lv2:requiredFeature urid:map, work:schedule ;
+ lv2:extensionData work:interface, state:interface ;
+ lv2:optionalFeature lv2:hardRTCapable;
- patch:writable <urn:ardour:a-fluidsynth:sf2file> ;
+ patch:writable <urn:ardour:a-fluidsynth:sf2file> ;
lv2:port [
a lv2:InputPort, atom:AtomPort ;
atom:bufferType atom:Sequence ;
- atom:supports patch:Message, midi:MidiEvent;
- lv2:designation lv2:control ;
+ atom:supports patch:Message, midi:MidiEvent;
+ lv2:designation lv2:control ;
lv2:index 0 ;
lv2:symbol "control" ;
lv2:name "Midi In" ;
] , [
a lv2:OutputPort, atom:AtomPort ;
atom:bufferType atom:Sequence ;
- atom:supports patch:Message;
- lv2:designation lv2:control ;
+ atom:supports patch:Message;
+ lv2:designation lv2:control ;
lv2:index 1 ;
lv2:symbol "notify" ;
lv2:name "UI Notifications" ;
@@ -64,4 +65,110 @@
lv2:index 3 ;
lv2:symbol "outR" ;
lv2:name "Output Right" ;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 4 ;
+ lv2:symbol "level" ;
+ lv2:name "Output Level" ;
+ lv2:default 0.0 ;
+ lv2:minimum -80.0 ;
+ lv2:maximum 20.0;
+ units:unit units:db ;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 5 ;
+ lv2:symbol "rev_enable" ;
+ lv2:name "Reverb Enable" ;
+ lv2:default 0 ;
+ lv2:minimum 0 ;
+ lv2:maximum 1 ;
+ lv2:portProperty lv2:integer, lv2:toggled;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 6 ;
+ lv2:symbol "rev_roomsize" ;
+ lv2:name "Reverb Roomsize" ;
+ lv2:default 0.5 ;
+ lv2:minimum 0.0 ;
+ lv2:maximum 1.2;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 7 ;
+ lv2:symbol "rev_damp" ;
+ lv2:name "Reverb Damping" ;
+ lv2:default 0.5 ;
+ lv2:minimum 0.0 ;
+ lv2:maximum 1.0;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 8 ;
+ lv2:symbol "rev_width" ;
+ lv2:name "Reverb Width" ;
+ lv2:default 10.0 ;
+ lv2:minimum 0.0 ;
+ lv2:maximum 100.0;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 9 ;
+ lv2:symbol "rev_level" ;
+ lv2:name "Reverb Dry/Wet" ;
+ lv2:default 0.1 ;
+ lv2:minimum 0.0 ;
+ lv2:maximum 1.0;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 10 ;
+ lv2:symbol "chorus_enable" ;
+ lv2:name "Chorus Enable" ;
+ lv2:default 0 ;
+ lv2:minimum 0 ;
+ lv2:maximum 1 ;
+ lv2:portProperty lv2:integer, lv2:toggled;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 11 ;
+ lv2:symbol "chorus_nr" ;
+ lv2:name "Chorus Voice Count" ;
+ lv2:default 1 ;
+ lv2:minimum 0 ;
+ lv2:maximum 99;
+ lv2:portProperty lv2:integer;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 12 ;
+ lv2:symbol "chorus_speed" ;
+ lv2:name "Chorus Speed" ;
+ lv2:default 1.0 ;
+ lv2:minimum 0.29 ;
+ lv2:maximum 5.0;
+ units:unit units:hz ;
+ lv2:portProperty pprop:logarithmic;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 13 ;
+ lv2:symbol "chorus_depth" ;
+ lv2:name "Chorus Depth" ;
+ lv2:default 0.0 ;
+ lv2:minimum 0.0 ;
+ lv2:maximum 21.0;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 14 ;
+ lv2:symbol "chorus_level" ;
+ lv2:name "Chorus Level" ;
+ lv2:default 0.0 ;
+ lv2:minimum -80.0 ;
+ lv2:maximum 20.0;
+ units:unit units:db ;
+ ] , [
+ a lv2:InputPort, lv2:ControlPort ;
+ lv2:index 15 ;
+ lv2:symbol "chorus_type" ;
+ lv2:name "Chorus Type" ;
+ lv2:default 0.0 ;
+ lv2:minimum 0.0 ;
+ lv2:maximum 1.0;
+ lv2:portProperty lv2:integer, lv2:enumeration;
+ lv2:scalePoint [ rdfs:label "Sine"; rdf:value 0.0 ; ] ;
+ lv2:scalePoint [ rdfs:label "Triangle"; rdf:value 1.0 ; ] ;
] .