Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
557 changes: 150 additions & 407 deletions apps/test/allugens.srp

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion apps/test/dspmanifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ spectralcentroid
spectralrolloff
o2audioio
sttest
# zitarev
zitarev
tableosc*
blend*
stdistr
monodistortion
30 changes: 30 additions & 0 deletions apps/test/init.srp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ def arco_ready():
Checkbox(win, "supersaw", 'S', 'D', WIDTH, 'S', 'supersawcheckbox')
supersawcheckbox.add_target_method(nil, 'supersawtest')

Checkbox(win, "Overdrive Test", 'S', 'D', WIDTH, 'S', 'overdrivecheckbox')
overdrivecheckbox.add_target_method(nil, 'overdrivetest')

ui_initialized = true
default_window.fit_to_children()

Expand Down Expand Up @@ -1374,6 +1377,33 @@ def supersawtest(obj, event, x, y):
return
sss.mute()

########## Overdrive Test ##############

ovd = nil

def overdrivetest(obj, event, x, y):
display "overdrivetest", x
if x:

var left_tone = sine(220, 0.3) // 220 Hz (A3)
var right_tone = sine(275, 0.3) // 275 Hz (~C#4)

var env = pweb(0.2, 0.5, 1)
var left_env = mult(left_tone, env)
var right_env = mult(right_tone, env)

// Mix left and right signals into a single mono signal before distortion
var mono_input = add(left_env, right_env)

// Apply distortion
ovd = monodistortion(mono_input, 0.85, 0.85, 0.8) // snd, gain, tone, volume
ovd.play()
else:
// Fade out and stop processing
ovd.set('snd', zero_ugen)
sched_select(rtsched)
sched_cause(6, ovd, 'mute')
ovd = nil


########## Main Initialization ################
Expand Down
46 changes: 46 additions & 0 deletions doc/ugens.md
Original file line number Diff line number Diff line change
Expand Up @@ -1942,3 +1942,49 @@ zero()

`/arco/zero/new id` - Create a signal consisting of all-zeros.

### monodistortion
'''
monodistortion(input, gain, tone, volume)
'''
The input signal can have multiple channels, which are first summed into
a mono signal and scaled by `gain`. After processing in mono, the signal
is fanned out and blended with the original input signal using `wetdry`
to control the balance from pure input (`wetdry` = 0) to pure effect
(`wetdry` = 1).

The processing chain contains a first-order high-pass filter set at 720 Hz,
which removes low-frequency components. The filtered signal is then passed
through a cubic nonlinear distortion function, which shapes the
signal by introducing harmonic content and saturation. After
distortion, the signal is passed through a low-pass filter with a cutoff
frequency determined by the `tone` parameter (in Hz), allowing for control
over the brightness or warmth of the effect. Finally, the signal is
multiplied by the `volume` parameter, controlling the output gain.

After the signal is processed, the `wetdry` parameter is used to blend the
distorted signal with the original input. When `wetdry` is set to 0, the
output consists entirely of the original input signal. When set to 1, the
output consists only of the distorted signal. Values in between allow for a
balance between the dry and processed signals

`/arco/monodistortion/new id chans gain tone volume` - Create a new
monodistortion unit generator with `gain`, `tone`, and `volume` control
inputs, along with an audio input and output.

`/arco/monodistortion/repl_gain id gain_id` - Set gain to object with id
`gain_id`.

`/arco/monodistortion/set_gain id chan gain` - Set gain of channel `chan` to
float value `gain`.

`/arco/monodistortion/repl_tone id tone_id` - Set tone to object with id
`tone_id`.

`/arco/monodistortion/set_tone id chan tone` - Set tone of channel `chan` to
float value `tone`.

`/arco/monodistortion/repl_volume id volume_id` - Set volume to object with
id `volume_id`.

`/arco/monodistortion/set_volume id chan volume` - Set volume of channel
`chan` to float value `volume`.
19 changes: 19 additions & 0 deletions serpent/srp/overdrive.srp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# overdrive.srp -- overdrive unit generator
#
# Vivek Mohan
# February 2025

