Browse Source

implemented full processing chain for multiple input pvoc nodes

Jonathan Higgins 3 months ago
parent
commit
036643665a
2 changed files with 106 additions and 85 deletions
  1. 0 6
      project.godot
  2. 106 79
      scenes/main/scripts/run_thread.gd

+ 0 - 6
project.godot

@@ -53,12 +53,6 @@ undo={
 "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"command_or_control_autoremap":true,"alt_pressed":false,"shift_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
 "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"command_or_control_autoremap":true,"alt_pressed":false,"shift_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
 ]
 ]
 }
 }
-redo={
-"deadzone": 0.2,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":89,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
-, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"command_or_control_autoremap":true,"alt_pressed":false,"shift_pressed":true,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
-]
-}
 save={
 save={
 "deadzone": 0.2,
 "deadzone": 0.2,
 "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"command_or_control_autoremap":true,"alt_pressed":false,"shift_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
 "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"command_or_control_autoremap":true,"alt_pressed":false,"shift_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)

+ 106 - 79
scenes/main/scripts/run_thread.gd

@@ -32,6 +32,8 @@ func init(main_node: Node, progresswindow: Window, progresslabel: Label, progres
 func run_thread_with_branches():
 func run_thread_with_branches():
 	process_cancelled = false
 	process_cancelled = false
 	process_successful = true
 	process_successful = true
+	progress_bar.value = 0
+	progress_label.text = "Initialising Inputs"
 	# Detect platform: Determine if the OS is Windows
 	# Detect platform: Determine if the OS is Windows
 	var is_windows := OS.get_name() == "Windows"
 	var is_windows := OS.get_name() == "Windows"
 	
 	
@@ -226,7 +228,7 @@ func run_thread_with_branches():
 	var output_files = {}
 	var output_files = {}
 	var process_count = 0
 	var process_count = 0
 
 
-	var current_infile
+	#var current_infile
 
 
 	# Iterate over the processing nodes in topological order
 	# Iterate over the processing nodes in topological order
 	for node_name in sorted:
 	for node_name in sorted:
@@ -296,7 +298,6 @@ func run_thread_with_branches():
 				current_infiles[key] = matched_files[idx]
 				current_infiles[key] = matched_files[idx]
 				idx += 1
 				idx += 1
 		
 		
-		
 		#check if node is some form of input node
 		#check if node is some form of input node
 		if node.get_input_port_count() == 0:
 		if node.get_input_port_count() == 0:
 			if node.get_meta("command") == "inputfile":
 			if node.get_meta("command") == "inputfile":
@@ -369,26 +370,18 @@ func run_thread_with_branches():
 			var slider_data = _get_slider_values_ordered(node)
 			var slider_data = _get_slider_values_ordered(node)
 			
 			
 			if node.get_slot_type_right(0) == 1: #detect if process outputs pvoc data
 			if node.get_slot_type_right(0) == 1: #detect if process outputs pvoc data
-				if typeof(current_infile) == TYPE_ARRAY:
-					#check if infile is an array meaning that the last pvoc process was run in dual mono mode
-					# Process left and right seperately
-					var pvoc_stereo_files = []
-					
-					for infile in current_infile:
-						var makeprocess = await make_process(node, process_count, infile, slider_data)
-						# run the command
-						await run_command(makeprocess[0], makeprocess[3])
-						await get_tree().process_frame
-						var output_file = makeprocess[1]
-						pvoc_stereo_files.append(output_file)
-						
-						# Mark file for cleanup if needed
-						if control_script.delete_intermediate_outputs:
-							for file in makeprocess[2]:
-								breakfiles.append(file)
-							intermediate_files.append(output_file)
-
-						process_count += 1
+				if is_pvoc_stereo(current_infiles): #check if infiles contain an array meaning at least one input pvoc process has be processed in dual mono mode
+					var split_files = await process_dual_mono_pvoc(current_infiles, node, process_count, slider_data)
+					var pvoc_stereo_files = split_files[0]
+								
+					# Mark file for cleanup if needed
+					if control_script.delete_intermediate_outputs:
+						for file in split_files[1]:
+							breakfiles.append(file)
+						for file in pvoc_stereo_files:
+							intermediate_files.append(file)
+							
+					process_count += 1
 						
 						
 					output_files[node_name] = pvoc_stereo_files
 					output_files[node_name] = pvoc_stereo_files
 				else:
 				else:
@@ -396,35 +389,32 @@ func run_thread_with_branches():
 					if input_stereo == true: 
 					if input_stereo == true: 
 						#audio file is stereo and needs to be split for pvoc processing
 						#audio file is stereo and needs to be split for pvoc processing
 						var pvoc_stereo_files = []
 						var pvoc_stereo_files = []
-						##Split stereo to c1/c2
-						await run_command(control_script.cdpprogs_location + "/housekeep",["chans", "2", current_infile])
-				
-						# Process left and right seperately
-						for channel in ["c1", "c2"]:
-							var dual_mono_file = current_infile.get_basename() + "_%s.%s" % [channel, current_infile.get_extension()]
-							
-							var makeprocess = await make_process(node, process_count, dual_mono_file, slider_data)
-							# run the command
-							await run_command(makeprocess[0], makeprocess[3])
-							await get_tree().process_frame
-							var output_file = makeprocess[1]
-							pvoc_stereo_files.append(output_file)
-							
-							# Mark file for cleanup if needed
-							if control_script.delete_intermediate_outputs:
-								for file in makeprocess[2]:
-									breakfiles.append(file)
-								intermediate_files.append(output_file)
+
+						##Split stereo to c1/c2 and process
+						var split_files = await stereo_split_and_process(current_infiles.values(), node, process_count, slider_data)
+						pvoc_stereo_files = split_files[0]
 							
 							
-							#Delete c1 and c2 because they can be in the wrong folder and if the same infile is used more than once
-							#with this stereo process CDP will throw errors in the console even though its fine
+						# Mark file for cleanup if needed
+						if control_script.delete_intermediate_outputs:
+							for file in split_files[1]:
+								breakfiles.append(file)
+							for file in pvoc_stereo_files:
+								intermediate_files.append(file)
+						
+						#Delete c1 and c2 because they can be in the wrong folder and if the same infile is used more than once
+						#with this stereo process CDP will throw errors in the console even though its fine
+						var files_to_delete = split_files[2] + split_files[3]
+						for file in files_to_delete:
 							if is_windows:
 							if is_windows:
-								dual_mono_file = dual_mono_file.replace("/", "\\")
-							await run_command(delete_cmd, [dual_mono_file])
-							process_count += 1
-							
-							# Store output file path for this node
+								file = file.replace("/", "\\")
+							await run_command(delete_cmd, [file])
+						
+						#advance process count to match the advancement in the stereo_split_and_process function
+						process_count += 1
+						
+						# Store output file path for this node
 						output_files[node_name] = pvoc_stereo_files
 						output_files[node_name] = pvoc_stereo_files
+						
 					else: 
 					else: 
 						#input file is mono run through process
 						#input file is mono run through process
 						var makeprocess = await make_process(node, process_count, current_infiles.values(), slider_data)
 						var makeprocess = await make_process(node, process_count, current_infiles.values(), slider_data)
@@ -447,28 +437,19 @@ func run_thread_with_branches():
 				
 				
 			else: 
 			else: 
 				#Process outputs audio
 				#Process outputs audio
-				#check if this is the last pvoc process in a stereo processing chain
-				if node.get_meta("command") == "pvoc_synth" and typeof(current_infile) == TYPE_ARRAY:
-				
-					#check if infile is an array meaning that the last pvoc process was run in dual mono mode
-					# Process left and right seperately
-					var pvoc_stereo_files = []
-					
-					for infile in current_infile:
-						var makeprocess = await make_process(node, process_count, infile, slider_data)
-						# run the command
-						await run_command(makeprocess[0], makeprocess[3])
-						await get_tree().process_frame
-						var output_file = makeprocess[1]
-						pvoc_stereo_files.append(output_file)
-						
-						# Mark file for cleanup if needed
-						if control_script.delete_intermediate_outputs:
-							for file in makeprocess[2]:
-								breakfiles.append(file)
-							intermediate_files.append(output_file)
-
-						process_count += 1
+				#check if this is the last pvoc process in a stereo processing chain and check if infile is an array meaning that the last pvoc process was run in dual mono mode
+				if node.get_meta("command") == "pvoc_synth" and is_pvoc_stereo(current_infiles):
+					var split_files = await process_dual_mono_pvoc(current_infiles, node, process_count, slider_data)
+					var pvoc_stereo_files = split_files[0]
+								
+					# Mark file for cleanup if needed
+					if control_script.delete_intermediate_outputs:
+						for file in split_files[1]:
+							breakfiles.append(file)
+						for file in pvoc_stereo_files:
+							intermediate_files.append(file)
+							
+					process_count += 1
 						
 						
 						
 						
 					#interleave left and right
 					#interleave left and right
@@ -482,9 +463,10 @@ func run_thread_with_branches():
 						intermediate_files.append(output_file)
 						intermediate_files.append(output_file)
 				elif node.get_meta("command") == "preview":
 				elif node.get_meta("command") == "preview":
 					var preview_audioplayer = node.get_child(1)
 					var preview_audioplayer = node.get_child(1)
-					preview_audioplayer._on_file_selected(current_infile)
-					if current_infile in intermediate_files:
-						intermediate_files.erase(current_infile)
+					var preview_file = current_infiles.values()[0]
+					preview_audioplayer._on_file_selected(preview_file)
+					if preview_file in intermediate_files:
+						intermediate_files.erase(preview_file)
 				else:
 				else:
 					#Detect if input file is mono or stereo
 					#Detect if input file is mono or stereo
 					var input_stereo = await is_stereo(current_infiles.values()[0])
 					var input_stereo = await is_stereo(current_infiles.values()[0])
@@ -508,7 +490,7 @@ func run_thread_with_branches():
 								intermediate_files.append(output_file)
 								intermediate_files.append(output_file)
 
 
 						else: #audio file is stereo and process is mono, split stereo, process and recombine
 						else: #audio file is stereo and process is mono, split stereo, process and recombine
-							##Split stereo to c1/c2
+							##Split stereo to c1/c2 and process
 							var split_files = await stereo_split_and_process(current_infiles.values(), node, process_count, slider_data)
 							var split_files = await stereo_split_and_process(current_infiles.values(), node, process_count, slider_data)
 							var dual_mono_output = split_files[0]
 							var dual_mono_output = split_files[0]
 								
 								
@@ -638,6 +620,8 @@ func run_thread_with_branches():
 	progress_bar.value = 100.0
 	progress_bar.value = 100.0
 	var interface_settings = ConfigHandler.load_interface_settings() #checks if close console is enabled and closes console on a success
 	var interface_settings = ConfigHandler.load_interface_settings() #checks if close console is enabled and closes console on a success
 	progress_window.hide()
 	progress_window.hide()
+	progress_bar.value = 0
+	progress_label.text = ""
 	if interface_settings.auto_close_console and process_successful == true:
 	if interface_settings.auto_close_console and process_successful == true:
 		console_window.hide()
 		console_window.hide()
 
 
@@ -669,6 +653,34 @@ func stereo_split_and_process(files: Array, node: Node, process_count: int, slid
 	#return the two output files, any breakfiles generated and the split files for deletion
 	#return the two output files, any breakfiles generated and the split files for deletion
 	return [dual_mono_output, intermediate_files, left, right]
 	return [dual_mono_output, intermediate_files, left, right]
 	
 	
+func process_dual_mono_pvoc(current_infiles: Dictionary, node: Node, process_count: int, slider_data: Array) -> Array:
+	match_pvoc_channels(current_infiles) #normalise dictionary to ensure that all entries are dual mono (any mono only processes are duplicated to both left and right)
+	
+	var infiles_left = []
+	var infiles_right = []
+	var pvoc_stereo_files = []
+	var intermediate_files = []
+	
+	# extract left and right infiles from dictionary
+	for value in current_infiles.values():
+		infiles_left.append(value[0])
+		infiles_right.append(value[1])
+		
+	for infiles in [infiles_left, infiles_right]:
+		var makeprocess = await make_process(node, process_count, infiles, slider_data)
+		# run the command
+		await run_command(makeprocess[0], makeprocess[3])
+		await get_tree().process_frame
+		var output_file = makeprocess[1]
+		pvoc_stereo_files.append(output_file)
+		for file in makeprocess[2]:
+			intermediate_files.append(file)
+		
+		#advance process count to maintain unique file names
+		process_count += 1
+		
+	return [pvoc_stereo_files, intermediate_files]
+	
 func is_stereo(file: String) -> bool:
 func is_stereo(file: String) -> bool:
 	var soundfile_properties = get_soundfile_properties(file)
 	var soundfile_properties = get_soundfile_properties(file)
 	if soundfile_properties[1] == 2:
 	if soundfile_properties[1] == 2:
@@ -676,6 +688,12 @@ func is_stereo(file: String) -> bool:
 	else:
 	else:
 		return false
 		return false
 
 
+func is_pvoc_stereo(current_infiles: Dictionary) -> bool:
+	for value in current_infiles.values():
+		if value is Array:
+			return true
+	return false
+
 func get_soundfile_properties(file: String) -> Array:
 func get_soundfile_properties(file: String) -> Array:
 	var format
 	var format
 	var channels
 	var channels
@@ -684,6 +702,9 @@ func get_soundfile_properties(file: String) -> Array:
 	
 	
 	#open the audio file
 	#open the audio file
 	var f = FileAccess.open(file, FileAccess.READ)
 	var f = FileAccess.open(file, FileAccess.READ)
+	if f == null:
+		log_console("Could not find file: " + file, true)
+		return [0, 0, 0, 0]  # couldn't open
 	
 	
 	#Skip the RIFF header (12 bytes: "RIFF", file size, "WAVE")
 	#Skip the RIFF header (12 bytes: "RIFF", file size, "WAVE")
 	f.seek(12)
 	f.seek(12)
@@ -716,7 +737,8 @@ func get_soundfile_properties(file: String) -> Array:
 		f.seek(f.get_position() + chunk_size)
 		f.seek(f.get_position() + chunk_size)
 	
 	
 	f.close()
 	f.close()
-	return [-1] #no fmt chunk found, invalid wav file
+	log_console("No valid fmt chunk found in wav file, unable to establish, format, channel count, samplerate or bit-depth", true)
+	return [0, 0, 0, 0] #no fmt chunk found, invalid wav file
 		
 		
 #func get_samplerate(file: String) -> int:
 #func get_samplerate(file: String) -> int:
 	#var output = await run_command(control_script.cdpprogs_location + "/sfprops", ["-r", file])
 	#var output = await run_command(control_script.cdpprogs_location + "/sfprops", ["-r", file])
@@ -898,7 +920,13 @@ func match_file_channels(inlet_id: int, process_count: int, input_files: Array)
 
 
 	return [input_files, converted_files]
 	return [input_files, converted_files]
 	
 	
-
+func match_pvoc_channels(dict: Dictionary) -> void:
+	#work through dictionary of files and make all entries dual arrays for stereo pvoc processing
+	for key in dict.keys():
+		var value = dict[key]
+		if value is String:
+			dict[key] = [value, value]
+			
 func _get_slider_values_ordered(node: Node) -> Array:
 func _get_slider_values_ordered(node: Node) -> Array:
 	var results := []
 	var results := []
 	for child in node.get_children():
 	for child in node.get_children():
@@ -1077,7 +1105,7 @@ func write_breakfile(points: Array, path: String):
 			file.store_string(line)
 			file.store_string(line)
 		file.close()
 		file.close()
 	else:
 	else:
-		print("Failed to open file for writing.")
+		log_console("Failed to open file to write breakfile", true)
 
 
 func _on_kill_process_button_down() -> void:
 func _on_kill_process_button_down() -> void:
 	if process_running and process_info.has("pid"):
 	if process_running and process_info.has("pid"):
@@ -1085,7 +1113,6 @@ func _on_kill_process_button_down() -> void:
 		# Terminate the process by PID
 		# Terminate the process by PID
 		OS.kill(process_info["pid"])
 		OS.kill(process_info["pid"])
 		process_running = false
 		process_running = false
-		print("Process cancelled.")
 		process_cancelled = true
 		process_cancelled = true
 
 
 	
 	
@@ -1157,7 +1184,7 @@ func run_command(command: String, args: Array) -> String:
 		process_info = OS.execute_with_pipe(command, args, false)
 		process_info = OS.execute_with_pipe(command, args, false)
 	# Check if the process was successfully started
 	# Check if the process was successfully started
 	if !process_info.has("pid"):
 	if !process_info.has("pid"):
-		print("Failed to start process.")
+		log_console("Failed to start process]", true)
 		return ""
 		return ""
 	
 	
 	process_running = true
 	process_running = true