diff --git a/README.md b/README.md index c289de8..d8e5ef9 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ glitch art "framework", ???????? language??? something? will likely be there by default) - the SWH plugins ( https://github.com/swh/lv2 ) - the Invada Studio plugins ( https://launchpad.net/invada-studio/ ) + - abGate plugin ```bash # build and install diff --git a/doc/README.md b/doc/README.md index 74a1445..bb312ee 100644 --- a/doc/README.md +++ b/doc/README.md @@ -181,9 +181,67 @@ just be different. ## `gate split index switch threshold attack hold decay gaterange` +**TODO:** find good parameters + - switch (bool): 0..1, default 0 - threshold (dB): -70..12, default -70 - attack (ms): 0.1..500, default 30 - hold (ms): 5..3000, default 500 - decay (ms): 5..4000, default 1000 - gaterange (dB): -90..-20, default -90 + +## `detune split index detune mix output latency` + +> A low-quality stereo pitch shifter for the sort of chorus and detune effects found on multi-effects hardware. + + - detune (cents, left channel is lowered in pitch, right channel is raised): 0..1, default 0.2 + - mix (wet/dry mix): 0..1, default 0.9 + - output (level trim): 0..1, default 0.5 + - latency (trade-off between latency and low-freq response): 0..1, default 0.5 + +other presets: + - stereo detune: 0.2 0.9 0.5 0.5 + - out of tune: 0.8 0.7 0.5 0.5 + + +## `overdrive split index drive muffle output` + +> Possible uses include adding body to drum loops, fuzz guitar, and that 'standing outside a nightclub' sound. This plug does not simulate valve distortion, and any attempt to process organ sounds through it will be extremely unrewarding! + + - drive (amount of distortion): 0..1, default 0 + - muffle (gentle low-pass filter): 0..1, default 0 + - output (level trim): 0..1, default 0.5 + +## `degrade split index headroom quant rate post_filt non_lin output` + +> Sample quality reduction + +**NOTE:** finding the right parameters is HARD for this plugin. + + - headroom (peak clipping threshold): 0..1, default 0.8 + - quant (bit depth, typically 8 or below for "telephone" quality): 0..1, default 0.5 + - rate (sample rate): 0..1, default 0.65 + - post_filt (low-pass filter to muffle the distortion): 0..1, default 0.9 + - non_lin (additional harmonic distortion "thickening"): 0..1, default 0.58 + - output: 0..1, default 0.5 + +## `repsycho split index tune fine decay thresh hold mix quality` + +**NOTE:** HARD to find good parameters + + - tune (coarse tune, semitones): 0..1, default 1 + - fine (fine tune, cents): 0..1, default 1 + - decay (adjust envelope of each trunk, a fast decay can be useful while setting up): 0..1, default 0.5 + - thresh (trigger level to divide the input into chunks): 0..1, default 0.6 + - hold (minimum chunk length): 0..1, default 0.45 + - mix (mix original signal with output): 0..1, default 1 + - quality (quality, bool. the high=1 setting uses smoother pitch-shifting and allows stereo): 0..1, default 0 + +## `talkbox split index wet dry carrier quality` + +> High resolution vocoder + + - wet: 0..1, default 0.5 + - dry: 0..1, default 0 + - carrier: 0..1, default 0 + - quality: 0..1, default 1 diff --git a/examples/degrade.scri b/examples/degrade.scri new file mode 100644 index 0000000..ccd1a2c --- /dev/null +++ b/examples/degrade.scri @@ -0,0 +1,5 @@ +load :0; +degrade 5 1 0.8 0.5 0.65 0.9 0.58 0.5; +degrade 5 2 0.1 1 0.65 0.5 0.5 0.4; +degrade 5 3 0.1 1 0.65 0.9 0.58 0.5; +quicksave; diff --git a/examples/detune.scri b/examples/detune.scri new file mode 100644 index 0000000..269e80d --- /dev/null +++ b/examples/detune.scri @@ -0,0 +1,3 @@ +load :0; +detune 3 1 0.2 0.9 0.5 0.5; +quicksave; diff --git a/examples/gate.scri b/examples/gate.scri index 9269932..7299d00 100644 --- a/examples/gate.scri +++ b/examples/gate.scri @@ -1,5 +1,3 @@ load :0; -gate 5 1 0 1 100 500 1000 -50; -gate 5 2 1 1 100 500 1000 -50; -gate 5 3 1 1 150 1000 1000 -50; +gate 3 1 0 -70 30 500 1000 -90; quicksave; diff --git a/examples/overdrive.scri b/examples/overdrive.scri new file mode 100644 index 0000000..585f8ad --- /dev/null +++ b/examples/overdrive.scri @@ -0,0 +1,5 @@ +load :0; +overdrive 5 1 0.5 0 0.4; +overdrive 5 2 0.6 0.2 0.3; +overdrive 5 3 0.7 0.3 0.2; +quicksave; diff --git a/examples/repsycho.scri b/examples/repsycho.scri new file mode 100644 index 0000000..757c728 --- /dev/null +++ b/examples/repsycho.scri @@ -0,0 +1,8 @@ +load :0; +repsycho 8 1 1 1 0.5 0.6 0.45 1 0; +repsycho 8 2 1 1 1 0.6 0.45 1 0; +repsycho 8 3 1 1 0.5 0.8 0.45 1 0; +repsycho 8 4 1 1 0.5 0.6 0.1 1 0; +repsycho 8 5 1 1 0.5 0.6 0.45 0.5 0; +repsycho 8 6 1 1 0.5 0.6 0.45 1 1; +quicksave; diff --git a/examples/talkbox.scri b/examples/talkbox.scri new file mode 100644 index 0000000..2f3c386 --- /dev/null +++ b/examples/talkbox.scri @@ -0,0 +1,3 @@ +load :0; +talkbox 3 1 0.5 0 0 1; +quicksave; diff --git a/src/lang.zig b/src/lang.zig index 07e5fb1..1ade59c 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -27,6 +27,11 @@ pub const CommandType = enum { Vinyl, RevDelay, Gate, + Detune, + Overdrive, + Degrade, + RePsycho, + TalkBox, Noise, WildNoise, @@ -186,12 +191,17 @@ pub const Lang = struct { _ = try self.keywords.put("vinyl", .Vinyl); _ = try self.keywords.put("revdelay", .RevDelay); _ = try self.keywords.put("gate", .Gate); + _ = try self.keywords.put("detune", .Detune); + _ = try self.keywords.put("overdrive", .Overdrive); + _ = try self.keywords.put("talkbox", .TalkBox); // custom implementations (not lv2) _ = try self.keywords.put("noise", .Noise); _ = try self.keywords.put("wildnoise", .WildNoise); _ = try self.keywords.put("write", .Write); _ = try self.keywords.put("embed", .Embed); + _ = try self.keywords.put("degrade", .Degrade); + _ = try self.keywords.put("repsycho", .RePsycho); // even more custom _ = try self.keywords.put("rotate", .Rotate); diff --git a/src/printer.zig b/src/printer.zig index faa863a..d685979 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -21,6 +21,11 @@ pub fn printList(list: langs.CommandList, stream: var) !void { .Vinyl => "vinyl", .RevDelay => "revdelay", .Gate => "gate", + .Detune => "detune", + .Overdrive => "overdrive", + .Degrade => "Degrade", + .RePsycho => "repsycho", + .TalkBox => "talkbox", .Noise => "noise", .WildNoise => "wildnoise", diff --git a/src/runner.zig b/src/runner.zig index 44c9fb4..86f6e06 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -299,6 +299,31 @@ pub const Runner = struct { try image.runPlugin("http://hippie.lt/lv2/gate", pos, params); } + fn detuneCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://drobilla.net/plugins/mda/Detune", pos, params); + } + + fn overdriveCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://drobilla.net/plugins/mda/Overdrive", pos, params); + } + + fn degradeCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://drobilla.net/plugins/mda/Degrade", pos, params); + } + + fn repsychoCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://drobilla.net/plugins/mda/RePsycho", pos, params); + } + + fn talkboxCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://drobilla.net/plugins/mda/TalkBox", pos, params); + } + fn runCommand(self: *Runner, cmd: *lang.Command) !void { var params = ParamList.init(self.allocator); defer params.deinit(); @@ -493,6 +518,54 @@ pub const Runner = struct { try self.gateCmd(pos, params); }, + .Detune => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "detune"); + try cmd.appendParam(¶ms, "mix"); + try cmd.appendParam(¶ms, "output"); + try cmd.appendParam(¶ms, "latency"); + try self.detuneCmd(pos, params); + }, + + .Overdrive => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "drive"); + try cmd.appendParam(¶ms, "muffle"); + try cmd.appendParam(¶ms, "output"); + try self.overdriveCmd(pos, params); + }, + + .Degrade => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "headroom"); + try cmd.appendParam(¶ms, "quant"); + try cmd.appendParam(¶ms, "rate"); + try cmd.appendParam(¶ms, "post_filt"); + try cmd.appendParam(¶ms, "non_lin"); + try cmd.appendParam(¶ms, "output"); + try self.degradeCmd(pos, params); + }, + + .RePsycho => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "tune"); + try cmd.appendParam(¶ms, "fine"); + try cmd.appendParam(¶ms, "decay"); + try cmd.appendParam(¶ms, "thresh"); + try cmd.appendParam(¶ms, "hold"); + try cmd.appendParam(¶ms, "mix"); + try cmd.appendParam(¶ms, "quality"); + try self.repsychoCmd(pos, params); + }, + + .TalkBox => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "wet"); + try cmd.appendParam(¶ms, "dry"); + try cmd.appendParam(¶ms, "carrier"); + try cmd.appendParam(¶ms, "quality"); + try self.talkboxCmd(pos, params); + }, else => blk: { std.debug.warn("Unsupported command: {}\n", .{cmd.command}); break :blk RunError.UnknownCommand;