diff --git a/src/lang.zig b/src/lang.zig index a455a1f..8b1e16e 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -88,30 +88,30 @@ pub const Command = struct { .rflanger => RFlanger, .eq => Eq, .phaser => Phaser, - .mbeq => Mbeq, - .chorus => Chorus, - .pitchscaler => Pitchscaler, - .reverb => Reverb, - .highpass => Highpass, - .delay => Delay, - .vinyl => Vinyl, - .revdelay => Revdelay, - .gate => Gate, - .detune => Detune, - .overdrive => Overdrive, - .degrade => Degrade, - .repsycho => Repsycho, - .talkbox => Talkbox, - .dyncomp => Dyncomp, - .thruzero => Thruzero, - .foverdrive => Foverdrive, - .gverb => Gverb, - .invert => Invert, - .tapedelay => Tapedelay, - .moddelay => Moddelay, - .multichorus => Multichorus, - .saturator => Saturator, - .vintagedelay => Vintagedelay, + // .mbeq => Mbeq, + // .chorus => Chorus, + // .pitchscaler => Pitchscaler, + // .reverb => Reverb, + // .highpass => Highpass, + // .delay => Delay, + // .vinyl => Vinyl, + // .revdelay => Revdelay, + // .gate => Gate, + // .detune => Detune, + // .overdrive => Overdrive, + // .degrade => Degrade, + // .repsycho => Repsycho, + // .talkbox => Talkbox, + // .dyncomp => Dyncomp, + // .thruzero => Thruzero, + // .foverdrive => Foverdrive, + // .gverb => Gverb, + // .invert => Invert, + // .tapedelay => Tapedelay, + // .moddelay => Moddelay, + // .multichorus => Multichorus, + // .saturator => Saturator, + // .vintagedelay => Vintagedelay, else => @panic("TODO"), }; @@ -175,252 +175,12 @@ pub const Command = struct { ); pub const Phaser = LV2Command( - .phaser, + .rflanger, "http://plugin.org.uk/swh-plugins/lfoPhaser", struct { lfo_rate: f32, lfo_depth: f32, fb: f32, spread: f32 }, ); - - pub const Mbeq = LV2Command( - .mbeq, - "http://plugin.org.uk/swh-plugins/mbeq", - struct { - band_1: f32, - band_2: f32, - band_3: f32, - band_4: f32, - band_5: f32, - band_6: f32, - band_7: f32, - band_8: f32, - band_9: f32, - band_10: f32, - band_11: f32, - band_12: f32, - band_13: f32, - band_14: f32, - band_15: f32, - }, - ); - - pub const Chorus = LV2Command( - .chorus, - "http://plugin.org.uk/swh-plugins/multivoiceChorus", - struct { - voices: f32, - delay_base: f32, - voice_spread: f32, - detune: f32, - law_freq: f32, - attendb: f32, - }, - ); - - pub const Pitchscaler = LV2Command( - .pitchscaler, - "http://plugin.org.uk/swh-plugins/pitchScaleHQ", - struct { mult: f32 }, - ); - - pub const Reverb = LV2Command( - .reverb, - "http://invadarecords.com/plugins/lv2/erreverb/mono", - struct { - roomLength: f32, - roomWidth: f32, - roomHeight: f32, - sourceLR: f32, - sourceFB: f32, - listLR: f32, - listFB: f32, - hpf: f32, - warmth: f32, - diffusion: f32, - }, - ); - - pub const Highpass = LV2Command(.highpass, "http://invadarecords.com/plugins/lv2/filter/hpf/mono", struct { - freq: f32, - gain: f32, - noClip: f32, - }); - - pub const Delay = LV2Command(.delay, "http://plugin.org.uk/swh-plugins/delayorama", struct { - seed: f32, - gain: f32, - feedback_pc: f32, - tap_count: f32, - first_delay: f32, - delay_range: f32, - delay_scale: f32, - delay_rand_pc: f32, - gain_scale: f32, - wet: f32, - }); - - pub const Vinyl = LV2Command(.vinyl, "http://plugin.org.uk/swh-plugins/vynil", struct { - year: f32, - rpm: f32, - warp: f32, - click: f32, - wear: f32, - }); - - pub const Revdelay = LV2Command(.revdelay, "http://plugin.org.uk/swh-plugins/revdelay", struct { - delay_time: f32, - dry_level: f32, - wet_level: f32, - feedback: f32, - xfade_samp: f32, - }); - // pub const Noise= LV2Command(.,,struct{}); - pub const Gate = LV2Command(.gate, "http://hippie.lt/lv2/gate", struct { - @"switch": f32, - threshold: f32, - attack: f32, - hold: f32, - decay: f32, - gaterange: f32, - }); - pub const Detune = LV2Command(.detune, "http://drobilla.net/plugins/mda/Detune", struct { - detune: f32, - mix: f32, - output: f32, - latency: f32, - }); - pub const Overdrive = LV2Command(.overdrive, "http://drobilla.net/plugins/mda/Overdrive", struct { - drive: f32, - muffle: f32, - output: f32, - }); - pub const Degrade = LV2Command(.degrade, "http://drobilla.net/plugins/mda/Degrade", struct { - headroom: f32, - quant: f32, - rate: f32, - post_filt: f32, - non_lin: f32, - output: f32, - }); - pub const Repsycho = LV2Command(.repsycho, "http://drobilla.net/plugins/mda/RePsycho", struct { - tune: f32, - fine: f32, - decay: f32, - thresh: f32, - hold: f32, - mix: f32, - quality: f32, - }); - pub const Talkbox = LV2Command(.talkbox, "http://drobilla.net/plugins/mda/TalkBox", struct { - wet: f32, - dry: f32, - carrier: f32, - quality: f32, - }); - pub const Dyncomp = LV2Command(.dyncomp, "http://gareus.org/oss/lv2/darc#mono", struct { - enable: f32, - hold: f32, - inputgain: f32, - threshold: f32, - ratio: f32, - attack: f32, - release: f32, - gain_min: f32, - gain_max: f32, - rms: f32, - }); - pub const Foverdrive = LV2Command(.foverdrive, "http://plugin.org.uk/swh-plugins/foverdrive", struct { - drive: f32, - }); - pub const Thruzero = LV2Command(.thruzero, "http://drobilla.net/plugins/mda/ThruZero", struct { - rate: f32, mix: f32, feedback: f32, depth_mod: f32 - }); - - pub const Gverb = LV2Command(.gverb, "http://plugin.org.uk/swh-plugins/gverb", struct { - roomsize: f32, - revtime: f32, - damping: f32, - inputbandwidth: f32, - drylevel: f32, - earlylevel: f32, - taillevel: f32, - }); - pub const Invert = LV2Command(.invert, "http://plugin.org.uk/swh-plugins/inv", struct {}); - pub const Tapedelay = LV2Command(.tapedelay, "http://plugin.org.uk/swh-plugins/tapeDelay", struct { - speed: f32, - da_db: f32, - - t1d: f32, - t1a_db: f32, - - t2d: f32, - t2a_db: f32, - - t3d: f32, - t3a_db: f32, - - t4d: f32, - t4a_db: f32, - }); - pub const Moddelay = LV2Command(.moddelay, "http://plugin.org.uk/swh-plugins/modDelay", struct { - base: f32, - }); - - pub const Multichorus = LV2Command(.multichorus, "http://calf.sourceforge.net/plugins/MultiChorus", struct { - min_delay: f32, - mod_depth: f32, - mod_rate: f32, - stereo: f32, - voices: f32, - vphase: f32, - amount: f32, - dry: f32, - freq: f32, - freq2: f32, - q: f32, - overlap: f32, - level_in: f32, - level_out: f32, - lfo: f32, - }); - pub const Saturator = LV2Command(.saturator, "http://calf.sourceforge.net/plugins/Saturator", struct { - bypass: f32, - level_in: f32, - level_out: f32, - mix: f32, - drive: f32, - blend: f32, - lp_pre_freq: f32, - hp_pre_freq: f32, - lp_post_freq: f32, - hp_post_freq: f32, - p_freq: f32, - p_level: f32, - p_q: f32, - pre: f32, - post: f32, - }); - pub const Vintagedelay = LV2Command(.vintagedelay, "http://calf.sourceforge.net/plugins/VintageDelay", struct { - level_in: f32, - level_out: f32, - subdiv: f32, - time_l: f32, - time_r: f32, - feedback: f32, - amount: f32, - mix_mode: f32, - medium: f32, - dry: f32, - width: f32, - fragmentation: f32, - pbeats: f32, - pfrag: f32, - timing: f32, - bpm: f32, - ms: f32, - hz: f32, - bpm_host: f32, - }); }; pub const CommandList = std.ArrayList(*Command); diff --git a/src/runner.zig b/src/runner.zig index e65bac0..962cfcc 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -190,6 +190,78 @@ pub const Runner = struct { _ = try proc.spawnAndWait(); } + /// Run the http://lv2plug.in/plugins/eg-amp plugin over the file. + fn ampCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://lv2plug.in/plugins/eg-amp", pos, params); + } + + fn rFlangerCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/retroFlange", pos, params); + } + + fn eqCmd(self: *Runner, position: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/dj_eq_mono", position, params); + } + + fn phaserCmd(self: *Runner, position: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/lfoPhaser", position, params); + } + + fn mbeqCmd(self: *Runner, position: Position, bands: []const f32) !void { + var image = try self.getImage(); + var params = ParamList.init(self.allocator); + defer params.deinit(); + + for (bands) |band_value, idx| { + var sym = try std.fmt.allocPrint(self.allocator, "band_{}", .{idx + 1}); + try params.append(plugin.Param{ + .sym = sym, + .value = band_value, + }); + } + + try image.runPlugin("http://plugin.org.uk/swh-plugins/mbeq", position, params); + } + + fn chorusCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/multivoiceChorus", pos, params); + } + + fn pitchScalerCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/pitchScaleHQ", pos, params); + } + + fn reverbCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://invadarecords.com/plugins/lv2/erreverb/mono", pos, params); + } + + fn highpassCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://invadarecords.com/plugins/lv2/filter/hpf/mono", pos, params); + } + + fn delayCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/delayorama", pos, params); + } + + fn vinylCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/vynil", pos, params); + } + + fn revDelayCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/revdelay", pos, params); + } + fn noiseCmd(self: *Runner, pos: Position, map: *ParamMap) !void { var image = try self.getImage(); try image.runCustomPlugin(custom.RandomNoise, pos, *ParamMap, map); @@ -222,6 +294,86 @@ pub const Runner = struct { try magick.runRotate(image, deg, c_bgfill); } + fn gateCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + 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 dynCompCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://gareus.org/oss/lv2/darc#mono", pos, params); + } + + fn foverdriveCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/foverdrive", pos, params); + } + + fn thruZeroCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://drobilla.net/plugins/mda/ThruZero", pos, params); + } + + fn gverbCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/gverb", pos, params); + } + + fn invertCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/inv", pos, params); + } + + fn tapedelayCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/tapeDelay", pos, params); + } + + fn moddelayCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://plugin.org.uk/swh-plugins/modDelay", pos, params); + } + + fn multichorusCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://calf.sourceforge.net/plugins/MultiChorus", pos, params); + } + + fn saturatorCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://calf.sourceforge.net/plugins/Saturator", pos, params); + } + + fn vintagedelayCmd(self: *Runner, pos: Position, params: ParamList) !void { + var image = try self.getImage(); + try image.runPlugin("http://calf.sourceforge.net/plugins/VintageDelay", pos, params); + } + fn executeLV2Command(self: *@This(), command: var) !void { const pos = plugin.Position{ .split = command.split, @@ -280,30 +432,30 @@ pub const Runner = struct { .rflanger => try self.newRunCommandSingle(cmd, .rflanger), .eq => try self.newRunCommandSingle(cmd, .eq), .phaser => try self.newRunCommandSingle(cmd, .phaser), - .mbeq => try self.newRunCommandSingle(cmd, .mbeq), - .chorus => try self.newRunCommandSingle(cmd, .chorus), - .pitchscaler => try self.newRunCommandSingle(cmd, .pitchscaler), - .reverb => try self.newRunCommandSingle(cmd, .reverb), - .highpass => try self.newRunCommandSingle(cmd, .highpass), - .delay => try self.newRunCommandSingle(cmd, .delay), - .vinyl => try self.newRunCommandSingle(cmd, .vinyl), - .revdelay => try self.newRunCommandSingle(cmd, .revdelay), - .gate => try self.newRunCommandSingle(cmd, .gate), - .detune => try self.newRunCommandSingle(cmd, .detune), - .overdrive => try self.newRunCommandSingle(cmd, .overdrive), - .degrade => try self.newRunCommandSingle(cmd, .degrade), - .repsycho => try self.newRunCommandSingle(cmd, .repsycho), - .talkbox => try self.newRunCommandSingle(cmd, .talkbox), - .dyncomp => try self.newRunCommandSingle(cmd, .dyncomp), - .thruzero => try self.newRunCommandSingle(cmd, .thruzero), - .foverdrive => try self.newRunCommandSingle(cmd, .foverdrive), - .gverb => try self.newRunCommandSingle(cmd, .gverb), - .invert => try self.newRunCommandSingle(cmd, .invert), - .tapedelay => try self.newRunCommandSingle(cmd, .tapedelay), - .moddelay => try self.newRunCommandSingle(cmd, .moddelay), - .multichorus => try self.newRunCommandSingle(cmd, .multichorus), - .saturator => try self.newRunCommandSingle(cmd, .saturator), - .vintagedelay => try self.newRunCommandSingle(cmd, .vintagedelay), + // .mbeq => try self.newRunCommandSingle(cmd, .mbeq), + // .chorus => try self.newRunCommandSingle(cmd, .chorus), + // .pitchscaler => try self.newRunCommandSingle(cmd, .pitchscaler), + // .reverb => try self.newRunCommandSingle(cmd, .reverb), + // .highpass => try self.newRunCommandSingle(cmd, .highpass), + // .delay => try self.newRunCommandSingle(cmd, .delay), + // .vinyl => try self.newRunCommandSingle(cmd, .vinyl), + // .revdelay => try self.newRunCommandSingle(cmd, .revdelay), + // .gate => try self.newRunCommandSingle(cmd, .gate), + // .detune => try self.newRunCommandSingle(cmd, .detune), + // .overdrive => try self.newRunCommandSingle(cmd, .overdrive), + // .degrade => try self.newRunCommandSingle(cmd, .degrade), + // .repsycho => try self.newRunCommandSingle(cmd, .repsycho), + // .talkbox => try self.newRunCommandSingle(cmd, .talkbox), + // .dyncomp => try self.newRunCommandSingle(cmd, .dyncomp), + // .thruzero => try self.newRunCommandSingle(cmd, .thruzero), + // .foverdrive => try self.newRunCommandSingle(cmd, .foverdrive), + // .gverb => try self.newRunCommandSingle(cmd, .gverb), + // .invert => try self.newRunCommandSingle(cmd, .invert), + // .tapedelay => try self.newRunCommandSingle(cmd, .tapedelay), + // .moddelay => try self.newRunCommandSingle(cmd, .moddelay), + // .multichorus => try self.newRunCommandSingle(cmd, .multichorus), + // .saturator => try self.newRunCommandSingle(cmd, .saturator), + // .vintagedelay => try self.newRunCommandSingle(cmd, .vintagedelay), else => { std.debug.warn("TODO support {}\n", .{@tagName(cmd.tag)}); @@ -331,6 +483,112 @@ pub const Runner = struct { .Quicksave => try self.quicksaveCmd(), .RunQS => try self.runQSCmd(cmd.args.items[0]), + .Phaser => blk: { + const pos = try cmd.consumePosition(); + + try cmd.appendParam(¶ms, "lfo_rate"); + try cmd.appendParam(¶ms, "lfo_depth"); + try cmd.appendParam(¶ms, "fb"); + try cmd.appendParam(¶ms, "spread"); + + try self.phaserCmd(pos, params); + }, + + .Mbeq => blk: { + const pos = try cmd.consumePosition(); + const bands = try cmd.floatArgMany(self.allocator, 2, 15, @as(f32, 0)); + defer self.allocator.free(bands); + + try self.mbeqCmd(pos, bands); + }, + + .Chorus => blk: { + const pos = try cmd.consumePosition(); + + try cmd.appendParam(¶ms, "voices"); + try cmd.appendParam(¶ms, "delay_base"); + try cmd.appendParam(¶ms, "voice_spread"); + try cmd.appendParam(¶ms, "detune"); + try cmd.appendParam(¶ms, "law_freq"); + try cmd.appendParam(¶ms, "attendb"); + + try self.chorusCmd(pos, params); + }, + + .PitchScaler => blk: { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "mult"); + try self.pitchScalerCmd(pos, params); + }, + + .Reverb => blk: { + const pos = try cmd.consumePosition(); + + try cmd.appendParam(¶ms, "roomLength"); + try cmd.appendParam(¶ms, "roomWidth"); + try cmd.appendParam(¶ms, "roomHeight"); + try cmd.appendParam(¶ms, "sourceLR"); + try cmd.appendParam(¶ms, "sourceFB"); + try cmd.appendParam(¶ms, "listLR"); + try cmd.appendParam(¶ms, "listFB"); + try cmd.appendParam(¶ms, "hpf"); + try cmd.appendParam(¶ms, "warmth"); + try cmd.appendParam(¶ms, "diffusion"); + + try self.reverbCmd(pos, params); + }, + + .Highpass => blk: { + const pos = try cmd.consumePosition(); + + try cmd.appendParam(¶ms, "freq"); + try cmd.appendParam(¶ms, "gain"); + try cmd.appendParam(¶ms, "noClip"); + + try self.highpassCmd(pos, params); + }, + + .Delay => blk: { + const pos = try cmd.consumePosition(); + + try cmd.appendParam(¶ms, "seed"); + try cmd.appendParam(¶ms, "gain"); + try cmd.appendParam(¶ms, "feedback_pc"); + try cmd.appendParam(¶ms, "tap_count"); + try cmd.appendParam(¶ms, "first_delay"); + try cmd.appendParam(¶ms, "delay_range"); + try cmd.appendParam(¶ms, "delay_scale"); + try cmd.appendParam(¶ms, "delay_rand_pc"); + try cmd.appendParam(¶ms, "gain_scale"); + try cmd.appendParam(¶ms, "wet"); + + try self.delayCmd(pos, params); + }, + + .Vinyl => blk: { + const pos = try cmd.consumePosition(); + + try cmd.appendParam(¶ms, "year"); + try cmd.appendParam(¶ms, "rpm"); + try cmd.appendParam(¶ms, "warp"); + try cmd.appendParam(¶ms, "click"); + try cmd.appendParam(¶ms, "wear"); + + try self.vinylCmd(pos, params); + }, + + .RevDelay => blk: { + const pos = try cmd.consumePosition(); + + try cmd.appendParam(¶ms, "delay_time"); + try cmd.appendParam(¶ms, "dry_level"); + try cmd.appendParam(¶ms, "wet_level"); + try cmd.appendParam(¶ms, "feedback"); + try cmd.appendParam(¶ms, "xfade_samp"); + + try self.revDelayCmd(pos, params); + }, + .Noise => blk: { const pos = try cmd.consumePosition(); @@ -367,6 +625,211 @@ pub const Runner = struct { try self.rotateCmd(deg, bgfill); }, + .Gate => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "switch"); + try cmd.appendParam(¶ms, "threshold"); + try cmd.appendParam(¶ms, "attack"); + try cmd.appendParam(¶ms, "hold"); + try cmd.appendParam(¶ms, "decay"); + try cmd.appendParam(¶ms, "gaterange"); + 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); + }, + + .DynComp => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "enable"); + try cmd.appendParam(¶ms, "hold"); + try cmd.appendParam(¶ms, "inputgain"); + try cmd.appendParam(¶ms, "threshold"); + try cmd.appendParam(¶ms, "ratio"); + try cmd.appendParam(¶ms, "attack"); + try cmd.appendParam(¶ms, "release"); + try cmd.appendParam(¶ms, "gain_min"); + try cmd.appendParam(¶ms, "gain_max"); + try cmd.appendParam(¶ms, "rms"); + try self.dynCompCmd(pos, params); + }, + + .ThruZero => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "rate"); + try cmd.appendParam(¶ms, "mix"); + try cmd.appendParam(¶ms, "feedback"); + try cmd.appendParam(¶ms, "depth_mod"); + try self.thruZeroCmd(pos, params); + }, + + .Foverdrive => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "drive"); + try self.foverdriveCmd(pos, params); + }, + + .Gverb => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "roomsize"); + try cmd.appendParam(¶ms, "revtime"); + try cmd.appendParam(¶ms, "damping"); + try cmd.appendParam(¶ms, "inputbandwidth"); + try cmd.appendParam(¶ms, "drylevel"); + try cmd.appendParam(¶ms, "earlylevel"); + try cmd.appendParam(¶ms, "taillevel"); + try self.gverbCmd(pos, params); + }, + + .Invert => { + const pos = try cmd.consumePosition(); + try self.gverbCmd(pos, params); + }, + + .TapeDelay => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "speed"); + try cmd.appendParam(¶ms, "da_db"); + + try cmd.appendParam(¶ms, "t1d"); + try cmd.appendParam(¶ms, "t1a_db"); + + try cmd.appendParam(¶ms, "t2d"); + try cmd.appendParam(¶ms, "t2a_db"); + + try cmd.appendParam(¶ms, "t3d"); + try cmd.appendParam(¶ms, "t3a_db"); + + try cmd.appendParam(¶ms, "t4d"); + try cmd.appendParam(¶ms, "t4a_db"); + + try self.tapedelayCmd(pos, params); + }, + + .ModDelay => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "base"); + try self.moddelayCmd(pos, params); + }, + + .MultiChorus => { + const pos = try cmd.consumePosition(); + try cmd.appendParam(¶ms, "min_delay"); + try cmd.appendParam(¶ms, "mod_depth"); + try cmd.appendParam(¶ms, "mod_rate"); + try cmd.appendParam(¶ms, "stereo"); + try cmd.appendParam(¶ms, "voices"); + try cmd.appendParam(¶ms, "vphase"); + try cmd.appendParam(¶ms, "amount"); + try cmd.appendParam(¶ms, "dry"); + try cmd.appendParam(¶ms, "freq"); + try cmd.appendParam(¶ms, "freq2"); + try cmd.appendParam(¶ms, "q"); + try cmd.appendParam(¶ms, "overlap"); + try cmd.appendParam(¶ms, "level_in"); + try cmd.appendParam(¶ms, "level_out"); + try cmd.appendParam(¶ms, "lfo"); + try self.multichorusCmd(pos, params); + }, + + .Saturator => { + const pos = try cmd.consumePosition(); + + try cmd.appendParam(¶ms, "bypass"); + try cmd.appendParam(¶ms, "level_in"); + try cmd.appendParam(¶ms, "level_out"); + try cmd.appendParam(¶ms, "mix"); + try cmd.appendParam(¶ms, "drive"); + try cmd.appendParam(¶ms, "blend"); + try cmd.appendParam(¶ms, "lp_pre_freq"); + try cmd.appendParam(¶ms, "hp_pre_freq"); + try cmd.appendParam(¶ms, "lp_post_freq"); + try cmd.appendParam(¶ms, "hp_post_freq"); + try cmd.appendParam(¶ms, "p_freq"); + try cmd.appendParam(¶ms, "p_level"); + try cmd.appendParam(¶ms, "p_q"); + try cmd.appendParam(¶ms, "pre"); + try cmd.appendParam(¶ms, "post"); + try self.saturatorCmd(pos, params); + }, + + .VintageDelay => { + const pos = try cmd.consumePosition(); + const PARAMS = [_][]const u8{ + "level_in", + "level_out", + "subdiv", + "time_l", + "time_r", + "feedback", + "amount", + "mix_mode", + "medium", + "dry", + "width", + "fragmentation", + "pbeats", + "pfrag", + "timing", + "bpm", + "ms", + "hz", + "bpm_host", + }; + + inline for (PARAMS) |param| { + try cmd.appendParam(¶ms, param); + } + + try self.vintagedelayCmd(pos, params); + }, + else => blk: { std.debug.warn("Unsupported command: {}\n", .{cmd.command}); break :blk RunError.UnknownCommand;