2 Parameters 1 Knob With a Switch and Soft Takeover mode?

Hi there,

I am trying my luck here, cause i am fighting with the logic of this and can not for the love of me figure it out and i think it is very easily doable.

i’m looking to use one knob to control two parameters with the use of a switch. = switch not pressed, control param 1 is the switch pressed and held control param 2.

when switching the current value is stored in a [sah] and when switching back i want a soft takeover to occur. so not a sudden change of the param value to the current knob value, but rather only change as soon as it crossed the value stored in the sah.

in attachement what i have now, i feel i am one or two nodes away of cracking it. controlling 2 params works, but the soft takeover mode is struggling. i think the answer lies within checking if the current knob value is above or below t he stored value and based on that waiting for it to [<=] or [>=] respectively before switching back to the knob value. maybe with a selector or a gate or something between the latch and the output?

my brain is exploding any help would be greatly appreciated!!

{
	"boxes" : [ 		{
			"box" : 			{
				"maxclass" : "comment",
				"text" : "switch to change between params",
				"linecount" : 2,
				"id" : "obj-7",
				"patching_rect" : [ 292.0, 121.0, 150.0, 33.0 ],
				"numinlets" : 1,
				"numoutlets" : 0
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "comment",
				"text" : "param 2 sah value",
				"id" : "obj-17",
				"patching_rect" : [ 439.0, 384.0, 150.0, 20.0 ],
				"numinlets" : 1,
				"numoutlets" : 0
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "comment",
				"text" : "param 1 sah value",
				"id" : "obj-16",
				"patching_rect" : [ 181.0, 384.0, 150.0, 20.0 ],
				"numinlets" : 1,
				"numoutlets" : 0
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "comment",
				"text" : "param 2",
				"id" : "obj-15",
				"patching_rect" : [ 439.0, 354.0, 150.0, 20.0 ],
				"numinlets" : 1,
				"numoutlets" : 0
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "comment",
				"text" : "param 1",
				"id" : "obj-14",
				"patching_rect" : [ 181.0, 353.0, 150.0, 20.0 ],
				"numinlets" : 1,
				"numoutlets" : 0
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "number~",
				"id" : "obj-12",
				"outlettype" : [ "signal", "float" ],
				"fontsize" : 12.0,
				"mode" : 2,
				"sig" : 0.0,
				"fontname" : "Arial",
				"patching_rect" : [ 379.0, 384.0, 56.0, 22.0 ],
				"numinlets" : 2,
				"fontface" : 0,
				"numoutlets" : 2
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "number~",
				"id" : "obj-11",
				"outlettype" : [ "signal", "float" ],
				"fontsize" : 12.0,
				"mode" : 2,
				"sig" : 0.0,
				"fontname" : "Arial",
				"patching_rect" : [ 118.5, 384.0, 56.0, 22.0 ],
				"numinlets" : 2,
				"fontface" : 0,
				"numoutlets" : 2
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "number~",
				"id" : "obj-10",
				"outlettype" : [ "signal", "float" ],
				"fontsize" : 12.0,
				"mode" : 2,
				"sig" : 0.0,
				"fontname" : "Arial",
				"patching_rect" : [ 379.0, 353.0, 56.0, 22.0 ],
				"numinlets" : 2,
				"fontface" : 0,
				"numoutlets" : 2
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "attrui",
				"id" : "obj-9",
				"parameter_enable" : 0,
				"outlettype" : [ "" ],
				"attr" : "sw1",
				"patching_rect" : [ 285.0, 162.0, 150.0, 22.0 ],
				"numinlets" : 1,
				"displaymode" : 8,
				"numoutlets" : 1
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "attrui",
				"id" : "obj-6",
				"parameter_enable" : 0,
				"outlettype" : [ "" ],
				"attr" : "knob1",
				"patching_rect" : [ 118.5, 162.0, 150.0, 22.0 ],
				"numinlets" : 1,
				"numoutlets" : 1
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "number~",
				"id" : "obj-3",
				"outlettype" : [ "signal", "float" ],
				"fontsize" : 12.0,
				"mode" : 2,
				"sig" : 0.0,
				"fontname" : "Arial",
				"patching_rect" : [ 118.5, 353.0, 56.0, 22.0 ],
				"numinlets" : 2,
				"fontface" : 0,
				"numoutlets" : 2
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "ezdac~",
				"id" : "obj-2",
				"patching_rect" : [ 228.0, 587.0, 45.0, 45.0 ],
				"numinlets" : 2,
				"numoutlets" : 0
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "gen~",
				"id" : "obj-1",
				"outlettype" : [ "signal", "signal", "signal", "signal" ],
				"patching_rect" : [ 232.5, 249.0, 36.0, 22.0 ],
				"numinlets" : 1,
				"numoutlets" : 4,
				"patcher" : 				{
					"fileversion" : 1,
					"appversion" : 					{
						"major" : 8,
						"minor" : 6,
						"revision" : 0,
						"architecture" : "x64",
						"modernui" : 1
					}
,
					"classnamespace" : "dsp.gen",
					"rect" : [ 757.0, 106.0, 937.0, 896.0 ],
					"bglocked" : 0,
					"openinpresentation" : 0,
					"default_fontsize" : 12.0,
					"default_fontface" : 0,
					"default_fontname" : "Arial",
					"gridonopen" : 1,
					"gridsize" : [ 15.0, 15.0 ],
					"gridsnaponopen" : 1,
					"objectsnaponopen" : 1,
					"statusbarvisible" : 2,
					"toolbarvisible" : 1,
					"lefttoolbarpinned" : 0,
					"toptoolbarpinned" : 0,
					"righttoolbarpinned" : 0,
					"bottomtoolbarpinned" : 0,
					"toolbars_unpinned_last_save" : 0,
					"tallnewobj" : 0,
					"boxanimatetime" : 200,
					"enablehscroll" : 1,
					"enablevscroll" : 1,
					"devicewidth" : 0.0,
					"description" : "",
					"digest" : "",
					"tags" : "",
					"style" : "",
					"subpatcher_template" : "",
					"assistshowspatchername" : 0,
					"boxes" : [ 						{
							"box" : 							{
								"maxclass" : "comment",
								"text" : "sample when switch is unpressed",
								"linecount" : 2,
								"id" : "obj-59",
								"patching_rect" : [ 487.0, 304.5, 122.0, 33.0 ],
								"numinlets" : 1,
								"numoutlets" : 0
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "comment",
								"text" : "sample when switch is pressed",
								"linecount" : 2,
								"id" : "obj-58",
								"patching_rect" : [ 205.0, 308.5, 122.0, 33.0 ],
								"numinlets" : 1,
								"numoutlets" : 0
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "comment",
								"text" : "latch when switch is pressed",
								"linecount" : 2,
								"id" : "obj-57",
								"patching_rect" : [ 299.0, 268.5, 122.0, 33.0 ],
								"numinlets" : 1,
								"numoutlets" : 0
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "comment",
								"text" : "latch when switch is unpressed",
								"linecount" : 2,
								"id" : "obj-55",
								"patching_rect" : [ 14.0, 268.5, 122.0, 33.0 ],
								"numinlets" : 1,
								"numoutlets" : 0
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "== 0",
								"id" : "obj-29",
								"outlettype" : [ "" ],
								"patching_rect" : [ 479.0, 215.0, 33.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 1
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "sah",
								"id" : "obj-28",
								"outlettype" : [ "" ],
								"patching_rect" : [ 188.0, 274.0, 40.0, 22.0 ],
								"numinlets" : 3,
								"numoutlets" : 1
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "out 3",
								"id" : "obj-27",
								"patching_rect" : [ 188.0, 367.0, 35.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 0
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "out 4",
								"id" : "obj-26",
								"patching_rect" : [ 468.5, 367.0, 35.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 0
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "sah",
								"id" : "obj-23",
								"outlettype" : [ "" ],
								"patching_rect" : [ 468.5, 274.0, 40.0, 22.0 ],
								"numinlets" : 3,
								"numoutlets" : 1
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "== 0",
								"id" : "obj-12",
								"outlettype" : [ "" ],
								"patching_rect" : [ 154.0, 221.0, 33.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 1
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "out 2",
								"id" : "obj-11",
								"patching_rect" : [ 423.0, 577.0, 35.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 0
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "latch",
								"id" : "obj-9",
								"outlettype" : [ "" ],
								"patching_rect" : [ 138.0, 274.0, 34.0, 22.0 ],
								"numinlets" : 2,
								"numoutlets" : 1
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "param sw1 @min 0 @max 1",
								"id" : "obj-8",
								"outlettype" : [ "" ],
								"patching_rect" : [ 423.0, 110.0, 160.0, 22.0 ],
								"numinlets" : 0,
								"numoutlets" : 1
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "latch",
								"id" : "obj-7",
								"outlettype" : [ "" ],
								"patching_rect" : [ 423.0, 274.0, 34.0, 22.0 ],
								"numinlets" : 2,
								"numoutlets" : 1
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "out 1",
								"id" : "obj-6",
								"patching_rect" : [ 138.0, 577.0, 35.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 0
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "param knob1 @min 0 @max 1",
								"id" : "obj-5",
								"outlettype" : [ "" ],
								"patching_rect" : [ 129.0, 110.0, 172.0, 22.0 ],
								"numinlets" : 0,
								"numoutlets" : 1
							}

						}
 ],
					"lines" : [ 						{
							"patchline" : 							{
								"source" : [ "obj-9", 0 ],
								"destination" : [ "obj-6", 0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-8", 0 ],
								"destination" : [ "obj-7", 1 ],
								"midpoints" : [ 432.5, 169.0, 447.5, 169.0 ],
								"order" : 1
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-8", 0 ],
								"destination" : [ "obj-29", 0 ],
								"midpoints" : [ 432.5, 201.0, 488.5, 201.0 ],
								"order" : 0
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-8", 0 ],
								"destination" : [ "obj-28", 1 ],
								"midpoints" : [ 432.5, 255.0, 208.0, 255.0 ],
								"order" : 2
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-8", 0 ],
								"destination" : [ "obj-12", 0 ],
								"midpoints" : [ 432.5, 207.0, 163.5, 207.0 ],
								"order" : 3
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-7", 0 ],
								"destination" : [ "obj-11", 0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-5", 0 ],
								"destination" : [ "obj-9", 0 ],
								"midpoints" : [ 138.5, 255.0, 147.5, 255.0 ],
								"order" : 3
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-5", 0 ],
								"destination" : [ "obj-7", 0 ],
								"midpoints" : [ 138.5, 180.0, 432.5, 180.0 ],
								"order" : 1
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-5", 0 ],
								"destination" : [ "obj-28", 0 ],
								"midpoints" : [ 138.5, 255.0, 197.5, 255.0 ],
								"order" : 2
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-5", 0 ],
								"destination" : [ "obj-23", 0 ],
								"midpoints" : [ 138.5, 196.0, 478.0, 196.0 ],
								"order" : 0
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-29", 0 ],
								"destination" : [ "obj-23", 1 ],
								"midpoints" : [ 488.5, 240.0, 488.5, 240.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-28", 0 ],
								"destination" : [ "obj-27", 0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-23", 0 ],
								"destination" : [ "obj-26", 0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-12", 0 ],
								"destination" : [ "obj-9", 1 ],
								"midpoints" : [ 163.5, 246.0, 162.5, 246.0 ]
							}

						}
 ]
				}

			}

		}
 ],
	"lines" : [ 		{
			"patchline" : 			{
				"source" : [ "obj-9", 0 ],
				"destination" : [ "obj-1", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-6", 0 ],
				"destination" : [ "obj-1", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-1", 0 ],
				"destination" : [ "obj-3", 0 ],
				"midpoints" : [ 242.0, 339.0, 128.0, 339.0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-1", 3 ],
				"destination" : [ "obj-12", 0 ],
				"midpoints" : [ 259.0, 427.0, 388.5, 427.0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-1", 2 ],
				"destination" : [ "obj-11", 0 ],
				"midpoints" : [ 253.333333333333314, 428.0, 128.0, 428.0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-1", 1 ],
				"destination" : [ "obj-10", 0 ],
				"midpoints" : [ 247.666666666666657, 339.0, 388.5, 339.0 ]
			}

		}
 ],
	"appversion" : 	{
		"major" : 8,
		"minor" : 6,
		"revision" : 0,
		"architecture" : "x64",
		"modernui" : 1
	}
,
	"classnamespace" : "box"
}

Hello Martin!

Let me make sure that I’m understanding what you want to achieve here.
So is the following example along the line of what you want to do?

  1. Toggle starts out OFF and you twist the knob from 0.0 to 0.6 position (param 1 is now 0.6)
  2. Toggle ON (param 1 sah value is now 0.6 and param 1 is also still 0.6)
  3. Twist knob from 0.6 to 0.8 (param 2 is now 0.8)
  4. Toggle OFF (param 2 sah value is now 0.8)

Then, do you want to patch it so that param 1 WON’T change until you move the knob to position 0.6? And once it reaches there, you want to be able to set a new param 1 value?
The current issue is that param1 becomes 0.8 at step 4.

1 Like

Yes that’s exactly it! (But not with a toggle but with a button held down, minor difference)

And once you switch back to param1 the same should happen for param 2 where it will again only start modifying that parameter once the knob reaches that position.

Thanks for your reply and hope we can find a way :slight_smile:

Yeah, I can see how this is a tricky one.
My intuition is to suggest that you use codebox since visual programming language can be tricky with conditionals.

But how though:)) I’m such a noobie with codebox I have no idea even how to approach that :grimacing:

@hooke: Here ya go! You should be able to copy this text and paste it into a Max window to get the patch. Let me know if for some reason there’s nothing inside the gen~ object. Make sure audio is turned on to test it out!

I agree with @Takumi_Ogata – this is the kind of thing that’s much easier inside a codebox. I had to do some silly stuff in order to make variables persist across audio frames – routing them out the bottom of the codebox and in the top, with a single-sample delay. Happy to explain the code if you like!

{
	"boxes" : [ 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "prepend switch",
				"patching_rect" : [ 281.0, 134.0, 89.0, 22.0 ],
				"numinlets" : 1,
				"numoutlets" : 1,
				"id" : "obj-31",
				"outlettype" : [ "" ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "snapshot~",
				"patching_rect" : [ 305.88233470916748, 276.470571756362915, 64.0, 22.0 ],
				"numinlets" : 2,
				"numoutlets" : 1,
				"id" : "obj-30",
				"outlettype" : [ "float" ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "button",
				"patching_rect" : [ 240.0, 167.0, 24.0, 24.0 ],
				"numinlets" : 1,
				"numoutlets" : 1,
				"id" : "obj-28",
				"parameter_enable" : 0,
				"outlettype" : [ "bang" ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "prepend knob",
				"patching_rect" : [ 266.0, 110.0, 82.0, 22.0 ],
				"numinlets" : 1,
				"numoutlets" : 1,
				"id" : "obj-19",
				"outlettype" : [ "" ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "snapshot~",
				"patching_rect" : [ 238.0, 276.470571756362915, 64.0, 22.0 ],
				"numinlets" : 2,
				"numoutlets" : 1,
				"id" : "obj-18",
				"outlettype" : [ "float" ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "live.dial",
				"varname" : "live.dial[3]",
				"patching_rect" : [ 306.0, 315.34872031211853, 41.0, 48.0 ],
				"numinlets" : 1,
				"numoutlets" : 2,
				"id" : "obj-11",
				"parameter_enable" : 1,
				"outlettype" : [ "", "float" ],
				"saved_attribute_attributes" : 				{
					"valueof" : 					{
						"parameter_longname" : "live.dial[3]",
						"parameter_mmax" : 1.0,
						"parameter_modmode" : 3,
						"parameter_shortname" : "live.dial",
						"parameter_type" : 0,
						"parameter_unitstyle" : 1
					}

				}

			}

		}
, 		{
			"box" : 			{
				"maxclass" : "live.dial",
				"varname" : "live.dial[2]",
				"patching_rect" : [ 238.0, 315.34872031211853, 41.0, 48.0 ],
				"numinlets" : 1,
				"numoutlets" : 2,
				"id" : "obj-10",
				"parameter_enable" : 1,
				"outlettype" : [ "", "float" ],
				"saved_attribute_attributes" : 				{
					"valueof" : 					{
						"parameter_longname" : "live.dial[2]",
						"parameter_mmax" : 1.0,
						"parameter_modmode" : 3,
						"parameter_shortname" : "live.dial",
						"parameter_type" : 0,
						"parameter_unitstyle" : 1
					}

				}

			}

		}
, 		{
			"box" : 			{
				"maxclass" : "live.toggle",
				"varname" : "live.toggle",
				"patching_rect" : [ 320.089282661676407, 51.785713791847229, 41.0, 41.0 ],
				"numinlets" : 1,
				"numoutlets" : 1,
				"id" : "obj-7",
				"parameter_enable" : 1,
				"outlettype" : [ "" ],
				"saved_attribute_attributes" : 				{
					"valueof" : 					{
						"parameter_enum" : [ "off", "on" ],
						"parameter_longname" : "live.toggle",
						"parameter_mmax" : 1,
						"parameter_modmode" : 0,
						"parameter_shortname" : "live.toggle",
						"parameter_type" : 2
					}

				}

			}

		}
, 		{
			"box" : 			{
				"maxclass" : "live.dial",
				"varname" : "live.dial",
				"patching_rect" : [ 266.0, 44.785713791847229, 41.0, 48.0 ],
				"numinlets" : 1,
				"numoutlets" : 2,
				"id" : "obj-2",
				"parameter_enable" : 1,
				"outlettype" : [ "", "float" ],
				"saved_attribute_attributes" : 				{
					"valueof" : 					{
						"parameter_longname" : "live.dial",
						"parameter_mmax" : 1.0,
						"parameter_modmode" : 3,
						"parameter_shortname" : "live.dial",
						"parameter_type" : 0,
						"parameter_unitstyle" : 1
					}

				}

			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "gen~",
				"patching_rect" : [ 266.0, 168.0, 36.0, 22.0 ],
				"numinlets" : 1,
				"numoutlets" : 2,
				"id" : "obj-1",
				"outlettype" : [ "signal", "signal" ],
				"patcher" : 				{
					"fileversion" : 1,
					"appversion" : 					{
						"major" : 8,
						"minor" : 6,
						"revision" : 2,
						"architecture" : "x64",
						"modernui" : 1
					}
,
					"classnamespace" : "dsp.gen",
					"rect" : [ 1062.0, 106.0, 960.0, 1105.0 ],
					"bglocked" : 0,
					"openinpresentation" : 0,
					"default_fontsize" : 12.0,
					"default_fontface" : 0,
					"default_fontname" : "Arial",
					"gridonopen" : 1,
					"gridsize" : [ 15.0, 15.0 ],
					"gridsnaponopen" : 1,
					"objectsnaponopen" : 1,
					"statusbarvisible" : 2,
					"toolbarvisible" : 1,
					"lefttoolbarpinned" : 0,
					"toptoolbarpinned" : 0,
					"righttoolbarpinned" : 0,
					"bottomtoolbarpinned" : 0,
					"toolbars_unpinned_last_save" : 0,
					"tallnewobj" : 0,
					"boxanimatetime" : 200,
					"enablehscroll" : 1,
					"enablevscroll" : 1,
					"devicewidth" : 0.0,
					"description" : "",
					"digest" : "",
					"tags" : "",
					"style" : "",
					"subpatcher_template" : "",
					"assistshowspatchername" : 0,
					"boxes" : [ 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"patching_rect" : [ 677.0, 61.0, 44.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-16",
								"outlettype" : [ "" ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"patching_rect" : [ 520.25, 61.0, 44.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-15",
								"outlettype" : [ "" ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"patching_rect" : [ 363.5, 61.0, 44.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-14",
								"outlettype" : [ "" ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "out 2",
								"patching_rect" : [ 677.0, 1064.0, 35.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 0,
								"id" : "obj-13"
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"patching_rect" : [ 206.75, 61.0, 44.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-12",
								"outlettype" : [ "" ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"patching_rect" : [ 50.0, 61.0, 44.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-11",
								"outlettype" : [ "" ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "codebox",
								"fontsize" : 12.0,
								"patching_rect" : [ 50.0, 85.0, 646.0, 936.0 ],
								"numinlets" : 5,
								"fontname" : "<Monospaced>",
								"numoutlets" : 5,
								"fontface" : 0,
								"id" : "obj-10",
								"outlettype" : [ "", "", "", "", "" ],
								"code" : "param1 = in1;\r\nparam2 = in2;\r\n\r\ncontrolling = in3;\r\nold = in4;\r\nside = in5;\r\n\r\nif (delta(switch))\r\n{\r\n\tcontrolling = 0;\r\n\tif (switch)\r\n\t{\r\n\t\told = param2;\r\n\t}\r\n\telse\r\n\t{\r\n\t\told = param1;\r\n\t}\r\n\tside = knob - old;\r\n}\r\n\r\nif (controlling)\r\n{\r\n\tif (switch)\r\n\t{\r\n\t\tparam2 = knob;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tparam1 = knob;\r\n\t}\r\n}\r\nelse\r\n{\r\n\tif (switch)\r\n\t{\r\n\t\tif (side * (knob - param2) <= 0)\r\n\t\t{\r\n\t\t\tcontrolling = 1;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontrolling = 0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (side * (knob - param1) <= 0)\r\n\t\t{\r\n\t\t\tcontrolling = 1;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontrolling = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nout1 = param1;\r\nout2 = param2;\r\nout3 = controlling;\r\nout4 = old;\r\nout5 = side;"
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "param @name switch",
								"patching_rect" : [ 169.0, 25.0, 125.0, 22.0 ],
								"numinlets" : 0,
								"numoutlets" : 1,
								"id" : "obj-7",
								"outlettype" : [ "" ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "param @name knob",
								"patching_rect" : [ 50.0, 25.0, 117.0, 22.0 ],
								"numinlets" : 0,
								"numoutlets" : 1,
								"id" : "obj-6",
								"outlettype" : [ "" ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "out 1",
								"patching_rect" : [ 50.0, 1064.0, 35.0, 22.0 ],
								"numinlets" : 1,
								"numoutlets" : 0,
								"id" : "obj-4"
							}

						}
 ],
					"lines" : [ 						{
							"patchline" : 							{
								"source" : [ "obj-16", 0 ],
								"destination" : [ "obj-10", 4 ],
								"midpoints" : [ 686.5, 84.0, 686.5, 84.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 4 ],
								"destination" : [ "obj-16", 0 ],
								"midpoints" : [ 686.5, 1023.0, 732.0, 1023.0, 732.0, 48.0, 686.5, 48.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-15", 0 ],
								"destination" : [ "obj-10", 3 ],
								"midpoints" : [ 529.75, 84.0, 529.75, 84.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 3 ],
								"destination" : [ "obj-15", 0 ],
								"midpoints" : [ 529.75, 1032.0, 732.0, 1032.0, 732.0, 48.0, 529.75, 48.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-14", 0 ],
								"destination" : [ "obj-10", 2 ],
								"midpoints" : [ 373.0, 84.0, 373.0, 84.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 2 ],
								"destination" : [ "obj-14", 0 ],
								"midpoints" : [ 373.0, 1032.0, 732.0, 1032.0, 732.0, 48.0, 373.0, 48.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 1 ],
								"destination" : [ "obj-12", 0 ],
								"midpoints" : [ 216.25, 1032.0, 36.0, 1032.0, 36.0, 57.0, 216.25, 57.0 ],
								"order" : 1
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 0 ],
								"destination" : [ "obj-11", 0 ],
								"midpoints" : [ 59.5, 1023.0, 36.0, 1023.0, 36.0, 57.0, 59.5, 57.0 ],
								"order" : 1
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 1 ],
								"destination" : [ "obj-13", 0 ],
								"midpoints" : [ 216.25, 1050.0, 686.5, 1050.0 ],
								"order" : 0
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-12", 0 ],
								"destination" : [ "obj-10", 1 ],
								"midpoints" : [ 216.25, 84.0, 216.25, 84.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-11", 0 ],
								"destination" : [ "obj-10", 0 ],
								"midpoints" : [ 59.5, 84.0, 59.5, 84.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 0 ],
								"destination" : [ "obj-4", 0 ],
								"midpoints" : [ 59.5, 1023.0, 59.5, 1023.0 ],
								"order" : 0
							}

						}
 ]
				}

			}

		}
 ],
	"lines" : [ 		{
			"patchline" : 			{
				"source" : [ "obj-28", 0 ],
				"destination" : [ "obj-30", 0 ],
				"order" : 0
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-1", 1 ],
				"destination" : [ "obj-30", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-31", 0 ],
				"destination" : [ "obj-28", 0 ],
				"order" : 1
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-31", 0 ],
				"destination" : [ "obj-1", 0 ],
				"order" : 0
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-7", 0 ],
				"destination" : [ "obj-31", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-30", 0 ],
				"destination" : [ "obj-11", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-19", 0 ],
				"destination" : [ "obj-28", 0 ],
				"order" : 1
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-28", 0 ],
				"destination" : [ "obj-18", 0 ],
				"order" : 1
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-19", 0 ],
				"destination" : [ "obj-1", 0 ],
				"order" : 0
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-2", 0 ],
				"destination" : [ "obj-19", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-18", 0 ],
				"destination" : [ "obj-10", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-1", 0 ],
				"destination" : [ "obj-18", 0 ]
			}

		}
 ],
	"appversion" : 	{
		"major" : 8,
		"minor" : 6,
		"revision" : 2,
		"architecture" : "x64",
		"modernui" : 1
	}
,
	"classnamespace" : "box"
}

you must be an angel, cause that’s so clean! wow, and it fully works in my patch on the computer.

BUT it doesnt seem to work on my daisy seed in eurorack yet, i am yet to figure out why :slight_smile: but this is so great, thank you sooo much!

would be great if you’d explain it a bit for a dummy like me :slight_smile: i’m really struggling getting it running on the daisy, but it works flawlessly in the digital domain.

maybe your explanation can help me out :wink: thank you so far though!

Here’s the gen~ code. The five outputs of the codebox are routed back to the inputs, through history objects, to make the variables persist across calls to the audio thread. Basically, we store the two param values in param1 and param2, along with a flag called controlling which reads whether or not we are actively controlling a parameter. We also store an old variable, which is the value of the old parameter when control was switched away from it.

Basically, if the switch changes state, we turn controlling off, store the old parameter value, and keep track of which side the knob is on from that old value. When the knob is on the other side (recorded by side * (knob - param) being negative), we resume control of the relevant parameter.

param1 = in1;
param2 = in2;

controlling = in3;
old = in4;
side = in5;

if (delta(switch))
{
	controlling = 0;
	if (switch)
	{
		old = param2;
	}
	else
	{
		old = param1;
	}
	side = knob - old;
}

if (controlling)
{
	if (switch)
	{
		param2 = knob;
	}
	else
	{
		param1 = knob;
	}
}
else
{
	if (switch)
	{
		if (side * (knob - param2) <= 0)
		{
			controlling = 1;
		}
		else
		{
			controlling = 0;
		}
	}
	else
	{
		if (side * (knob - param1) <= 0)
		{
			controlling = 1;
		}
		else
		{
			controlling = 0;
		}
	}
}

out1 = param1;
out2 = param2;
out3 = controlling;
out4 = old;
out5 = side;

perfect, thank you so much!

@Takumi_Ogata maybe you have any idea why this wouldnt work on the seed? i have tried many different things, also a simple test patch just controlling the amplitude and frequecne of a cycle but it still doesnt work on the seed.

i’ve also tested that the switch works correctly by sending it to a led and turning that on and off, that all works fine.

any idea?

anyone else maybe have any idea why something would work in the patch on the comptuer but not on the seed itself? any help much appreciated! :smiling_face_with_three_hearts:

I’m as confused as you that it doesn’t work on the Seed…. All I can think of is that there might be some issue with variables getting initialized. The code as written can’t give initial values to param1 and param2, since they persist across audio frames by being assigned their previous values, and there’s no option in gen~ to run a bit of code before the audio thread starts. It looks like gen~ smartly initializes the variables to 0, which works out fine for this use case. But if for some reason the variables on the Seed just hold junk, the code won’t work because the knob (which has range 0 to 1) never reaches the almost-certainly-not-in-that-range junk value to take it over.

Try replacing the first few lines in the codebox with this:


param1 = clamp(in1, 0, 1);
param2 = clamp(in2, 0, 1);

controlling = clamp(in3, 0, 1);
old = clamp(in4, 0, 1);

Curious to hear if it works…

tried and tested, but that doesn’t really change anything unfortunately :frowning:

i also have no idea why it would set those variables then anything other then 0 if they have no declaration for another value or a physical knob to read from.

ughh and so the search continues… thanks for the suggestion though

It’s really a question of what goes on behind the hood when the gen code gets converted to C++ and compiled for the Daisy. In C++, variable creation and initialization are separate. You can create a variable and access its value without initializing it, in which case you’re reading whatever happens to be in RAM at the location where the variable is stored. I wondered whether something like that was going on here – maybe the full-blown Max environment does a good job of initializing things with default values, like zero, but the generated C++ code for the Seed isn’t as smart.

yea that kinda makes sense, many a people told me to start to learn c++, but i’m just way more comfortable (if you can even call it that) with gen~ right now and its a lot more visual for me to wrap my head around things.

anyway lets just leave this open here and if anything comes to mind think about me and maybe someone else can shine a light on the problem potentially.

this is the cpp code btw generated by the sample test patch i made to try out your code(perhaps you can see something there?):

#include "test2funct.h"

namespace test2funct {

/****************************************************************************************
Copyright (c) 2023 Cycling '74

The code that Max generates automatically and that end users are capable of
exporting and using, and any associated documentation files (the “Software”)
is a work of authorship for which Cycling '74 is the author and owner for
copyright purposes.

This Software is dual-licensed either under the terms of the Cycling '74
License for Max-Generated Code for Export, or alternatively under the terms
of the General Public License (GPL) Version 3. You may use the Software
according to either of these licenses as it is most appropriate for your
project on a case-by-case basis (proprietary or not).

A) Cycling '74 License for Max-Generated Code for Export

A license is hereby granted, free of charge, to any person obtaining a copy
of the Software (“Licensee”) to use, copy, modify, merge, publish, and
distribute copies of the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following conditions:

The Software is licensed to Licensee for all uses that do not include the sale,
sublicensing, or commercial distribution of software that incorporates this
source code. This means that the Licensee is free to use this software for
educational, research, and prototyping purposes, to create musical or other
creative works with software that incorporates this source code, or any other
use that does not constitute selling software that makes use of this source
code. Commercial distribution also includes the packaging of free software with
other paid software, hardware, or software-provided commercial services.

For entities with UNDER 200k USD in annual revenue or funding, a license is hereby
granted, free of charge, for the sale, sublicensing, or commercial distribution
of software that incorporates this source code, for as long as the entity's
annual revenue remains below 200k USD annual revenue or funding.

For entities with OVER 200k USD in annual revenue or funding interested in the
sale, sublicensing, or commercial distribution of software that incorporates
this source code, please send inquiries to licensing (at) cycling74.com.

The above copyright notice and this license shall be included in all copies or
substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Please see
https://support.cycling74.com/hc/en-us/articles/360050779193-Gen-Code-Export-Licensing-FAQ
for additional information

B) General Public License Version 3 (GPLv3)
Details of the GPLv3 license can be found at: https://www.gnu.org/licenses/gpl-3.0.html
****************************************************************************************/

// global noise generator
Noise noise;
static const int GENLIB_LOOPCOUNT_BAIL = 100000;


// The State struct contains all the state and procedures for the gendsp kernel
typedef struct State {
	CommonState __commonstate;
	Delta __m_delta_9;
	Delta __m_delta_8;
	SineCycle __m_cycle_10;
	SineData __sinedata;
	int __exception;
	int vectorsize;
	t_sample samplerate;
	t_sample m_history_3;
	t_sample m_history_2;
	t_sample m_sw_7;
	t_sample m_history_5;
	t_sample m_test_6;
	t_sample m_history_1;
	t_sample m_history_4;
	// re-initialize all member variables;
	inline void reset(t_param __sr, int __vs) {
		__exception = 0;
		vectorsize = __vs;
		samplerate = __sr;
		m_history_1 = ((int)0);
		m_history_2 = ((int)0);
		m_history_3 = ((int)0);
		m_history_4 = ((int)0);
		m_history_5 = ((int)0);
		m_test_6 = ((int)0);
		m_sw_7 = ((int)0);
		__m_delta_8.reset(0);
		__m_delta_9.reset(0);
		__m_cycle_10.reset(samplerate, 0);
		genlib_reset_complete(this);
		
	};
	// the signal processing routine;
	inline int perform(t_sample ** __ins, t_sample ** __outs, int __n) {
		vectorsize = __n;
		const t_sample * __in1 = __ins[0];
		t_sample * __out1 = __outs[0];
		t_sample * __out2 = __outs[1];
		if (__exception) {
			return __exception;
			
		} else if (( (__in1 == 0) || (__out1 == 0) || (__out2 == 0) )) {
			__exception = GENLIB_ERR_NULL_BUFFER;
			return __exception;
			
		};
		t_sample knob = m_test_6;
		// the main sample loop;
		while ((__n--)) {
			const t_sample in1 = (*(__in1++));
			t_sample param1 = m_history_2;
			t_sample param2 = m_history_1;
			t_sample controlling = m_history_5;
			t_sample old = m_history_4;
			t_sample side = m_history_3;
			if (__m_delta_8(m_sw_7)) {
				controlling = ((int)0);
				if (m_sw_7) {
					old = param2;
					
				} else {
					old = param1;
					
				};
				side = (knob - old);
				
			};
			if (controlling) {
				if (m_sw_7) {
					param2 = knob;
					
				} else {
					param1 = knob;
					
				};
				
			} else {
				if (m_sw_7) {
					if (((side * (knob - param2)) <= ((int)0))) {
						controlling = ((int)1);
						
					} else {
						controlling = ((int)0);
						
					};
					
				} else {
					if (((side * (knob - param1)) <= ((int)0))) {
						controlling = ((int)1);
						
					} else {
						controlling = ((int)0);
						
					};
					
				};
				
			};
			t_sample expr_9217 = param1;
			t_sample expr_9218 = param2;
			t_sample expr_9219 = controlling;
			t_sample expr_9220 = old;
			t_sample expr_9221 = side;
			t_sample delta_9068 = __m_delta_9(m_sw_7);
			t_sample out2 = delta_9068;
			t_sample sub_9242 = (expr_9217 - ((int)0));
			t_sample scale_9239 = ((safepow((sub_9242 * ((t_sample)1)), ((int)1)) * ((int)100)) + ((int)100));
			__m_cycle_10.freq(scale_9239);
			t_sample cycle_8856 = __m_cycle_10(__sinedata);
			t_sample cycleindex_8857 = __m_cycle_10.phase();
			t_sample mul_8963 = (cycle_8856 * expr_9218);
			t_sample out1 = mul_8963;
			t_sample history_2226_next_9222 = fixdenorm(expr_9219);
			t_sample history_2225_next_9223 = fixdenorm(expr_9220);
			t_sample history_2224_next_9224 = fixdenorm(expr_9221);
			t_sample history_2228_next_9225 = fixdenorm(expr_9217);
			t_sample history_2227_next_9226 = fixdenorm(expr_9218);
			m_history_5 = history_2226_next_9222;
			m_history_4 = history_2225_next_9223;
			m_history_3 = history_2224_next_9224;
			m_history_2 = history_2228_next_9225;
			m_history_1 = history_2227_next_9226;
			// assign results to output buffer;
			(*(__out1++)) = out1;
			(*(__out2++)) = out2;
			
		};
		return __exception;
		
	};
	inline void set_test(t_param _value) {
		m_test_6 = (_value < 0 ? 0 : (_value > 1 ? 1 : _value));
	};
	inline void set_sw1(t_param _value) {
		m_sw_7 = (_value < 0 ? 0 : (_value > 1 ? 1 : _value));
	};
	
} State;


///
///	Configuration for the genlib API
///

/// Number of signal inputs and outputs

int gen_kernel_numins = 1;
int gen_kernel_numouts = 2;

int num_inputs() { return gen_kernel_numins; }
int num_outputs() { return gen_kernel_numouts; }
int num_params() { return 2; }

/// Assistive lables for the signal inputs and outputs

const char *gen_kernel_innames[] = { "in1" };
const char *gen_kernel_outnames[] = { "out1", "out2" };

/// Invoke the signal process of a State object

int perform(CommonState *cself, t_sample **ins, long numins, t_sample **outs, long numouts, long n) {
	State* self = (State *)cself;
	return self->perform(ins, outs, n);
}

/// Reset all parameters and stateful operators of a State object

void reset(CommonState *cself) {
	State* self = (State *)cself;
	self->reset(cself->sr, cself->vs);
}

/// Set a parameter of a State object

void setparameter(CommonState *cself, long index, t_param value, void *ref) {
	State *self = (State *)cself;
	switch (index) {
		case 0: self->set_sw1(value); break;
		case 1: self->set_test(value); break;
		
		default: break;
	}
}

/// Get the value of a parameter of a State object

void getparameter(CommonState *cself, long index, t_param *value) {
	State *self = (State *)cself;
	switch (index) {
		case 0: *value = self->m_sw_7; break;
		case 1: *value = self->m_test_6; break;
		
		default: break;
	}
}

/// Get the name of a parameter of a State object

const char *getparametername(CommonState *cself, long index) {
	if (index >= 0 && index < cself->numparams) {
		return cself->params[index].name;
	}
	return 0;
}

/// Get the minimum value of a parameter of a State object

t_param getparametermin(CommonState *cself, long index) {
	if (index >= 0 && index < cself->numparams) {
		return cself->params[index].outputmin;
	}
	return 0;
}

/// Get the maximum value of a parameter of a State object

t_param getparametermax(CommonState *cself, long index) {
	if (index >= 0 && index < cself->numparams) {
		return cself->params[index].outputmax;
	}
	return 0;
}

/// Get parameter of a State object has a minimum and maximum value

char getparameterhasminmax(CommonState *cself, long index) {
	if (index >= 0 && index < cself->numparams) {
		return cself->params[index].hasminmax;
	}
	return 0;
}

/// Get the units of a parameter of a State object

const char *getparameterunits(CommonState *cself, long index) {
	if (index >= 0 && index < cself->numparams) {
		return cself->params[index].units;
	}
	return 0;
}

/// Get the size of the state of all parameters of a State object

size_t getstatesize(CommonState *cself) {
	return genlib_getstatesize(cself, &getparameter);
}

/// Get the state of all parameters of a State object

short getstate(CommonState *cself, char *state) {
	return genlib_getstate(cself, state, &getparameter);
}

/// set the state of all parameters of a State object

short setstate(CommonState *cself, const char *state) {
	return genlib_setstate(cself, state, &setparameter);
}

/// Allocate and configure a new State object and it's internal CommonState:

void *create(t_param sr, long vs) {
	State *self = new State;
	self->reset(sr, vs);
	ParamInfo *pi;
	self->__commonstate.inputnames = gen_kernel_innames;
	self->__commonstate.outputnames = gen_kernel_outnames;
	self->__commonstate.numins = gen_kernel_numins;
	self->__commonstate.numouts = gen_kernel_numouts;
	self->__commonstate.sr = sr;
	self->__commonstate.vs = vs;
	self->__commonstate.params = (ParamInfo *)genlib_sysmem_newptr(2 * sizeof(ParamInfo));
	self->__commonstate.numparams = 2;
	// initialize parameter 0 ("m_sw_7")
	pi = self->__commonstate.params + 0;
	pi->name = "sw1";
	pi->paramtype = GENLIB_PARAMTYPE_FLOAT;
	pi->defaultvalue = self->m_sw_7;
	pi->defaultref = 0;
	pi->hasinputminmax = false;
	pi->inputmin = 0;
	pi->inputmax = 1;
	pi->hasminmax = true;
	pi->outputmin = 0;
	pi->outputmax = 1;
	pi->exp = 0;
	pi->units = "";		// no units defined
	// initialize parameter 1 ("m_test_6")
	pi = self->__commonstate.params + 1;
	pi->name = "test";
	pi->paramtype = GENLIB_PARAMTYPE_FLOAT;
	pi->defaultvalue = self->m_test_6;
	pi->defaultref = 0;
	pi->hasinputminmax = false;
	pi->inputmin = 0;
	pi->inputmax = 1;
	pi->hasminmax = true;
	pi->outputmin = 0;
	pi->outputmax = 1;
	pi->exp = 0;
	pi->units = "";		// no units defined
	
	return self;
}

/// Release all resources and memory used by a State object:

void destroy(CommonState *cself) {
	State *self = (State *)cself;
	genlib_sysmem_freeptr(cself->params);
		
	delete self;
}


} // test2funct::

Okay, one more go:

{
	"boxes" : [ 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "metro 20 @active 1",
				"numinlets" : 2,
				"numoutlets" : 1,
				"id" : "obj-5",
				"outlettype" : [ "bang" ],
				"patching_rect" : [ 305.88233470916748, 168.0, 113.0, 22.0 ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "prepend switch",
				"numinlets" : 1,
				"numoutlets" : 1,
				"id" : "obj-31",
				"outlettype" : [ "" ],
				"patching_rect" : [ 281.0, 134.0, 89.0, 22.0 ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "snapshot~",
				"numinlets" : 2,
				"numoutlets" : 1,
				"id" : "obj-30",
				"outlettype" : [ "float" ],
				"patching_rect" : [ 305.88233470916748, 276.470571756362915, 64.0, 22.0 ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "prepend knob",
				"numinlets" : 1,
				"numoutlets" : 1,
				"id" : "obj-19",
				"outlettype" : [ "" ],
				"patching_rect" : [ 266.0, 110.0, 82.0, 22.0 ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "snapshot~",
				"numinlets" : 2,
				"numoutlets" : 1,
				"id" : "obj-18",
				"outlettype" : [ "float" ],
				"patching_rect" : [ 238.0, 276.470571756362915, 64.0, 22.0 ]
			}

		}
, 		{
			"box" : 			{
				"maxclass" : "live.dial",
				"varname" : "live.dial[3]",
				"numinlets" : 1,
				"numoutlets" : 2,
				"id" : "obj-11",
				"parameter_enable" : 1,
				"outlettype" : [ "", "float" ],
				"patching_rect" : [ 306.0, 315.34872031211853, 41.0, 48.0 ],
				"saved_attribute_attributes" : 				{
					"valueof" : 					{
						"parameter_longname" : "live.dial[3]",
						"parameter_mmax" : 1.0,
						"parameter_modmode" : 3,
						"parameter_shortname" : "live.dial",
						"parameter_type" : 0,
						"parameter_unitstyle" : 1
					}

				}

			}

		}
, 		{
			"box" : 			{
				"maxclass" : "live.dial",
				"varname" : "live.dial[2]",
				"numinlets" : 1,
				"numoutlets" : 2,
				"id" : "obj-10",
				"parameter_enable" : 1,
				"outlettype" : [ "", "float" ],
				"patching_rect" : [ 238.0, 315.34872031211853, 41.0, 48.0 ],
				"saved_attribute_attributes" : 				{
					"valueof" : 					{
						"parameter_longname" : "live.dial[2]",
						"parameter_mmax" : 1.0,
						"parameter_modmode" : 3,
						"parameter_shortname" : "live.dial",
						"parameter_type" : 0,
						"parameter_unitstyle" : 1
					}

				}

			}

		}
, 		{
			"box" : 			{
				"maxclass" : "live.toggle",
				"varname" : "live.toggle",
				"numinlets" : 1,
				"numoutlets" : 1,
				"id" : "obj-7",
				"parameter_enable" : 1,
				"outlettype" : [ "" ],
				"patching_rect" : [ 320.089282661676407, 51.785713791847229, 41.0, 41.0 ],
				"saved_attribute_attributes" : 				{
					"valueof" : 					{
						"parameter_enum" : [ "off", "on" ],
						"parameter_longname" : "live.toggle",
						"parameter_mmax" : 1,
						"parameter_modmode" : 0,
						"parameter_shortname" : "live.toggle",
						"parameter_type" : 2
					}

				}

			}

		}
, 		{
			"box" : 			{
				"maxclass" : "live.dial",
				"varname" : "live.dial",
				"numinlets" : 1,
				"numoutlets" : 2,
				"id" : "obj-2",
				"parameter_enable" : 1,
				"outlettype" : [ "", "float" ],
				"patching_rect" : [ 266.0, 44.785713791847229, 41.0, 48.0 ],
				"saved_attribute_attributes" : 				{
					"valueof" : 					{
						"parameter_longname" : "live.dial",
						"parameter_mmax" : 1.0,
						"parameter_modmode" : 3,
						"parameter_shortname" : "live.dial",
						"parameter_type" : 0,
						"parameter_unitstyle" : 1
					}

				}

			}

		}
, 		{
			"box" : 			{
				"maxclass" : "newobj",
				"text" : "gen~",
				"numinlets" : 1,
				"numoutlets" : 2,
				"id" : "obj-1",
				"outlettype" : [ "signal", "signal" ],
				"patching_rect" : [ 266.0, 168.0, 36.0, 22.0 ],
				"patcher" : 				{
					"fileversion" : 1,
					"appversion" : 					{
						"major" : 8,
						"minor" : 6,
						"revision" : 2,
						"architecture" : "x64",
						"modernui" : 1
					}
,
					"classnamespace" : "dsp.gen",
					"rect" : [ 1062.0, 106.0, 960.0, 1104.0 ],
					"bglocked" : 0,
					"openinpresentation" : 0,
					"default_fontsize" : 12.0,
					"default_fontface" : 0,
					"default_fontname" : "Arial",
					"gridonopen" : 1,
					"gridsize" : [ 15.0, 15.0 ],
					"gridsnaponopen" : 1,
					"objectsnaponopen" : 1,
					"statusbarvisible" : 2,
					"toolbarvisible" : 1,
					"lefttoolbarpinned" : 0,
					"toptoolbarpinned" : 0,
					"righttoolbarpinned" : 0,
					"bottomtoolbarpinned" : 0,
					"toolbars_unpinned_last_save" : 0,
					"tallnewobj" : 0,
					"boxanimatetime" : 200,
					"enablehscroll" : 1,
					"enablevscroll" : 1,
					"devicewidth" : 0.0,
					"description" : "",
					"digest" : "",
					"tags" : "",
					"style" : "",
					"subpatcher_template" : "",
					"assistshowspatchername" : 0,
					"boxes" : [ 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-16",
								"outlettype" : [ "" ],
								"patching_rect" : [ 677.300659418106079, 61.0, 44.0, 22.0 ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-15",
								"outlettype" : [ "" ],
								"patching_rect" : [ 520.25, 61.0, 44.0, 22.0 ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-14",
								"outlettype" : [ "" ],
								"patching_rect" : [ 363.5, 61.0, 44.0, 22.0 ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "out 2",
								"numinlets" : 1,
								"numoutlets" : 0,
								"id" : "obj-13",
								"patching_rect" : [ 677.0, 1064.0, 35.0, 22.0 ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-12",
								"outlettype" : [ "" ],
								"patching_rect" : [ 206.75, 61.0, 44.0, 22.0 ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "history",
								"numinlets" : 1,
								"numoutlets" : 1,
								"id" : "obj-11",
								"outlettype" : [ "" ],
								"patching_rect" : [ 50.0, 61.0, 44.0, 22.0 ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "codebox",
								"numinlets" : 5,
								"fontface" : 0,
								"numoutlets" : 5,
								"id" : "obj-10",
								"fontsize" : 12.0,
								"outlettype" : [ "", "", "", "", "" ],
								"fontname" : "<Monospaced>",
								"patching_rect" : [ 50.0, 85.0, 646.0, 936.0 ],
								"code" : "param1 = clamp(in1, 0, 1);\r\nparam2 = clamp(in2, 0, 1);\r\n\r\ncontrolling = clamp(in3, 0, 1);\r\nold = clamp(in4, 0, 1);\r\nside = in5;\r\n\r\nif (abs(delta(switch)) > 0.5)\r\n{\r\n\tcontrolling = 0;\r\n\tif (switch > 0.5)\r\n\t{\r\n\t\told = param2;\r\n\t}\r\n\telse\r\n\t{\r\n\t\told = param1;\r\n\t}\r\n\tside = knob - old;\r\n}\r\n\r\nif (controlling > 0.5)\r\n{\r\n\tif (switch > 0.5)\r\n\t{\r\n\t\tparam2 = knob;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tparam1 = knob;\r\n\t}\r\n}\r\nelse\r\n{\r\n\tif (switch > 0.5)\r\n\t{\r\n\t\tif (side * (knob - param2) <= 0)\r\n\t\t{\r\n\t\t\tcontrolling = 1;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontrolling = 0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (side * (knob - param1) <= 0)\r\n\t\t{\r\n\t\t\tcontrolling = 1;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcontrolling = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nout1 = param1;\r\nout2 = param2;\r\nout3 = controlling;\r\nout4 = old;\r\nout5 = side;"
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "param @name switch",
								"numinlets" : 0,
								"numoutlets" : 1,
								"id" : "obj-7",
								"outlettype" : [ "" ],
								"patching_rect" : [ 169.0, 25.0, 125.0, 22.0 ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "param @name knob",
								"numinlets" : 0,
								"numoutlets" : 1,
								"id" : "obj-6",
								"outlettype" : [ "" ],
								"patching_rect" : [ 50.0, 25.0, 117.0, 22.0 ]
							}

						}
, 						{
							"box" : 							{
								"maxclass" : "newobj",
								"text" : "out 1",
								"numinlets" : 1,
								"numoutlets" : 0,
								"id" : "obj-4",
								"patching_rect" : [ 50.0, 1064.0, 35.0, 22.0 ]
							}

						}
 ],
					"lines" : [ 						{
							"patchline" : 							{
								"source" : [ "obj-16", 0 ],
								"destination" : [ "obj-10", 4 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-15", 0 ],
								"destination" : [ "obj-10", 3 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-14", 0 ],
								"destination" : [ "obj-10", 2 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-12", 0 ],
								"destination" : [ "obj-10", 1 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 4 ],
								"destination" : [ "obj-16", 0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 3 ],
								"destination" : [ "obj-15", 0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 2 ],
								"destination" : [ "obj-14", 0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 0 ],
								"destination" : [ "obj-11", 0 ],
								"midpoints" : [ 59.5, 1023.0, 36.0, 1023.0, 36.0, 57.0, 59.5, 57.0 ],
								"order" : 1
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 1 ],
								"destination" : [ "obj-12", 0 ],
								"midpoints" : [ 216.25, 1032.0, 36.0, 1032.0, 36.0, 57.0, 216.25, 57.0 ],
								"order" : 1
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-11", 0 ],
								"destination" : [ "obj-10", 0 ],
								"midpoints" : [ 59.5, 84.0, 59.5, 84.0 ]
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 0 ],
								"destination" : [ "obj-4", 0 ],
								"midpoints" : [ 59.5, 1023.0, 59.5, 1023.0 ],
								"order" : 0
							}

						}
, 						{
							"patchline" : 							{
								"source" : [ "obj-10", 1 ],
								"destination" : [ "obj-13", 0 ],
								"midpoints" : [ 216.25, 1050.0, 686.5, 1050.0 ],
								"order" : 0
							}

						}
 ]
				}

			}

		}
 ],
	"lines" : [ 		{
			"patchline" : 			{
				"source" : [ "obj-5", 0 ],
				"destination" : [ "obj-30", 0 ],
				"order" : 0
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-5", 0 ],
				"destination" : [ "obj-18", 0 ],
				"order" : 1
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-7", 0 ],
				"destination" : [ "obj-31", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-31", 0 ],
				"destination" : [ "obj-1", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-30", 0 ],
				"destination" : [ "obj-11", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-2", 0 ],
				"destination" : [ "obj-19", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-19", 0 ],
				"destination" : [ "obj-1", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-18", 0 ],
				"destination" : [ "obj-10", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-1", 1 ],
				"destination" : [ "obj-30", 0 ]
			}

		}
, 		{
			"patchline" : 			{
				"source" : [ "obj-1", 0 ],
				"destination" : [ "obj-18", 0 ]
			}

		}
 ],
	"appversion" : 	{
		"major" : 8,
		"minor" : 6,
		"revision" : 2,
		"architecture" : "x64",
		"modernui" : 1
	}
,
	"classnamespace" : "box"
}

All variables in gen~ are floating-point, so sometimes if (variable) behaves unpredictably.

that still doesn’t do it for me :frowning: wish i had better news, thanks sooo much for the help, it’s really appreciated.

maybe @Takumi_Ogata has any suggestion as to why this might not work still :slight_smile: ?

Okay, one more idea - try changing the if blocks to read


if (side * (knob - param) <= 0.01)
{ . . . }

It’s possible the analog reading of the pot never gets exactly to zero, where the parameter values are initialized, so the knob can never take over a parameter. This gives a little leeway. If it still doesn’t work, try a slightly larger value instead of 0.01…

1 Like

that did it!! so stupid that i didnt think of that!! thanks a bunch