ソースを参照

added checkbutton as a ui option for processing nodes and added a few formant processes

Jonathan Higgins 6 ヶ月 前
コミット
7e20e7cf52

+ 380 - 0
scenes/main/process_help.json

@@ -3804,6 +3804,234 @@
 	"subcategory": "convert",
 	"title": "Resynthesise"
   },
+  "specfnu_specfnu_3": {
+	"category": "pvoc",
+	"description": "A spectral peak is an area of higher amplitude among the frequencies of the spectrum. A trough is an area of low amplitude between spectral peaks. The INVERT mode swaps these, so that the peaks become troughs and vice versa. This should make the sound noisier, with buzzy high frequencies. Vibrate allow you to oscillate between the original and inverted states this works particularly well when set to a very low value e.g. 0.01.",
+	"inputtype": "[1]",
+	"outputtype": "[1]",
+	"parameters": {
+	  "param1": {
+		"paramname": "Vibrate",
+		"paramdescription": "The speed to oscillate between inverted and original state",
+		"automatable": true,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "",
+		"minrange": 0.0,
+		"maxrange": 2.0,
+		"step": 0.01,
+		"value": 0.0,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param2": {
+		"paramname": "Output Gain",
+		"paramdescription": "Amount of gain applied to the output signal",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-g",
+		"minrange": 0.1,
+		"maxrange": 10.0,
+		"step": 0.01,
+		"value": 1.0,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param3": {
+		"paramname": "Omit Inharmonic Partials",
+		"paramdescription": "Removes inharmonic partials from the sound",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-x",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  },
+	  "param4": {
+		"paramname": "Omit Harmonic Partials",
+		"paramdescription": "Removes harmonic partials from the sound",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-k",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  }
+	},
+	"short_description": "Inverts peaks and troughs",
+	"stereo": false,
+	"subcategory": "formants",
+	"title": "Invert Formants"
+  },
+  "specfnu_specfnu_1": {
+	"category": "pvoc",
+	"description": "Narrow steepen skirts of formant peaks by power factor. This focuses energy on the spectral peaks and therefore acts like an increasingly tight filter. As Narrowing is increased the material between the peaks is diminished and eventually disappears.",
+	"inputtype": "[1]",
+	"outputtype": "[1]",
+	"parameters": {
+	  "param1": {
+		"paramname": "Narrowing",
+		"paramdescription": "The amount to narrow the formants by",
+		"automatable": true,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "",
+		"minrange": 1.0,
+		"maxrange": 1000.0,
+		"step": 1.0,
+		"value": 4.0,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param2": {
+		"paramname": "Output Gain",
+		"paramdescription": "Amount of gain applied to the output signal",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-g",
+		"minrange": 0.1,
+		"maxrange": 10.0,
+		"step": 0.01,
+		"value": 1.0,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param3": {
+		"paramname": "Omit Inharmonic Partials",
+		"paramdescription": "Removes inharmonic partials from the sound",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-x",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  },
+	  "param4": {
+		"paramname": "Omit Harmonic Partials",
+		"paramdescription": "Removes harmonic partials from the sound",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-k",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  }
+	},
+	"short_description": "Narrows formants, focusing energy at spectral peaks",
+	"stereo": false,
+	"subcategory": "formants",
+	"title": "Narrow Formants"
+  },
+  "specfnu_specfnu_4": {
+	"category": "pvoc",
+	"description": "Rotates formants using an LFO, moving their peaks and frequencies up or down the spectrum. When a formant reaches the edge of the formant area they wrap around appearing at the bottom or top of the area.",
+	"inputtype": "[1]",
+	"outputtype": "[1]",
+	"parameters": {
+	  "param1": {
+		"paramname": "Rotation Speed",
+		"paramdescription": "The speed to move formants up or down",
+		"automatable": true,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "",
+		"minrange": -4.0,
+		"maxrange": 4.0,
+		"step": 0.01,
+		"value": 0.1,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param2": {
+		"paramname": "Output Gain",
+		"paramdescription": "Amount of gain applied to the output signal",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-g",
+		"minrange": 0.1,
+		"maxrange": 10.0,
+		"step": 0.01,
+		"value": 1.0,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param3": {
+		"paramname": "Omit Inharmonic Partials",
+		"paramdescription": "Removes inharmonic partials from the sound",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-x",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  },
+	  "param4": {
+		"paramname": "Omit Harmonic Partials",
+		"paramdescription": "Removes harmonic partials from the sound",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-k",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  }
+	},
+	"short_description": "Move formants up or down spectrum",
+	"stereo": false,
+	"subcategory": "formants",
+	"title": "Rotate Formants"
+  },
   "strange_glis_1": {
 	"category": "pvoc",
 	"description": "Extracts the spectral contour of the sound retaining any spectral articulation, such as patterns of speech, but replaces the signal by an endlessly rising (positive values for Glissando Rate) or falling (negative values for Glissando Rate) shepard tone.",
@@ -3848,6 +4076,158 @@
 	"subcategory": "formants",
 	"title": "Shepard Tone"
   },
+  "specfnu_specfnu_5": {
+	"category": "pvoc",
+	"description": "This mode inverts the spectral values for each channel, usually producing a highly distorted output.",
+	"inputtype": "[1]",
+	"outputtype": "[1]",
+	"parameters": {
+	  "param1": {
+		"paramname": "Output Gain",
+		"paramdescription": "Amount of gain applied to the output signal",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-g",
+		"minrange": 0.1,
+		"maxrange": 10.0,
+		"step": 0.01,
+		"value": 1.0,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param2": {
+		"paramname": "Flat",
+		"paramdescription": "Does not re-envelope the output spectrum",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-f",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  }
+	},
+	"short_description": "Spectral values are inverted for each channel",
+	"stereo": false,
+	"subcategory": "formants",
+	"title": "Spectral Negative"
+  },
+  "specfnu_specfnu_2": {
+	"category": "pvoc",
+	"description": "This process shifts all formants in the sound towards the specified formants, this will usually result in a lowering of the overal timbre of the sound e.g. high voices become deep voices.",
+	"inputtype": "[1]",
+	"outputtype": "[1]",
+	"parameters": {
+	  "param1": {
+		"paramname": "Squeeze",
+		"paramdescription": "The amount to squeeze the formants by",
+		"automatable": true,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "",
+		"minrange": 1.0,
+		"maxrange": 10.0,
+		"step": 1.0,
+		"value": 4.0,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param2": {
+		"paramname": "Centre Formant",
+		"paramdescription": "The formant to squeeze around",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "",
+		"minrange": 1.0,
+		"maxrange": 4.0,
+		"step": 1.0,
+		"value": 1.0,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param3": {
+		"paramname": "Output Gain",
+		"paramdescription": "The gain applied to the output",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-g",
+		"minrange": 0.1,
+		"maxrange": 10.0,
+		"step": 0.01,
+		"value": 1.0,
+		"exponential": false,
+		"uitype": "hslider"
+	  },
+	  "param4": {
+		"paramname": "Invert",
+		"paramdescription": "Squeeze around trough above specified peak",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-t",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  },
+	  "param5": {
+		"paramname": "Omit Inharmonic Partials",
+		"paramdescription": "Removes inharmonic partials from the sound",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-x",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  },
+	  "param6": {
+		"paramname": "Omit Harmonic Partials",
+		"paramdescription": "Removes harmonic partials from the sound",
+		"automatable": false,
+		"outputduration": false,
+		"time": false,
+		"min": false,
+		"max": false,
+		"flag": "-k",
+		"minrange": "",
+		"maxrange": "",
+		"step": "",
+		"value": false,
+		"exponential": false,
+		"uitype": "checkbutton"
+	  }
+	},
+	"short_description": "Squeeze the spectrum around a specified formant",
+	"stereo": false,
+	"subcategory": "formants",
+	"title": "Squeeze Formants"
+  },
   "blur_spread": {
 	"category": "pvoc",
 	"description": "This process introduces noise into the spectrum in a way which is coherent with the spectral envelope. The formants in each window are retained, and the level in every channel is made to approximate this average spectral contour to a greater or lesser extent, depending on spread. This process tends to exaggerate the less prominent noise constituents of the spectrum.",

+ 24 - 0
scenes/main/scripts/graph_edit.gd

@@ -178,6 +178,30 @@ func _make_node(command: String, skip_undo_redo := false) -> GraphNode:
 							graphnode.set_meta("outputduration", value)
 						
 						graphnode.add_child(slider)
+					
+					elif param_data.get("uitype", "") == "checkbutton":
+						#make a checkbutton
+						var checkbutton = CheckButton.new()
+						
+						#get button text
+						var checkbutton_label = param_data.get("paramname", "")
+						var checkbutton_tooltip  = param_data.get("paramdescription", "")
+						
+						#get checkbutton properties
+						var flag = param_data.get("flag", "")
+						
+						checkbutton.text = checkbutton_label
+						checkbutton.tooltip_text = checkbutton_tooltip
+						
+						var checkbutton_pressed = param_data.get("value", "false")
+						#get button state
+						if str(checkbutton_pressed).to_lower() == "true":
+							checkbutton.button_pressed = true
+							
+						#set checkbutton meta
+						checkbutton.set_meta("flag", flag)
+						
+						graphnode.add_child(checkbutton)
 			
 			
 			graphnode.set_script(node_logic)

+ 85 - 74
scenes/main/scripts/run_thread.gd

@@ -647,8 +647,12 @@ func _get_slider_values_ordered(node: Node) -> Array:
 			var exp = child.exp_edit
 			if child.has_meta("brk_data"):
 				brk_data = child.get_meta("brk_data")
-			results.append([flag, child.value, time, brk_data, min_slider, max_slider, exp])
-		elif child.get_child_count() > 0:
+			results.append(["slider", flag, child.value, time, brk_data, min_slider, max_slider, exp])
+		elif child is CheckButton:
+			var flag = child.get_meta("flag") if child.has_meta("flag") else ""
+			results.append(["checkbutton", flag, child.button_pressed])
+		#call this function recursively to find any nested sliders in scenes
+		if child.get_child_count() > 0:
 			var nested := _get_slider_values_ordered(child)
 			results.append_array(nested)
 	return results
@@ -682,79 +686,86 @@ func make_process(node: Node, process_count: int, current_infile: String, slider
 	# Append parameter values from the sliders, include flags if present
 	var slider_count = 0
 	for entry in slider_data:
-		var flag = entry[0]
-		var value = entry[1]
-		#if value == int(value):
-			#value = int(value)
-		var time = entry[2] #checks if slider is a time percentage slider
-		var brk_data = entry[3]
-		var min_slider = entry[4]
-		var max_slider = entry[5]
-		var exp = entry[6]
-		if brk_data.size() > 0: #if breakpoint data is present on slider
-			#Sort all points by time
-			var sorted_brk_data = []
-			sorted_brk_data = brk_data.duplicate()
-			sorted_brk_data.sort_custom(sort_points)
-			
-			var calculated_brk = []
-			
-			#get length of input file in seconds
-			var infile_length = 1 #set infile length to dummy value just incase it does get used where it shouldn't to avoid crashes
-			if current_infile != "none":
-				infile_length = await run_command(control_script.cdpprogs_location + "/sfprops", ["-d", current_infile])
-				infile_length = float(infile_length.strip_edges())
-			
-			#scale values from automation window to the right length for file and correct slider values
-			#if node has an output duration then breakpoint files should be x = outputduration y= slider value else x=input duration, y=value
-			if node.has_meta("outputduration"):
-				for i in range(sorted_brk_data.size()):
-					var point = sorted_brk_data[i]
-					var new_x = float(node.get_meta("outputduration")) * (point.x / 700) #output time
-					if i == sorted_brk_data.size() - 1: #check if this is last automation point
-						new_x = float(node.get_meta("outputduration")) + 0.1  # force last point's x to infile_length + 100ms to make sure the file is defo over
-					var new_y
-					#check if slider is exponential and scale automation
-					if exp:
-						new_y = remap_y_to_log_scale(point.y, 0.0, 255.0, min_slider, max_slider)
-					else:
-						new_y = remap(point.y, 255, 0, min_slider, max_slider) #slider value
-					if time: #check if this is a time slider and convert to percentage of input file
-						new_y = infile_length * (new_y / 100)
-					calculated_brk.append(Vector2(new_x, new_y))
-			else:
-				for i in range(sorted_brk_data.size()):
-					var point = sorted_brk_data[i]
-					var new_x = infile_length * (point.x / 700) #time
-					if i == sorted_brk_data.size() - 1: #check if this is last automation point
-						new_x = infile_length + 0.1  # force last point's x to infile_length + 100ms to make sure the file is defo over
-					var new_y
-					#check if slider is exponential and scale automation
-					if exp:
-						new_y = remap_y_to_log_scale(point.y, 0.0, 255.0, min_slider, max_slider)
-					else:
-						new_y = remap(point.y, 255, 0, min_slider, max_slider) #slider value
-					calculated_brk.append(Vector2(new_x, new_y))
+		if entry[0] == "slider":
+			var flag = entry[1]
+			var value = entry[2]
+			#if value == int(value):
+				#value = int(value)
+			var time = entry[3] #checks if slider is a time percentage slider
+			var brk_data = entry[4]
+			var min_slider = entry[5]
+			var max_slider = entry[6]
+			var exp = entry[7]
+			if brk_data.size() > 0: #if breakpoint data is present on slider
+				#Sort all points by time
+				var sorted_brk_data = []
+				sorted_brk_data = brk_data.duplicate()
+				sorted_brk_data.sort_custom(sort_points)
 				
-			#make text file
-			var brk_file_path = output_file.get_basename() + "_" + str(slider_count) + ".txt"
-			write_breakfile(calculated_brk, brk_file_path)
-			
-			#append text file in place of value
-			#line += ("\"%s\" " % brk_file_path)
-			if flag.begins_with("-"):
-				brk_file_path = flag + brk_file_path
-			args.append(brk_file_path)
-			
-			cleanup.append(brk_file_path)
-		else:
-			if time == true:
-				var infile_length = await run_command(control_script.cdpprogs_location + "/sfprops", ["-d", current_infile])
-				infile_length = float(infile_length.strip_edges())
-				value = infile_length * (value / 100) #calculate percentage time of the input file
-			#line += ("%s%.2f " % [flag, value]) if flag.begins_with("-") else ("%.2f " % value)
-			args.append(("%s%.2f " % [flag, value]) if flag.begins_with("-") else str(value))
-			
+				var calculated_brk = []
+				
+				#get length of input file in seconds
+				var infile_length = 1 #set infile length to dummy value just incase it does get used where it shouldn't to avoid crashes
+				if current_infile != "none":
+					infile_length = await run_command(control_script.cdpprogs_location + "/sfprops", ["-d", current_infile])
+					infile_length = float(infile_length.strip_edges())
+				
+				#scale values from automation window to the right length for file and correct slider values
+				#if node has an output duration then breakpoint files should be x = outputduration y= slider value else x=input duration, y=value
+				if node.has_meta("outputduration"):
+					for i in range(sorted_brk_data.size()):
+						var point = sorted_brk_data[i]
+						var new_x = float(node.get_meta("outputduration")) * (point.x / 700) #output time
+						if i == sorted_brk_data.size() - 1: #check if this is last automation point
+							new_x = float(node.get_meta("outputduration")) + 0.1  # force last point's x to infile_length + 100ms to make sure the file is defo over
+						var new_y
+						#check if slider is exponential and scale automation
+						if exp:
+							new_y = remap_y_to_log_scale(point.y, 0.0, 255.0, min_slider, max_slider)
+						else:
+							new_y = remap(point.y, 255, 0, min_slider, max_slider) #slider value
+						if time: #check if this is a time slider and convert to percentage of input file
+							new_y = infile_length * (new_y / 100)
+						calculated_brk.append(Vector2(new_x, new_y))
+				else:
+					for i in range(sorted_brk_data.size()):
+						var point = sorted_brk_data[i]
+						var new_x = infile_length * (point.x / 700) #time
+						if i == sorted_brk_data.size() - 1: #check if this is last automation point
+							new_x = infile_length + 0.1  # force last point's x to infile_length + 100ms to make sure the file is defo over
+						var new_y
+						#check if slider is exponential and scale automation
+						if exp:
+							new_y = remap_y_to_log_scale(point.y, 0.0, 255.0, min_slider, max_slider)
+						else:
+							new_y = remap(point.y, 255, 0, min_slider, max_slider) #slider value
+						calculated_brk.append(Vector2(new_x, new_y))
+					
+				#make text file
+				var brk_file_path = output_file.get_basename() + "_" + str(slider_count) + ".txt"
+				write_breakfile(calculated_brk, brk_file_path)
+				
+				#append text file in place of value
+				#line += ("\"%s\" " % brk_file_path)
+				if flag.begins_with("-"):
+					brk_file_path = flag + brk_file_path
+				args.append(brk_file_path)
+				
+				cleanup.append(brk_file_path)
+			else: #no break file append slider value
+				if time == true:
+					var infile_length = await run_command(control_script.cdpprogs_location + "/sfprops", ["-d", current_infile])
+					infile_length = float(infile_length.strip_edges())
+					value = infile_length * (value / 100) #calculate percentage time of the input file
+				#line += ("%s%.2f " % [flag, value]) if flag.begins_with("-") else ("%.2f " % value)
+				args.append(("%s%.2f " % [flag, value]) if flag.begins_with("-") else str(value))
+				
+		elif entry[0] == "checkbutton":
+			var flag = entry[1]
+			var value = entry[2]
+			#if button is pressed add the flag to the arguments list
+			if value == true:
+				args.append(flag)
 		slider_count += 1
 	return [command, output_file, cleanup, args]
 	#return [line.strip_edges(), output_file, cleanup]