- commit
- a48e0e3be30723d86374323543d298a5c33b6da4
- parent
- a0335318475750af60e9fe7e6cbaca19e25fb8dc
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2022-08-26 21:26
add README.md
Diffstat
| A | README.md | 136 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | screenshots/example.png | 0 | |
| A | screenshots/simple.png | 0 |
3 files changed, 136 insertions, 0 deletions
diff --git a/README.md b/README.md
@@ -0,0 +1,136 @@
-1 1 xipd is a programming language for audio processing that compiles to
-1 2 [PureData](http://msp.ucsd.edu/Pd_documentation/index.htm).
-1 3
-1 4 ## Example
-1 5
-1 6 ```
-1 7 include "std.xipd"
-1 8
-1 9 osc(freq) {
-1 10 osc = `osc~`
-1 11 freq -> osc
-1 12 return osc
-1 13 }
-1 14
-1 15 osc1 = osc(1)
-1 16 osc2 = osc(osc1 *~ 20 +~ 440)
-1 17 osc2 -> `dac~`
-1 18 ```
-1 19
-1 20 ## PureData Primer
-1 21
-1 22 PureData is a graphical programming environment for real-time audio processing.
-1 23 It consists of *nodes* and *connections*. For example, there could be one
-1 24 oscillator node, one node for audio output, and a connection between them.
-1 25
-1 26 
-1 27
-1 28 There are two kinds of connections: *control* connections for sporadic messages
-1 29 and *signal* connections for continuous streams. Nodes that expect signal
-1 30 connections are usually suffixed with "~". For example, the `+` node can be
-1 31 used to add two numbers, but if you want to mix audio streams you have to use
-1 32 `+~` instead.
-1 33
-1 34 Nodes can have multiple *inlets* and *outlets*. For example, the `+` node has
-1 35 two inlets. The value of a node is only updated when it receives a message to
-1 36 its first inlet. The first inlet is therefore referred to as *hot* while the
-1 37 others are called *cold*.
-1 38
-1 39 PureData comes with a large set of built-in nodes for low-level audio
-1 40 processing. There is also a large community that shares more high-level
-1 41 structures.
-1 42
-1 43 ## Goals
-1 44
-1 45 I personally had some issues with PureData, so I tried to wrap it in something
-1 46 that feels more familiar to me. The result of that attempt is xipd. The goals
-1 47 are:
-1 48
-1 49 - **Text-based instead of visual programming language**: This is crucial so
-1 50 authors can use common tools like vim or git. PureData does have a [text
-1 51 representation](http://puredata.info/docs/developer/PdFileFormat), but it is
-1 52 not really meant for humans.
-1 53 - **Variables**: In its text representation, PureData references nodes by
-1 54 index. I want to use human-readable names instead.
-1 55 - **Includes**: In order to structure code, I want to be able to split it into
-1 56 several files.
-1 57 - **Functions**: With PureData it is common to copy large sets of nodes.
-1 58 Instead I want to have functions so that code can be reused in a structured
-1 59 way.
-1 60 - **Inlets are hot by default**: While I understand that cold inlets are a
-1 61 powerful tool for control flow, I found it to be very unintuitive.
-1 62 - **Small language, extensive standard library**: The language itself should be
-1 63 simple and stable. Over time, a standard library of functions should emerge
-1 64 that provides useful abstractions.
-1 65 - **Intuitive standard library**: I had a hard time adjusting to the built-in
-1 66 nodes. I still don't really understand some of them, while some features that
-1 67 I would have expected are missing. I hope that a standard library of
-1 68 functions can provide a more intuitive set of primitives by wrapping those
-1 69 builtins.
-1 70 - **No loss of features**: xipd should be able to express everything that
-1 71 PureData can express.
-1 72
-1 73 ## Features
-1 74
-1 75 ### Names
-1 76
-1 77 Names for functions and variables must consist of upper and lower letters,
-1 78 digits, and underscores. The first character must not be a digit.
-1 79
-1 80 ### Expressions
-1 81
-1 82 An expression always represents a node combined with a default inlet/outlet. If
-1 83 no inlet/outlet is provided it always defaults to 0. There are many
-1 84 different types of expressions:
-1 85
-1 86 - **String**: (e.g. `"foo"`)
-1 87 - **Integer**: (e.g. `1`)
-1 88 - **Float**: (e.g. `1.0`)
-1 89 - **Raw**: a raw PureData object node (e.g. `` `osc~ 440` ``)
-1 90 - **Reference**: A variable with an optional explicit inlet/outlet that
-1 91 overwrites the default one (e.g. `foo:1`)
-1 92 - **Function call**: The arguments can be arbitrary expressions (e.g.
-1 93 ``foo(`osc~`, 15)``)
-1 94 - **Operator**: (e.g. `foo:1 * 2 + 15`)
-1 95
-1 96 ### Statements
-1 97
-1 98 Each file is parsed line by line. Empty lines and lines starting with `#` are
-1 99 ignored, as is leading and trailing whitespace. All other lines must match one
-1 100 of the following patterns:
-1 101
-1 102 - **Assignment**: Assign an expression to a name (e.g. `foo = 1`)
-1 103 - **Connection**: Create a connection between two nodes. (e.g. ``foo:1 ->
-1 104 `dac~` ``)
-1 105 - **Include**: Include code from another file (e.g. `include "../foo.xirb"`)
-1 106 - **Start a function**: (e.g. `foo(a, b) {`)
-1 107 - **End a function**: Each function must end with `}`
-1 108 - **Return**: Each function must return an expression. This should be the
-1 109 last statement of the function because no further statements are executed.
-1 110 (e.g. `return foo:1`)
-1 111
-1 112 ## Low-level language
-1 113
-1 114 By not using functions and operators you can have a low-level language that is
-1 115 quite close to the PureData text representation:
-1 116
-1 117 ```
-1 118 X1 = 1
-1 119 X2 = `osc~`
-1 120 X3 = 20
-1 121 X4 = `*~`
-1 122 X5 = 440
-1 123 X6 = `+~`
-1 124 X7 = `osc~`
-1 125 X8 = `dac~`
-1 126 X1:0 -> X2:0
-1 127 X2:0 -> X4:0
-1 128 X3:0 -> X4:1
-1 129 X4:0 -> X6:0
-1 130 X5:0 -> X6:1
-1 131 X6:0 -> X7:0
-1 132 X7:0 -> X8:0
-1 133 ```
-1 134
-1 135 
-1 136