Fully featured LFO for CV-based automation (unmaintained - use zplugins)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

303 lines
5.9 KiB

/*
* Copyright (C) 2019-2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZLFO
*
* ZLFO 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.
*
* ZLFO 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 ZLFO. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file
*
* Common code for both the DSP and the UI.
*/
#ifndef __Z_LFO_COMMON_H__
#define __Z_LFO_COMMON_H__
#include "config.h"
#include <math.h>
#include <string.h>
#include "lv2/atom/atom.h"
#include "lv2/log/log.h"
#include "lv2/urid/urid.h"
/** Min, max and default frequency. */
#define MIN_FREQ 0.1f
#define DEF_FREQ 1.f
#define MAX_FREQ 20.f
typedef struct ZLfoUris
{
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;
/* custom URIs */
LV2_URID ui_state;
LV2_URID ui_on;
LV2_URID ui_off;
LV2_URID ui_state_current_sample;
LV2_URID ui_state_samplerate;
} ZLfoUris;
typedef enum PortIndex
{
/** GUI to plugin communication. */
ZLFO_CONTROL,
/** Plugin to UI communication. */
ZLFO_NOTIFY,
ZLFO_CV_GATE,
ZLFO_CV_TRIGGER,
ZLFO_GATE,
ZLFO_TRIGGER,
ZLFO_SYNC_RATE,
ZLFO_SYNC_RATE_TYPE,
ZLFO_FREQ,
ZLFO_SHIFT,
ZLFO_RANGE_MIN,
ZLFO_RANGE_MAX,
ZLFO_STEP_MODE,
ZLFO_FREE_RUNNING,
ZLFO_HINVERT,
ZLFO_VINVERT,
ZLFO_NODE_1_POS,
ZLFO_NODE_1_VAL,
ZLFO_NODE_1_CURVE,
ZLFO_NODE_2_POS,
ZLFO_NODE_2_VAL,
ZLFO_NODE_2_CURVE,
ZLFO_NODE_3_POS,
ZLFO_NODE_3_VAL,
ZLFO_NODE_3_CURVE,
ZLFO_NODE_4_POS,
ZLFO_NODE_4_VAL,
ZLFO_NODE_4_CURVE,
ZLFO_NODE_5_POS,
ZLFO_NODE_5_VAL,
ZLFO_NODE_5_CURVE,
ZLFO_NODE_6_POS,
ZLFO_NODE_6_VAL,
ZLFO_NODE_6_CURVE,
ZLFO_NODE_7_POS,
ZLFO_NODE_7_VAL,
ZLFO_NODE_7_CURVE,
ZLFO_NODE_8_POS,
ZLFO_NODE_8_VAL,
ZLFO_NODE_8_CURVE,
ZLFO_NODE_9_POS,
ZLFO_NODE_9_VAL,
ZLFO_NODE_9_CURVE,
ZLFO_NODE_10_POS,
ZLFO_NODE_10_VAL,
ZLFO_NODE_10_CURVE,
ZLFO_NODE_11_POS,
ZLFO_NODE_11_VAL,
ZLFO_NODE_11_CURVE,
ZLFO_NODE_12_POS,
ZLFO_NODE_12_VAL,
ZLFO_NODE_12_CURVE,
ZLFO_NODE_13_POS,
ZLFO_NODE_13_VAL,
ZLFO_NODE_13_CURVE,
ZLFO_NODE_14_POS,
ZLFO_NODE_14_VAL,
ZLFO_NODE_14_CURVE,
ZLFO_NODE_15_POS,
ZLFO_NODE_15_VAL,
ZLFO_NODE_15_CURVE,
ZLFO_NODE_16_POS,
ZLFO_NODE_16_VAL,
ZLFO_NODE_16_CURVE,
ZLFO_NUM_NODES,
ZLFO_SINE_OUT,
ZLFO_TRIANGLE_OUT,
ZLFO_SAW_OUT,
ZLFO_SQUARE_OUT,
ZLFO_RND_OUT,
ZLFO_CUSTOM_OUT,
NUM_ZLFO_PORTS,
} PortIndex;
typedef enum SyncRate
{
SYNC_1_128,
SYNC_1_64,
SYNC_1_32,
SYNC_1_16,
SYNC_1_8,
SYNC_1_4,
SYNC_1_2,
SYNC_1_1,
SYNC_2_1,
SYNC_4_1,
NUM_SYNC_RATES,
} SyncRate;
typedef enum SyncRateType
{
SYNC_TYPE_NORMAL,
SYNC_TYPE_DOTTED,
SYNC_TYPE_TRIPLET,
NUM_SYNC_RATE_TYPES,
} SyncRateType;
typedef enum CurveAlgorithm
{
CURVE_ALGORITHM_EXPONENT,
CURVE_ALGORITHM_SUPERELLIPSE,
} CurveAlgorithm;
static inline void
map_uris (
LV2_URID_Map* map,
ZLfoUris* uris)
{
#define MAP(x,uri) \
uris->x = map->map (map->handle, uri)
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);
MAP (ui_on, LFO_URI "#ui_on");
MAP (ui_off, LFO_URI "#ui_off");
MAP (ui_state, LFO_URI "#ui_state");
MAP (
ui_state_current_sample,
LFO_URI "#ui_state_current_sample");
MAP (
ui_state_samplerate,
LFO_URI "#ui_state_samplerate");
}
/**
* Logs an error.
*/
static inline void
log_error (
LV2_Log_Log * log,
ZLfoUris * uris,
const char * _fmt,
...)
{
va_list args;
va_start (args, _fmt);
char fmt[900];
strcpy (fmt, _fmt);
strcat (fmt, "\n");
if (log)
{
log->vprintf (
log->handle, uris->log_Error,
fmt, args);
}
else
{
vfprintf (stderr, fmt, args);
}
va_end (args);
}
/**
* Gets the y value for a node at the given X coord.
*
* See https://stackoverflow.com/questions/17623152/how-map-tween-a-number-based-on-a-dynamic-curve
* @param x X-coordinate.
* @param curviness Curviness variable (1.0 is
* a straight line, 0.0 is full curved).
* @param start_higher Start at higher point.
*/
double
get_y_normalized (
double x,
double curviness,
CurveAlgorithm algo,
int start_higher,
int curve_up);
#ifdef pow
double
get_y_normalized (
double x,
double curviness,
CurveAlgorithm algo,
int start_higher,
int curve_up)
{
if (!start_higher)
x = 1.0 - x;
if (curve_up)
x = 1.0 - x;
double val;
switch (algo)
{
case CURVE_ALGORITHM_EXPONENT:
val =
pow (x, curviness);
break;
case CURVE_ALGORITHM_SUPERELLIPSE:
val =
pow (
1.0 - pow (x, curviness),
(1.0 / curviness));
break;
}
if (curve_up)
{
val = 1.0 - val;
}
return val;
fprintf (
stderr, "This line should not be reached");
}
#endif
#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
#endif