class Overdrive(Instrument):
def init(input, gain, tone, volume, wetdry):

mono_input = route(1)
for i = 0 to input.chans:
mono_input.ins(input, i, 0)

scale_factor = 1.0 / sqrt(input.chans)

processed = monodistortion(mono_input, gain, tone, volume * scale_factor)

final_output = add(mult(input, mult(scale_factor,subb(1, wetdry))), mult(processed, mult(scale_factor,wetdry)))

super.init("Overdrive", final_output)
179 changes: 179 additions & 0 deletions ugens/monodistortion/monodistortion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/* monodistortion -- unit generator for arco
*
* generated by f2a.py
*/

#include "arcougen.h"
#include "monodistortion.h"

const char *Monodistortion_name = "Monodistortion";

/* O2SM INTERFACE: /arco/monodistortion/new int32 id, int32 chans, int32 snd, int32 gain, int32 tone, int32 volume;
*/
void arco_monodistortion_new(O2SM_HANDLER_ARGS)
{
// begin unpack message (machine-generated):
int32_t id = argv[0]->i;
int32_t chans = argv[1]->i;
int32_t snd = argv[2]->i;
int32_t gain = argv[3]->i;
int32_t tone = argv[4]->i;
int32_t volume = argv[5]->i;
// end unpack message

ANY_UGEN_FROM_ID(snd_ugen, snd, "arco_monodistortion_new");
ANY_UGEN_FROM_ID(gain_ugen, gain, "arco_monodistortion_new");
ANY_UGEN_FROM_ID(tone_ugen, tone, "arco_monodistortion_new");
ANY_UGEN_FROM_ID(volume_ugen, volume, "arco_monodistortion_new");

new Monodistortion(id, chans, snd_ugen, gain_ugen, tone_ugen, volume_ugen);
}


/* O2SM INTERFACE: /arco/monodistortion/repl_snd int32 id, int32 snd_id;
*/
static void arco_monodistortion_repl_snd(O2SM_HANDLER_ARGS)
{
// begin unpack message (machine-generated):
int32_t id = argv[0]->i;
int32_t snd_id = argv[1]->i;
// end unpack message

UGEN_FROM_ID(Monodistortion, monodistortion, id, "arco_monodistortion_repl_snd");
ANY_UGEN_FROM_ID(snd, snd_id, "arco_monodistortion_repl_snd");
monodistortion->repl_snd(snd);
}


/* O2SM INTERFACE: /arco/monodistortion/set_snd int32 id, int32 chan, float val;
*/
static void arco_monodistortion_set_snd (O2SM_HANDLER_ARGS)
{
// begin unpack message (machine-generated):
int32_t id = argv[0]->i;
int32_t chan = argv[1]->i;
float val = argv[2]->f;
// end unpack message

UGEN_FROM_ID(Monodistortion, monodistortion, id, "arco_monodistortion_set_snd");
monodistortion->set_snd(chan, val);
}


/* O2SM INTERFACE: /arco/monodistortion/repl_gain int32 id, int32 gain_id;
*/
static void arco_monodistortion_repl_gain(O2SM_HANDLER_ARGS)
{
// begin unpack message (machine-generated):
int32_t id = argv[0]->i;
int32_t gain_id = argv[1]->i;
// end unpack message

UGEN_FROM_ID(Monodistortion, monodistortion, id, "arco_monodistortion_repl_gain");
ANY_UGEN_FROM_ID(gain, gain_id, "arco_monodistortion_repl_gain");
monodistortion->repl_gain(gain);
}


/* O2SM INTERFACE: /arco/monodistortion/set_gain int32 id, int32 chan, float val;
*/
static void arco_monodistortion_set_gain (O2SM_HANDLER_ARGS)
{
// begin unpack message (machine-generated):
int32_t id = argv[0]->i;
int32_t chan = argv[1]->i;
float val = argv[2]->f;
// end unpack message

UGEN_FROM_ID(Monodistortion, monodistortion, id, "arco_monodistortion_set_gain");
monodistortion->set_gain(chan, val);
}


