Browse Source

add zverb (WIP), simplify ttl generation

master
Alexandros Theodotou 2 years ago
parent
commit
88088c0004
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 7
      README.md
  2. 30
      plugins/chordz/ttl.h
  3. 30
      plugins/compressor/ttl.h
  4. 10
      plugins/meson.build
  5. 30
      plugins/saw/ttl.h
  6. 51
      plugins/ttl_gen.c
  7. 166
      plugins/verb/common.h
  8. 143
      plugins/verb/ttl.h
  9. 259
      plugins/verb/verb.c

7
README.md

@ -9,9 +9,10 @@ Zrythm DAW. @@ -9,9 +9,10 @@ Zrythm DAW.
Plugins
-------
- **Chordz** - plays chords using white keys
- **Compressor** - compressor
- **Saw** - a supersaw synth with 1 parameter
- **ZChordz** - plays chords using white keys
- **ZCompressor** - compressor
- **ZVerb** - reverb based on zita-rev
- **ZSaw** - a supersaw synth with 1 parameter
Dependencies
------------

30
plugins/chordz/ttl_gen.c → plugins/chordz/ttl.h

@ -17,31 +17,9 @@ @@ -17,31 +17,9 @@
* along with ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
#include PLUGIN_CONFIG
#include <stdio.h>
#include "common.h"
int main (
int argc, const char* argv[])
static void
print_ttl (FILE * f)
{
if (argc != 2)
{
fprintf (
stderr,
"Need 1 argument, received %d\n", argc - 1);
return -1;
}
FILE * f = fopen (argv[1], "w");
if (!f)
{
fprintf (
stderr, "Failed to open file %s\n", argv[1]);
return -1;
}
fprintf (f,
"@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n\
@prefix doap: <http://usefulinc.com/ns/doap#> .\n\
@ -198,8 +176,4 @@ int main ( @@ -198,8 +176,4 @@ int main (
lv2:name \"MIDI out\" ;\n\
rdfs:comment \"MIDI output\" ;\n\
] .\n\n", CHORDZ_MIDI_OUT);
fclose (f);
return 0;
}

30
plugins/compressor/ttl_gen.c → plugins/compressor/ttl.h

@ -17,31 +17,9 @@ @@ -17,31 +17,9 @@
* along with ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
#include PLUGIN_CONFIG
#include <stdio.h>
#include "common.h"
int main (
int argc, const char* argv[])
static void
print_ttl (FILE * f)
{
if (argc != 2)
{
fprintf (
stderr,
"Need 1 argument, received %d\n", argc - 1);
return -1;
}
FILE * f = fopen (argv[1], "w");
if (!f)
{
fprintf (
stderr, "Failed to open file %s\n", argv[1]);
return -1;
}
fprintf (f,
"@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n\
@prefix doap: <http://usefulinc.com/ns/doap#> .\n\
@ -162,8 +140,4 @@ int main ( @@ -162,8 +140,4 @@ int main (
1.0, 1.0, 40.0,
/* threshold */
0.0, -80.0, 0.0);
fclose (f);
return 0;
}

