Pdscript

I’ve recently been frustrated the lack of facility for sharing Pd and Max patches in an textual format. They are, after all graphical dataflow languages, which is great most of the time, but what if you want to share a bit of Pd code with someone on Twitter, or via chat? Do you attach the Pd file? A screenshot? … all of these seem too ‘heavyweight’ for the underlying medium. Personally, I’d like to be able to share Pd code in textual snippets as Perl and SuperCollider users do.

This has led me to think of a simple ‘lightweight’ scripting layer that runs on top of Pd’s native ‘FUDI’ interface. I want it to be as close to Pd patching as possible to make it easy for Pd-users to learn and to not introduce any new language-level constructs that aren’t already in Pd. Here’s where I am at so far:

Syntax

These are just ideas, not formal syntax rules, but could serve as a starting point.

  • Objects are instantiated using <object name> <arguments> e.g. cycle~ 440
  • Connections are made using curly braces: <source object>{<target object>}. This makes an implicit connection from the first outlet of the source object to the first inlet of the target object. If inlets other than the first are required then inlet/outlet labels can be referenced using the slash notation: \<source label>{\<target label>}
  • Inlets can be given labels using \<inlet number from zero>:<inlet label>
  • Outlets can be given labels using \\<outlet number from zero>:<inlet label>
  • Sub-patches can created using \pd <subpatch name> \{ <subpatch content> \}
  • Messages are indicated with \msg

Curly braces and the backslash character have been chosen here because they are disallowed characters in Pd, thus avoiding ambiguities between the scripting code and the Pd code.

Example

To test the scripting language properly, I’ve constructed an example of medium complexity that illustrates a number of aspects of Pd patching.

Pd-karplus.png

In the fledgling pdscript, this would be represented as:

\pd mtodt \{
    inlet
    {
        mtof
        {
            \msg 1000 $1
            {
                /
                {
                    sig~
                    {
                        outlet
                    }
                }
            }
        }
    }
\} \0:midiin \\0:dtout

noise~
{
    *~ 0 \1:noisemul
    {
        delwrite~ buff 256 \0:delayin
    }
}

notein \\1:velocity
{
    {
        spigot \1:noteoff_filter
        {
            t b a \\1:pitch
            {
                {
                    f 1 \1:amplitude
                    {
                        \noisemul
                    }
                } 
                {
                    del 2
                    {
                        \msg 0
                        {
                            \noisemul
                        }
                    }
                }
            }
        } 
    }
}

\velocity
{
    / 127
    {
        \amplitude
    }

}

\pitch
{
    \midiin
}

\dtout
    {
        vd~ buff
        {
            {
                *~ 0.995
                {
                    lop~ 5000
                    {
                        \delayin
                    }
                }
            }
            {
                dac~ \1:rightout
            }
            {
                \rightout
            }
        }
    }
}

Implementation

I’m thinking that this could be implemented by writing a pdscript interpreter, which parses the script and compiles it into a list of FUDI commands to be sent to Pd via a network connection. If the script proves to be popular the interpreter could be built into Pd itself and maybe invoked with a command line flag:

pd -script myscript

Or maybe even run interactively

pd -ishell

Outro

These are just a few ideas as a starting point. Comments welcome!


Update 10/4/09

Thinking about this a bit more, the closing braces are redundant except in the case of branching. This means we can reduce the verbosity of the syntax a bit if we introduce a block delimeter. I therefore propose the comma for this purpose. I’ve also introduced the semicolon as comment identifier and changed the inlet/outlet labelling syntax to use an array-like syntax ‘\in[n]:label’ labels the nth inlet, ‘\out[n]:label’ labels the nth outlet.

;We define a subpatch using '\pd <subpatch name>'

\pd mtodt \in[0]:midiin \out[0]:dtout
    inlet
    {
        mtof
        {
            msg 1000 $1
            {
                /
                {
                    sig~
                    {
                        outlet

;A comma acts as a block delimeter
,

noise~
{
    *~ 0 \in[1]:noisemul
    {
        delwrite~ buff 256 \in[0]:delayin
,

notein \out[1]:velocity
{
    {
        spigot \in[1]:noteoff_filter
        {
            t b a \out[1]:pitch
            {
                {
                    f 1 \in[1]:amplitude
                    {
                        \noisemul
                    }
                }
                {
                    del 2
                    {
                        msg 0
                        {
                            \noisemul
                        }
                    }
                }
,

\velocity
{
    / 127
    {
        \amplitude
,

\pitch
{
    \midiin
,

\dtout
    {
        vd~ buff
        {
            {
                *~ 0.995
                {
                    lop~ 5000
                    {
                        \delayin
                    }
                }
            }
            {
                dac~ \in[1]:rightout
            }
            {
                \rightout
            }
,

This reduces down to the following if we remove the newlines and whitespace:

\pd mtodt \in[0]:midiin \out[0]:dtout 
     inlet{mtof{msg 1000 $1{/{sig~{outlet, 

noise~{*~ 0 \in[1]:noisemul{
    delwrite~ buff 256 \in[0]:delayin,

notein \out[1]:velocity{{spigot \in[1]:noteoff_filter{
     t b a \out[1]:pitch{{f 1 \in[1]:amplitude{
          \noisemul}}{del 2{msg 0{\noisemul}}},

\velocity{/ 127{\amplitude,

\pitch{\midiin,

\dtout{vd~ buff{{*~ 0.995{lop~ 5000{\delayin}}}
     {dac~ \in[1]:rightout}{\rightout},

Related Entries

3 Comments

Hi

intriguing idea, very ambitious...

as sharing of code goes: pd files are text files, you can always open then with a common text editor, and post the contents to a list (it does happen).

You can also generate pd patches dynamically using other programs (written in Perl, Python, Java) by saving strings to a file.

Pd's internal format is not very human readable, and it mixes the presentation data with control- and data- flow. So a script language like yours, that doesn't have presentation data embedded would definitely be an improvement, from a theoretical perspective. But patches would probably not be compatible.

What about automated conversion from pd to supercollider? Wouldn't that be a more feasible approach?

best regards
Alvaro

Thanks for the feedback. My concern with a Supercollider Pd converter is that they use very different language paradigms. Pd is a dataflow language, whilst SClang is an object-oriented language. I think establishing a mapping between the two would in itself be a challenging task.

Converting between a Pd and SCSynth synthesis graphs on the DSP side would be feasible, but would be quite limiting since you lose the power of the language side.

To follow up on what Alvaro said, one of the neat features in DesireData was that any objects you selected and copied graphically were automatically placed on the system clipboard in textual form along with all their connections.

That meant that, to share a patch with someone you could just open it up, select everything, copy, and then paste into whatever textual medium you are communicating in (email, a chat program). They would in turn copy the text and paste it into a blank canvas where all the original objects and their connections would appear.

Hopefully that feature will make it into Pd itself someday.

Leave a comment

About

I work at Birmingham Conservatoire as senior researcher and software development manager for the Integra Project. I live with my wife and three beautiful children in Birmingham, UK.» More...

Tag Cloud

Projects

-->
Close