Connecting Godot to Pure Data?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By AydinHumphries

I have made several questions about this on the facebook page but nobody really seems to know how. It is a shame I can’t share videos here as I would be able to share more detail that way.

Anyway, I have come across two different possible solutions for my problem as to how to connect Godot to Pure Data, one is to turn a Pure Data (Pd) patch into a plugin maybe for WWise and run through Godot. I got stuck with the one minute WWise tutorial online at the part he says to use the X: command. But windows cmd doesn’t recognise the X drive and I don’t know how to configure it to. Also I’ve heard the heavy compiler for WWise doesn’t recognise all externals in the Pd-vanilla library.

Another possible solution is to network between Godot and Pure Data like how Frankie Zafe’s project works over on Gitlab. But I have cloned his repository and finding it full of bugs, plus for Pd uses a very old externals library that with updated Pd-Vanilla features is mostly not necessary now. Otherwise, I am stuck on solutions for this and really need to figure out how to do this soon. I looked at GamingFromScratch’s tutorial on networking but this is all about communication between servers and clients run solely on Godot. No information about how to connect with an external application like Pd.

As for the reason why use Pd and not Godot’s own audio BUS features, that is because I need real time manipulation of audio parameters for generative music processes that uses synthesisers built from scratch. Looking at Godot’s audio BUS, I don’t believe it does any of this.

As for information about what Pd is, here’s the online explanation from Wikipedia:

“Pure Data is a visual programming language developed by Miller Puckette in the 1990s for creating interactive computer music and multimedia works.”

:bust_in_silhouette: Reply From: klaas

Hi,
as i read in the peer data docs. It uses a very simple text based tcp protocol named FUDI

This should be easy to connect this with the StreamPeerTCP …

… and send string messages with put_string()

What messages should/can be transmitted i dont know

**Thank you very much for getting back to me, I’ve been looking to get an answer for this for some time. You will have to forgive my questions how to implement this - but I have at best a very basic understanding of gdscript.
So I have created a gd project with a Node 2d, child node “Button” attached with function “_on_Button_pressed()” and script “Button.gd” attached to the button. My intention is to send a message through IP, 127.0.0.1, port 4242 but I don’t really know how to write the script for this.
My attempt (indentations are supposed to be on line 4, 6 and 9):
extends Button

func _init():
var done = false

var socket = StreamPeerTCP.new()
func _on_Button_pressed():
connect_to_host.socket("127.0.0.1", "4242")

And the error message on that last line of code:
error(9,1): The identifier “connect_to_host” isn’t declared in the current scope.
Do you have any idea what I can do to make this script work?**

AydinHumphries | 2020-09-11 15:59

your addressing the socket wrong
its socket.function_to_call()

Putting the stream in a button dont seam the best place to me, but will work

extends Button
var socket

func _init():
    var done = false
    socket = StreamPeerTCP.new()

func _on_Button_pressed():
    socket.connect_to_host("127.0.0.1", "4242")

to put up a proper testing setup i would go like this

– Control (create script here)
----- buttonConnect
----- buttonMessage

extends Control
var socket

func _ready():
    socket = StreamPeerTCP.new()
    $buttonConnect.connect("pressed",self,"on_connect")
    $buttonMEssage.connect("pressed",self,"on_message")

func _on_connect():
    socket.connect_to_host("127.0.0.1", "4242")

func _on_message():
    socket.put_string("my message;")

klaas | 2020-09-11 16:09

So I am a little confused as I don’t know where the “_on_buttonConnect_pressed()” or the “_on_buttonMessage_pressed()” is meant to connect for “control.gd”. Or am I supposed to abbreviate those function titles to “_on_connect()” and “_on_message()”?

Additionally, is the first script you wrote still supposed to be attached buttonConnect and work in conjunction with the second script? Or is the ideal solution to disregard the first script and only use the second?

AydinHumphries | 2020-09-11 16:26

ok, i suggested you know the basics of signals.

the first code is a correction for your posted code.

the second one is a more structured setup to expand your test environment.

So you should use the first or the second

and you should read this for more insight in godots signals:
Using signals — Godot Engine (stable) documentation in English

klaas | 2020-09-11 16:31

ok that is clearer. so I have detached the script from “buttonConnect”.

I am still unsure though if where I have connected the nodes they are supposed to be

_on_connect

and

_on_message

or not, so I have assumed and changed the names.

I have run the godot file and on line 10 of the code where it is written:

socket.connect_to_host("127.0.0.1", "4242")

And the error returned when I press “buttonConnect”:

"Invalid type in function 'connect_to_host' in base 'StreamPeerTCP. Cannot convert argument 2 from String to int."

I am going to read that document you linked me now.

AydinHumphries | 2020-09-11 16:42

ok, I just read that article. so am I supposed to create a timer to emit the signals in the project?

AydinHumphries | 2020-09-11 17:04

I thought you should know, since writing the above comments, I played around with the Godot project files and managed to send the “my_message;” to the Pd but it is received not as the exact string but the  character. actually, it is lucky you - intentionally or by mistake - included the semicolon because that is the only character which is sent and received by Pd. no other character seems to send, so the message may as well just be “;” actually. it seems you were correct that the final problem would be about what messages to send, or how to find a way to convert the string into binary and back into ascii for pd. how to do this, I will just have to research.

anyway I have cloned the project folder (including the Pd file) as a github repo.

AydinHumphries | 2020-09-11 20:35

the github repo:

GitHub - AydinHumphries/StreamPeerTCP-to-FUDI

AydinHumphries | 2020-09-11 20:36

There is no thing as binary text. Strings are binary as well. It may depend on the encoding. Godot sends the string length first when using put_string, this could be the problem.

put_data("my message;".to_ascii())

You have to read the FUDI protocol description!!! The semikolon is the message terminator!

FUDI is a packet oriented protocol.
Each message consists of one or more atoms, separated by one or more whitespace characters, and it’s terminated by a semicolon character.
An atom is a sequence of one or more characters; whitespaces inside atoms can be escaped by the backslash (ascii 92) character (see Examples below).
A whitespace is either a space (ascii 32), a tab (ascii 9) or a newline (ascii 10).
A semicolon (ascii 59) is mandatory to terminate (and send) a message. A newline is just treated as whitespace and not needed for message termination.

klaas | 2020-09-11 21:28