Skip to content

Commit

Permalink
Optimizing pitchshifters for MOD Duo, changing from lookup table to e…
Browse files Browse the repository at this point in the history
…fficient generation of sine, cosine and arctan, small optimizations to the code, adding fidelity options
  • Loading branch information
Jesse Verhage committed Sep 14, 2016
1 parent f8b4735 commit 57b2051
Show file tree
Hide file tree
Showing 28 changed files with 730 additions and 380 deletions.
69 changes: 54 additions & 15 deletions 2Voices/src/2Voices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@

#define PLUGIN_URI "http://moddevices.com/plugins/mod-devel/2Voices"
#define N_SAMPLES_DEFAULT 128
enum {IN, OUT_1, OUT_2, STEP_1, STEP_2, GAIN_1, GAIN_2, PLUGIN_PORT_COUNT};
#define FIDELITY0 6,3,2,1
#define FIDELITY1 12,6,3,2
#define FIDELITY2 16,8,4,2
#define FIDELITY3 20,10,5,3
enum {IN, OUT_1, OUT_2, STEP_1, STEP_2, GAIN_1, GAIN_2, FIDELITY, PLUGIN_PORT_COUNT};

/**********************************************************************************************************************************************************/

Expand Down Expand Up @@ -48,6 +52,43 @@ class TwoVoices
Construct(n_samples, nBuffers, SampleRate, wisdomFile.c_str());
}

void SetFidelity(int fidelity, uint32_t n_samples)
{
switch (fidelity)
{
case 0:
if ((nBuffers) != nBuffersSW(n_samples,FIDELITY0))
{
Realloc(n_samples, nBuffersSW(n_samples,FIDELITY0));
return;
}
break;
case 1:
if ((nBuffers) != nBuffersSW(n_samples,FIDELITY1))
{
Realloc(n_samples, nBuffersSW(n_samples,FIDELITY1));
return;
}
break;
case 2:
if ((nBuffers) != nBuffersSW(n_samples,FIDELITY2))
{
Realloc(n_samples, nBuffersSW(n_samples,FIDELITY2));
return;
}
break;
case 3:
if ((nBuffers) != nBuffersSW(n_samples,FIDELITY3))
{
Realloc(n_samples, nBuffersSW(n_samples,FIDELITY3));
return;
}
break;
default:
break;
}
}