/* O2SM INTERFACE: /arco/monodistortion/repl_tone int32 id, int32 tone_id;
*/
static void arco_monodistortion_repl_tone(O2SM_HANDLER_ARGS)
{
// begin unpack message (machine-generated):
int32_t id = argv[0]->i;
int32_t tone_id = argv[1]->i;
// end unpack message

UGEN_FROM_ID(Monodistortion, monodistortion, id, "arco_monodistortion_repl_tone");
ANY_UGEN_FROM_ID(tone, tone_id, "arco_monodistortion_repl_tone");
monodistortion->repl_tone(tone);
}


/* O2SM INTERFACE: /arco/monodistortion/set_tone int32 id, int32 chan, float val;
*/
static void arco_monodistortion_set_tone (O2SM_HANDLER_ARGS)
{
// begin unpack message (machine-generated):
int32_t id = argv[0]->i;
int32_t chan = argv[1]->i;
float val = argv[2]->f;
// end unpack message

UGEN_FROM_ID(Monodistortion, monodistortion, id, "arco_monodistortion_set_tone");
monodistortion->set_tone(chan, val);
}


/* O2SM INTERFACE: /arco/monodistortion/repl_volume int32 id, int32 volume_id;
*/
static void arco_monodistortion_repl_volume(O2SM_HANDLER_ARGS)
{
// begin unpack message (machine-generated):
int32_t id = argv[0]->i;
int32_t volume_id = argv[1]->i;
// end unpack message

UGEN_FROM_ID(Monodistortion, monodistortion, id, "arco_monodistortion_repl_volume");
ANY_UGEN_FROM_ID(volume, volume_id, "arco_monodistortion_repl_volume");
monodistortion->repl_volume(volume);
}


/* O2SM INTERFACE: /arco/monodistortion/set_volume int32 id, int32 chan, float val;
*/
static void arco_monodistortion_set_volume (O2SM_HANDLER_ARGS)
{
// begin unpack message (machine-generated):
int32_t id = argv[0]->i;
int32_t chan = argv[1]->i;
float val = argv[2]->f;
// end unpack message

UGEN_FROM_ID(Monodistortion, monodistortion, id, "arco_monodistortion_set_volume");
monodistortion->set_volume(chan, val);
}


static void monodistortion_init()
{
// O2SM INTERFACE INITIALIZATION: (machine generated)
o2sm_method_new("/arco/monodistortion/new", "iiiiii",
arco_monodistortion_new, NULL, true, true);
o2sm_method_new("/arco/monodistortion/repl_snd", "ii",
arco_monodistortion_repl_snd, NULL, true, true);
o2sm_method_new("/arco/monodistortion/set_snd", "iif",
arco_monodistortion_set_snd, NULL, true, true);
o2sm_method_new("/arco/monodistortion/repl_gain", "ii",
arco_monodistortion_repl_gain, NULL, true, true);
o2sm_method_new("/arco/monodistortion/set_gain", "iif",
arco_monodistortion_set_gain, NULL, true, true);
o2sm_method_new("/arco/monodistortion/repl_tone", "ii",
arco_monodistortion_repl_tone, NULL, true, true);
o2sm_method_new("/arco/monodistortion/set_tone", "iif",
arco_monodistortion_set_tone, NULL, true, true);
o2sm_method_new("/arco/monodistortion/repl_volume", "ii",
arco_monodistortion_repl_volume, NULL, true, true);
o2sm_method_new("/arco/monodistortion/set_volume", "iif",
arco_monodistortion_set_volume, NULL, true, true);
// END INTERFACE INITIALIZATION

// class initialization code from faust:
}

Initializer monodistortion_init_obj(monodistortion_init);
Loading