shithub: soundpipe

Download patch

ref: 74c207afba3b7bf6533b4a5a8bc3022136eb2855
parent: 4c66535a76024eb5098ae62199308011babf3d68
author: Paul Batchelor <thisispaulbatchelor@gmail.com>
date: Fri Mar 26 13:28:57 EDT 2021

verbity: initial import

--- a/config.def.mk
+++ b/config.def.mk
@@ -86,6 +86,7 @@
 phasewarp \
 tread \
 oscmorph \
+verbity \
 
 TANGLED += \
 tangled/osc.o \
--- /dev/null
+++ b/h/verbity.h
@@ -1,0 +1,96 @@
+typedef struct {
+    SPFLOAT bigness;
+    SPFLOAT longness;
+    SPFLOAT darkness;
+
+	SPFLOAT iirAL;
+	SPFLOAT iirBL;
+
+	SPFLOAT aIL[6480];
+	SPFLOAT aJL[3660];
+	SPFLOAT aKL[1720];
+	SPFLOAT aLL[680];
+
+	SPFLOAT aAL[9700];
+	SPFLOAT aBL[6000];
+	SPFLOAT aCL[2320];
+	SPFLOAT aDL[940];
+
+	SPFLOAT aEL[15220];
+	SPFLOAT aFL[8460];
+	SPFLOAT aGL[4540];
+	SPFLOAT aHL[3200];
+
+	SPFLOAT feedbackAL;
+	SPFLOAT feedbackBL;
+	SPFLOAT feedbackCL;
+	SPFLOAT feedbackDL;
+	SPFLOAT previousAL;
+	SPFLOAT previousBL;
+	SPFLOAT previousCL;
+	SPFLOAT previousDL;
+
+	SPFLOAT lastRefL[7];
+	SPFLOAT thunderL;
+
+	SPFLOAT iirAR;
+	SPFLOAT iirBR;
+
+	SPFLOAT aIR[6480];
+	SPFLOAT aJR[3660];
+	SPFLOAT aKR[1720];
+	SPFLOAT aLR[680];
+
+	SPFLOAT aAR[9700];
+	SPFLOAT aBR[6000];
+	SPFLOAT aCR[2320];
+	SPFLOAT aDR[940];
+
+	SPFLOAT aER[15220];
+	SPFLOAT aFR[8460];
+	SPFLOAT aGR[4540];
+	SPFLOAT aHR[3200];
+
+	SPFLOAT feedbackAR;
+	SPFLOAT feedbackBR;
+	SPFLOAT feedbackCR;
+	SPFLOAT feedbackDR;
+	SPFLOAT previousAR;
+	SPFLOAT previousBR;
+	SPFLOAT previousCR;
+	SPFLOAT previousDR;
+
+	SPFLOAT lastRefR[7];
+	SPFLOAT thunderR;
+
+	int countA, delayA;
+	int countB, delayB;
+	int countC, delayC;
+	int countD, delayD;
+	int countE, delayE;
+	int countF, delayF;
+	int countG, delayG;
+	int countH, delayH;
+	int countI, delayI;
+	int countJ, delayJ;
+	int countK, delayK;
+	int countL, delayL;
+	int cycle;
+
+    int sr;
+
+    SPFLOAT psize;
+    SPFLOAT onedsr;
+} sp_verbity;
+
+int sp_verbity_create(sp_verbity **v);
+int sp_verbity_destroy(sp_verbity **v);
+int sp_verbity_init(sp_data *sp, sp_verbity *v);
+int sp_verbity_compute(sp_data *sp,
+                       sp_verbity *v,
+                       SPFLOAT *inL, SPFLOAT *inR,
+                       SPFLOAT *outL, SPFLOAT *outR);
+void sp_verbity_bigness(sp_verbity *c, SPFLOAT bigness);
+void sp_verbity_longness(sp_verbity *c, SPFLOAT longness);
+void sp_verbity_darkness(sp_verbity *c, SPFLOAT darkness);
+void sp_verbity_reset(sp_verbity *v, int sr);
--- /dev/null
+++ b/modules/verbity.c
@@ -1,0 +1,491 @@
+/*
+ * Verbity
+ *
+ * This is a self-contained ANSI-C soundpipe port of the
+ * Verbity
+ * VST plugin by Chris Johnson of AirWindows:
+ *
+ * http://www.airwindows.com/verbity/
+ *
+ * In addition to the C++->C rewrites, a few notable
+ * adjustments have been made to the
+ * algorithm. Wet/Dry control has been removed in favor
+ * of 100% wet (balance can be done externally).
+ * The dithering has been taken out as well (empirically,
+ * this seemed to be a CPU hog).
+ *
+ * The original C++ code is under an MIT license
+ * (same license as Soundpipe), Copyright 2021 Chris
+ * Johnson.
+ *
+ * If you like this plugin, please please please consider
+ * supporting Chris and AirWindows via Patreon:
+ * https://www.patreon.com/airwindows
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "soundpipe.h"
+
+int sp_verbity_create(sp_verbity **p)
+{
+    *p = malloc(sizeof(sp_verbity));
+    return SP_OK;
+}
+
+int sp_verbity_destroy(sp_verbity **p)
+{
+    free(*p);
+    return SP_OK;
+}
+
+void sp_verbity_reset(sp_verbity *v, int sr)
+{
+    int count;
+
+    v->sr = sr;
+
+	v->bigness = 0.25;
+	v->longness = 0.0;
+	v->darkness = 0.25;
+
+	v->iirAL = 0.0;
+    v->iirAR = 0.0;
+
+	v->iirBL = 0.0;
+    v->iirBR = 0.0;
+
+	for (count = 0; count < 6479; count++) {
+        v->aIL[count] = 0.0;
+        v->aIR[count] = 0.0;
+    }
+
+	for (count = 0; count < 3659; count++) {
+        v->aJL[count] = 0.0;
+        v->aJR[count] = 0.0;
+    }
+
+	for (count = 0; count < 1719; count++) {
+        v->aKL[count] = 0.0;
+        v->aKR[count] = 0.0;
+    }
+
+	for (count = 0; count < 679; count++) {
+        v->aLL[count] = 0.0;
+        v->aLR[count] = 0.0;
+    }
+
+	for (count = 0; count < 9699; count++) {
+        v->aAL[count] = 0.0;
+        v->aAR[count] = 0.0;
+    }
+
+	for (count = 0; count < 5999; count++) {
+        v->aBL[count] = 0.0;
+        v->aBR[count] = 0.0;
+    }
+
+	for (count = 0; count < 2319; count++) {
+        v->aCL[count] = 0.0;
+        v->aCR[count] = 0.0;
+    }
+
+	for (count = 0; count < 939; count++) {
+        v->aDL[count] = 0.0;
+        v->aDR[count] = 0.0;
+    }
+
+	for (count = 0; count < 15219; count++) {
+        v->aEL[count] = 0.0;
+        v->aER[count] = 0.0;
+    }
+
+	for (count = 0; count < 8459; count++) {
+        v->aFL[count] = 0.0;
+        v->aFR[count] = 0.0;
+    }
+
+	for (count = 0; count < 4539; count++) {
+        v->aGL[count] = 0.0;
+        v->aGR[count] = 0.0;
+    }
+
+	for (count = 0; count < 3199; count++) {
+        v->aHL[count] = 0.0;
+        v->aHR[count] = 0.0;
+    }
+
+	v->feedbackAL = 0.0; v->feedbackAR = 0.0;
+	v->feedbackBL = 0.0; v->feedbackBR = 0.0;
+	v->feedbackCL = 0.0; v->feedbackCR = 0.0;
+	v->feedbackDL = 0.0; v->feedbackDR = 0.0;
+	v->previousAL = 0.0; v->previousAR = 0.0;
+	v->previousBL = 0.0; v->previousBR = 0.0;
+	v->previousCL = 0.0; v->previousCR = 0.0;
+	v->previousDL = 0.0; v->previousDR = 0.0;
+
+	for (count = 0; count < 6; count++) {
+        v->lastRefL[count] = 0.0;
+        v->lastRefR[count] = 0.0;
+    }
+
+	v->thunderL = 0;
+    v->thunderR = 0;
+
+	v->countI = 1;
+	v->countJ = 1;
+	v->countK = 1;
+	v->countL = 1;
+
+	v->countA = 1;
+	v->countB = 1;
+	v->countC = 1;
+	v->countD = 1;
+
+	v->countE = 1;
+	v->countF = 1;
+	v->countG = 1;
+	v->countH = 1;
+	v->cycle = 0;
+
+    v->psize = -1;
+    v->onedsr = 1.0 / sr;
+}
+
+int sp_verbity_init(sp_data *sp, sp_verbity *v)
+{
+    sp_verbity_reset(v, sp->sr);
+    return SP_OK;
+}
+
+int sp_verbity_compute(sp_data *sp,
+                       sp_verbity *v,
+                       SPFLOAT *inL, SPFLOAT *inR,
+                       SPFLOAT *outL, SPFLOAT *outR)
+{
+	SPFLOAT overallscale;
+	int cycleEnd;
+	SPFLOAT size;
+	SPFLOAT regen;
+	SPFLOAT lowpass;
+	SPFLOAT interpolate;
+	SPFLOAT thunderAmount;
+    SPFLOAT inputSampleL;
+    SPFLOAT inputSampleR;
+
+    overallscale = 1.0;
+	overallscale *= v->onedsr;
+	overallscale *= v->sr;
+
+	cycleEnd = floor(overallscale);
+	if (cycleEnd < 1) cycleEnd = 1;
+	if (cycleEnd > 4) cycleEnd = 4;
+
+	/* this is going to be 2 for 88.1 or 96k,
+     * 3 for silly people, 4 for 176 or 192k
+     */
+
+    /* sanity check */
+	if (v->cycle > cycleEnd-1) v->cycle = cycleEnd-1;
+
+	size = (v->bigness*1.77)+0.1;
+	regen = 0.0625+(v->longness*0.03125); /* 0.09375 max; */
+	lowpass = (1.0-pow(v->darkness,2.0))/sqrt(overallscale);
+	interpolate = pow(v->darkness,2.0)*0.618033988749894848204586; /* has IIRlike qualities */
+	thunderAmount = (0.3-(v->longness*0.22))*v->darkness*0.1;
+
+    if (size != v->psize) {
+        v->psize = size;
+        v->delayI = 3407.0*size;
+        v->delayJ = 1823.0*size;
+        v->delayK = 859.0*size;
+        v->delayL = 331.0*size;
+
+        v->delayA = 4801.0*size;
+        v->delayB = 2909.0*size;
+        v->delayC = 1153.0*size;
+        v->delayD = 461.0*size;
+
+        v->delayE = 7607.0*size;
+        v->delayF = 4217.0*size;
+        v->delayG = 2269.0*size;
+        v->delayH = 1597.0*size;
+    }
+
+    inputSampleL = *inL;
+    inputSampleR = *inR;
+
+    if (fabs(v->iirAL)<1.18e-37) v->iirAL = 0.0;
+    v->iirAL =
+        (v->iirAL*(1.0-lowpass)) +
+        (inputSampleL*lowpass);
+    inputSampleL = v->iirAL;
+
+    if (fabs(v->iirAR)<1.18e-37) v->iirAR = 0.0;
+    v->iirAR =
+        (v->iirAR*(1.0-lowpass))+
+        (inputSampleR*lowpass);
+    inputSampleR = v->iirAR;
+
+    /* initial filter */
+
+    v->cycle++;
+    if (v->cycle == cycleEnd) {
+        /* hit the end point and we do a reverb sample */
+        SPFLOAT ainterp = 1.0 - interpolate;
+        v->feedbackAL = (v->feedbackAL*(ainterp))+
+            (v->previousAL*interpolate);
+        v->previousAL = v->feedbackAL;
+        v->feedbackBL = (v->feedbackBL*(ainterp))+
+            (v->previousBL*interpolate);
+        v->previousBL = v->feedbackBL;
+        v->feedbackCL = (v->feedbackCL*(ainterp))+
+            (v->previousCL*interpolate);
+        v->previousCL = v->feedbackCL;
+        v->feedbackDL = (v->feedbackDL*(ainterp))+
+            (v->previousDL*interpolate);
+        v->previousDL = v->feedbackDL;
+        v->feedbackAR = (v->feedbackAR*(ainterp))+
+            (v->previousAR*interpolate);
+        v->previousAR = v->feedbackAR;
+
+        v->feedbackBR = (v->feedbackBR*(ainterp))+
+            (v->previousBR*interpolate);
+        v->previousBR = v->feedbackBR;
+        v->feedbackCR = (v->feedbackCR*(ainterp))+
+            (v->previousCR*interpolate);
+        v->previousCR = v->feedbackCR;
+        v->feedbackDR = (v->feedbackDR*(ainterp))+
+            (v->previousDR*interpolate);
+        v->previousDR = v->feedbackDR;
+
+        v->thunderL =
+            (v->thunderL*0.99)-(v->feedbackAL*thunderAmount);
+        v->thunderR =
+            (v->thunderR*0.99)-(v->feedbackAR*thunderAmount);
+
+        v->aIL[v->countI] = inputSampleL +
+            ((v->feedbackAL+v->thunderL) * regen);
+        v->aJL[v->countJ] = inputSampleL +
+            (v->feedbackBL * regen);
+        v->aKL[v->countK] = inputSampleL +
+            (v->feedbackCL * regen);
+        v->aLL[v->countL] = inputSampleL +
+            (v->feedbackDL * regen);
+        v->aIR[v->countI] = inputSampleR +
+            ((v->feedbackAR+v->thunderR) * regen);
+
+        v->aJR[v->countJ] = inputSampleR +
+            (v->feedbackBR * regen);
+        v->aKR[v->countK] = inputSampleR +
+            (v->feedbackCR * regen);
+        v->aLR[v->countL] = inputSampleR +
+            (v->feedbackDR * regen);
+
+        v->countI++;
+        if (v->countI < 0 || v->countI > v->delayI) v->countI = 0;
+
+        v->countJ++;
+        if (v->countJ < 0 || v->countJ > v->delayJ) v->countJ = 0;
+
+        v->countK++;
+        if (v->countK < 0 || v->countK > v->delayK) v->countK = 0;
+
+        v->countL++;
+        if (v->countL < 0 || v->countL > v->delayL) v->countL = 0;
+
+        {
+            SPFLOAT outIL = v->aIL[v->countI-((v->countI > v->delayI)?v->delayI+1:0)];
+            SPFLOAT outJL = v->aJL[v->countJ-((v->countJ > v->delayJ)?v->delayJ+1:0)];
+            SPFLOAT outKL = v->aKL[v->countK-((v->countK > v->delayK)?v->delayK+1:0)];
+            SPFLOAT outLL = v->aLL[v->countL-((v->countL > v->delayL)?v->delayL+1:0)];
+            SPFLOAT outIR = v->aIR[v->countI-((v->countI > v->delayI)?v->delayI+1:0)];
+            SPFLOAT outJR = v->aJR[v->countJ-((v->countJ > v->delayJ)?v->delayJ+1:0)];
+            SPFLOAT outKR = v->aKR[v->countK-((v->countK > v->delayK)?v->delayK+1:0)];
+            SPFLOAT outLR = v->aLR[v->countL-((v->countL > v->delayL)?v->delayL+1:0)];
+            /* first block: now we have four outputs */
+
+            v->aAL[v->countA] = (outIL - (outJL + outKL + outLL));
+            v->aBL[v->countB] = (outJL - (outIL + outKL + outLL));
+            v->aCL[v->countC] = (outKL - (outIL + outJL + outLL));
+            v->aDL[v->countD] = (outLL - (outIL + outJL + outKL));
+            v->aAR[v->countA] = (outIR - (outJR + outKR + outLR));
+            v->aBR[v->countB] = (outJR - (outIR + outKR + outLR));
+            v->aCR[v->countC] = (outKR - (outIR + outJR + outLR));
+            v->aDR[v->countD] = (outLR - (outIR + outJR + outKR));
+        }
+
+        v->countA++;
+        if (v->countA < 0 || v->countA > v->delayA) v->countA = 0;
+        v->countB++;
+        if (v->countB < 0 || v->countB > v->delayB) v->countB = 0;
+        v->countC++;
+        if (v->countC < 0 || v->countC > v->delayC) v->countC = 0;
+        v->countD++;
+        if (v->countD < 0 || v->countD > v->delayD) v->countD = 0;
+
+        {
+            SPFLOAT outAL = v->aAL[v->countA-((v->countA > v->delayA)?v->delayA+1:0)];
+            SPFLOAT outBL = v->aBL[v->countB-((v->countB > v->delayB)?v->delayB+1:0)];
+            SPFLOAT outCL = v->aCL[v->countC-((v->countC > v->delayC)?v->delayC+1:0)];
+            SPFLOAT outDL = v->aDL[v->countD-((v->countD > v->delayD)?v->delayD+1:0)];
+            SPFLOAT outAR = v->aAR[v->countA-((v->countA > v->delayA)?v->delayA+1:0)];
+            SPFLOAT outBR = v->aBR[v->countB-((v->countB > v->delayB)?v->delayB+1:0)];
+            SPFLOAT outCR = v->aCR[v->countC-((v->countC > v->delayC)?v->delayC+1:0)];
+            SPFLOAT outDR = v->aDR[v->countD-((v->countD > v->delayD)?v->delayD+1:0)];
+
+            /* second block: four more outputs */
+
+            v->aEL[v->countE] = (outAL - (outBL + outCL + outDL));
+            v->aFL[v->countF] = (outBL - (outAL + outCL + outDL));
+            v->aGL[v->countG] = (outCL - (outAL + outBL + outDL));
+            v->aHL[v->countH] = (outDL - (outAL + outBL + outCL));
+            v->aER[v->countE] = (outAR - (outBR + outCR + outDR));
+            v->aFR[v->countF] = (outBR - (outAR + outCR + outDR));
+            v->aGR[v->countG] = (outCR - (outAR + outBR + outDR));
+            v->aHR[v->countH] = (outDR - (outAR + outBR + outCR));
+        }
+
+        v->countE++;
+        if (v->countE < 0 || v->countE > v->delayE) v->countE = 0;
+
+        v->countF++;
+        if (v->countF < 0 || v->countF > v->delayF) v->countF = 0;
+
+        v->countG++;
+        if (v->countG < 0 || v->countG > v->delayG) v->countG = 0;
+
+        v->countH++;
+        if (v->countH < 0 || v->countH > v->delayH) v->countH = 0;
+
+        {
+            SPFLOAT outEL = v->aEL[v->countE-((v->countE > v->delayE)?v->delayE+1:0)];
+            SPFLOAT outFL = v->aFL[v->countF-((v->countF > v->delayF)?v->delayF+1:0)];
+            SPFLOAT outGL = v->aGL[v->countG-((v->countG > v->delayG)?v->delayG+1:0)];
+            SPFLOAT outHL = v->aHL[v->countH-((v->countH > v->delayH)?v->delayH+1:0)];
+            SPFLOAT outER = v->aER[v->countE-((v->countE > v->delayE)?v->delayE+1:0)];
+            SPFLOAT outFR = v->aFR[v->countF-((v->countF > v->delayF)?v->delayF+1:0)];
+            SPFLOAT outGR = v->aGR[v->countG-((v->countG > v->delayG)?v->delayG+1:0)];
+            SPFLOAT outHR = v->aHR[v->countH-((v->countH > v->delayH)?v->delayH+1:0)];
+            /* third block: final outputs */
+
+            v->feedbackAL = (outEL - (outFL + outGL + outHL));
+            v->feedbackBL = (outFL - (outEL + outGL + outHL));
+            v->feedbackCL = (outGL - (outEL + outFL + outHL));
+            v->feedbackDL = (outHL - (outEL + outFL + outGL));
+            v->feedbackAR = (outER - (outFR + outGR + outHR));
+            v->feedbackBR = (outFR - (outER + outGR + outHR));
+            v->feedbackCR = (outGR - (outER + outFR + outHR));
+            v->feedbackDR = (outHR - (outER + outFR + outGR));
+
+            /* which we need to feed back into the input again, a bit */
+
+            inputSampleL = (outEL + outFL + outGL + outHL) * 0.125;
+            inputSampleR = (outER + outFR + outGR + outHR) * 0.125;
+        }
+
+        /* and take the final combined sum of outputs */
+        if (cycleEnd == 4) {
+            /* start from previous last */
+            v->lastRefL[0] = v->lastRefL[4];
+
+            /* half */
+            v->lastRefL[2] = (v->lastRefL[0] + inputSampleL) * 0.5;
+
+            /* one quarter */
+            v->lastRefL[1] = (v->lastRefL[0] + v->lastRefL[2]) * 0.5;
+
+            /* three quarters */
+            v->lastRefL[3] = (v->lastRefL[2] + inputSampleL) * 0.5;
+
+            /* full */
+            v->lastRefL[4] = inputSampleL;
+
+            /* start from previous last */
+            v->lastRefR[0] = v->lastRefR[4];
+
+            /* half */
+            v->lastRefR[2] = (v->lastRefR[0] + inputSampleR) * 0.5;
+
+            /* one quarter */
+            v->lastRefR[1] = (v->lastRefR[0] + v->lastRefR[2]) * 0.5;
+            /* three quarters */
+            v->lastRefR[3] = (v->lastRefR[2] + inputSampleR) * 0.5;
+            /* full */
+            v->lastRefR[4] = inputSampleR;
+        }
+        if (cycleEnd == 3) {
+            /* start from previous last */
+            v->lastRefL[0] = v->lastRefL[3];
+            /* third */
+            v->lastRefL[2] = (v->lastRefL[0]+v->lastRefL[0]+inputSampleL) * 0.33333;
+            /* two thirds */
+            v->lastRefL[1] = (v->lastRefL[0]+inputSampleL+inputSampleL) * 0.33333;
+            /* full */
+            v->lastRefL[3] = inputSampleL;
+            /* start from previous last */
+            v->lastRefR[0] = v->lastRefR[3];
+
+            /* third */
+            v->lastRefR[2] = (v->lastRefR[0]+v->lastRefR[0]+inputSampleR) * 0.33333;
+            /* two thirds */
+            v->lastRefR[1] = (v->lastRefR[0]+inputSampleR+inputSampleR) * 0.33333;
+
+            /* full */
+            v->lastRefR[3] = inputSampleR;
+        }
+
+        if (cycleEnd == 2) {
+            /* start from previous last */
+            v->lastRefL[0] = v->lastRefL[2];
+            /* half */
+            v->lastRefL[1] = (v->lastRefL[0] + inputSampleL) * 0.5;
+            /* full */
+            v->lastRefL[2] = inputSampleL;
+
+            /* start from previous last */
+            v->lastRefR[0] = v->lastRefR[2];
+
+            /* half */
+            v->lastRefR[1] = (v->lastRefR[0] + inputSampleR) * 0.5;
+
+            /* full */
+            v->lastRefR[2] = inputSampleR;
+        }
+        v->cycle = 0; /* reset */
+    } else {
+        inputSampleL = v->lastRefL[v->cycle];
+        inputSampleR = v->lastRefR[v->cycle];
+        /* we are going through our references now */
+    }
+
+    if (fabs(v->iirBL)<1.18e-37) v->iirBL = 0.0;
+    v->iirBL = (v->iirBL*(1.0-lowpass))+(inputSampleL*lowpass);
+    inputSampleL = v->iirBL;
+    if (fabs(v->iirBR)<1.18e-37) v->iirBR = 0.0;
+    v->iirBR = (v->iirBR*(1.0-lowpass))+(inputSampleR*lowpass);
+    inputSampleR = v->iirBR;
+
+    *outL = inputSampleL;
+    *outR = inputSampleR;
+
+    return SP_OK;
+}
+
+void sp_verbity_bigness(sp_verbity *c, SPFLOAT bigness)
+{
+    c->bigness = bigness;
+}
+
+void sp_verbity_longness(sp_verbity *c, SPFLOAT longness)
+{
+    c->longness = longness;
+}
+
+void sp_verbity_darkness(sp_verbity *c, SPFLOAT darkness)
+{
+    c->darkness = darkness;
+}