static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double samplerate, const char* bundle_path, const LV2_Feature* const* features);
static void activate(LV2_Handle instance);
static void deactivate(LV2_Handle instance);
Expand Down Expand Up @@ -97,7 +138,7 @@ LV2_Handle TwoVoices::instantiate(const LV2_Descriptor* descriptor, double sampl
{
std::string wisdomFile = bundle_path;
wisdomFile += "/harmonizer.wisdom";
TwoVoices *plugin = new TwoVoices(N_SAMPLES_DEFAULT, nBuffersSW(N_SAMPLES_DEFAULT,16,8,4,3), samplerate, wisdomFile);
TwoVoices *plugin = new TwoVoices(N_SAMPLES_DEFAULT, nBuffersSW(N_SAMPLES_DEFAULT,FIDELITY1), samplerate, wisdomFile);
return (LV2_Handle)plugin;
}

Expand Down Expand Up @@ -125,24 +166,22 @@ void TwoVoices::run(LV2_Handle instance, uint32_t n_samples)
TwoVoices *plugin;
plugin = (TwoVoices *) instance;

float *in = plugin->ports[IN];
float *out_1 = plugin->ports[OUT_1];
float *out_2 = plugin->ports[OUT_2];
double s_1 = (double)(*(plugin->ports[STEP_1]));
double s_2 = (double)(*(plugin->ports[STEP_2]));
double gain_1 = (double)(*(plugin->ports[GAIN_1]));
double gain_2 = (double)(*(plugin->ports[GAIN_2]));
float *in = plugin->ports[IN];
float *out_1 = plugin->ports[OUT_1];
float *out_2 = plugin->ports[OUT_2];
double s_1 = (double)(*(plugin->ports[STEP_1]));
double s_2 = (double)(*(plugin->ports[STEP_2]));
double gain_1 = (double)(*(plugin->ports[GAIN_1]));
double gain_2 = (double)(*(plugin->ports[GAIN_2]));
int fidelity = (int)(*(plugin->ports[FIDELITY]));

plugin->SetFidelity(fidelity, n_samples);

if ( (plugin->obja)->hopa != (int)n_samples )
{
plugin->Realloc(n_samples, nBuffersSW(n_samples,16,8,4,3));
plugin->Realloc(n_samples, nBuffersSW(n_samples,FIDELITY1));
return;
}

float sum_abs = 0;

for (uint32_t i=0; i<n_samples; i++)
sum_abs = sum_abs + abs(in[i]);

if (InputAbsSum(in, n_samples) == 0)
{
Expand Down
43 changes: 34 additions & 9 deletions 2Voices/ttl/2Voices.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix lv2: <http://lv2plug.in/ns/lv2core#>.
@prefix mod: <http://moddevices.com/ns/mod#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix units: <http://lv2plug.in/ns/extensions/units#>.

Expand Down Expand Up @@ -35,8 +36,17 @@ lv2:minorVersion 0;
lv2:microVersion 4;

rdfs:comment """
It's a pitch shifter which can rise the pitch until 4 semitones (steps).
Despite being more limited than Super Whammy it uses less processing.
If a MOD Drop and Mod SuperCapo had a baby, it would be the MOD 2Voices! It sports two outputs with independent pitch-shift controls. The pitch of the input signal can be shifted anywhere between -12 semitones down, and +24 semitones up.
Using a 2Voices plugin rather than both a Drop and a SuperCapo lowers the CPU load on the device.
All plugins in the MOD-pitchshifter family have an option to set the fidelity of the plugin. As you lower the fidelity, the sound will become less pristine, but the plugin will also use less processing. The opposite holds true for increasing the fidelity, this will grant you a clearer pitch-shifted signal at the cost of significantly more processing being used.
*The Lo-Fi setting is reminiscent of bit-crushed sounds, if you are looking for those synthesizer-like basslines, or dirty octave-up sounds, this is your setting!
*The Hi-Fi setting is great if you are looking to emulate (for example) something like a 12-string guitar, be sure to mind that CPU-meter in the bottom-right of the screen though!
*The settings in between are created to let you make the perfect trade-off between quality and performance.
A hint for making the right decision: the more you shift the pitch up, the higher you will need to set the Fidelity to get a clear sound.
""";

lv2:port
Expand All @@ -45,28 +55,28 @@ lv2:port
lv2:index 0;
lv2:symbol "In";
lv2:name "In";
lv2:shortname "In";
lv2:shortName "In";
],
[
a lv2:AudioPort, lv2:OutputPort;
lv2:index 1;
lv2:symbol "Out1";
lv2:name "Out 1";
lv2:shortname "Out 1";
lv2:shortName "Out 1";
],
[
a lv2:AudioPort, lv2:OutputPort;
lv2:index 2;
lv2:symbol "Out2";
lv2:name "Out 2";
lv2:shortname "Out 2";
lv2:shortName "Out 2";
],
[
a lv2:ControlPort, lv2:InputPort;
lv2:index 3;
lv2:symbol "Step1";
lv2:name "Step 1";
lv2:shortname "Step 1";
lv2:shortName "Step 1";
lv2:default 0;
lv2:minimum -12;
lv2:maximum 24;
Expand All @@ -77,7 +87,7 @@ lv2:port
lv2:index 4;
lv2:symbol "Step2";
lv2:name "Step 2";
lv2:shortname "Step 2";
lv2:shortName "Step 2";
lv2:default 0;
lv2:minimum -12;
lv2:maximum 24;
Expand All @@ -88,7 +98,7 @@ lv2:port
lv2:index 5;
lv2:symbol "Gain_1";
lv2:name "Gain 1";
lv2:shortname "Gain 1";
lv2:shortName "Gain 1";
lv2:default 3.0;
lv2:minimum -20.0;
lv2:maximum 20.0;
Expand All @@ -99,9 +109,24 @@ lv2:port
lv2:index 6;
lv2:symbol "Gain_2";
lv2:name "Gain 2";
lv2:shortname "Gain 2";
lv2:shortName "Gain 2";
lv2:default 3.0;
lv2:minimum -20.0;
lv2:maximum 20.0;
units:unit units:db;
],
[
a lv2:ControlPort, lv2:InputPort;
lv2:index 7;
lv2:symbol "Fidelity";
lv2:name "Fidelity";
lv2:shortname "Fidelity";
lv2:default 1;
lv2:minimum 0;
lv2:maximum 3;
lv2:portProperty lv2:integer, lv2:enumeration;
lv2:scalePoint [rdfs:label "Lo-Fi"; rdf:value 0];
lv2:scalePoint [rdfs:label "Medium"; rdf:value 1];
lv2:scalePoint [rdfs:label "High"; rdf:value 2];
lv2:scalePoint [rdfs:label "Hi-Fi"; rdf:value 3];
].
52 changes: 44 additions & 8 deletions Capo/src/Capo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

#define PLUGIN_URI "http://moddevices.com/plugins/mod-devel/Capo"
#define N_SAMPLES_DEFAULT 128
enum {IN, OUT, STEP, GAIN, PLUGIN_PORT_COUNT};
#define FIDELITY0 4,2,1,1
#define FIDELITY1 12,6,3,2
#define FIDELITY2 20,10,5,3
enum {IN, OUT, STEP, GAIN, FIDELITY, PLUGIN_PORT_COUNT};

/**********************************************************************************************************************************************************/

Expand Down Expand Up @@ -44,6 +47,36 @@ class Capo
Construct(n_samples, nBuffers, SampleRate, wisdomFile.c_str());
}