10
plugins/meson.build

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
plugins = [
['Chordz', 'MIDIPlugin', '1.0.0'],
['Compressor', 'CompressorPlugin', '1.0.0'],
['Verb', 'ReverbPlugin', '0.1.0'],
['Saw', 'InstrumentPlugin', '1.0.0'],
]
@ -68,6 +69,10 @@ foreach pl : plugins @@ -68,6 +69,10 @@ foreach pl : plugins
pl_cdata.get ('PLUGIN_URI'))
config_h_data.set_quoted (
'PLUGIN_TYPE', pl_type)
config_h_data.set_quoted (
'PLUGIN_COMMON', join_paths (pl_lowercase, 'common.h'))
config_h_data.set_quoted (
'PLUGIN_TTL_H', join_paths (pl_lowercase, 'ttl.h'))
config_h_data.set_quoted (
'INSTALL_PATH', pl_dir)
if get_option('buildtype') == 'release'
@ -135,10 +140,9 @@ foreach pl : plugins @@ -135,10 +140,9 @@ foreach pl : plugins
# create and install ttl
lv2_ttl_gen = executable (
pl_lowercase + 'ttl_gen',
pl_lowercase + '_ttl_gen',
sources: [
join_paths (
pl_lowercase, 'ttl_gen.c'),
'ttl_gen.c'
],
include_directories: pl_inc_dirs,
dependencies: lv2_dep,

30
plugins/saw/ttl_gen.c → plugins/saw/ttl.h

@ -17,31 +17,9 @@ @@ -17,31 +17,9 @@
* along with ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
#include PLUGIN_CONFIG
#include <stdio.h>
#include "common.h"
int main (
int argc, const char* argv[])
static void
print_ttl (FILE * f)
{
if (argc != 2)
{
fprintf (
stderr,
"Need 1 argument, received %d\n", argc - 1);
return -1;
}
FILE * f = fopen (argv[1], "w");
if (!f)
{
fprintf (
stderr, "Failed to open file %s\n", argv[1]);
return -1;
}
fprintf (f,
"@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n\
@prefix doap: <http://usefulinc.com/ns/doap#> .\n\
@ -110,8 +88,4 @@ int main ( @@ -110,8 +88,4 @@ int main (
lv2:symbol \"out_r\" ;\n\
lv2:name \"Stereo Out R\" ;\n\
] .\n\n", 0.12, 0.0, 1.0);
fclose (f);
return 0;
}

51
plugins/ttl_gen.c

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins 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.
*
* ZPlugins 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 ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
#include PLUGIN_CONFIG
#include <stdio.h>
#include PLUGIN_COMMON
#include PLUGIN_TTL_H
int main (
int argc, const char* argv[])
{
if (argc != 2)
{
fprintf (
stderr,
"Need 1 argument, received %d\n", argc - 1);
return -1;
}
FILE * f = fopen (argv[1], "w");
if (!f)
{
fprintf (
stderr, "Failed to open file %s\n", argv[1]);
return -1;
}
print_ttl (f);
fclose (f);
return 0;
}

166
plugins/verb/common.h

@ -0,0 +1,166 @@ @@ -0,0 +1,166 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins 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.
*
* ZPlugins 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 ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file
*
* Common code for both the DSP and the UI.
*/
#ifndef __Z_COMMON_H__
#define __Z_COMMON_H__
#include PLUGIN_CONFIG
#include <string.h>
#include "lv2/atom/atom.h"
#include "lv2/atom/forge.h"
#include "lv2/core/lv2.h"
#include "lv2/log/log.h"
#include "lv2/log/logger.h"
#include "lv2/midi/midi.h"
#include "lv2/urid/urid.h"
#include "lv2/time/time.h"
#include "lv2/worker/worker.h"
typedef struct CompressorUris
{
LV2_URID atom_eventTransfer;
LV2_URID atom_Blank;
LV2_URID atom_Object;
LV2_URID atom_Float;
LV2_URID atom_Double;
LV2_URID atom_Int;
LV2_URID atom_Long;
LV2_URID log_Entry;
LV2_URID log_Error;
LV2_URID log_Note;
LV2_URID log_Trace;
LV2_URID log_Warning;
} CompressorUris;
typedef enum PortIndex
{
/** GUI to plugin communication. */
COMPRESSOR_CONTROL,
/** Plugin to UI communication. */
COMPRESSOR_NOTIFY,
COMPRESSOR_STEREO_IN_L,
COMPRESSOR_STEREO_IN_R,
COMPRESSOR_ATTACK,
COMPRESSOR_RELEASE,
COMPRESSOR_RATIO,
COMPRESSOR_THRESHOLD,
/** Outputs. */
COMPRESSOR_STEREO_OUT_L,
COMPRESSOR_STEREO_OUT_R,
NUM_PORTS,
} PortIndex;
/**
* Group of variables needed by both the DSP and
* the UI.
*/
typedef struct CompressorCommon
{
/** Log feature. */
LV2_Log_Log * log;
/** Map feature. */
LV2_URID_Map * map;
/** Logger convenience API. */
LV2_Log_Logger logger;
/** Atom forge. */
LV2_Atom_Forge forge;
/** URIs. */
CompressorUris uris;
/** Plugin samplerate. */
double samplerate;
} CompressorCommon;
static inline void
map_uris (
LV2_URID_Map* map,
CompressorUris* uris)
{
#define MAP(x,uri) \
uris->x = map->map (map->handle, uri)
/* official URIs */
MAP (atom_Blank, LV2_ATOM__Blank);
MAP (atom_Object, LV2_ATOM__Object);
MAP (atom_Float, LV2_ATOM__Float);
MAP (atom_Double, LV2_ATOM__Double);
MAP (atom_Int, LV2_ATOM__Int);
MAP (atom_Long, LV2_ATOM__Long);
MAP (atom_eventTransfer, LV2_ATOM__eventTransfer);
MAP (log_Entry, LV2_LOG__Entry);
MAP (log_Error, LV2_LOG__Error);
MAP (log_Note, LV2_LOG__Note);
MAP (log_Trace, LV2_LOG__Trace);
MAP (log_Warning, LV2_LOG__Warning);
/* custom URIs */
//MAP (saw_freeValues, PLUGIN_URI "#freeValues");
//MAP (saw_calcValues, PLUGIN_URI "#calcValues");
}
#ifndef MAX
# define MAX(x,y) (x > y ? x : y)
#endif
#ifndef MIN
# define MIN(x,y) (x < y ? x : y)
#endif
#ifndef CLAMP
# define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#endif
/**
* Rounds a float to a given type.
*/
#define math_round_float_to_type(x,type) \
((type) (x + 0.5f - (x < 0.f)))
/**
* Rounds a float to an int.
*/
#define math_round_float_to_int(x) \
math_round_float_to_type (x,int)
/**
* Checks if 2 floats are equal.
*/
#define math_floats_equal(a,b) \
((a) > (b) ? \
(a) - (b) < FLT_EPSILON : \
(b) - (a) < FLT_EPSILON)
#endif

143
plugins/verb/ttl.h

@ -0,0 +1,143 @@ @@ -0,0 +1,143 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins 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.
*
* ZPlugins 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 ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
static void
print_ttl (FILE * f)
{
fprintf (f,
"@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n\
@prefix doap: <http://usefulinc.com/ns/doap#> .\n\
@prefix log: <http://lv2plug.in/ns/ext/log#> .\n\
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n\
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .\n\
@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .\n\
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n\
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\
@prefix rsz: <http://lv2plug.in/ns/ext/resize-port#> .\n\
@prefix time: <http://lv2plug.in/ns/ext/time#> .\n\
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .\n\
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .\n\
@prefix units: <http://lv2plug.in/ns/extensions/units#> .\n\
@prefix work: <http://lv2plug.in/ns/ext/worker#> .\n\n");
fprintf (f,
"<" PLUGIN_URI ">\n\
a lv2:Plugin,\n\
lv2:" PLUGIN_TYPE " ;\n\
doap:name \"" PLUGIN_NAME "\" ;\n\
doap:license <https://www.gnu.org/licenses/agpl-3.0.html> ;\n\
lv2:project <" PROJECT_URI "> ;\n\
lv2:requiredFeature urid:map ;\n\
lv2:optionalFeature log:log ,\n\
lv2:hardRTCapable ;\n\
lv2:port [\n\
a lv2:InputPort ,\n\
atom:AtomPort ;\n\
atom:bufferType atom:Sequence ;\n\
lv2:index 0 ;\n\
lv2:designation lv2:control ;\n\
lv2:symbol \"control\" ;\n\
lv2:name \"Control\" ;\n\
rdfs:comment \"GUI/host to plugin communication\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
atom:AtomPort ;\n\
atom:bufferType atom:Sequence ;\n\
lv2:index 1 ;\n\
lv2:designation lv2:control ;\n\
lv2:symbol \"notify\" ;\n\
lv2:name \"Notify\" ;\n\
rdfs:comment \"Plugin to GUI communication\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 2 ;\n\
lv2:symbol \"stereo_in_l\" ;\n\
lv2:name \"Stereo In L\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 3 ;\n\
lv2:symbol \"stereo_in_r\" ;\n\
lv2:name \"Stereo In L\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index 4 ;\n\
lv2:symbol \"attack\" ;\n\
lv2:name \"Attack\" ;\n\
lv2:default %f ;\n\
lv2:minimum %f ;\n\
lv2:maximum %f ;\n\
lv2:portProperty pprop:logarithmic; \n\
rdfs:comment \"Compressor attack\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index 5 ;\n\
lv2:symbol \"release\" ;\n\
lv2:name \"Release\" ;\n\
lv2:default %f ;\n\
lv2:minimum %f ;\n\
lv2:maximum %f ;\n\
lv2:portProperty pprop:logarithmic; \n\
rdfs:comment \"Compressor release\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index 6 ;\n\
lv2:symbol \"ratio\" ;\n\
lv2:name \"Ratio\" ;\n\
lv2:default %f ;\n\
lv2:minimum %f ;\n\
lv2:maximum %f ;\n\
rdfs:comment \"Ratio to compress with. A value > 1 will compress\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index 7 ;\n\
lv2:symbol \"threshold\" ;\n\
lv2:name \"Threshold\" ;\n\
lv2:default %f ;\n\
lv2:minimum %f ;\n\
lv2:maximum %f ;\n\
units:unit units:db ;\n\
rdfs:comment \"Threshold (in dB) 0 = max\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 8 ;\n\
lv2:symbol \"stereo_out_l\" ;\n\
lv2:name \"Stereo Out L\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 9 ;\n\
lv2:symbol \"stereo_out_r\" ;\n\
lv2:name \"Stereo Out R\" ;\n\
] .\n",
/* attack */
0.1, 0.000001, 10.0,
/* release */
0.1, 0.000001, 10.0,
/* ratio */
1.0, 1.0, 40.0,
/* threshold */
0.0, -80.0, 0.0);
}

259
plugins/verb/verb.c

@ -0,0 +1,259 @@ @@ -0,0 +1,259 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins 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.
*
* ZPlugins 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 ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "common.h"
#include "soundpipe.h"
typedef struct Compressor
{
/** Plugin ports. */
const LV2_Atom_Sequence* control;
LV2_Atom_Sequence* notify;
const float * stereo_in_l;
const float * stereo_in_r;
const float * attack;
const float * release;
const float * ratio;
const float * threshold;
/* outputs */
float * stereo_out_l;
float * stereo_out_r;
CompressorCommon common;
sp_data * sp;
sp_compressor * compressor;
} Compressor;
static LV2_Handle
instantiate (
const LV2_Descriptor* descriptor,
double rate,
const char* bundle_path,
const LV2_Feature* const* features)
{
Compressor * self = calloc (1, sizeof (Compressor));
self->common.samplerate = rate;
#define HAVE_FEATURE(x) \
(!strcmp(features[i]->URI, x))
for (int i = 0; features[i]; ++i)
{
if (HAVE_FEATURE (LV2_URID__map))
{
self->common.map =
(LV2_URID_Map*) features[i]->data;
}
else if (HAVE_FEATURE (LV2_LOG__log))
{
self->common.log =
(LV2_Log_Log *) features[i]->data;
}
}
#undef HAVE_FEATURE
if (!self->common.map)
{
lv2_log_error (
&self->common.logger, "Missing feature urid:map\n");
goto fail;
}
/* map uris */
map_uris (self->common.map, &self->common.uris);
/* init atom forge */
lv2_atom_forge_init (
&self->common.forge, self->common.map);
/* init logger */
lv2_log_logger_init (
&self->common.logger, self->common.map, self->common.log);
return (LV2_Handle) self;
fail:
free (self);
return NULL;
}
static void
connect_port (
LV2_Handle instance,
uint32_t port,
void * data)
{
Compressor * self = (Compressor *) instance;
switch ((PortIndex) port)
{
case COMPRESSOR_CONTROL:
self->control =
(const LV2_Atom_Sequence *) data;
break;
case COMPRESSOR_NOTIFY:
self->notify =
(LV2_Atom_Sequence *) data;
break;
case COMPRESSOR_STEREO_IN_L:
self->stereo_in_l = (const float *) data;
break;
case COMPRESSOR_STEREO_IN_R:
self->stereo_in_r = (const float *) data;
break;
case COMPRESSOR_ATTACK:
self->attack = (const float *) data;
break;
case COMPRESSOR_RELEASE:
self->release = (const float *) data;
break;
case COMPRESSOR_RATIO:
self->ratio = (const float *) data;
break;
case COMPRESSOR_THRESHOLD:
self->threshold = (const float *) data;
break;
case COMPRESSOR_STEREO_OUT_L:
self->stereo_out_l = (float *) data;
break;
case COMPRESSOR_STEREO_OUT_R:
self->stereo_out_r = (float *) data;
break;
default:
break;
}
}
static void
activate (
LV2_Handle instance)
{
Compressor * self = (Compressor*) instance;
sp_create (&self->sp);
sp_compressor_create (&self->compressor);
sp_compressor_init (self->sp, self->compressor);
}
static void
run (
LV2_Handle instance,
uint32_t n_samples)
{
Compressor * self = (Compressor *) instance;
#ifndef RELEASE
struct timeval tp;
gettimeofday(&tp, NULL);
long int ms = tp.tv_sec * 1000000 + tp.tv_usec;
#endif
/* read incoming events from host and UI */
LV2_ATOM_SEQUENCE_FOREACH (
self->control, ev)
{
/* TODO */
}
/* compress */
*self->compressor->ratio = *self->ratio;
*self->compressor->thresh = *self->threshold;
*self->compressor->atk = *self->attack;
*self->compressor->rel = *self->release;
for (uint32_t i = 0; i < n_samples; i++)
{
float current_in = self->stereo_in_l[i];
sp_compressor_compute (
self->sp, self->compressor,
&current_in, &self->stereo_out_l[i]);
current_in = self->stereo_in_r[i];
sp_compressor_compute (
self->sp, self->compressor,
&current_in, &self->stereo_out_r[i]);
}
#ifndef RELEASE
gettimeofday(&tp, NULL);
ms = (tp.tv_sec * 1000000 + tp.tv_usec) - ms;
printf("us taken %ld\n", ms);
#endif
}
static void
deactivate (
LV2_Handle instance)
{
Compressor * self = (Compressor *) instance;
sp_destroy (&self->sp);
sp_compressor_destroy (&self->compressor);
}
static void
cleanup (
LV2_Handle instance)
{
Compressor * self = (Compressor *) instance;
free (self);
}
static const void*
extension_data (
const char * uri)
{
return NULL;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
activate,
run,
deactivate,
cleanup,
extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor*
lv2_descriptor (
uint32_t index)
{
switch (index)
{
case 0:
return &descriptor;
default:
return NULL;
}
}
Loading…
Cancel
Save