[PD] Implementing a scheme extension language
lt at westnet.com
Sun Apr 29 00:22:02 CEST 2001
I am attempting to implement an library which will provide a scheme
extension language, and would welcome any comments.
First I should say what my motivation is. I have found PD very fun and
practical, except where any kind of serious programming logic is needed.
In these cases, I have found it a mind bender to try to implement
graphically what could be accomplished very easily using a text-oriented
language. As a case in point, I want to create a PD piano instrument
that uses a piano sample CD. Although I got it working with a particular
set of sample files, it is clear that the graphical hookup technique is
certainly not a sensible way to go about this. As a result (well, not
only because of this, but also because of several other similar
situations), I have longed to drop down into a textual language to
implement PD objects.
True, I could use C and implement what I need directly as a loadable
object, but I though that an interpreted language would be in general
nicer, and fast enough, for most purposes like this.
I have decided at first to use "scheme in one defun" (siod), simply
because my time is limited, and siod it takes much less brain power to
integrate siod, then to learn how to implement guile or elk.
Of course, guile/elk is more complete and probably will run a lot
faster, and this is a future option.
I'd like to present my first-attempt specs for how this would work, and
see if anyone has any comments. This is very rough-draft and not
precise, but just to give a general idea...
1) implement a global receiver (like "pd"), that when it receives any
message, sends it to the sheme interpreter to evaluate. This would not
be as nice as a seperate interpreter console, but for now, it will avoid
me to have to deal with a new gui for an interpreter. Question: what to
name this? I will take "scm" for now, so that for example, in a message
box, "; scm foo `( 1 2)" will call the scheme function "foo" with the
list (1 2) as an argument. The outer pair of parenthesis is implicitly
2) The scheme function (pdsend 'receiver arg1 arg2 ..) will send its
args to the pd receiver named "receiver". For example, (pdsend 'pd
3) The scheme function (pdreceive 'x fn) will create a pd receiver, so
that when pd sends a message to "x", the scheme function "fn" will be
called, and passed the message as a list.
4) The pd object "scmob" (Question: better name?) will instantiate a pd
object implemented in scheme (for now I won't deal with DSP signals).
Its first argument, prepended with "make-", will be the name of a scheme
function which will create a closure which will become the object. The
number of inlets to this object will be determined by the number of the
arguments in the lambda expression returned by the generation function.
And the number of outlets will be determined by, well I don't know yet.
The additional creation arguments will be passed to the creation
function. Within the lambda, the function (pdout n val) would send val
to the n'th outlet of the object. When anything is received at the first
inlet to the object, the arguments of the lambda will be bound to the
current values at the inlets, and the lambda will be called.
For example, say we have in the scheme environment (note, I just typed
this in without a proper editor, so there could be paren mismatches,
etc, but to give the general idea...) :
(define (make-integrator initial-value)
(let ((current initial-value))
((and (symbol? x) (eq x 'reset))
(set! current initial-value))
(set! current (+ current x))))
(pdout 0 current)
(pdout 1 x)))
Given that the above has been evaluated in the scheme environment, then
typing "scmob integrator 10" into a PD object would create a an object
with one inlet, whose first outlet would be a sum of the number object
received at the inlet, or be reset to 10 if the "reset" message is
received at the inlet. The second outlet would be a copy of the inlet.
More information about the Pd-list