|
|
|
09-29-2019, 09:09 PM
|
#1
|
Human being with feelings
Join Date: Dec 2015
Location: SE TN USA
Posts: 77
|
jsfx jcjr_ChaosPhaser
ChaosPhaser Download link, Manual and Audio Examples here:
http://errnum.com/html/jcjr_chaosphaser.html
ChaosPhaser is a Reaper jsfx Phaser plugin.
I like Phasers, Flangers and Chorus but my ear gets tired of the usual robotically repetitive sweep rate. With most such gadgets, regardless whether you set the sweep rate fast or slow, deep or shallow, it just keeps repetitively grinding on at the current rate. Which gets old to my ear after a few seconds.
Chaos Phaser has two independent phasers. If you need/want robotic regularity then the dual LFO sweeps can be as robotically repetitive as any other phaser. However ChaosPhaser can also have slight random or chaotic staggering LFO rate, up to extreme blind-drunk staggering LFO sweeps.
The input Audio Envelope Level can modulate either LFO Rate or Phaser Center frequency. All four parameters can work simultaneously-- LFO Random Rate, LFO Chaotic Rate, Envelope Modulation of LFO Rate, and Envelope Modulation of Phaser Center Frequency.
ChaosPhaser can have anywhere from 1 to 16 phase shifter stages and the two independent phasers can be flexibly mixed to the dry signal.
When the plugin window is sized bigger than necessary to display all the sliders, ChaosPhaser uses the remaining space as a scope display. Assuming that your computer screens are big enough, drag the plugin window bigger to see a bigger scope window.
The continuous top-to-bottom repeating traces display LFO waves. Left LFO is green and Right LFO is Orange. To help the eye make better sense of the information, each new scope sweep syncs to the next Left LFO positive zero crossing. When LFO sweep rate is very slow, occasional waits occur between scope sweeps, as the scope waits for the next Left LFO positive zero crossing to come along and trigger the next display sweep. At faster LFO rates, zero crossings come along often enough that the scope display always seems busy drawing new data.
|
|
|
09-29-2019, 10:50 PM
|
#2
|
Human being with feelings
Join Date: Dec 2017
Posts: 179
|
Very cool effect thanks!
|
|
|
09-29-2019, 11:54 PM
|
#3
|
Human being with feelings
Join Date: Apr 2016
Location: Stuttgart, Germany
Posts: 217
|
Fantastic, looking forward to checking it out! Thank you
|
|
|
09-30-2019, 03:34 AM
|
#4
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 9,900
|
Interesting concept, and what an exhaustive doc !
Thx for sharing !
|
|
|
09-30-2019, 05:17 AM
|
#5
|
Human being with feelings
Join Date: Mar 2017
Location: France
Posts: 628
|
Very nice ! Thanks a lot for sharing
|
|
|
09-30-2019, 09:01 AM
|
#6
|
Human being with feelings
Join Date: Jan 2019
Location: Toronto, Canada
Posts: 542
|
Awesome - thanks for this!!
|
|
|
10-18-2019, 02:45 PM
|
#7
|
Human being with feelings
Join Date: Dec 2015
Location: SE TN USA
Posts: 77
|
Thanks to those who tried the plugin!
|
|
|
03-15-2023, 04:13 AM
|
#8
|
Human being with feelings
Join Date: Jul 2022
Location: Japan
Posts: 814
|
This looks interesting, but unfortunately the site is down. Could you possibly re-upload the file?
|
|
|
03-15-2023, 07:15 AM
|
#9
|
Human being with feelings
Join Date: Jan 2020
Location: In the studio at my desk
Posts: 365
|
Looks as your site got hijacked and replaced by a dating site.
Don't think my wife would like me using this new plugin :>)
W
|
|
|
03-15-2023, 09:43 AM
|
#11
|
Human being with feelings
Join Date: Jul 2022
Location: Japan
Posts: 814
|
Quote:
Originally Posted by X-Raym
|
Thanks for sharing it! It works!
Do you also happen to have jcjr CosmoDepot? https://forum.cockos.com/showthread.php?t=226209 His other scripts are uploaded on stash
Last edited by Suzuki; 03-15-2023 at 10:12 AM.
|
|
|
03-15-2023, 10:09 AM
|
#13
|
Human being with feelings
Join Date: Jan 2020
Location: In the studio at my desk
Posts: 365
|
Thanks X-Raym
Downloaded and will try it out soon!
Warren
|
|
|
03-16-2023, 03:38 AM
|
#14
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 9,900
|
Nope I dont have this one.
|
|
|
03-16-2023, 05:33 AM
|
#15
|
Human being with feelings
Join Date: Jul 2022
Location: Japan
Posts: 814
|
Quote:
Originally Posted by X-Raym
Nope I dont have this one.
|
Nvm, I found it in SNJUK2's "Ableton Live Config".
Code:
desc:jcjr_CosmoDepot
// James Chandler Jr
// http://www.errnum.com
// errnum@gmail.com
// License: GPL - http://www.gnu.org/licenses/gpl.html
slider1:60<1,200,0.1>Pre-Delay [ms]
slider2:250<125,1000,0.1>Delay Loop Len [ms]
slider3:90<0,100,0.1>Rvb Taps Feedback [Percent]
slider4:7.5<5,20,0.1>Rvb Taps Mod [Cents]
slider5:0<0,100,0.1>Output Taps Feedback [Percent]
slider6:2<0,20,0.1>Output Taps Mod [Cents]
slider7:100<40,400,1>Low Freq Damp [Hz]
slider8:5000<1000,10000,1>Hi Freq Damp [Hz]
slider9:20<0,100,0.1>AutoPan Mod [Percent]
slider10:0<0,14,1{[X][X][X][X],[X][X][X][_],[X][X][_][X],[X][_][X][X],[X][X][_][_],[X][_][X][_],[X][_][_][X],[X][_][_][_],[_][X][X][X],[_][X][X][_],[_][X][_][X],[_][X][_][_],[_][_][X][X],[_][_][X][_],[_][_][_][X]}>Output Taps Selection
slider11:50<0,100,0.1>Wet Mix Level [Percent]
slider12:100<0,100,0.1>Dry Mix Level [Percent]
slider13:-2<-24,6,0.1>Output Gain [dB]
@init
//should only call js_malloc within js @init section
JS_MALLOC_NO_CLEARMEM = 0;
JS_MALLOC_CLEARMEM = 1;
g_next_js_malloc = 0;
function js_malloc(a_size, a_clearmem)
local (l_result)
(
l_result = g_next_js_malloc;
(a_clearmem != 0) ?
memset(l_result, 0, a_size);
g_next_js_malloc += a_size;
l_result;
);
//Given Frequency, calculate first-order exponential Time Constant
function FrequencyToTimeConstant(a_Frequency)
local (l_result)
(
l_result = 1.0 / (2.0 * $pi * a_Frequency);
);
//Given first-order exponential Time Constant, calculate Frequency
function TimeConstantToFrequency(a_TimeConstant)
local (l_result)
(
l_result = 1.0 / (2.0 * $pi * a_TimeConstant);
);
LN2_VAL = log(2.0);
INV_LN2_VAL = 1.0 / LN2_VAL;
//arbitrary limits are imposed, which may or may not be sensible
MIN_LOG2_INPUT = 10 ^ -15; //about -300 dB
MIN_LOG2_OUTPUT = log(MIN_LOG2_INPUT) * INV_LN2_VAL;
MAX_LOG2_INPUT = 10 ^ 15; //about +300 dB
MAX_LOG2_OUTPUT = log(MAX_LOG2_INPUT) * INV_LN2_VAL;
function Log_2(a_x)
local (l_result)
(
((a_x += MIN_LOG2_INPUT) >= MAX_LOG2_INPUT) ?
l_result = MAX_LOG2_OUTPUT
:
l_result = log(a_x) * INV_LN2_VAL;
l_result;
);
function Exp_2(a_x)
local (l_result)
(
(a_x <= MIN_LOG2_OUTPUT) ?
l_result = MIN_LOG2_INPUT
:
(a_x >= MAX_LOG2_OUTPUT) ?
l_result = MAX_LOG2_INPUT
:
l_result = exp(a_x * LN2_VAL);
l_result;
);
LOG2_TO_DB_AMPLITUDE_MUL = 20.0 * log10(2.0);
LOG2_TO_DB_POWER_MUL = 10.0 * log10(2.0);
DB_AMPLITUDE_TO_LOG2_MUL = 1.0 / LOG2_TO_DB_AMPLITUDE_MUL;
DB_POWER_TO_LOG2_MUL = 1.0 / LOG2_TO_DB_POWER_MUL;
function DB_Amplitude_To_Log2(a_DBVal) //given a dB value, calc the equivalent as raw log2 value
(
a_DBVal * DB_AMPLITUDE_TO_LOG2_MUL;
);
function DB_Power_To_Log2(a_DBVal) //given a dB value, calc the equivalent as raw log2 value
(
a_DBVal * DB_POWER_TO_LOG2_MUL;
);
function Log2_To_DB_Amplitude(a_Log2Val) //given a raw log2 value, calc the equivalent as dB
(
a_Log2Val * LOG2_TO_DB_AMPLITUDE_MUL;
);
function Log2_To_DB_Power(a_Log2Val) //given a raw log2 value, calc the equivalent as dB
(
a_Log2Val * LOG2_TO_DB_POWER_MUL;
);
LN10_VAL = log(10.0);
INV_LN10_VAL = 1.0 / LN10_VAL;
DB_LN10_AMPLITUDE_MUL = LN10_VAL * 0.05;
DB_LN10_POWER_MUL = LN10_VAL * 0.1;
AMPLITUDE_LN10_DB_MUL = 20.0 * INV_LN10_VAL;
POWER_LN10_DB_MUL = 10.0 * INV_LN10_VAL;
function DB_To_Amplitude(a_DBVal)
(
exp(a_DBVal * DB_LN10_AMPLITUDE_MUL);
);
function DB_To_Power(a_DBVal)
(
exp(a_DBVal * DB_LN10_POWER_MUL);
);
function Amplitude_To_DB(a_AmplitudeVal)
(
log(a_AmplitudeVal) * AMPLITUDE_LN10_DB_MUL;
);
function Power_To_DB(a_PowerVal)
(
log(a_PowerVal) * POWER_LN10_DB_MUL;
);
//initialize sin lookup table
SIN_TBL_SIZE = 4096;
INV_SIN_TBL_SIZE = 1.0 / SIN_TBL_SIZE;
SIN_TBL_SQUARED = js_malloc(SIN_TBL_SIZE + 1, JS_MALLOC_CLEARMEM);
TWO_PI = 2 * $pi;
//_phaseinc = TWO_PI / 4096;
_phaseinc = $pi / 4096; //squared sin table is double freq, bottom peak 0, top peak 1.0
_phase = _phaseinc;
SIN_TBL_SQUARED[0] = 0;
SIN_TBL_SQUARED[4096] = 0;
//SIN_TBL_SQUARED[0] = 0 and also SIN_TBL_SQUARED[4096] = 0 to ease phase wrapping interpolation
_i = 1;
while (_i < 4096) //fill out elements [1] thru [4095]
(
SIN_TBL_SQUARED[_i] = sin(_phase) ^ 2;
_i += 1;
_phase += _phaseinc;
);
//First order trapezoidal filter object
//Code adapted from Vadim Zavalishin's book "The Art of VA Filter Design"
FIRST_ORD_FILTTYPE_LOPASS = 0;
FIRST_ORD_FILTTYPE_HIPASS = 1;
FIRST_ORD_FILTTYPE_ALLPASS_ADV = 2; //+180 degrees phase shift at DC, descending to 0 degrees phase shift at nyquist
FIRST_ORD_FILTTYPE_ALLPASS_RET = 3; //0 degrees phase shift at DC, descending to -180 degrees phase shift at nyquist
//FiltTypes: Use one of the above to set the return value of FirstOrdTrapezoidFilter_DoSamp()
// : However, all values are simultaneously accessible after calling DoSamp() by reading
// : TheFilter.lp, TheFilter.hp, TheFilter.ap_A, TheFilter.ap_R
//a_FiltFC: Filter center frequency in Hz
//a_SampRate: Samplerate of filter
function FirstOrdTrapezoidFilter_Init(a_FiltType, a_FiltFC, a_SampRate)
(
this.FT = a_FiltType;
this.SR = a_SampRate;
this.Nyquist = floor(this.SR * 0.49);
this.FC = min(a_FiltFC, this.Nyquist);
this.s = 0.0;
this.lp = 0;
this.hp = 0;
this.ap_A = 0;
this.ap_R = 0;
//calculate coefficient
this.g = tan($pi * this.FC / this.SR);
this.g /= (1 + this.g);
);
function FirstOrdTrapezoidFilter_SetFC(a_FiltFC)
(
this.FC = min(a_FiltFC, this.Nyquist);
this.g = tan($pi * this.FC / this.SR);
this.g /= (1 + this.g);
);
//Returns the filtered sample
function FirstOrdTrapezoidFilter_DoSamp(a_InSamp)
local (l_v, l_result)
(
//Vadim Zavalishin code
//v = (x-z1_state)*g/(1+g);
//y = v + z1_state;
//z1_state = y + v;
l_v = (a_InSamp - this.s) * this.g;
this.lp = l_v + this.s;
this.s = this.lp + l_v;
this.hp = a_InSamp - this.lp;
this.ap_A = this.hp - this.lp;
this.ap_R = this.lp - this.hp;
(this.FT == FIRST_ORD_FILTTYPE_LOPASS) ?
l_result = this.lp
:
(this.FT == FIRST_ORD_FILTTYPE_HIPASS) ?
l_result = this.hp
:
(this.FT == FIRST_ORD_FILTTYPE_ALLPASS_ADV) ?
l_result = this.ap_A
:
l_result = this.ap_R;
l_result;
);
//managing so many tap wraps can be a cpu hog, try to minimize the if/then checking as much possible
function MTapDly_FindNextTapWrap()
local (l_i, l_MaxTapTime, l_MaxTapTimeSlot)
(
l_MaxTapTime = -1;
l_MaxTapTimeSlot = -1;
l_i = 0;
while (l_i < 26)
(
(l_MaxTapTime < this.MasterTapAry[l_i]) ?
(
l_MaxTapTime = this.MasterTapAry[l_i];
l_MaxTapTimeSlot = l_i;
);
l_i += 1;
);
this.TapWrapCountdown = this.DlyBufTop - l_MaxTapTime;
this.TapWrapSlot = l_MaxTapTimeSlot;
);
function MTapDly_ForceTapsInBounds()
local (l_i)
(
l_i = 0;
while (l_i < 26)
(
this.MasterTapAry[l_i] += (this.MasterTapAry[l_i] < 0) * this.DlyBufTop; //wrap up if less than bottom
this.MasterTapAry[l_i] -= (this.MasterTapAry[l_i] >= this.DlyBufTop) * this.DlyBufTop; //wrap down if greater than top
l_i += 1;
);
);
function MTapDly_EliminateDupeTapTimes() //low probability belt and suspenders
local (l_i, l_j)
(
l_i = 0;
while (l_i < 25)
(
l_j = l_i + 1;
while (l_j < 26)
(
(this.MasterTapAry[l_i] == this.MasterTapAry[l_j]) ?
(
((this.MasterTapAry[l_j] -= 1) < 0) ?
this.MasterTapAry[l_j] += this.DlyBufTop;
);
l_j += 1;
);
l_i += 1;
);
);
function MTapDly_SetOutTapSelection(a_OutTapSelection)
local (l_tga)
(
l_tga = this.AudOutTapGainAry;
this.OutTapSelection = a_OutTapSelection;
(this.OutTapSelection == 0) ? //XXXX
(
l_tga[0] = l_tga[4] = 0.5; l_tga[1] = l_tga[5] = 0.5; l_tga[2] = l_tga[6] = 0.5; l_tga[3] = l_tga[7] = 0.5;
);
(this.OutTapSelection == 1) ? //XXX0
(
l_tga[0] = l_tga[4] = 0.592167; l_tga[1] = l_tga[5] = 0.592167; l_tga[2] = l_tga[6] = 0.592167; l_tga[3] = l_tga[7] = 0.0;
);
(this.OutTapSelection == 2) ? //XX0X
(
l_tga[0] = l_tga[4] = 0.592167; l_tga[1] = l_tga[5] = 0.592167; l_tga[2] = l_tga[6] = 0.0; l_tga[3] = l_tga[7] = 0.592167;
);
(this.OutTapSelection == 3) ? //X0XX
(
l_tga[0] = l_tga[4] = 0.592167; l_tga[1] = l_tga[5] = 0.0; l_tga[2] = l_tga[6] = 0.592167; l_tga[3] = l_tga[7] = 0.592167;
);
(this.OutTapSelection == 4) ? //XX00
(
l_tga[0] = l_tga[4] = 0.707946; l_tga[1] = l_tga[5] = 0.707946; l_tga[2] = l_tga[6] = 0.0; l_tga[3] = l_tga[7] = 0.0;
);
(this.OutTapSelection == 5) ? //X0X0
(
l_tga[0] = l_tga[4] = 0.707946; l_tga[1] = l_tga[5] = 0.0; l_tga[2] = l_tga[6] = 0.707946; l_tga[3] = l_tga[7] = 0.0;
);
(this.OutTapSelection == 6) ? //X00X
(
l_tga[0] = l_tga[4] = 0.707946; l_tga[1] = l_tga[5] = 0.0; l_tga[2] = l_tga[6] = 0.0; l_tga[3] = l_tga[7] = 0.707946;
);
(this.OutTapSelection == 7) ? //X000
(
l_tga[0] = l_tga[4] = 1.0; l_tga[1] = l_tga[5] = 0.0; l_tga[2] = l_tga[6] = 0.0; l_tga[3] = l_tga[7] = 0.0;
);
(this.OutTapSelection == 8) ? //0XXX
(
l_tga[0] = l_tga[4] = 0.0; l_tga[1] = l_tga[5] = 0.592167; l_tga[2] = l_tga[6] = 0.592167; l_tga[3] = l_tga[7] = 0.592167;
);
(this.OutTapSelection == 9) ? //0XX0
(
l_tga[0] = l_tga[4] = 0.0; l_tga[1] = l_tga[5] = 0.707946; l_tga[2] = l_tga[6] = 0.707946; l_tga[3] = l_tga[7] = 0.0;
);
(this.OutTapSelection == 10) ? //0X0X
(
l_tga[0] = l_tga[4] = 0.0; l_tga[1] = l_tga[5] = 0.707946; l_tga[2] = l_tga[6] = 0.0; l_tga[3] = l_tga[7] = 0.707946;
);
(this.OutTapSelection == 11) ? //0X00
(
l_tga[0] = l_tga[4] = 0.0; l_tga[1] = l_tga[5] = 1.0; l_tga[2] = l_tga[6] = 0.0; l_tga[3] = l_tga[7] = 0.0;
);
(this.OutTapSelection == 12) ? //00XX
(
l_tga[0] = l_tga[4] = 0.0; l_tga[1] = l_tga[5] = 0.0; l_tga[2] = l_tga[6] = 0.707946; l_tga[3] = l_tga[7] = 0.707946;
);
(this.OutTapSelection == 13) ? //00X0
(
l_tga[0] = l_tga[4] = 0.0; l_tga[1] = l_tga[5] = 0.0; l_tga[2] = l_tga[6] = 1.0; l_tga[3] = l_tga[7] = 0.0;
);
(this.OutTapSelection == 14) ? //000X
(
l_tga[0] = l_tga[4] = 0.0; l_tga[1] = l_tga[5] = 0.0; l_tga[2] = l_tga[6] = 0.0; l_tga[3] = l_tga[7] = 1.0;
);
);
function MTapDly_SetDlyLoopLen(a_DlyLoopMs)
local (l_i, l_scale, l_DlyLoopHeadIdx)
(
this.SuspendCount += 1.0;
this.DlyLoop_Secs = a_DlyLoopMs * 0.001;
this.DlyLoop_Samps = ceil(this.DlyLoop_Secs * this.SR);
l_scale = this.SR * this.DlyLoop_Secs / 0.250;
l_DlyLoopHeadIdx = this.DlyLoopHead[0];
this.OutTapAry[0] = floor(l_DlyLoopHeadIdx - 0.058719 * l_scale);
this.OutTapAry[1] = floor(l_DlyLoopHeadIdx - 0.147135 * l_scale);
this.OutTapAry[2] = floor(l_DlyLoopHeadIdx - 0.167387 * l_scale);
this.OutTapAry[3] = floor(l_DlyLoopHeadIdx - 0.210065 * l_scale);
this.OutTapAry[4] = floor(l_DlyLoopHeadIdx - 0.093690 * l_scale);
this.OutTapAry[5] = floor(l_DlyLoopHeadIdx - 0.122839 * l_scale);
this.OutTapAry[6] = floor(l_DlyLoopHeadIdx - 0.184267 * l_scale);
this.OutTapAry[7] = floor(l_DlyLoopHeadIdx - 0.198337 * l_scale);
this.RvbTapAry[0] = floor(l_DlyLoopHeadIdx - 0.047 * l_scale);
this.RvbTapAry[1] = floor(l_DlyLoopHeadIdx - 0.073359 * l_scale);
this.RvbTapAry[2] = floor(l_DlyLoopHeadIdx - 0.096939 * l_scale);
this.RvbTapAry[3] = floor(l_DlyLoopHeadIdx - 0.118034 * l_scale);
this.RvbTapAry[4] = floor(l_DlyLoopHeadIdx - 0.136903 * l_scale);
this.RvbTapAry[5] = floor(l_DlyLoopHeadIdx - 0.153784 * l_scale);
this.RvbTapAry[6] = floor(l_DlyLoopHeadIdx - 0.168884 * l_scale);
this.RvbTapAry[7] = floor(l_DlyLoopHeadIdx - 0.182392 * l_scale);
this.RvbTapAry[8] = floor(l_DlyLoopHeadIdx - 0.194476 * l_scale);
this.RvbTapAry[9] = floor(l_DlyLoopHeadIdx - 0.205286 * l_scale);
this.RvbTapAry[10] = floor(l_DlyLoopHeadIdx - 0.214956 * l_scale);
this.RvbTapAry[11] = floor(l_DlyLoopHeadIdx - 0.223607 * l_scale);
this.RvbTapAry[12] = floor(l_DlyLoopHeadIdx - 0.231345 * l_scale);
this.RvbTapAry[13] = floor(l_DlyLoopHeadIdx - 0.238268 * l_scale);
this.RvbTapAry[14] = floor(l_DlyLoopHeadIdx - 0.244460 * l_scale);
this.RvbTapAry[15] = floor(l_DlyLoopHeadIdx - 0.250000 * l_scale);
this.MTapDly_ForceTapsInBounds();
this.MTapDly_EliminateDupeTapTimes();
this.MTapDly_FindNextTapWrap();
this.SuspendCount -= 1.0;
);
function MTapDly_SetLFDamp(a_LFDampHz)
(
this.gm_LFDamp = tan(a_LFDampHz * this.PiDivSR);
this.gm_LFDamp /= (1 + this.gm_LFDamp);
);
function MTapDly_SetHFDamp(a_HFDampHz)
(
this.gm_HFDamp = tan(a_HFDampHz * this.PiDivSR);
this.gm_HFDamp /= (1 + this.gm_HFDamp);
);
function MTapDly_Init(a_PreDlyMs, a_DlyLoopMs, a_OutTapFB, a_RvbTapFB, a_LFDampHz, a_HFDampHz, a_RvbModCents, a_OutModCents, a_AutoPanMul, a_OutTapSelection, a_SampRate)
local (l_i, l_scale, l_LFOPeriodSamps, l_TCSamps)
(
this.SuspendCount = 1.0;
this.SR = a_SampRate;
this.Nyquist = floor(this.SR * 0.49);
this.PiDivSR = $pi / this.SR;
this.PreDly_Secs = a_PreDlyMs * 0.001;
this.DlyLoop_Secs = a_DlyLoopMs * 0.001;
this.OutTapFB = a_OutTapFB;
this.RvbTapFB = a_RvbTapFB;
this.RvbModCents = a_RvbModCents;
this.OutModCents = a_OutModCents;
this.AutoPanMul = a_AutoPanMul;
this.DlyLoop_Samps = ceil(this.DlyLoop_Secs * this.SR);
this.PreDly_Samps = ceil(this.PreDly_Secs * this.SR);
this.DlyBufTop = ceil(1.300 * this.SR); //max 1000 ms for DlyLoop, max 200 ms for PreDly, 100 ms for slop
this.DlyBuf = js_malloc(this.DlyBufTop + 2, JS_MALLOC_CLEARMEM); //dup head to top and bottom for easier interpolation
this.AudOutputsAry = js_malloc(8, JS_MALLOC_CLEARMEM);
this.AudOutTapGainAry = js_malloc(8, JS_MALLOC_CLEARMEM);
this.MTapDly_SetOutTapSelection(a_OutTapSelection);
this.MasterTapAry = js_malloc(26, JS_MALLOC_CLEARMEM); //pre-delay head, delay loop head, 8 output taps and 16 reverb taps
this.PreDlyHead = this.MasterTapAry; //PreDlyHead[0] is value of MasterTapAry[0]
this.DlyLoopHead = this.MasterTapAry + 1; //DlyLoopHead[0] is value of MasterTapAry[1]
this.OutTapAry = this.MasterTapAry + 2; //OutTapAry[0] thru [7] is value of MasterTapAry [2] thru [9]
this.RvbTapAry = this.MasterTapAry + 10; //RvbTapAry[0] thru [15] is value of MasterTapAry [10] thru [25]
this.PreDlyHead[0] = this.DlyBufTop - 1;
this.DlyLoopHead[0] = this.PreDlyHead[0] - this.PreDly_Samps;
this.MTapDly_SetDlyLoopLen(a_DlyLoopMs);
this.s_LFDamp = 0.0;
this.s_HFDamp = 0.0;
this.MTapDly_SetLFDamp(a_LFDampHz);
this.MTapDly_SetHFDamp(a_HFDampHz);
this.RvbModSlopeIncPerSamp = (2 ^ (this.RvbModCents / 1200.0)) - 1.0;
this.OutModSlopeIncPerSamp = (2 ^ (this.OutModCents / 1200.0)) - 1.0;
this.LFO_SinTblIncRatio = SIN_TBL_SIZE / this.SR;
this.LFO_FreqHzAry = js_malloc(32, JS_MALLOC_CLEARMEM);
this.LFO_TblIncPerSampAry = js_malloc(32, JS_MALLOC_CLEARMEM);
this.LFO_TblPhaseIdxAry = js_malloc(32, JS_MALLOC_CLEARMEM);
this.LFO_AmpMulAry = js_malloc(32, JS_MALLOC_CLEARMEM);
this.LFO_OutAry = js_malloc(32, JS_MALLOC_CLEARMEM);
l_i = 0;
while (l_i < 32)
(
this.LFO_FreqHzAry[l_i] = 0.5 * (1 + rand(3)); //scramble LFO startup freq between 0.5 and 2 Hz
this.LFO_TblIncPerSampAry[l_i] = this.LFO_FreqHzAry[l_i] * this.LFO_SinTblIncRatio;
this.LFO_TblPhaseIdxAry[l_i] = floor((SIN_TBL_SIZE - 1) * rand(1)); //scramble LFO startup phases
l_LFOPeriodSamps = this.SR / this.LFO_FreqHzAry[l_i];
(l_i < 16) ? //FB Taps
this.LFO_AmpMulAry[l_i] = 0.636620 * l_LFOPeriodSamps * this.RvbModSlopeIncPerSamp //scale by 2/pi = 0.636620
: //else Out Taps or AutoPan
(
(l_i < 24) ?
this.LFO_AmpMulAry[l_i] = 0.636620 * l_LFOPeriodSamps * this.OutModSlopeIncPerSamp //scale by 2/pi = 0.636620
:
this.LFO_AmpMulAry[l_i] = 1.0; //AutoPan
);
l_i += 1;
);
//setup delay line feedback runaway limiter
l_TCSamps = 0.02 * this.SR; //20 ms attack time constant
this.FBEnv_ACoff = 1.0 / (2.0 * l_TCSamps);
this.FBEnv_ACoff /= (1 + this.FBEnv_ACoff);
l_TCSamps = 1.0 * this.SR; //1000 ms release time constant
this.FBEnv_RCoff = 1.0 / (2.0 * l_TCSamps);
this.FBEnv_RCoff /= (1 + this.FBEnv_RCoff);
this.FBEnv_s = 1.0; //attack-release state variable
this.Initted = 1.0;
this.SuspendCount = 0.0;
);
function MTapDly_SetRvbModCents(a_RvbModCents)
local (l_i, l_LFOPeriodSamps)
(
this.SuspendCount += 1.0;
this.RvbModCents = a_RvbModCents;
this.RvbModSlopeIncPerSamp = (2 ^ (this.RvbModCents / 1200.0)) - 1.0;
l_i = 0;
while (l_i < 16)
(
l_LFOPeriodSamps = this.SR / this.LFO_FreqHzAry[l_i];
this.LFO_AmpMulAry[l_i] = 0.636620 * l_LFOPeriodSamps * this.RvbModSlopeIncPerSamp;
l_i += 1;
);
this.SuspendCount -= 1.0;
);
function MTapDly_SetOutModCents(a_OutModCents)
local (l_i, l_LFOPeriodSamps)
(
this.SuspendCount += 1.0;
this.OutModCents = a_OutModCents;
this.OutModSlopeIncPerSamp = (2 ^ (this.OutModCents / 1200.0)) - 1.0;
l_i = 16;
while (l_i < 24)
(
l_LFOPeriodSamps = this.SR / this.LFO_FreqHzAry[l_i];
this.LFO_AmpMulAry[l_i] = 0.636620 * l_LFOPeriodSamps * this.OutModSlopeIncPerSamp;
l_i += 1;
);
this.SuspendCount -= 1.0;
);
function MTapDly_SetPreDelay(a_PreDlyMs)
(
this.SuspendCount += 1.0;
this.PreDly_Secs = a_PreDlyMs * 0.001;
this.PreDly_Samps = ceil(this.PreDly_Secs * this.SR);
this.PreDlyHead[0] = this.DlyLoopHead[0] + this.PreDly_Samps;
this.PreDlyHead[0] -= (this.PreDlyHead[0] >= this.DlyBufTop) * this.DlyBufTop;
this.MTapDly_EliminateDupeTapTimes();
this.MTapDly_FindNextTapWrap();
this.SuspendCount -= 1.0;
);
function MTapDly_RunLFOs()
local (l_i, l_TblPhaseIdx, l_int, l_frac, l_LFOPeriodSamps, l_MaxNewPhaseIdx)
(
l_MaxNewPhaseIdx = 0;
l_i = 0;
while (l_i < 32)
(
l_TblPhaseIdx = this.LFO_TblPhaseIdxAry[l_i];
l_int = floor(l_TblPhaseIdx);
l_frac = l_TblPhaseIdx - l_int;
this.LFO_OutAry[l_i] = this.LFO_AmpMulAry[l_i] * (SIN_TBL_SQUARED[l_int] * (1 - l_frac) + SIN_TBL_SQUARED[l_int + 1] * l_frac); //linear interpolate
l_MaxNewPhaseIdx = max(this.LFO_TblPhaseIdxAry[l_i] = l_TblPhaseIdx + this.LFO_TblIncPerSampAry[l_i], l_MaxNewPhaseIdx);
l_i += 1;
);
(l_MaxNewPhaseIdx >= SIN_TBL_SIZE) ? //only do wraparound checking if necessary
(
l_i = 0;
while (l_i < 32)
(
(this.LFO_TblPhaseIdxAry[l_i] >= SIN_TBL_SIZE) ? //possibly phase wrap and choose new random freq
(
this.LFO_TblPhaseIdxAry[l_i] -= SIN_TBL_SIZE;
this.LFO_FreqHzAry[l_i] = 0.5 * (1 + rand(3)); //choose new random freq between 0.5 and 1.0
this.LFO_TblIncPerSampAry[l_i] = this.LFO_FreqHzAry[l_i] * this.LFO_SinTblIncRatio;
l_LFOPeriodSamps = this.SR / this.LFO_FreqHzAry[l_i];
(l_i < 16) ? //FB Taps
this.LFO_AmpMulAry[l_i] = 0.636620 * l_LFOPeriodSamps * this.RvbModSlopeIncPerSamp //scale by 2/pi = 0.636620
: //else Out Taps or AutoPan
(
(l_i < 24) ?
this.LFO_AmpMulAry[l_i] = 0.636620 * l_LFOPeriodSamps * this.OutModSlopeIncPerSamp //scale by 2/pi = 0.636620
: //else AutoPan
this.LFO_AmpMulAry[l_i] = 1.0;
);
);
l_i += 1;
);
);
);
function MTapDly_DoSamp(a_In_L, a_In_R)
local (l_i, l_DlyBuf, l_OutTapAry, l_RvbTapAry, l_AudOutputsAry, l_FBSum, l_v, l_lp, l_idx, l_int, l_frac, l_samp, l_mul, l_autopan_L, l_autopan_R, l_tga)
(
(this.SuspendCount < 1.0) ?
(
l_DlyBuf = this.DlyBuf;
l_OutTapAry = this.OutTapAry; //maybe faster local vars for multiple de-referencing, dunno
l_RvbTapAry = this.RvbTapAry;
l_AudOutputsAry = this.AudOutputsAry;
l_tga = this.AudOutTapGainAry;
l_idx = this.PreDlyHead[0];
l_DlyBuf[l_idx] = l_samp = ((a_In_L + a_In_R) * 0.5);
(l_idx == 0) ? //dup also "above top" for easier tail interpolation
l_DlyBuf[this.DlyBufTop] = l_samp;
this.MTapDly_RunLFOs(); //update all 32 LFOs
(this.OutModCents > 0) ? //pitch modulate the output taps
(
l_i = 0;
while (l_i < 8)
(
l_idx = l_OutTapAry[l_i] + this.LFO_OutAry[l_i + 16];
l_idx -= this.DlyBufTop * (l_idx >= this.DlyBufTop); //possibly wrap
l_int = floor(l_idx);
l_frac = l_idx - l_int;
l_AudOutputsAry[l_i] = l_tga[l_i] * (l_DlyBuf[l_int] * (1 - l_frac) + l_DlyBuf[l_int + 1] * l_frac); //linear interpolate
l_i += 1;
);
)
: //else no Output pitch mod, no need to interpolate samples
(
l_i = 0;
while (l_i < 8)
(
l_AudOutputsAry[l_i] = l_tga[l_i] * l_DlyBuf[l_OutTapAry[l_i]];
l_i += 1;
);
);
this.Out_L = l_AudOutputsAry[0] + l_AudOutputsAry[1] + l_AudOutputsAry[2] + l_AudOutputsAry[3];
this.Out_R = l_AudOutputsAry[4] + l_AudOutputsAry[5] + l_AudOutputsAry[6] + l_AudOutputsAry[7];
l_FBSum = 0;
(this.RvbTapFB > 0.0) ? //don't bother with calc if no rvb feedback
(
l_i = 0;
while (l_i < 16)
(
l_idx = l_RvbTapAry[l_i] + this.LFO_OutAry[l_i];
l_idx -= this.DlyBufTop * (l_idx >= this.DlyBufTop); //possibly wrap
l_int = floor(l_idx);
l_frac = l_idx - l_int;
l_samp = l_DlyBuf[l_int] * (1 - l_frac) + l_DlyBuf[l_int + 1] * l_frac;
l_FBSum += l_samp;
l_i += 1;
);
l_FBSum *= (this.RvbTapFB * 0.1875);
);
l_FBSum += (this.OutTapFB * 0.5 * (this.Out_L + this.Out_R));
((l_v = (max(abs(l_FBSum), 1.0) - this.FBEnv_s)) > 0.0) ? //attack-release envelope for runaway protect limiter
l_v *= this.FBEnv_ACoff //attack
:
l_v *= this.FBEnv_RCoff; //release
l_lp = l_v + this.FBEnv_s; //l_lp here is temporarily the smoothed feedback envelope value
this.FBEnv_s = l_lp + l_v;
l_frac = (1.0 / l_lp); //l_frac is temporarily the feedback limiter gain
l_FBSum *= (l_frac * l_frac); //possibly hard-limit, lowering output BELOW thresh by squaring the (less than 1.0) gain
l_idx = this.DlyLoopHead[0]; //temp use l_idx avoid repeatedly de-referencing DlyLoopHead[0]
l_FBSum += l_DlyBuf[l_idx]; //add possible rvb feedback and out taps feedback to the fresh audio input
//do HFDamp and LFDamp on the mix of fresh audio input plus rvb feedback plus out taps feedback
//hipass for LFDamp
l_v = (l_FBSum - this.s_LFDamp) * this.gm_LFDamp;
l_lp = l_v + this.s_LFDamp;
this.s_LFDamp = l_lp + l_v;
l_FBSum -= l_lp; //make LFDamp Hipass
//lopass for HFDamp
l_v = (l_FBSum - this.s_HFDamp) * this.gm_HFDamp;
l_lp = l_v + this.s_HFDamp;
this.s_HFDamp = l_lp + l_v;
l_FBSum = l_lp;
l_DlyBuf[l_idx] = l_FBSum; //write the HF and LF damped, [input + feedback] mix back into the delay loop head
(l_idx == 0) ? //dup also "above top" for easier tail interpolation
l_DlyBuf[this.DlyBufTop] = l_FBSum;
(this.AutoPanMul > 0.0) ?
(
l_autopan_L = 0;
l_autopan_R = 0;
l_i = 0;
while (l_i < 8)
(
l_mul = this.LFO_OutAry[l_i + 24];
l_samp = l_AudOutputsAry[l_i];
l_autopan_L += l_samp * (1 - l_mul);
l_autopan_R += l_samp * l_mul;
l_i += 1;
);
this.Out_L = this.Out_L * (1 - this.AutoPanMul) + l_autopan_L * this.AutoPanMul;
this.Out_R = this.Out_R * (1 - this.AutoPanMul) + l_autopan_R * this.AutoPanMul;
);
l_i = 0;
while (l_i < 26)
(
this.MasterTapAry[l_i] += 1;
l_i += 1;
);
((this.TapWrapCountdown -= 1) <= 0) ?
(
this.MasterTapAry[this.TapWrapSlot] = 0; //wrap the single tap ptr needs wrapping
this.MTapDly_FindNextTapWrap(); //find next one that will need wrapping
);
);
);
//global vars
g_PreDlyMs = 60; //slider1
g_DlyLoopMs = 250; //slider2
g_RvbTapFB_Percent = 90; //slider3
g_RvbModCents = 7.5; //slider4
g_OutTapFB_Percent = 0.0; //slider5
g_OutModCents = 2.0; //slider6
g_LFDampHz = 100; //slider7
g_HFDampHz = 5000; //slider8
g_AutoPan_Percent = 20; //slider9
g_OutTapSelection = 0; //slider10
g_WetMix_Percent = 50; //slider11
g_DryMix_Percent = 100; //slider12
g_OutGainDB = -2; //slider13
g_RvbTapFB = g_RvbTapFB_Percent * 0.01;
g_OutTapFB = g_OutTapFB_Percent * 0.01;
g_AutoPan_Mul = g_AutoPan_Percent * 0.01;
g_WetMix_Mul = g_WetMix_Percent * 0.01;
g_DryMix_Mul = g_DryMix_Percent * 0.01;
g_OutGain_Mul = DB_To_Amplitude(g_OutGainDB);
o_MTap.MTapDly_Init(g_PreDlyMs, g_DlyLoopMs, g_OutTapFB, g_RvbTapFB, g_LFDampHz, g_HFDampHz, g_RvbModCents, g_OutModCents, g_AutoPan_Mul, g_OutTapSelection, srate);
@slider
(slider1 != g_PreDlyMs) ?
(
slider1 = max(min(slider1, 200), 1);
g_PreDlyMs = slider1;
(o_MTap.Initted == 1.0) ?
o_MTap.MTapDly_SetPreDelay(g_PreDlyMs);
);
(slider2 != g_DlyLoopMs) ?
(
slider2 = max(min(slider2, 1000), 125);
g_DlyLoopMs = slider2;
(o_MTap.Initted == 1.0) ?
o_MTap.MTapDly_SetDlyLoopLen(g_DlyLoopMs);
);
(slider3 != g_RvbTapFB_Percent) ?
(
slider3 = max(min(slider3, 100.0), 0.0);
g_RvbTapFB_Percent = slider3;
g_RvbTapFB = g_RvbTapFB_Percent * 0.01;
(o_MTap.Initted == 1.0) ?
o_MTap.RvbTapFB = g_RvbTapFB;
);
(slider4 != g_RvbModCents) ?
(
slider4 = max(min(slider4, 20.0), 5.0);
g_RvbModCents = slider4;
(o_MTap.Initted == 1.0) ?
o_MTap.MTapDly_SetRvbModCents(g_RvbModCents);
);
(slider5 != g_OutTapFB_Percent) ?
(
slider5 = max(min(slider5, 100.0), 0.0);
g_OutTapFB_Percent = slider5;
g_OutTapFB = g_OutTapFB_Percent * 0.01;
(o_MTap.Initted == 1.0) ?
o_MTap.OutTapFB = g_OutTapFB;
);
(slider6 != g_OutModCents) ?
(
slider6 = max(min(slider6, 20.0), 0.0);
g_OutModCents = slider6;
(o_MTap.Initted == 1.0) ?
o_MTap.MTapDly_SetOutModCents(g_OutModCents);
);
(slider7 != g_LFDampHz) ?
(
slider7 = max(min(slider7, 400), 40);
g_LFDampHz = slider7;
(o_MTap.Initted == 1.0) ?
o_MTap.MTapDly_SetLFDamp(g_LFDampHz);
);
(slider8 != g_HFDampHz) ?
(
slider8 = max(min(slider8, 10000), 1000);
g_HFDampHz = slider8;
(o_MTap.Initted == 1.0) ?
o_MTap.MTapDly_SetHFDamp(g_HFDampHz);
);
(slider9 != g_AutoPan_Percent) ?
(
slider9 = max(min(slider9, 100), 0);
g_AutoPan_Percent = slider9;
g_AutoPan_Mul = g_AutoPan_Percent * 0.01;
(o_MTap.Initted == 1.0) ?
o_MTap.AutoPanMul = g_AutoPan_Mul;
);
(slider10 != g_OutTapSelection) ?
(
slider10 = max(min(slider10, 14), 0);
g_OutTapSelection = slider10;
(o_MTap.Initted == 1.0) ?
o_MTap.MTapDly_SetOutTapSelection(g_OutTapSelection);
);
(slider11 != g_WetMix_Percent) ?
(
slider11 = max(min(slider11, 100), 0);
g_WetMix_Percent = slider11;
g_WetMix_Mul = g_WetMix_Percent * 0.01;
);
(slider12 != g_DryMix_Percent) ?
(
slider12 = max(min(slider12, 100), 0);
g_DryMix_Percent = slider12;
g_DryMix_Mul = g_DryMix_Percent * 0.01;
);
(slider13 != g_OutGainDB) ?
(
slider13 = max(min(slider13, 6), -24);
g_OutGainDB = slider13;
g_OutGain_Mul = DB_To_Amplitude(g_OutGainDB);
);
@block
@sample
o_MTap.MTapDly_DoSamp(spl0, spl1);
spl0 = g_OutGain_Mul * (g_DryMix_Mul * spl0 + g_WetMix_Mul * o_MTap.Out_L);
spl1 = g_OutGain_Mul * (g_DryMix_Mul * spl1 + g_WetMix_Mul * o_MTap.Out_R);
|
|
|
03-16-2023, 05:34 AM
|
#16
|
Human being with feelings
Join Date: Feb 2006
Location: Helsinki, Finland
Posts: 315
|
Quote:
Originally Posted by Suzuki
Do you also happen to have jcjr CosmoDepot?
|
Here you go
https://www.dropbox.com/s/ekxcr8vwba...Depot.zip?dl=1
edit: posted simultaneously with the previous post XD
I'll keep this up in any case since this zip includes the manual
|
|
|
03-16-2023, 05:39 AM
|
#17
|
Human being with feelings
Join Date: Jul 2022
Location: Japan
Posts: 814
|
Quote:
Originally Posted by Paul Eye
|
Oh we seem to have crossed in the post, but thanks anyway!
|
|
|
01-11-2024, 03:13 PM
|
#18
|
Human being with feelings
Join Date: Feb 2009
Location: Reaper HAS send control via midi !!!
Posts: 4,032
|
Thanks for sharing CosmoDepot here!
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 07:24 AM.
|