Browse Source

add peak limiter

master
Alexandros Theodotou 3 years ago
parent
commit
c80fe4c0b7
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 1
      ext/Soundpipe/modules/meson.build
  2. 2
      meson_options.txt
  3. 2
      plugins/chordz/chordz.c
  4. 6
      plugins/compressor/compressor.c
  5. 2
      plugins/compressor/ttl.h
  6. 245
      plugins/limiter/limiter.c
  7. 87
      plugins/limiter/limiter_common.h
  8. 133
      plugins/limiter/ttl.h
  9. 1
      plugins/meson.build
  10. 2
      plugins/verb/verb.c

1
ext/Soundpipe/modules/meson.build

@ -21,6 +21,7 @@ soundpipe_module_files = files([ @@ -21,6 +21,7 @@ soundpipe_module_files = files([
'blsaw.c',
'compressor.c',
'dist.c',
'peaklim.c',
'spa.c',
'saturator.c',
'zitarev.c',

2
meson_options.txt

@ -26,7 +26,7 @@ option ( @@ -26,7 +26,7 @@ option (
option (
'plugins', type : 'array',
choices : [
'Chordz', 'Compressor', 'Verb', 'Saw'
'Chordz', 'Compressor', 'Limiter', 'Verb', 'Saw'
],
description: 'Plugins to build')

2
plugins/chordz/chordz.c

@ -85,7 +85,7 @@ instantiate ( @@ -85,7 +85,7 @@ instantiate (
PluginCommon * pl_common = &self->common.pl_common;
int ret =
plugin_common_instantiate (
pl_common, features, 1);
pl_common, features, 0);
if (ret)
goto fail;

6
plugins/compressor/compressor.c

@ -69,7 +69,7 @@ instantiate ( @@ -69,7 +69,7 @@ instantiate (
PluginCommon * pl_common = &self->common.pl_common;
int ret =
plugin_common_instantiate (
pl_common, features, 1);
pl_common, features, 0);
if (ret)
goto fail;
@ -162,7 +162,7 @@ run ( @@ -162,7 +162,7 @@ run (
return;
#endif
#ifndef RELEASE
#if 0
struct timeval tp;
gettimeofday(&tp, NULL);
long int ms = tp.tv_sec * 1000000 + tp.tv_usec;
@ -192,7 +192,7 @@ run ( @@ -192,7 +192,7 @@ run (
&current_in, &self->stereo_out_r[i]);
}
#ifndef RELEASE
#if 0
gettimeofday(&tp, NULL);
ms = (tp.tv_sec * 1000000 + tp.tv_usec) - ms;
printf("us taken %ld\n", ms);

2
plugins/compressor/ttl.h

@ -118,7 +118,7 @@ print_ttl (FILE * f) @@ -118,7 +118,7 @@ print_ttl (FILE * f)
lv2:minimum %f ;\n\
lv2:maximum %f ;\n\
units:unit units:db ;\n\
rdfs:comment \"Threshold (in dB) 0 = max\" ;\n\
rdfs:comment \"Threshold (0 = max)\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
lv2:AudioPort ;\n\

245
plugins/limiter/limiter.c

@ -0,0 +1,245 @@ @@ -0,0 +1,245 @@
/*
* 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 <float.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "../math.h"
#include PLUGIN_COMMON
#include "soundpipe.h"
typedef struct Limiter
{
/** 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 * threshold;
/* outputs */
float * stereo_out_l;
float * stereo_out_r;
LimiterCommon common;
sp_data * sp;
sp_peaklim * limiter;
} Limiter;
static LV2_Handle
instantiate (
const LV2_Descriptor* descriptor,
double rate,
const char* bundle_path,
const LV2_Feature* const* features)
{
Limiter * self = calloc (1, sizeof (Limiter));
SET_SAMPLERATE (self, rate);
PluginCommon * pl_common = &self->common.pl_common;
int ret =
plugin_common_instantiate (
pl_common, features, false);
if (ret)
goto fail;
/* map uris */
map_uris (pl_common->map, &self->common);
/* init atom forge */
lv2_atom_forge_init (
&pl_common->forge, pl_common->map);
/* init logger */
lv2_log_logger_init (
&pl_common->logger, pl_common->map, pl_common->log);
return (LV2_Handle) self;
fail:
free (self);
return NULL;
}
static void
connect_port (
LV2_Handle instance,
uint32_t port,
void * data)
{
Limiter * self = (Limiter *) instance;
switch ((PortIndex) port)
{
case LIMITER_CONTROL:
self->control =
(const LV2_Atom_Sequence *) data;
break;
case LIMITER_NOTIFY:
self->notify =
(LV2_Atom_Sequence *) data;
break;
case LIMITER_STEREO_IN_L:
self->stereo_in_l = (const float *) data;
break;
case LIMITER_STEREO_IN_R:
self->stereo_in_r = (const float *) data;
break;
case LIMITER_ATTACK:
self->attack = (const float *) data;
break;
case LIMITER_RELEASE:
self->release = (const float *) data;
break;
case LIMITER_THRESHOLD:
self->threshold = (const float *) data;
break;
case LIMITER_STEREO_OUT_L:
self->stereo_out_l = (float *) data;
break;
case LIMITER_STEREO_OUT_R:
self->stereo_out_r = (float *) data;
break;
default:
break;
}
}
static void
activate (
LV2_Handle instance)
{
Limiter * self = (Limiter*) instance;
sp_create (&self->sp);
sp_peaklim_create (&self->limiter);
sp_peaklim_init (self->sp, self->limiter);
}
static void
run (
LV2_Handle instance,
uint32_t n_samples)
{
Limiter * self = (Limiter *) instance;
#ifdef TRIAL_VER
if (get_time_since_instantiation (
&self->common.pl_common) > SECONDS_TO_SILENCE)
return;
#endif
#if 0
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->limiter->thresh = *self->threshold;
self->limiter->atk = *self->attack;
self->limiter->rel = *self->release;
for (uint32_t i = 0; i < n_samples; i++)
{
float current_in = self->stereo_in_l[i];
sp_peaklim_compute (
self->sp, self->limiter,
&current_in, &self->stereo_out_l[i]);
current_in = self->stereo_in_r[i];
sp_peaklim_compute (
self->sp, self->limiter,
&current_in, &self->stereo_out_r[i]);
}
#if 0
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)
{
Limiter * self = (Limiter *) instance;
sp_destroy (&self->sp);
sp_peaklim_destroy (&self->limiter);
}
static void
cleanup (
LV2_Handle instance)
{
Limiter * self = (Limiter *) 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;
}
}

87
plugins/limiter/limiter_common.h

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
/*
* 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_COMPRESSOR_COMMON_H__
#define __Z_COMPRESSOR_COMMON_H__
#include PLUGIN_CONFIG
#include "../common.h"
typedef struct LimiterUris
{
} LimiterUris;
typedef enum PortIndex
{
/** GUI to plugin communication. */
LIMITER_CONTROL,
/** Plugin to UI communication. */
LIMITER_NOTIFY,
LIMITER_STEREO_IN_L,
LIMITER_STEREO_IN_R,
LIMITER_ATTACK,
LIMITER_RELEASE,
LIMITER_THRESHOLD,
/** Outputs. */
LIMITER_STEREO_OUT_L,
LIMITER_STEREO_OUT_R,
NUM_PORTS,
} PortIndex;
/**
* Group of variables needed by both the DSP and
* the UI.
*/
typedef struct LimiterCommon
{
/** URIs. */
LimiterUris uris;
PluginCommon pl_common;
} LimiterCommon;
static inline void
map_uris (
LV2_URID_Map* urid_map,
LimiterCommon * limiter_common)
{
map_common_uris (
urid_map, &limiter_common->pl_common.uris);
#define MAP(x,uri) \
limiter_common->uris.x = \
urid_map->map (urid_map->handle, uri)
/* custom URIs */
#undef MAP
}
#endif

133
plugins/limiter/ttl.h

@ -0,0 +1,133 @@ @@ -0,0 +1,133 @@
/*
* 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 R\" ;\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\
units:unit units:s ;\n\
rdfs:comment \"Attack time\" ;\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\
units:unit units:s ;\n\
rdfs:comment \"Release time\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index 6 ;\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\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 7 ;\n\
lv2:symbol \"stereo_out_l\" ;\n\
lv2:name \"Stereo Out L\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 8 ;\n\
lv2:symbol \"stereo_out_r\" ;\n\
lv2:name \"Stereo Out R\" ;\n\
] .\n",
/* attack */
0.01, 0.000001, 1.0,
/* release */
0.1, 0.000001, 1.0,
/* threshold */
0.0, -40.0, 3.0);
}

1
plugins/meson.build

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
plugins = [
['Chordz', 'MIDIPlugin', '1.0.0'],
['Compressor', 'CompressorPlugin', '1.0.0'],
['Limiter', 'LimiterPlugin', '0.0.1'],
['Verb', 'ReverbPlugin', '0.1.0'],
['Saw', 'InstrumentPlugin', '1.0.0'],
]

2
plugins/verb/verb.c

@ -76,7 +76,7 @@ instantiate ( @@ -76,7 +76,7 @@ instantiate (
PluginCommon * pl_common = &self->common.pl_common;
int ret =
plugin_common_instantiate (
pl_common, features, 1);
pl_common, features, false);
if (ret)
goto fail;

Loading…
Cancel
Save