void SetFidelity(int fidelity, uint32_t n_samples)
{
switch (fidelity)
{
case 0:
if ((nBuffers) != nBuffersSW(n_samples,FIDELITY0))
{
Realloc(n_samples, nBuffersSW(n_samples,FIDELITY0));
return;
}
break;
case 1:
if ((nBuffers) != nBuffersSW(n_samples,FIDELITY1))
{
Realloc(n_samples, nBuffersSW(n_samples,FIDELITY1));
return;
}
break;
case 2:
if ((nBuffers) != nBuffersSW(n_samples,FIDELITY2))
{
Realloc(n_samples, nBuffersSW(n_samples,FIDELITY2));
return;
}
break;
default:
break;
}
}

static LV2_Handle instantiate(const LV2_Descriptor* descriptor, double samplerate, const char* bundle_path, const LV2_Feature* const* features);
static void activate(LV2_Handle instance);
static void deactivate(LV2_Handle instance);
Expand Down Expand Up @@ -91,7 +124,7 @@ LV2_Handle Capo::instantiate(const LV2_Descriptor* descriptor, double samplerate
{
std::string wisdomFile = bundle_path;
wisdomFile += "/harmonizer.wisdom";
Capo *plugin = new Capo(N_SAMPLES_DEFAULT, nBuffersSW(N_SAMPLES_DEFAULT,16,8,4,3), samplerate, wisdomFile);
Capo *plugin = new Capo(N_SAMPLES_DEFAULT, nBuffersSW(N_SAMPLES_DEFAULT,FIDELITY1), samplerate, wisdomFile);
return (LV2_Handle)plugin;
}

Expand All @@ -109,7 +142,7 @@ void Capo::connect_port(LV2_Handle instance, uint32_t port, void *data)
{
Capo *plugin;
plugin = (Capo *) instance;
plugin->ports[port] = (float*) data;
plugin->ports[port] = (float*) data;
}

/**********************************************************************************************************************************************************/
Expand All @@ -119,14 +152,17 @@ void Capo::run(LV2_Handle instance, uint32_t n_samples)
Capo *plugin;
plugin = (Capo *) instance;

float *in = plugin->ports[IN];
float *out = plugin->ports[OUT];
double s = (double)(*(plugin->ports[STEP]));
double gain = (double)(*(plugin->ports[GAIN]));
float *in = plugin->ports[IN];
float *out = plugin->ports[OUT];
double s = (double)(*(plugin->ports[STEP]));
double gain = (double)(*(plugin->ports[GAIN]));
int fidelity = (int)(*(plugin->ports[FIDELITY]));

plugin->SetFidelity(fidelity, n_samples);

if ( (plugin->obja)->hopa != (int)n_samples )
{
plugin->Realloc(n_samples, nBuffersSW(n_samples,16,8,4,3));
plugin->Realloc(n_samples, nBuffersSW(n_samples,FIDELITY1));
return;
}

Expand Down
35 changes: 29 additions & 6 deletions Capo/ttl/Capo.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#>.
@prefix mod: <http://moddevices.com/ns/mod#>.
@prefix modgui: <http://moddevices.com/ns/modgui#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix units: <http://lv2plug.in/ns/extensions/units#>.

Expand Down Expand Up @@ -36,7 +37,15 @@ lv2:minorVersion 0;
lv2:microVersion 4;

rdfs:comment """
It's a pitch shifter which can rise the pitch until 4 semitones (steps). Despite being more limited than Super Whammy, it uses less processing.
It’s a pitchshifter that can raise the pitch with a maximum of +12 semitones (steps). It is more limited than the SuperCapo, but it also uses less processing, allowing you to use the resources for more other plugins!
All plugins in the MOD-pitchshifter family have an option to set the fidelity of the plugin. As you lower the fidelity, the sound will become less pristine, but the plugin will also use less processing. The opposite holds true for increasing the fidelity, this will grant you a clearer pitch-shifted signal at the cost of significantly more processing being used.
*The Lo-Fi setting is reminiscent of bit-crushed sounds, if you are looking for those synthesizer-like basslines, or dirty octave-up sounds, this is your setting!
*The Hi-Fi setting is great if you are looking to emulate (for example) something like a 12-string guitar, be sure to mind that CPU-meter in the bottom-right of the screen though!
*The settings in between are created to let you make the perfect trade-off between quality and performance.
A hint for making the right decision: the more you shift the pitch up, the higher you will need to set the Fidelity to get a clear sound.
""";

lv2:port
Expand All @@ -45,36 +54,50 @@ lv2:port
lv2:index 0;
lv2:symbol "In";
lv2:name "In";
lv2:shortname "In";
lv2:shortName "In";
],
[
a lv2:AudioPort, lv2:OutputPort;
lv2:index 1;
lv2:symbol "Out";
lv2:name "Out";
lv2:shortname "Out";
lv2:shortName "Out";
],
[
a lv2:ControlPort, lv2:InputPort;
lv2:index 2;
lv2:symbol "Step";
lv2:name "Step";
lv2:shortname "Step";
lv2:shortName "Step";
lv2:default 0;
lv2:minimum 0;
lv2:maximum 4;
lv2:maximum 12;
lv2:portProperty lv2:integer;
],
[
a lv2:ControlPort, lv2:InputPort;
lv2:index 3;
lv2:symbol "Gain";
lv2:name "Gain";
lv2:shortname "Gain";
lv2:shortName "Gain";
lv2:default 3.0;
lv2:minimum -20.0;
lv2:maximum 20.0;
units:unit units:db;
],
[
a lv2:ControlPort, lv2:InputPort;
lv2:index 4;
lv2:symbol "Fidelity";
lv2:name "Fidelity";
lv2:shortname "Fidelity";
lv2:default 1;
lv2:minimum 0;
lv2:maximum 2;
lv2:portProperty lv2:integer, lv2:enumeration;
lv2:scalePoint [rdfs:label "Lo-Fi"; rdf:value 0];
lv2:scalePoint [rdfs:label "Normal"; rdf:value 1];
lv2:scalePoint [rdfs:label "Hi-Fi"; rdf:value 2];
];

modgui:gui [
Expand Down
2 changes: 1 addition & 1 deletion Capo/ttl/modgui/capo-stylesheet.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
}
.mod-capo .mod-knob {
position: absolute;
margin: 84px 36px;
margin: 84px 26px;
z-index: 100
}
.mod-capo .mod-knob .mod-knob-image {
Expand Down
Binary file modified Capo/ttl/modgui/slider-serial-capo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 57b2051

Please sign in to comment.