|
|
|
@ -1,20 +1,20 @@
@@ -1,20 +1,20 @@
|
|
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2019-2020 Alexandros Theodotou <alex at zrythm dot org> |
|
|
|
|
* |
|
|
|
|
* This file is part of ZSuperSaw |
|
|
|
|
* This file is part of ZSaw |
|
|
|
|
* |
|
|
|
|
* ZSuperSaw is free software: you can redistribute it and/or modify |
|
|
|
|
* ZSaw is free software: you can redistribute it and/or modify |
|
|
|
|
* it under the terms of the GNU Affero General Public License as |
|
|
|
|
* published by the Free Software Foundation, either version 3 of the |
|
|
|
|
* License, or (at your option) any later version. |
|
|
|
|
* |
|
|
|
|
* ZSuperSaw is distributed in the hope that it will be useful, |
|
|
|
|
* ZSaw is distributed in the hope that it will be useful, |
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
|
* GNU Affero General Public License for more details. |
|
|
|
|
* |
|
|
|
|
* You should have received a copy of the GNU General Affero Public License |
|
|
|
|
* along with ZSuperSaw. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
* along with ZSaw. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include <float.h> |
|
|
|
@ -53,13 +53,33 @@ typedef struct MidiKey
@@ -53,13 +53,33 @@ typedef struct MidiKey
|
|
|
|
|
} MidiKey; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* One voice per active key. |
|
|
|
|
* Worker data. |
|
|
|
|
*/ |
|
|
|
|
/*typedef struct Voice*/ |
|
|
|
|
/*{*/ |
|
|
|
|
/*} Voice;*/ |
|
|
|
|
typedef struct SawValues |
|
|
|
|
{ |
|
|
|
|
float attack; |
|
|
|
|
float decay; |
|
|
|
|
float sustain; |
|
|
|
|
float release; |
|
|
|
|
|
|
|
|
|
float saturator_drive; |
|
|
|
|
float saturator_dcoffset; |
|
|
|
|
float distortion_shape1; |
|
|
|
|
float distortion_shape2; |
|
|
|
|
float reverb_mix; |
|
|
|
|
float keyfreqs[128][7]; |
|
|
|
|
} SawValues; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Atom message. |
|
|
|
|
*/ |
|
|
|
|
typedef struct SawValuesMessage |
|
|
|
|
{ |
|
|
|
|
LV2_Atom atom; |
|
|
|
|
SawValues * values; |
|
|
|
|
} SawValuesMessage; |
|
|
|
|
|
|
|
|
|
typedef struct SuperSaw |
|
|
|
|
typedef struct Saw |
|
|
|
|
{ |
|
|
|
|
/** Plugin ports. */ |
|
|
|
|
const LV2_Atom_Sequence* control; |
|
|
|
@ -73,11 +93,11 @@ typedef struct SuperSaw
@@ -73,11 +93,11 @@ typedef struct SuperSaw
|
|
|
|
|
/** Events in the queue. */ |
|
|
|
|
MidiKey keys[128]; |
|
|
|
|
|
|
|
|
|
/** Current values based on \ref SuperSaw.amount. */ |
|
|
|
|
float attack; |
|
|
|
|
float decay; |
|
|
|
|
float sustain; |
|
|
|
|
float release; |
|
|
|
|
/** Current values based on \ref Saw.amount. */ |
|
|
|
|
/*float attack;*/ |
|
|
|
|
/*float decay;*/ |
|
|
|
|
/*float sustain;*/ |
|
|
|
|
/*float release;*/ |
|
|
|
|
/*int num_voices;*/ |
|
|
|
|
|
|
|
|
|
sp_saturator * saturator; |
|
|
|
@ -85,11 +105,170 @@ typedef struct SuperSaw
@@ -85,11 +105,170 @@ typedef struct SuperSaw
|
|
|
|
|
sp_zitarev * reverb; |
|
|
|
|
sp_data * sp; |
|
|
|
|
|
|
|
|
|
SuperSawCommon common; |
|
|
|
|
SawCommon common; |
|
|
|
|
|
|
|
|
|
SawValues * values; |
|
|
|
|
|
|
|
|
|
/* cache */ |
|
|
|
|
float last_amount; |
|
|
|
|
} SuperSaw; |
|
|
|
|
} Saw; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* To be called by the worker function. |
|
|
|
|
*/ |
|
|
|
|
static SawValues * |
|
|
|
|
calc_values ( |
|
|
|
|
Saw * self) |
|
|
|
|
{ |
|
|
|
|
lv2_log_note ( |
|
|
|
|
&self->common.logger, "calculating values\n"); |
|
|
|
|
SawValues * values = calloc (1, sizeof (SawValues)); |
|
|
|
|
|
|
|
|
|
values->attack = 0.02f; |
|
|
|
|
values->decay = 0.04f + *self->amount * 0.4f; |
|
|
|
|
values->sustain = 0.5f; |
|
|
|
|
values->release = 0.04f + *self->amount * 0.4f; |
|
|
|
|
values->saturator_drive = *self->amount * 0.3f; |
|
|
|
|
values->saturator_dcoffset = *self->amount * 0.3f; |
|
|
|
|
values->distortion_shape1 = *self->amount * 0.2f; |
|
|
|
|
values->distortion_shape2 = *self->amount * 0.2f; |
|
|
|
|
values->reverb_mix = *self->amount * 0.5f; |
|
|
|
|
|
|
|
|
|
float freq_delta = |
|
|
|
|
(*self->amount + 0.4f * (1.f - *self->amount)) * |
|
|
|
|
2.4f; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 128; i++) |
|
|
|
|
{ |
|
|
|
|
for (int j = 0; j < 7; j++) |
|
|
|
|
{ |
|
|
|
|
/* voice spread */ |
|
|
|
|
int is_even = (j % 2) == 0; |
|
|
|
|
float freq_apart; |
|
|
|
|
if (is_even) |
|
|
|
|
{ |
|
|
|
|
freq_apart = (float) (j / 2) * freq_delta; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
freq_apart = (float) (j / 2 + 1) * - freq_delta; |
|
|
|
|
} |
|
|
|
|
values->keyfreqs[i][j] = |
|
|
|
|
self->keys[i].base_freq + |
|
|
|
|
math_round_float_to_int (freq_apart); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return values; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Cleanup function after work is finished. |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
free_values ( |
|
|
|
|
Saw * self, |
|
|
|
|
SawValues * values) |
|
|
|
|
{ |
|
|
|
|
lv2_log_note ( |
|
|
|
|
&self->common.logger, "freeing values\n"); |
|
|
|
|
free (values); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the values from the SawValues struct on the |
|
|
|
|
* actual plugin. |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
set_values ( |
|
|
|
|
Saw * self, |
|
|
|
|
SawValues * values) |
|
|
|
|
{ |
|
|
|
|
lv2_log_note ( |
|
|
|
|
&self->common.logger, "setting values\n"); |
|
|
|
|
self->saturator->drive = values->saturator_drive; |
|
|
|
|
self->saturator->dcoffset = values->saturator_dcoffset; |
|
|
|
|
self->distortion->shape1 = values->distortion_shape1; |
|
|
|
|
self->distortion->shape2 = values->distortion_shape2; |
|
|
|
|
*self->reverb->mix = values->reverb_mix; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 128; i++) |
|
|
|
|
{ |
|
|
|
|
MidiKey * key = &self->keys[i]; |
|
|
|
|
|
|
|
|
|
/* adsr */ |
|
|
|
|
key->adsr->atk = values->attack; |
|
|
|
|
key->adsr->dec = values->decay; |
|
|
|
|
key->adsr->sus = values->sustain; |
|
|
|
|
key->adsr->rel = values->release; |
|
|
|
|
|
|
|
|
|
for (int j = 0; j < 7; j++) |
|
|
|
|
{ |
|
|
|
|
/* spread voices */ |
|
|
|
|
*key->blsaws[j]->freq = values->keyfreqs[i][j]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static LV2_Worker_Status |
|
|
|
|
work ( |
|
|
|
|
LV2_Handle instance, |
|
|
|
|
LV2_Worker_Respond_Function respond, |
|
|
|
|
LV2_Worker_Respond_Handle handle, |
|
|
|
|
uint32_t size, |
|
|
|
|
const void * data) |
|
|
|
|
{ |
|
|
|
|
Saw * self = (Saw *) instance; |
|
|
|
|
|
|
|
|
|
lv2_log_note ( |
|
|
|
|
&self->common.logger, "working\n"); |
|
|
|
|
const LV2_Atom * atom = |
|
|
|
|
(const LV2_Atom *) data; |
|
|
|
|
if (atom->type == self->common.uris.saw_freeValues) |
|
|
|
|
{ |
|
|
|
|
/* free old values */ |
|
|
|
|
const SawValuesMessage * msg = |
|
|
|
|
(const SawValuesMessage *) data; |
|
|
|
|
free_values (self, msg->values); |
|
|
|
|
} |
|
|
|
|
else if (atom->type == self->common.uris.saw_calcValues) |
|
|
|
|
{ |
|
|
|
|
/* recalc values */ |
|
|
|
|
SawValues * values = calc_values (self); |
|
|
|
|
respond (handle, sizeof (values), &values); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return LV2_WORKER_SUCCESS; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static LV2_Worker_Status |
|
|
|
|
work_response ( |
|
|
|
|
LV2_Handle instance, |
|
|
|
|
uint32_t size, |
|
|
|
|
const void* data) |
|
|
|
|
{ |
|
|
|
|
Saw * self = (Saw *) instance; |
|
|
|
|
|
|
|
|
|
/* install the new values */ |
|
|
|
|
SawValues * values = * (SawValues * const *) data; |
|
|
|
|
set_values (self, values); |
|
|
|
|
|
|
|
|
|
/* send a message to the worker to free the
|
|
|
|
|
* values */ |
|
|
|
|
SawValuesMessage msg = { |
|
|
|
|
{ sizeof (SawValues *), |
|
|
|
|
self->common.uris.saw_freeValues }, |
|
|
|
|
values }; |
|
|
|
|
|
|
|
|
|
self->common.schedule->schedule_work ( |
|
|
|
|
self->common.schedule->handle, |
|
|
|
|
sizeof (msg), &msg); |
|
|
|
|
lv2_log_note ( |
|
|
|
|
&self->common.logger, "inside work response\n"); |
|
|
|
|
|
|
|
|
|
return LV2_WORKER_SUCCESS; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static LV2_Handle |
|
|
|
|
instantiate ( |
|
|
|
@ -98,7 +277,7 @@ instantiate (
@@ -98,7 +277,7 @@ instantiate (
|
|
|
|
|
const char* bundle_path, |
|
|
|
|
const LV2_Feature* const* features) |
|
|
|
|
{ |
|
|
|
|
SuperSaw * self = calloc (1, sizeof (SuperSaw)); |
|
|
|
|
Saw * self = calloc (1, sizeof (Saw)); |
|
|
|
|
|
|
|
|
|
self->common.samplerate = rate; |
|
|
|
|
|
|
|
|
@ -112,6 +291,11 @@ instantiate (
@@ -112,6 +291,11 @@ instantiate (
|
|
|
|
|
self->common.map = |
|
|
|
|
(LV2_URID_Map*) features[i]->data; |
|
|
|
|
} |
|
|
|
|
else if (HAVE_FEATURE (LV2_WORKER__schedule)) |
|
|
|
|
{ |
|
|
|
|
self->common.schedule = |
|
|
|
|
(LV2_Worker_Schedule *) features[i]->data; |
|
|
|
|
} |
|
|
|
|
else if (HAVE_FEATURE (LV2_LOG__log)) |
|
|
|
|
{ |
|
|
|
|
self->common.log = |
|
|
|
@ -122,8 +306,16 @@ instantiate (
@@ -122,8 +306,16 @@ instantiate (
|
|
|
|
|
|
|
|
|
|
if (!self->common.map) |
|
|
|
|
{ |
|
|
|
|
fprintf (stderr, "Missing feature urid:map\n"); |
|
|
|
|
return NULL; |
|
|
|
|
lv2_log_error ( |
|
|
|
|
&self->common.logger, "Missing feature urid:map\n"); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
else if (!self->common.schedule) |
|
|
|
|
{ |
|
|
|
|
lv2_log_error ( |
|
|
|
|
&self->common.logger, |
|
|
|
|
"Missing feature work:schedule\n"); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* map uris */ |
|
|
|
@ -133,97 +325,11 @@ instantiate (
@@ -133,97 +325,11 @@ instantiate (
|
|
|
|
|
lv2_atom_forge_init ( |
|
|
|
|
&self->common.forge, self->common.map); |
|
|
|
|
|
|
|
|
|
return (LV2_Handle) self; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
connect_port ( |
|
|
|
|
LV2_Handle instance, |
|
|
|
|
uint32_t port, |
|
|
|
|
void * data) |
|
|
|
|
{ |
|
|
|
|
SuperSaw * self = (SuperSaw*) instance; |
|
|
|
|
|
|
|
|
|
switch ((PortIndex) port) |
|
|
|
|
{ |
|
|
|
|
case SUPERSAW_CONTROL: |
|
|
|
|
self->control = |
|
|
|
|
(const LV2_Atom_Sequence *) data; |
|
|
|
|
break; |
|
|
|
|
case SUPERSAW_NOTIFY: |
|
|
|
|
self->notify = |
|
|
|
|
(LV2_Atom_Sequence *) data; |
|
|
|
|
break; |
|
|
|
|
case SUPERSAW_AMOUNT: |
|
|
|
|
self->amount = (const float *) data; |
|
|
|
|
break; |
|
|
|
|
case SUPERSAW_STEREO_OUT_L: |
|
|
|
|
self->stereo_out_l = (float *) data; |
|
|
|
|
break; |
|
|
|
|
case SUPERSAW_STEREO_OUT_R: |
|
|
|
|
self->stereo_out_r = (float *) data; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* To be called when the amount changes. |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
recalc_values ( |
|
|
|
|
SuperSaw * self) |
|
|
|
|
{ |
|
|
|
|
self->attack = 0.02f; |
|
|
|
|
self->decay = 0.04f + *self->amount * 0.4f; |
|
|
|
|
self->sustain = 0.5f; |
|
|
|
|
self->release = 0.04f + *self->amount * 0.4f; |
|
|
|
|
self->saturator->drive = *self->amount * 0.3f; |
|
|
|
|
self->saturator->dcoffset = *self->amount * 0.3f; |
|
|
|
|
self->distortion->shape1 = *self->amount * 0.2f; |
|
|
|
|
self->distortion->shape2 = *self->amount * 0.2f; |
|
|
|
|
*self->reverb->mix = *self->amount * 0.5f; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 128; i++) |
|
|
|
|
{ |
|
|
|
|
MidiKey * key = &self->keys[i]; |
|
|
|
|
|
|
|
|
|
/* adsr */ |
|
|
|
|
key->adsr->atk = self->attack; |
|
|
|
|
key->adsr->dec = self->decay; |
|
|
|
|
key->adsr->sus = self->sustain; |
|
|
|
|
key->adsr->rel = self->release; |
|
|
|
|
|
|
|
|
|
for (int j = 0; j < 7; j++) |
|
|
|
|
{ |
|
|
|
|
/* voice spread */ |
|
|
|
|
int is_even = (j % 2) == 0; |
|
|
|
|
float freq_apart; |
|
|
|
|
float freq_delta = |
|
|
|
|
(*self->amount + 0.4f * (1.f - *self->amount)) * |
|
|
|
|
2.4f; |
|
|
|
|
if (is_even) |
|
|
|
|
{ |
|
|
|
|
freq_apart = (float) (j / 2) * freq_delta; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
freq_apart = (float) (j / 2 + 1) * - freq_delta; |
|
|
|
|
} |
|
|
|
|
*key->blsaws[j]->freq = |
|
|
|
|
key->base_freq + |
|
|
|
|
math_round_float_to_int (freq_apart); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
activate ( |
|
|
|
|
LV2_Handle instance) |
|
|
|
|
{ |
|
|
|
|
SuperSaw * self = (SuperSaw*) instance; |
|
|
|
|
/* init logger */ |
|
|
|
|
lv2_log_logger_init ( |
|
|
|
|
&self->common.logger, self->common.map, self->common.log); |
|
|
|
|
|
|
|
|
|
/* create synth */ |
|
|
|
|
srand (time (NULL)); |
|
|
|
|
for (int i = 0; i < 128; i++) |
|
|
|
|
{ |
|
|
|
@ -284,7 +390,55 @@ activate (
@@ -284,7 +390,55 @@ activate (
|
|
|
|
|
sp_zitarev_init (self->sp, self->reverb); |
|
|
|
|
*self->reverb->level = 0.f; |
|
|
|
|
|
|
|
|
|
recalc_values (self); |
|
|
|
|
return (LV2_Handle) self; |
|
|
|
|
|
|
|
|
|
fail: |
|
|
|
|
free (self); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
connect_port ( |
|
|
|
|
LV2_Handle instance, |
|
|
|
|
uint32_t port, |
|
|
|
|
void * data) |
|
|
|
|
{ |
|
|
|
|
Saw * self = (Saw*) instance; |
|
|
|
|
|
|
|
|
|
switch ((PortIndex) port) |
|
|
|
|
{ |
|
|
|
|
case SUPERSAW_CONTROL: |
|
|
|
|
self->control = |
|
|
|
|
(const LV2_Atom_Sequence *) data; |
|
|
|
|
break; |
|
|
|
|
case SUPERSAW_NOTIFY: |
|
|
|
|
self->notify = |
|
|
|
|
(LV2_Atom_Sequence *) data; |
|
|
|
|
break; |
|
|
|
|
case SUPERSAW_AMOUNT: |
|
|
|
|
self->amount = (const float *) data; |
|
|
|
|
break; |
|
|
|
|
case SUPERSAW_STEREO_OUT_L: |
|
|
|
|
self->stereo_out_l = (float *) data; |
|
|
|
|
break; |
|
|
|
|
case SUPERSAW_STEREO_OUT_R: |
|
|
|
|
self->stereo_out_r = (float *) data; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
activate ( |
|
|
|
|
LV2_Handle instance) |
|
|
|
|
{ |
|
|
|
|
Saw * self = (Saw*) instance; |
|
|
|
|
|
|
|
|
|
/* load the default values */ |
|
|
|
|
SawValues * values = calc_values (self); |
|
|
|
|
set_values (self, values); |
|
|
|
|
free_values (self, values); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -292,11 +446,13 @@ activate (
@@ -292,11 +446,13 @@ activate (
|
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
process ( |
|
|
|
|
SuperSaw * self, |
|
|
|
|
Saw * self, |
|
|
|
|
uint32_t * offset) |
|
|
|
|
{ |
|
|
|
|
self->stereo_out_l[*offset] = 0.f; |
|
|
|
|
self->stereo_out_r[*offset] = 0.f; |
|
|
|
|
float * current_l = &self->stereo_out_l[*offset]; |
|
|
|
|
float * current_r = &self->stereo_out_r[*offset]; |
|
|
|
|
*current_l = 0.f; |
|
|
|
|
*current_r = 0.f; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 128; i++) |
|
|
|
|
{ |
|
|
|
@ -333,13 +489,13 @@ process (
@@ -333,13 +489,13 @@ process (
|
|
|
|
|
|
|
|
|
|
if (j % 2 == 0) |
|
|
|
|
{ |
|
|
|
|
self->stereo_out_l[*offset] += val * 0.8f; |
|
|
|
|
self->stereo_out_r[*offset] += val * 0.2f; |
|
|
|
|
*current_l += val * 0.8f; |
|
|
|
|
*current_r += val * 0.2f; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
self->stereo_out_l[*offset] += val * 0.2f; |
|
|
|
|
self->stereo_out_r[*offset] += val * 0.8f; |
|
|
|
|
*current_l += val * 0.2f; |
|
|
|
|
*current_r += val * 0.8f; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -347,37 +503,38 @@ process (
@@ -347,37 +503,38 @@ process (
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
/* saturate */ |
|
|
|
|
float saturated = 0; |
|
|
|
|
sp_saturator_compute ( |
|
|
|
|
self->sp, self->saturator, &self->stereo_out_l[*offset], |
|
|
|
|
&saturated); |
|
|
|
|
self->stereo_out_l[*offset] += saturated; |
|
|
|
|
sp_saturator_compute ( |
|
|
|
|
self->sp, self->saturator, &self->stereo_out_r[*offset], |
|
|
|
|
&saturated); |
|
|
|
|
self->stereo_out_r[*offset] += saturated; |
|
|
|
|
#endif |
|
|
|
|
/* saturate - for some reason it makes noise when it's
|
|
|
|
|
* silent */ |
|
|
|
|
if (fabsf (*current_l) > 0.001f || |
|
|
|
|
fabsf (*current_r) > 0.001f) |
|
|
|
|
{ |
|
|
|
|
float saturated = 0; |
|
|
|
|
sp_saturator_compute ( |
|
|
|
|
self->sp, self->saturator, current_l, |
|
|
|
|
&saturated); |
|
|
|
|
*current_l += saturated; |
|
|
|
|
sp_saturator_compute ( |
|
|
|
|
self->sp, self->saturator, current_r, |
|
|
|
|
&saturated); |
|
|
|
|
*current_r += saturated; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* distort */ |
|
|
|
|
float distortion = 0; |
|
|
|
|
sp_dist_compute ( |
|
|
|
|
self->sp, self->distortion, &self->stereo_out_l[*offset], |
|
|
|
|
self->sp, self->distortion, current_l, |
|
|
|
|
&distortion); |
|
|
|
|
self->stereo_out_l[*offset] += distortion; |
|
|
|
|
*current_l += distortion; |
|
|
|
|
sp_dist_compute ( |
|
|
|
|
self->sp, self->distortion, &self->stereo_out_r[*offset], |
|
|
|
|
self->sp, self->distortion, current_r, |
|
|
|
|
&distortion); |
|
|
|
|
self->stereo_out_r[*offset] += distortion; |
|
|
|
|
*current_r += distortion; |
|
|
|
|
|
|
|
|
|
/* reverb */ |
|
|
|
|
sp_zitarev_compute ( |
|
|
|
|
self->sp, self->reverb, |
|
|
|
|
&self->stereo_out_l[*offset], |
|
|
|
|
&self->stereo_out_r[*offset], |
|
|
|
|
&self->stereo_out_l[*offset], |
|
|
|
|
&self->stereo_out_r[*offset]); |
|
|
|
|
current_l, current_r, |
|
|
|
|
current_l, current_r); |
|
|
|
|
|
|
|
|
|
(*offset)++; |
|
|
|
|
} |
|
|
|
@ -387,13 +544,24 @@ run (
@@ -387,13 +544,24 @@ run (
|
|
|
|
|
LV2_Handle instance, |
|
|
|
|
uint32_t n_samples) |
|
|
|
|
{ |
|
|
|
|
SuperSaw * self = (SuperSaw *) instance; |
|
|
|
|
Saw * self = (Saw *) instance; |
|
|
|
|
|
|
|
|
|
uint32_t processed = 0; |
|
|
|
|
|
|
|
|
|
if (!math_floats_equal (self->last_amount, *self->amount)) |
|
|
|
|
{ |
|
|
|
|
recalc_values (self); |
|
|
|
|
/* send a message to the worker to calculate new
|
|
|
|
|
* values */ |
|
|
|
|
SawValuesMessage msg = { |
|
|
|
|
{ 0, |
|
|
|
|
self->common.uris.saw_calcValues } |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
self->common.schedule->schedule_work ( |
|
|
|
|
self->common.schedule->handle, |
|
|
|
|
sizeof (msg), &msg); |
|
|
|
|
lv2_log_note ( |
|
|
|
|
&self->common.logger, "scheduled to recalculate\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* read incoming events from host and UI */ |
|
|
|
@ -450,7 +618,7 @@ static void
@@ -450,7 +618,7 @@ static void
|
|
|
|
|
deactivate ( |
|
|
|
|
LV2_Handle instance) |
|
|
|
|
{ |
|
|
|
|
SuperSaw * self = (SuperSaw *) instance; |
|
|
|
|
Saw * self = (Saw *) instance; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 128; i++) |
|
|
|
|
{ |
|
|
|
@ -467,13 +635,20 @@ static void
@@ -467,13 +635,20 @@ static void
|
|
|
|
|
cleanup ( |
|
|
|
|
LV2_Handle instance) |
|
|
|
|
{ |
|
|
|
|
free (instance); |
|
|
|
|
Saw * self = (Saw *) instance; |
|
|
|
|
free (self); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const void* |
|
|
|
|
extension_data ( |
|
|
|
|
const char* uri) |
|
|
|
|
const char * uri) |
|
|
|
|
{ |
|
|
|
|
static const LV2_Worker_Interface worker = |
|
|
|
|
{ work, work_response, NULL }; |
|
|
|
|
if (!strcmp(uri, LV2_WORKER__interface)) |
|
|
|
|
{ |
|
|
|
|
return &worker; |
|
|
|
|
} |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|