[text] contents are indexed by message, not line, right?
The top-level help for [text] suggests that you can access and manipulate its contents by line, but is that really true? [text] seems to be message oriented and the line structure is just a side-effect of what terminators (comma or semicolon) are bound with each message. One has to add extra plumbing to make [text get] behave as though it were line oriented, e.g. "please return the 2nd message on the 5th line".
Follow up: OK well, as far as I can tell, here's what I have to go through to make [text get] line oriented. I happened to notice that if each line only contains one message and all messages contain the same number of atoms, then the contents start to resemble a 2D table. So I made such a table that contains the message indexes of the irregular table that I'm really interested in, i.e. the former table helps me translate line indexing to the kind of message indexing that [text] prefers. See what I'm sayin'?
text by line.pd

finding a bug in a patch causing PD crash via text edit?
Hi again,
a new problem...
While, after having worked with 2 video monitors, I was trying to correct the windows subpatch positions via text, putting the canvas values to 0 0... I have probably involuntarily messed up something else in my patch. Now the patch doesn't open anymore, and it causes PD to crash! Is there any way to correct the patch via text... to correct the mistake that causes the crash? I don't know how or where to start to debug this. Any help super appreciated, stefano
#N canvas 0 0 1920 976 12;
#X obj 166 93 tgl 60 0 empty empty player_A 12 28 0 8 #00f8fc #000000 #000000 0 1;
#X msg 72 198 1;
#X obj 72 222 +, f 8;
#X obj 72 173 gate;
#X obj 637 90 tgl 60 0 empty empty player_B 12 28 0 8 #fc8000 #000000 #000000 0 1;
#X msg 772 180 1;
#X obj 772 204 +, f 8;
#X obj 772 153 gate;
#X obj 71 150 r score;
#X obj 419 2 r ch-pl;
#X obj 419 26 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 317 221 nbx 2 50 -1e+37 1e+37 0 0 score-updA reset empty 0 -8 0 30 #00f8fc #000000 #000000 0 256;
#X obj 468 221 nbx 2 50 -1e+37 1e+37 0 0 score-updB reset empty 0 -8 0 30 #fc8000 #000000 #000000 0 256;
#X msg 104 271 0;
#X msg 828 285 0;
#X obj 773 129 r score;
#X obj 230 155 s gA;
#X obj 606 156 s gB;
#X obj 269 405 r move-nrA;
#X obj 507 392 r move-nrB;
#X obj 109 197 r score-updA;
#X obj 825 179 r score-updB;
#X obj 103 247 sel 1;
#X obj 730 232 sel 1;
#X symbolatom 540 186 3 0 0 2 scelta\ n° - - 0;
#X symbolatom 388 187 3 0 0 2 scelta\ n° - - 0;
#X obj 103 295 s plB-st;
#X obj 758 54 r plB-st;
#X obj 828 309 s plA-st;
#X obj 74 56 r plA-st;
#X obj 417 75 r pl-reset;
#X obj 419 46 t b b;
#X obj 730 256 del 1;
#X obj 107 347 s gAs;
#X obj 190 265 sel 1;
#X msg 191 289 1;
#X obj 643 269 sel 1;
#X msg 643 293 1;
#X obj 654 340 s gBs;
#X obj 237 281 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 152 346 s butt-gate;
#X obj 696 338 s butt-gate;
#X text 150 365 ai pulsanti;
#X text 820 332 ai pulsanti;
#X text 83 365 al player;
#X text 614 364 al player;
#X obj 317 139 bng 65 250 50 0 empty A-bc A 29 32 0 10 #ffffef #000000 #000000;
#N canvas 0 0 1920 976 set-player-warning 1;
#X obj 529 511 outlet;
#X obj 1644 400 r player-choosen;
#X obj 1766 400 r set-player-warn;
#X text 648 115 riceve la scelta dal decide contenuto in [init&reset];
#X obj 162 301 r moves;
#X obj 460 320 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 348 316 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X msg 400 315 stop;
#X obj 348 356 del 400;
#X obj 461 372 del 400;
#X msg 331 390 set ...;
#X msg 661 384 set ...;
#X obj 770 306 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 689 306 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X msg 725 312 stop;
#X obj 689 346 del 400;
#X obj 770 346 del 400;
#X msg 1060 530 set ...;
#X obj 1144 449 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 1063 449 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X msg 1099 455 stop;
#X obj 1063 489 del 600;
#X obj 1145 489 del 600;
#X msg 1154 530 set GAME_OVER!;
#X obj 1303 599 r instructions;
#X msg 403 425 set A:_IT'S_YOUR_TURN!;
#X msg 743 420 set B:_IT'S_YOUR_TURN!;
#X obj 460 197 r A-turn;
#X obj 772 186 r B-turn;
#X obj 8 51 inlet;
#X obj 218 50 inlet;
#X obj 524 48 inlet;
#X obj 823 47 inlet;
#X obj 294 676 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 84 602 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X msg 302 628 stop;
#X text 147 706 rosso;
#X text 405 711 bianco;
#X msg 80 727 \; A-bc color -1.67117e+07 -1 -1;
#X msg 341 729 \; A-bc color -1.67772e+07 -1 -1;
#X obj 834 676 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 618 612 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X msg 923 644 stop;
#X text 683 703 rosso;
#X text 941 708 bianco;
#X msg 616 724 \; B-bc color -1.67117e+07 -1 -1;
#X msg 877 726 \; B-bc color -1.67772e+07 -1 -1;
#X obj 305 599 t b b;
#X obj 898 608 t b b;
#X obj 208 662 del 400;
#X obj 744 659 del 400;
#X obj 232 701 del 400;
#X obj 768 698 del 400;
#X obj 874 512 r stop-player-flashing;
#X obj 79 773 cnv 19 470 30 empty empty empty 20 12 0 12 #feffc6 #404040 0;
#X obj 614 769 cnv 19 470 30 empty empty empty 20 12 0 12 #feffc6 #404040 0;
#X text 87 777 stato flashing A: sta giocando A;
#X text 619 776 stato flashing B: sta giocando B;
#X obj 8 155 s open-gateA;
#X text 76 867 serve a fare in modo che soltanto A possa fare l'assessment;
#X text 598 868 serve a fare in modo che soltanto B possa fare l'assessment;
#X obj 524 151 s open-gateB;
#X text 51 50 A rosso flashing;
#X text 261 51 A bianco + stop;
#X text 577 48 B rosso flashing;
#X text 867 48 B bianco + stop;
#X obj 460 221 sel 1;
#X obj 770 222 sel 1;
#X obj 379 259 bng 19 250 50 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000;
#X connect 5 0 9 0;
#X connect 5 0 25 0;
#X connect 6 0 8 0;
#X connect 6 0 10 0;
#X connect 7 0 8 0;
#X connect 7 0 9 0;
#X connect 8 0 5 0;
#X connect 9 0 6 0;
#X connect 10 0 0 0;
#X connect 11 0 0 0;
#X connect 12 0 16 0;
#X connect 12 0 26 0;
#X connect 13 0 15 0;
#X connect 13 0 11 0;
#X connect 14 0 15 0;
#X connect 14 0 16 0;
#X connect 15 0 12 0;
#X connect 16 0 13 0;
#X connect 18 0 22 0;
#X connect 19 0 21 0;
#X connect 20 0 21 0;
#X connect 20 0 22 0;
#X connect 21 0 18 0;
#X connect 21 0 17 0;
#X connect 22 0 19 0;
#X connect 22 0 23 0;
#X connect 25 0 0 0;
#X connect 26 0 0 0;
#X connect 27 0 66 0;
#X connect 27 0 68 0;
#X connect 28 0 67 0;
#X connect 29 0 58 0;
#X connect 31 0 61 0;
#X connect 33 0 39 0;
#X connect 33 0 51 0;
#X connect 34 0 38 0;
#X connect 34 0 49 0;
#X connect 35 0 49 0;
#X connect 35 0 51 0;
#X connect 40 0 46 0;
#X connect 40 0 52 0;
#X connect 41 0 45 0;
#X connect 41 0 50 0;
#X connect 42 0 50 0;
#X connect 42 0 52 0;
#X connect 47 0 39 0;
#X connect 47 1 35 0;
#X connect 48 0 46 0;
#X connect 48 1 42 0;
#X connect 49 0 33 0;
#X connect 50 0 40 0;
#X connect 51 0 34 0;
#X connect 52 0 41 0;
#X connect 53 0 48 0;
#X connect 53 0 47 0;
#X connect 66 0 5 0;
#X connect 66 0 14 0;
#X connect 66 0 34 0;
#X connect 66 0 48 0;
#X connect 67 0 12 0;
#X connect 67 0 7 0;
#X connect 67 0 47 0;
#X connect 67 0 41 0;
#X restore 362 492 pd set-player-warning;
#X symbolatom 358 275 18 0 0 0 - - - 16;
#X obj 579 403 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#N canvas 64 64 1920 976 who_wins? 0;
#X obj 273 124 +, f 5;
#X obj 273 83 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 273 60 t b f;
#X floatatom 272 148 5 0 0 0 - - - 0;
#X obj 28 211 >;
#X obj 22 182 int;
#X obj 53 182 int;
#X obj 272 193 tgl 15 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000 0 1;
#X obj 272 213 sel 1;
#X obj 272 235 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 119 116 t b b;
#X obj 460 205 >;
#X obj 456 169 int;
#X obj 490 167 int;
#X obj 421 118 t b b;
#X obj 459 229 sel 1;
#X obj 459 254 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 28 233 sel 1;
#X obj 28 264 bng 15 250 50 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000;
#X obj 451 31 t f f f;
#X obj 20 28 t f f f;
#X obj 20 1 inlet A;
#X obj 451 3 inlet B;
#X obj 156 334 outlet;
#X msg 459 281 set ..and the winner is B!;
#X msg 28 285 set ..and the winner is A!;
#X obj 272 171 == 4;
#X connect 0 0 3 0;
#X connect 1 0 0 0;
#X connect 2 0 1 0;
#X connect 2 1 0 1;
#X connect 3 0 26 0;
#X connect 4 0 17 0;
#X connect 5 0 4 0;
#X connect 6 0 4 1;
#X connect 7 0 8 0;
#X connect 8 0 9 0;
#X connect 9 0 10 0;
#X connect 9 0 14 0;
#X connect 10 0 5 0;
#X connect 10 1 6 0;
#X connect 11 0 15 0;
#X connect 12 0 11 0;
#X connect 13 0 11 1;
#X connect 14 0 12 0;
#X connect 14 1 13 0;
#X connect 15 0 16 0;
#X connect 16 0 24 0;
#X connect 17 0 18 0;
#X connect 18 0 25 0;
#X connect 19 0 2 0;
#X connect 19 1 12 1;
#X connect 19 2 6 1;
#X connect 20 0 0 0;
#X connect 20 1 5 1;
#X connect 20 2 13 1;
#X connect 21 0 20 0;
#X connect 22 0 19 0;
#X connect 24 0 23 0;
#X connect 25 0 23 0;
#X connect 26 0 7 0;
#X restore 386 407 pd who_wins?;
#X obj 468 138 bng 65 250 50 0 empty B-bc B 29 32 0 10 #ffffef #000000 #000000;
#X text 27 32 DECISO DAL DECIDE IN INIT;
#X text 730 35 DECISO DAL DECIDE IN INIT;
#X obj 374 918 s player-turn;
#X msg 704 727 0;
#X msg 129 709 1;
#X obj 314 435 r A-turn;
#X obj 462 436 r B-turn;
#X obj 221 200 r A-score;
#X obj 590 200 r B-score;
#X obj 296 515 cnv 19 300 400 empty empty empty 20 12 0 12 #faff00 #404040 0;
#X obj 156 53 r A-turn;
#X obj 833 56 r B-turn;
#X msg 341 804 \; \$1-overctrl-gate 0;
#X obj 363 663 sel 1;
#X obj 407 669 r played-button;
#X floatatom 407 693 5 0 0 0 - - - 0;
#X obj 407 721 vs.group 2;
#X obj 477 762 vs.prepend set;
#X msg 477 786 5 8;
#X obj 385 750 unpack 0 0;
#X obj 341 842 print;
#X obj 429 778 int;
#X obj 341 775 int;
#X obj 336 748 t b b;
#X obj 478 581 >;
#X obj 478 605 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 361 587 >;
#X obj 361 611 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1;
#X obj 409 573 loadbang;
#X msg 409 599 0;
#X obj 512 552 int;
#X obj 454 541 t b f;
#X obj 376 548 int;
#X obj 318 537 t b f;
#X text 541 657 questa parte serve a mandare il segnale del fatto che l'ultimo giocatore è salito di un punto quindi l'ultima coppia era corretta quindi deve essere disabilitata (vedi patch button \, colore nero);
#X text 700 363 ai pulsanti;
#X connect 0 0 3 1;
#X connect 0 0 22 0;
#X connect 0 0 34 0;
#X connect 0 0 16 0;
#X connect 1 0 2 0;
#X connect 3 0 1 0;
#X connect 4 0 7 1;
#X connect 4 0 17 0;
#X connect 4 0 23 0;
#X connect 4 0 36 0;
#X connect 5 0 6 0;
#X connect 7 0 5 0;
#X connect 8 0 3 0;
#X connect 9 0 10 0;
#X connect 10 0 31 0;
#X connect 11 0 50 0;
#X connect 11 0 84 1;
#X connect 11 0 85 0;
#X connect 12 0 50 1;
#X connect 12 0 82 1;
#X connect 12 0 83 0;
#X connect 13 0 26 0;
#X connect 14 0 28 0;
#X connect 15 0 7 0;
#X connect 18 0 25 0;
#X connect 19 0 24 0;
#X connect 20 0 2 1;
#X connect 21 0 6 1;
#X connect 22 0 13 0;
#X connect 23 0 32 0;
#X connect 27 0 4 0;
#X connect 29 0 0 0;
#X connect 30 0 0 0;
#X connect 30 0 4 0;
#X connect 31 0 0 0;
#X connect 31 1 4 0;
#X connect 32 0 14 0;
#X connect 34 0 35 0;
#X connect 34 0 39 0;
#X connect 35 0 33 0;
#X connect 35 0 40 0;
#X connect 36 0 37 0;
#X connect 36 0 49 0;
#X connect 37 0 38 0;
#X connect 37 0 41 0;
#X connect 46 0 56 0;
#X connect 46 0 47 0;
#X connect 46 0 47 3;
#X connect 47 0 48 0;
#X connect 50 0 48 0;
#X connect 51 0 55 0;
#X connect 51 0 47 1;
#X connect 51 0 47 2;
#X connect 55 0 54 0;
#X connect 56 0 54 0;
#X connect 57 0 47 0;
#X connect 57 0 47 3;
#X connect 58 0 47 1;
#X connect 58 0 47 2;
#X connect 59 0 11 0;
#X connect 60 0 12 0;
#X connect 62 0 0 0;
#X connect 63 0 4 0;
#X connect 64 0 72 0;
#X connect 65 0 75 0;
#X connect 66 0 67 0;
#X connect 67 0 68 0;
#X connect 68 0 69 0;
#X connect 68 0 71 0;
#X connect 69 0 70 0;
#X connect 71 0 74 1;
#X connect 71 1 73 1;
#X connect 73 0 64 0;
#X connect 74 0 64 0;
#X connect 75 0 74 0;
#X connect 75 1 73 0;
#X connect 76 0 77 0;
#X connect 77 0 65 0;
#X connect 78 0 79 0;
#X connect 79 0 65 0;
#X connect 80 0 81 0;
#X connect 81 0 84 1;
#X connect 81 0 82 1;
#X connect 82 0 76 1;
#X connect 83 0 82 0;
#X connect 83 1 76 0;
#X connect 84 0 78 1;
#X connect 85 0 84 0;
#X connect 85 1 78 0;
#X coords 0 -1 1 1 300 240 2 300 130;
Tracker style "FX" list
@cfry said:
The problem that arise is that when I start to improvise I kind of "break the (your) concept". And I would like to avoid ending up in another patch that is so messy that I can not use it if I bring it up after a half a year or so. Lets continue working on it!
You are definitely getting parts of it and seeing how to develop it but there are parts you don't quite have yet and I can't quite identify what those are so I can explain things. I made a sizable patch that adds a lot of commands but last night I realized I went to far and it would probably confuse things for you, so I will reduce it down to just the things you mentioned, I will follow your lead.
Passing the text name as an argument is just a matter of using your dollar arguments, [text get $1], but you will want to tweak your input for text symbols some.

So our right inlet for text symbols goes to a send now so we can easily access that text anywhere in the patch, like in our commands, and we also reset the counter which uses a value for its float for the same reason, we will want to be able to access and change its value from commands. "pc" is short for program counter and it is important that we increment its value before sending a float to the text get otherwise if we change its value in some command it will get overwritten, so having a [t f f] here is almost a must. This also means that [v $0pc] points to the next line to be run and not the one that is currently being run, this is important, fairly useful, and occasionally irksome.
The left inlet has change some as well, we have a [route bang float], bangs and floats go to the counter so we can increment the program or set the next line to be run, the right outlet sends to our [list-drip] which enables us to run commands from the parent patch so when things don't work you can run that print command to print the stack and get some insight or just run commands from a listbox to test things out or whatnot. We also have [r $0bang] on the counter, this lets us increment the counter immediately from a command and start the next line. And finally we have a new outlet that bangs when we reach the end of the text file so we can turn off the metro in the parent patch which is doing the banging, reset the counter to zero, load a new program, or what ever you want to do when the program completes. Middle outlet I did away with, globals can be done as a command, as can most everything.
Variables we can implement with some dynamic patching and a simple abstraction to create the commands for setting and getting the value of any variable.

This looks more complicated than it is. If we have the line var val1 10 in our program it runs the var command which bangs [v $0pc] and subtracts 1 from it to get the current line from the text holding our program and then appends our $0 to it giving us the list var val1 10 $0. The first message it goes to creates an instance of the var.pd abstraction in [pd $0var] with the second and fourth elements of the list as arguments, val1 and $0. Second message sends $3 to $4->$2, 10 to $0->val1. To finish off we use that new $0bang receive to bang [v $0pc] so we don't execute the rest of the line which would run val1 pushing 10 to the stack and then push another 10 to the stack. Variable name with a > prepended to it is the command for setting the value of a variable, 22 >val1 in your program would set the value of val1 to 22, val1 would push 22 to the stack. If we could see how pd expands all those dollar arguments in the abstraction it would look like this:

Now you can create as many variables as you would like in your programs and a couple tweaks you can have the abstraction global.pd and subpatch [pd $0globals] so you can have the line global val2 0 and get a global variable that all instances of tracky can read and write from. There are a couple catches, each variable definition must appear on its own line with nothing else after it and with our simple parsing there is nothing to stop you from creating multiple instances of the same variable, if you run the line var val1 10 a second time it will create a second abstraction so when you run val1 it will bang both and each will push 10 to the stack giving you an extra 10 and screw up your program. We can fix this with adding a registry to the var command which searches a [text] to see if it has been created already, something like this after the [list $0] should do it:

And you will want to create a command to clear all variables (and the text if you use it) by sending [clear( to [pd-$0var], or get fancy and add another command in var.pd which bangs [iemguts/canvasdelete] so you can delete individual variables. Using [canvasdelete] has the advantage of not needing a registry for variables, you can just always run ```delete-<variable name>, or what ever you name your delete command, before creating a new variable. Each method has advantages.
Your loop does not work because the unpack needs to go into the left inlet of the float, that triggers the first loop and causes it to go back, each time the program gets back up to the loop command it increments [v $0loopi] until the select hits the target number of loops which sets $0loopi to -1 which ends the looping.
Not sure what you mean by groups/exclusive groups, can you elaborate or show it with a patch?
None of the above has been tested, but I did think them through better than I did the loop, fairly certain all is well but there might be a bug or two for you to find. Letting you patch them since we think about how things work more when we patch than when we use a patch. Try and sort out and how they work from the pictures and then patch them together without the pictures, following your understanding of them instead of your memory of how I did it. And change them as needed to suit your needs.
Tracker style "FX" list
@cfry Don't think you will find an external or abstraction which will be easier/better for this than [text] unless someone made exactly what you were looking for and even then it will only be easier until you decide to change things and start banging your head against the limitations of the external or abstraction. This is a pretty simple thing to throw together using [text] and [text get] or [text sequence] depending on your needs, a simple looping [text get] sequencer is not complex and easy to expand to a full tracker like interface even.

[text sequence] is even simpler but has some limitations, it is great when your needs align with it but almost everytime I use it my needs grow beyond its limitations and I switch to [text get]. [text get] also tends to result in neater, easier to read patches since you don't have all those messages going to one inlet.
Edit: Must not have been quite awake when I patched that moses in, bet I thought I was being clever.
ELSE 1.0-0 RC13 with Live Electronics Tutorial Released
Ok, the cat is out of the bag --> https://github.com/porres/pd-else/releases/tag/1.0-rc13 I'm officialy announcing the update and uploaded binaries to deken for mac (intel/arm), Win and Linux. It all looks ok but tell me if you see something funny please. There's also a raspberry pi binary but not working 100%yet and we'll still look into that. Hopefully someone could help me/us with it. I might make another upload just for the pi later on if/when we figure it out. Find release notes and changelog below.
RELEASE NOTES:
Please support me on Patreon https://www.patreon.com/porres I'll now try to add special content for subscribers. You can follow me on instagram as well if you like... I'm always posting Pd development stuff over there https://www.instagram.com/alexandre.torres.porres/
It's been a little bit over 7 months since the last update and I almost broke the record for taking too long to release an update (which had happened in my previous update). So yeah, there's just too much to talk about! I guess the delays in releasing updates is because it's been a little tricky and hard to sync the release cycles of ELSE with PlugData, which includes ELSE in its download.
Plugdata 0.9.2 should come out soon with ELSE RC13 and it's supposedly the last update before 1.0.0, so I've heard. And the plans was to get to that still in 2025! This means ELSE could be at its last "Release Candidate" phase as I'm aiming to sync the final release with PlugData. Until then, I'll still make breaking changes and I can't wait until I can't do that anymore as I really feel bad. On the other hand, it's kind of inevitable when I'm always adding new stuff and redesigning and reconfiguring objects to include more functionalities. And I always got a lot of new stuff! So I'm thinking that I will eventually try some mechanism like Pd's compatibility flag or something. I'll try to come up with something like that in the next update.
This update has 22 new objects for a total of 573 and 26 new examples in my tutorial for a total of 554 examples. Let's dive into the highlights (see full changelog below after the release notes).
-
Multichannel Support: Last release had 92 MC aware objects, now it's 139! Over a 50% increase that include old and new objects (all the new ones have been coming with MC support). Virtually all oscillators and envelope generators now have MC support, plus some other random ones. Let me highlight the new [lace~]/[delace~] objects that are 'MC' tools that perform interleave/deinterleave in Multichannel connections. My bare minimum number of objects "to start with" would be at least a bit over half the number of signal objects. That was my target for 1.0! ELSE right now has 319 signal objects, so that'd be at least 160. I will definitely pass this milestone in the next update. I guess a good number of MC objects would be around 75% of the signal objects. I will aim for that as soon as I can. Some objects simply can't be MC at all, so 100% will never be the case, but maybe an ideal 90% eventually? We'll see... I am just proud and happy that ELSE is taking such a big jump on MC awareness in less than a couple years.
-
Envelope generators ([adsr~]/[asr~]/[envgen~]/[function~]) now have more curve options. For [adsr~]/[asr~] the default is now a new log curve that you can set the curve parameter (and was 'stolen' from SuperCollider). A new [smooth~] family of objects perform the same kind of curved smoothening for alternating inputs - [envgen~] and [function~] also have that but also '1-pole' filtering, 'sine' and 'hann' curves. You can now trigger [adsr~] and [asr~] with impulses.
-
The [play.file~] object now supports even more file formats besides MP3 and stuff. Hey, you can even stream the supported formats from weblinks! The [sfload] object (which loads files into arrays) also gained support for more formats and can download from weblinks as well! It also has a new threaded mode, so loading big files won't choke Pd. It now also outputs the file information, which is a way to tell you when loading finished in threaded mode. The [sample~], [player~], [gran.player~] and [pvoc.player~] objects are now also based on [sfload], so they support all these file formats!!! Now [sample~] and [tabplayer~] are integrated in a way that [tabplayer~] is always aware of the sample rate of the file loaded in [sample~] (so it reads in the "correct speed"). A new [sfinfo] object is able to extract looping regions and instrument metadata information from AIFF files (which is something I wanted for ages) - it should do more stuff in the future.
-
[knob] has become the ultimate featured bloated creep GUI I always feared and avoided. MAX is envy! but I'm happy with this structure and I want to replicate in other GUIs in the future (yeah, I got plans to offer alternatives to all iemguis). I wanna highlight a new 'param' symbol I added that allows you to remotely set a particular method in an object, so you don't to connect to a "method $1" message and you can even do this wirelessly with a send symbol. [knob] now also acts like a number box, where you can type in the value, which may also be displayed in different ways or the value can be sent elsewhere via another send symbol so you can temper with it using [makefilename] or [else/format]. I've been using this for the MERDA modules and it's really cool.
-
We finally have a [popmenu] GUI object! This was in my to do list forever and was crucial to improve the MERDA modules to set waveforms, instruments and whatnot.
-
Let's about MERDA, the "Modular Euroracks Dancing Along" subset of abstractions in ELSE. It was first released in the last update and it's been driving lots of the development in ELSE as you can see. I now added a MIDI Learn feature for all knobs that feels great and quite handy! There are many fixes and improvements in general and some new modules. I wanna highlight the new [sfont.m~] module, which loads "sound font" banks and you can just click on a [popmenu] to choose the instrument you want. The default bank has numerous (hundreds) options and also comes with PlugData. The sequencer module [seq8.m~] was rather worthless but it's now a whole new cool thingie. It allows you to set pitches with symbols and even has quarter tone resolution. I added a right outlet to send impulses to trigger envelopes and stuff (there's still more stuff of course, see full changelog below).
-
There are newly designed/renamed/recreated [resonbank~]/[resonbank2~] objects that are well suited for Modal Synthesis.
-
What actually drives my development is my Live Electronics tutorial, which got a fair upgrade with a new chapter on Modal Synthesis amongst other things, such as new subtractive synthesis examples and a revision of envelope generators with examples on AHDSR and DAHDSR - by the way, there are new gaterelease~/gatedelay~ objects for handling envelopes (and other processes).
-
I have to thank some people. Tim added 'zoom' to the [pic] object, as well as an image offset. Tim also implemented a new and better technique for bandlimited oscillators. Ben Wesh gave me a new [scope3d~] GUI object, pretty cool, that plots an oscilloscope in 3 dimensions, which is coded in LUA - and ELSE has been carrying a modified version of [pdlua] because it now depends on it for a couple of GUIs. Tim and Ben made many improvements to [pdlua] (as well as Albert Graef, of course).
-
For more new objects, let me also tell you about the simple and cool [float2imp~], that is based on [vline~] and can convert floats to impulses with sample accuracy (don't know why I didn't think of that earlier). A new [tanh~] object has Multichannel support. A bit earlier I made an update to Cyclone that actually "borrows" and includes this one from ELSE instead of its original one (which does not have Multichannel support). PlugData users will load the one from ELSE. This is another tiny step that sort of integrates ELSE and Cyclone, specially for PlugData users.
happy patching.
CHANGELOG:
LIBRARY:
Breaking changes:
- [adsr~]/[asr~]: now a gate off before reaching the sustain point does not start the release right away (this allows you to trigger it with impulses). There's a new mode just for immediate release. There's a new exponential setting for curve factors, the old 'log' mode is renamed to 'lag' as it's the same as used in the [lag~] object. For [adsr~], a bang now is not "retrigger", but an impulse at control rate, there's a new 'retrigger' message for control rate retriggering (and now it only retriggers if the gate is on). For [asr~] a bang now also works like an impulse.
- [sample~]: no more 'load' message, args to 'open' message changed, size is now only in 'ms'.
- [format]: outputs are now always symbols, before you could get float outputs. Also, we just have a simplified symbol output, no more lists or anythings. Hopefully I'll be able to get the 'list' output back, but it involved some bugs that I couldn't fix so I just removed it. You cannot use bangs and lists in secondary inlets no more (this is cylone/max crappy paradigm we don't want here). Bang method was actually removed as well.
- [pack2]: no more support for anythings, also no more support for lists in secondary inlets and output has a list selector (I wanna make this more Pd like and not a silly clone from MAX's [pak], cause fuck MAX).
- [merge]/[unmerge]/[group]: no more '-trim' flag (again, respecting pd's usual list paradigm), in [merge] now there's no more 'hot' argument and a bang now represents an empty list and inlets initialized with empty lists
- [mono]: 1st argument is now 'glide' in ms.
- [sfont~] now uses 'mma' for bank selection (this alters how CC messages set the bank number).
- [player~]/[play.file~]: 'open' message does not play files right away anymore.
- [tabplayer~]/[player~]: play message without args now play at the default settings (whole file at regular speed).
- [envgen~]: removed the 'maxsustain' parameter, use the new [gaterelease~] or [gaterelease] objects instead. Removed the rightmost inlet just to set envelopes, now a list input only sets the envelope and doesn't trigger it. The 'set' message is then removed.
- [envgen~]/[function~]: simplified and got rid of '-exp' flag and message, also deleted 'expl' and 'expi' messages. A new 'curve' and cimpler message sets exponential factors for all or individual segments, and includes more curve formats.
- [knob]: 'esc' key now deactivates the object. The 'ticks' message is renamed to 'steps' and there is a new 'ticks' message that toggles showing ticks on and off. The 'start' message has been renamed to 'arcstart'. The 'outline' message has been renamed to 'square' for better clarity. Design changed a bit to make it like it is in PlugData (they won), so we now fill the whole background color when in 'square mode' and the knob circle has an 85% proportion in this case inside the full 100% square size (so it grows bigger when not in 'square' mode). Now, by default, the GUI is in a new 'loadbang' mode (I don't think this will influence old patches). I'm afraid some old patches might behave really weird since I added a lot of new stuff. I changed the 'load' message behaviour to not update the object (this can arguably be considered a bug fix).
- [wavetable~], [bl.wavetable~] and [wt2d~]: 'set' message now sets frequencies because of the MC support in [wt~] and [wt2d~], while there's a new 'table' method to set the table name.
- [gbman~]/[cusp~] list method is now for MC, old list method is now renamed back to an old 'coeffs' method.
- [f2s~]/[float2sig~] default value is now 10 ms.
- [op] now behaves like [*~] where the smaller list wraps til reaching the size of the longer one.
- [list.seq] does not loop anymore by default.
- [impseq~] list input removed, use the new [float2imp~] object to convert floats to impulses.
- [resonant~] now has 'q' as the default.
- [resonant2~] has been removed.
- [decay2~] has also been removed ([asr~] much better).
- [vcf2~] has been renamed to [resonator2~].
- [resonbank~]/[resonbank2~] have basically been deleted and replaced by new objects with the same name... [resonator~] is based on a new [resonator~] object which is similar to [resonant~] and [resonbank2~] is now based on [resonator2~] (old [vcf2~] instead of [resonant2~] that got deleted). These are well suited objects for Modal Synthesis.
- [oscbank~] now uses a 'partial' list and not a frequency list. The freq input now defaults to '1' and this makes [oscbank2~] completely obsolete.
- [oscbank2~] has been deleted since it became completely obsolete.
- [sfload] load message changed the behaviour a bit.
Enhancements/fixes/other changes:
- [adsr~]: We have now a new mode for immediate release (see breaking changes above, I'm not repeating it). Fixed ADSR signal inputs (it was simply not really working, specially for linear). Fixed status output for MC signals. There's a new curve parameter that allows you to set the curvature.
- [asr~] I actually just made the new [adsr~] code into a new [asr~] code as a simplified version (as it was before)... so it's got the same impromevents/fixes.
- [play.file~]: added support for more file formats and even weblinks for online streaming!
- [sfload]: added an outlet to output information, added threaded mode, added support for more file formats and even weblinks for downloading.
- [sample~], [player~], [gran.player~] and [pvoc.player~] are now also based on [sfload], so they support more file formats!
- [sample~]: improved extension management with [file splitext].
- [sample~] and [tabplayer~] now are automatically integrated in a way that [tabplayer~] is always aware of the sample rate of the file loaded in [sample~], so it automatically adjusts the reading speed if it is different than the one Pd is running with.
- [numbox~]'s number display is not preceded by "~" anymore (that was just kinda stupid to have).
- [format]: fixed issues where empty symbols and symbols with escaped spaces didn't work. Added support '%a' and '%A' type. Added support for an escaped 'space' flag. Improved and added support for length modifiers. Improved syntax check which prevents a crash. Improved documentation.
- [knob]: added new 'param', 'var', 'savestate', 'read only', 'loadbang', "active", "reset" and 'ticks' methods. Added the possibility to type in number values and also modes on how to display these number values, plus new send symbols for 'activity', 'typing', 'tab' and 'enter'. New design more like plugdata. Changed some shortcuts to make it simpler. If you have the yet unreleased Pd 0.56-0 you can also use 'double clicking' in the same way that works in PlugData. Properties were also significantly improved (I'm finally starting to learn how to deal with this tcl/tk thingie). Yup, a lot of shit here...
- [autofade2~]/[autofade2.mc~]: fixed immediate jump up for 0 ramp up.
- [synth~]: fixed polyphony bug.
- [metronome~]: fixed bug with 'set' message.
- [midi2note]: fixed range (octaves 0-8).
- [pulsecount~]: fixed reset count to not output immediately, added bang to reset counter at control rate
- [click]: fixed regression bug where it stopped working.
- [else]: new 'dir' method to output ELSE's binary directory in a new rightmost outlet. The print information also includes the directory.
- [pic]: added zoom capability finally (thanks to tim schoen) and added offset message (also thanks to tim).
- [store]: added 'sort' functionality.
- [scales]: fixed octave number argument. Added functionality to allow octave number as part of the note symbol.
- [mono]: added 'glide' parameter, as in [mono~].
- [pluck~]: fixed list input.
- [rescale]/[rescale~]: added a "reverse log" mode.
- [limit]: added a new second ignore mode.
- [graph~]: added an external source input for plotting the graph and a 'clear' message.
- [canvas.setname]: added a new argument for "abstraction mode" and methods to set name, depth (and mode).
- [midi.learn]: added a new argument for "abstraction mode", fixed 'dirty' message sent to parent.
- [brickwall~]: fixed initialization.
- [list.seq]: added a loop mode and a 2nd outlet to send a bang when the sequence is done.
- [delete]: fixed index for positive numbers.
- [dust~]: added 'list', 'set' and '-mc' flag for managing the already existing Multichannel capabilities.
- Thanks to Tim we have many fixes and a whole new technique for band limited oscillators. Now [bl.saw~], [bl.saw2~], [bl.vsaw~], [bl.square~], [bl.tri~], [bl.imp~] and [bl.imp2~] have been redesigned to implement elliptic blep, which should provide better anti-aliasing.
- [parabolic~] now uses and internal wavetable for more efficiency.
- [resonant~]: added 'bw' resonance mode.
- [lowpass~]/[highpass~]: added 't60' resonance mode.
- [quantizer~]/[quantizer]: added a new mode, which combines floor (for negative) and ceil (for positive) values.
- [crusher~]: now uses the new [quantizer~] mode from above (arguably a breaking change).
- [envgen~]: fixed a bug (actually a misconception) where ramps started one sample earlier. Fixed 0-length lines. Added a possibility to set time in samples instead of ms. Maximum number of lines is now 1024. Added loop mode. Added many curve options (sin/hann/log curve/lag).
- [function~]: Added many curve options (sin/hann/log curve/lag).
- [The out~] family of abstractions now use [bitnormal~] so you won't blow your speakers beyond repair in edge cases.
- [trig.delay~]/[trig.delay2~]: fixed bug where impulse values different than '1' didn't work.
- Added MC support to: [trig.delay~], [trig.delay2~], [gatehold~], [vca.m~], [gain2~], [decay~], [asr~], [envgen~], [function~], [bl.osc~], [bl.saw~], [bl.saw2~], [bl.vsaw~], [bl.square~], [bl.tri~], [bl.imp~], [bl.imp2~], [imp2~], [tri~], [saw~], [saw2~], [vsaw~], [square~], [pulse~], [parabolic~], [gaussian~], [wavetable~], [wt2d~], [randpulse~], [randpulse2~], [stepnoise~], [rampnoise~] [pink~], [gbamn~], [cusp~], [gray~] and [white~].
- Also added MIDI input and soft sync to [imp2~], [tri~], [saw~], [saw2~], [vsaw~], [square~], [pulse~], [gaussian~] and [parabolic~].
- [wavetable~] and [wt2d~] gained args to set xfading.
- Updated pdlua to 0.12.23.
- M.E.R.D.A: Added MIDI-LEARN for all modules (this is only for the knobs). Replaced some number boxes that were attached to knobs by an internal number display mechanism (new feature from knob). Improved interface of [gendyn.m~]. Preset/symbol name fixes to [flanger.m~]. Now we have automatic MIDI mode detection for [plaits.m~] and [pluck.m~] when no signals are connected (still trying to get plaits right, huh? Yup! And bow MIDI input with monophony and trigger mode has been fixed in [plaits.m~]). Added MC support to [vca.m~]. Increased range of [drive.m~] down to 0.1. Changed some objects to include the new [popmenu] GUI. [vco.m~] now uses the new MC functionalities of oscillators and doesn't need to load abstractions into [clone], I hope it makes this more efficient and clean. The [seq8.m~] module was worthless and got a decent upgrade, it's practically a new module. Added new modules (see below). Note that MERDA is still at alpha development phase, much experimental. Expect changes as it evolves.
- 22 new objects: [float2imp~], [lace], [delace], [lace~], [delace~], [gatehold], [gatedelay],[gatedelay~], [gaterelease~], [gaterelease], [popmenu], [scope3d~], [tanh~], [resonator~], [sfinfo], [smooth], [smooth2], [smooth~], [smooth2~], [dbgain~], [level~] plus [crusher.m~], [sfont.m~] and [level.m~] MERDA Modules.
Objects count: total of 573 (319 signal objects [139 of which are MC aware] and 254 control objects)!
- 323 coded objects (210 signal objects / 113 control objects)
- 227 abstractions objects (87 signal objects / 140 control objects)
- 23 MERDA modular abstractions (22 audio / 1 control)
TUTORIAL:
- New examples and revisions to add the new objects, features and breaking changes in ELSE.
- Added the MERDA modules into the examples for reference.
- Revised section on envelopes.
- New subtractive synthesis examples.
- New chapter on Modal Synthesis.
- Total number of examples is now 554! (26 new ones)
record polyphonic notes into a table
@impression said:
- for what are you using text search parsing->moses->1000 for? I just noticed it turns voice number 1 into a zero, but don`t really get how and why.
[poly] assigns an index to note numbers. You'd think this would be easy to use directly as a row number in the [text], but [text] treats high row indices as "append" rather than "put at this exact row," so you don't have a guarantee that poly index 3 maps onto text row 2 (poly counts from 1, not 0).
So to find the row index to use, there are two cases:
- Search for the poly index and find it -- the [text search] result is >= 0. In that case we just want to pass the row index through -- that's the right branch of moses.
- Or, [text search] didn't find it. Then its result is -1. That's not a valid row index for [text put], so, we have to replace it with a high number, to tell [text put] to append. So moses --> "1000" means simply, replace negative numbers with 1000 but pass 0 or positive numbers through.
- also I don't fully understand "pd notecount", even you explained already what it does, it lets my brain explode
You count up + 1 once a note is pressed and count down -1 once its released. I don`t know what's the idea of "max 0" feeding itself back into + though.
A negative note count is invalid, but could happen if, for instance, you started the patch running while holding keys on the MIDI keyboard. The max 0 just prevents the count from being negative.
It all works as you showed, but when I set list split to 3 it basically freezes PD. Do you know by any chance why?
I would need to split my list into 3 later on.
It's very important, when using [until] for looping, to use either a fixed count of loop iterations or to make sure that the stop "bang" signal goes into the right inlet. If it's freezing, probably that's not happening.
hjh
Audio-rate round-robin impulse generator?
A few years ago I made a convoluted patch (no pun intended) that outputs a single sample 1-valued pulse on each of its [outlet~]s sequentially in round-robin fashion in response to a positive transition on its [input~]. It's pretty gruesome so I don't want to post it here, but for the morbidly curious suffice it to say it's based on cascaded shift registers with the last stage fed back to the first stage and requires [block~ 8 1 1] to work reliably at 2500 Hz. Anyway, it behaves like this:
- positive transition seen on [input~] -> pulse first [outlet~]
- positive transition seen on [input~] -> pulse second [outlet~]
- positive transition seen on [input~] -> pulse third [outlet~]
... - positive transition seen on [input~] -> pulse last [outlet~]
- positive transition seen on [input~] -> pulse first [outlet~]
...
Anytime I look at my code I gag. Does anyone in the esteemed readership of this forum have a suggestion on how to do this in a less offensive way? I don't care about the signal specifics of the inputs and outputs as long as they are at audio-rate and easily detectable within a constant number of samples. I would gladly accept consistent latency in exchange for efficiency and elegance. Extra respect if the number of outputs can be easily changed without dynamic patching.
problem creating objects from external iemlib
hi everyone!
I'm trying to run the patch "Ambisonic_2d_example.pd" from the iem_ambi external. While trying to get it to run, I made some changes to the declare statement. You can find the code below..
I installed the externals needed for this patch through deken and I also set the "-lib iemlib" startup flag in PD.
Unfortunately I get the following errors. As you can see PD fails to create some objects (e.g. fadtodb, rbpq, mull~, dsp). These objects seem to all come from the iemlib which is loaded successfully. I have also checked the /externals/iemlib directory.. the four mentioned object-patches are there.
I am running PD on a VM running Debian 11.7 on a M1 MacBook Pro.
I have been trying to solve this for a couple of hours now.. Does anyone know why it's not working?
iemlib (1.22-1) library loaded! (c) Thomas Musil Jul 7 2023 : 18:09:42
musil@iem.at iem KUG Graz Austria
iem_ambi (1.21.1) library loaded! (c) Thomas Musil Jul 18 2023 : 11:42:00
musil@iem.at iem KUG Graz Austria
iemmatrix 0.3.3
objects for manipulating 2d-matrices
(c) 2001-2015 iem
IOhannes m zmölnig
Thomas Musil
Franz Zotter
compiled Jul 18 2023 : 22:25:45
iemlib (1.22-1) library loaded! (c) Thomas Musil Jul 7 2023 : 18:09:42
musil@iem.at iem KUG Graz Austria
♡♡♡
♡ the zexy external 2.4.2
♡ (c) 1999-2023 IOhannes m zmölnig
♡ forum::für::umläute
♡ iem @ kug
♡ compiled Jul 7 2023
♡ send me a 'help' message
♡♡♡
matchbox: OSC-pattern matching code (c) Matt Wright, CNMAT
iemgui (1.21-1) library loaded! (c) Thomas Musil Sep 13 2022 : 19:34:09
musil@iem.at iem KUG Graz Austria
dsp
... couldn't create
rbpq2~ 1000 2 100
... couldn't create
mull~ 1 100
... couldn't create
fadtodb
... couldn't create
matrix_inverse nonsingular
modified_Ambisonic_2d_example.pd:
#N canvas 1512 175 1512 1715 10;
#X declare -stdlib /home/amir/Documents/Pd/externals/iem_ambi -stdlib
/home/amir/Documents/Pd/externals/iemmatrix -stdlib /home/amir/Documents/Pd/externals/iemlib
-stdlib /home/amir/Documents/Pd/externals/zexy -stdlib /home/amir/Documents/Pd/externals/iemgui
;
#X obj 20 44 dsp;
#X obj 20 24 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0 1
;
#X floatatom 20 83 5 0 0 0 - - -;
#X floatatom 33 65 5 0 0 0 - - -;
#X obj 230 88 ambi_encode 2;
#X obj 469 102 mtx_*~ 5 1 100;
#X obj 509 11 noise~;
#X obj 509 32 rbpq2~ 1000 2 100;
#X obj 225 591 mtx_print;
#X obj 230 140 mtx 5 1;
#X msg 230 51 col 1 \$1;
#X obj 230 109 t b a;
#X obj 699 118 prvu~;
#X obj 700 142 vu 15 120 empty empty -1 -8 0 8 -66577 -1 0 0;
#X obj 719 118 prvu~;
#X obj 720 142 vu 15 120 empty empty -1 -8 0 8 -66577 -1 0 0;
#X obj 739 118 prvu~;
#X obj 740 142 vu 15 120 empty empty -1 -8 0 8 -66577 -1 0 0;
#X obj 759 118 prvu~;
#X obj 760 142 vu 15 120 empty empty -1 -8 0 8 -66577 -1 0 0;
#X obj 779 118 prvu~;
#X obj 780 142 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
#X obj 115 222 loadbang;
#X obj 442 257 mtx_*~ 2 2 100;
#X obj 537 257 mtx_*~ 2 2 100;
#X obj 233 240 ambi_rot 2;
#X obj 699 273 prvu~;
#X obj 700 297 vu 15 120 empty empty -1 -8 0 8 -66577 -1 0 0;
#X obj 719 273 prvu~;
#X obj 720 297 vu 15 120 empty empty -1 -8 0 8 -66577 -1 0 0;
#X obj 739 273 prvu~;
#X obj 740 297 vu 15 120 empty empty -1 -8 0 8 -66577 -1 0 0;
#X obj 759 273 prvu~;
#X obj 760 297 vu 15 120 empty empty -1 -8 0 8 -66577 -1 0 0;
#X obj 779 273 prvu~;
#X obj 780 297 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
#X obj 411 257 *~ 1;
#X obj 131 436 round_zero 1e-06;
#X msg 147 343 real_ls \$1 \$2;
#X msg 131 364 begin_pseudo_inverse;
#X msg 115 385 end_pseudo_inverse;
#X obj 115 245 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 131 414 ambi_decode3 2 2 8 0;
#X msg 147 322 1 0 \, 2 45 \, 3 90 \, 4 135 \, 5 180 \, 6 225 \, 7
270 \, 8 315;
#X obj 425 381 mtx_*~ 8 5 0 ________________;
#X obj 115 264 t b b b b;
#X obj 508 75 mull~ 1 100;
#X obj 678 27 fadtodb;
#X obj 551 55 dbtorms;
#X obj 618 58 - 100;
#X obj 618 82 vsl 15 121 0 120 0 1 empty empty empty 0 -8 0 8 -260818
-1 -1 24000 1;
#X floatatom 637 80 5 0 0 0 - - -;
#N canvas 0 0 462 312 __________________________ 0;
#X obj 25 66 rvu~;
#X obj 25 86 + 100;
#X obj 25 106 dbtorms;
#X obj 25 127 outlet;
#X obj 75 66 rvu~;
#X obj 75 86 + 100;
#X obj 75 106 dbtorms;
#X obj 75 127 outlet;
#X obj 125 66 rvu~;
#X obj 125 86 + 100;
#X obj 125 106 dbtorms;
#X obj 125 127 outlet;
#X obj 175 66 rvu~;
#X obj 175 86 + 100;
#X obj 175 106 dbtorms;
#X obj 175 127 outlet;
#X obj 225 66 rvu~;
#X obj 225 86 + 100;
#X obj 225 106 dbtorms;
#X obj 225 127 outlet;
#X obj 275 66 rvu~;
#X obj 275 86 + 100;
#X obj 275 106 dbtorms;
#X obj 275 127 outlet;
#X obj 325 66 rvu~;
#X obj 325 86 + 100;
#X obj 325 106 dbtorms;
#X obj 325 127 outlet;
#X obj 375 66 rvu~;
#X obj 375 86 + 100;
#X obj 375 106 dbtorms;
#X obj 375 127 outlet;
#X obj 25 45 inlet~;
#X obj 75 45 inlet~;
#X obj 125 45 inlet~;
#X obj 175 45 inlet~;
#X obj 225 45 inlet~;
#X obj 275 45 inlet~;
#X obj 325 45 inlet~;
#X obj 375 46 inlet~;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 2 0 3 0;
#X connect 4 0 5 0;
#X connect 5 0 6 0;
#X connect 6 0 7 0;
#X connect 8 0 9 0;
#X connect 9 0 10 0;
#X connect 10 0 11 0;
#X connect 12 0 13 0;
#X connect 13 0 14 0;
#X connect 14 0 15 0;
#X connect 16 0 17 0;
#X connect 17 0 18 0;
#X connect 18 0 19 0;
#X connect 20 0 21 0;
#X connect 21 0 22 0;
#X connect 22 0 23 0;
#X connect 24 0 25 0;
#X connect 25 0 26 0;
#X connect 26 0 27 0;
#X connect 28 0 29 0;
#X connect 29 0 30 0;
#X connect 30 0 31 0;
#X connect 32 0 0 0;
#X connect 33 0 4 0;
#X connect 34 0 8 0;
#X connect 35 0 12 0;
#X connect 36 0 16 0;
#X connect 37 0 20 0;
#X connect 38 0 24 0;
#X connect 39 0 28 0;
#X restore 425 406 pd __________________________;
#X obj 459 490 vsl 15 51 0 0.2 0 0 empty empty empty 0 -8 0 8 -1 -24198
-1 0 1;
#X obj 486 460 vsl 15 51 0 0.2 0 0 empty empty empty 0 -8 0 8 -1 -24198
-1 0 1;
#X obj 486 528 vsl 15 51 0 0.2 0 0 empty empty empty 0 -8 0 8 -1 -24198
-1 0 1;
#X obj 516 450 vsl 15 51 0 0.2 0 0 empty empty empty 0 -8 0 8 -1 -24198
-1 0 1;
#X obj 516 538 vsl 15 51 0 0.2 0 0 empty empty empty 0 -8 0 8 -1 -24198
-1 0 1;
#X obj 546 460 vsl 15 51 0 0.2 0 0 empty empty empty 0 -8 0 8 -1 -24198
-1 0 1;
#X obj 546 528 vsl 15 51 0 0.2 0 0 empty empty empty 0 -8 0 8 -1 -24198
-1 0 1;
#X obj 573 490 vsl 15 51 0 0.2 0 0 empty empty empty 0 -8 0 8 -1 -24198
-1 0 1;
#X msg 310 58 ambi_weight 1 1 1;
#X msg 164 299 ambi_weight 1 1 0.3904;
#X msg 89 466 ambi_weight 1 1 1;
#X text 388 509 +90 degree;
#X text 601 506 -90 degree;
#X text 486 602 +-180 degree;
#X obj 234 220 cnv 12 30 12 empty empty empty 20 12 0 14 -260818 -66577
0;
#X obj 231 32 cnv 12 30 12 empty empty empty 20 12 0 14 -260818 -66577
0;
#X floatatom 230 31 5 -180 180 0 - - -;
#X text 232 14 phi;
#X floatatom 233 219 5 -180 180 0 - - -;
#X text 231 201 rho_z;
#X obj 264 213 cnv 8 8 8 empty empty empty 20 12 0 14 -262144 -66577
0;
#X obj 260 24 cnv 8 8 8 empty empty empty 20 12 0 14 -262144 -66577
0;
#X text 341 114 ENCODING;
#X text 309 378 DECODING;
#X text 323 257 ROTATING;
#X text 587 90 gain;
#X text 24 119 iemmatrix \, iem_ambi \, iemgui;
#X text 17 108 we need iemlib1 \, iemlib2 \,;
#X text 78 596 IEM KUG;
#X text 62 584 musil;
#X text 92 584 @;
#X text 98 584 iem.at;
#X text 61 606 Graz \, Austria;
#X text 13 573 (c) Thomas Musil 2000 - 2006;
#X obj 182 647 declare -stdlib /home/amir/Documents/Pd/externals/iem_ambi
-stdlib /home/amir/Documents/Pd/externals/iemmatrix -stdlib /home/amir/Documents/Pd/externals/iemlib
-stdlib /home/amir/Documents/Pd/externals/zexy -stdlib /home/amir/Documents/Pd/externals/iemgui
;
#X connect 0 0 2 0;
#X connect 0 1 3 0;
#X connect 1 0 0 0;
#X connect 4 0 11 0;
#X connect 5 0 12 0;
#X connect 5 0 36 0;
#X connect 5 1 14 0;
#X connect 5 1 23 1;
#X connect 5 2 16 0;
#X connect 5 2 23 2;
#X connect 5 3 18 0;
#X connect 5 3 24 1;
#X connect 5 4 20 0;
#X connect 5 4 24 2;
#X connect 6 0 7 0;
#X connect 7 0 46 0;
#X connect 9 0 5 0;
#X connect 10 0 4 0;
#X connect 11 0 9 0;
#X connect 11 1 9 0;
#X connect 12 0 13 0;
#X connect 14 0 15 0;
#X connect 16 0 17 0;
#X connect 18 0 19 0;
#X connect 20 0 21 0;
#X connect 22 0 41 0;
#X connect 23 0 28 0;
#X connect 23 0 44 2;
#X connect 23 1 30 0;
#X connect 23 1 44 3;
#X connect 24 0 32 0;
#X connect 24 0 44 4;
#X connect 24 1 34 0;
#X connect 24 1 44 5;
#X connect 25 0 23 0;
#X connect 25 1 24 0;
#X connect 26 0 27 0;
#X connect 28 0 29 0;
#X connect 30 0 31 0;
#X connect 32 0 33 0;
#X connect 34 0 35 0;
#X connect 36 0 26 0;
#X connect 36 0 44 1;
#X connect 37 0 44 0;
#X connect 38 0 42 0;
#X connect 39 0 42 0;
#X connect 40 0 42 0;
#X connect 41 0 45 0;
#X connect 42 0 37 0;
#X connect 43 0 38 0;
#X connect 44 0 52 0;
#X connect 44 1 52 1;
#X connect 44 2 52 2;
#X connect 44 3 52 3;
#X connect 44 4 52 4;
#X connect 44 5 52 5;
#X connect 44 6 52 6;
#X connect 44 7 52 7;
#X connect 45 0 40 0;
#X connect 45 1 39 0;
#X connect 45 2 43 0;
#X connect 45 3 62 0;
#X connect 46 0 5 1;
#X connect 47 0 48 0;
#X connect 47 0 49 0;
#X connect 48 0 46 1;
#X connect 49 0 51 0;
#X connect 50 0 47 0;
#X connect 52 0 56 0;
#X connect 52 1 54 0;
#X connect 52 2 53 0;
#X connect 52 3 55 0;
#X connect 52 4 57 0;
#X connect 52 5 59 0;
#X connect 52 6 60 0;
#X connect 52 7 58 0;
#X connect 61 0 4 0;
#X connect 62 0 42 0;
#X connect 63 0 42 0;
#X connect 69 0 10 0;
#X connect 71 0 25 0;
Performance of [text] objects
@zigmhount said:
TL;DR: Is it more efficient to
[text search],[text get]and[text set]91 times in one[text]object, or to[text get]and[text set]1 time in each of 91[text]objects? or in 91[list]objects?
Going back to the original question...
In the source code, the function that locates a line by number is text_nthline(). This implements a linear search from the beginning of the text buffer, counting character by character, until it's crossed n newlines (semicolons or commas).
So performance will depend on how many lines, and how long the lines are.
Accessing lines near the end will be slower than accessing lines near the beginning.
For a linear search, you would predict that the time is proportional to the size. I built a benchmark where the lines are all roughly the same size, comparing 10 lines vs 100, 1000 and 10000, doing a million random accesses for each one.

The smaller buffers are a bit slower than "linear" would predict, but this is probably because of function call overhead and can't be avoided. (x1000 vs x10000 is linear.)
Still, if you're wondering how a single text buffer of ~100 lines would do... 100 ms for 1,000,000 queries is pretty fast. So... don't worry about it...?
Or you could run this yourself on the lower-end laptop that you mentioned. (But... before you do... go into the [pd 1000000_queries] subpatch and change the 1e+06 message box to, say, 10000 or 100000. Otherwise you might be sitting there a while. And be sure to init the buffers first, should be clear where to click.)
I didn't benchmark the performance of accessing multiple separate text objects. Based on the source code, if you access line 0, then text_nthlne() will scan only the one line (to determine the endpoint). I don't know what is the overhead of switching a [text get] between buffers.
Honestly I think the Pd GUI stuff will be a heavier drain on CPU than either [text] approach.
hjh
Performance of [text] objects
Hey all,
I am integrating a Pd patch with an existing sequencer/looper (Seq192) with an OSC interface, where my patch should convert my MIDI controller's button presses to OSC commands and send back MIDI signal out to lighten the controller's LEDs.
I can retrieve periodically the status and details of all clips/sequences and aggregate it into a list of parameters for each sequence. The LED colors and the actions that the next button press will trigger depend on these parameters, so I need to store them for reuse, which I like doing with [text] objects. I am then handling buttons' light status in a [clone 90] (where each instance of the clone handles one button).
This should be running on a fairly low-end laptop, so I'm wondering which of these approaches is the most CPU-efficient - if there is any significant difference at all - and I couldn't come up with a way to properly measure the performance difference:
- one
[text define $1-seq-status]object in each clone, with one single line in each. I compare the new sequence status input with[text get $1-seq-status 0]so that I update only line 0 with[text set $1-seq-status]when I know that the content has changed. - one single
[text define all-seq-status]object with 91 lines. I compare the new sequence status with
[ <button number> (
|
[text search all-seq-status 0]
|
[sel -1]
|
[text get all-seq-status]
and if it has changed, I update a button's line with
[ <new status content> (
|
| [ <line number> (
| |
[text set all-seq-status]
The order in which buttons/sequence statuses are listed in the file might change, so I can't really avoid searching at least once per button to update.
- Should I instead uses simple lists in each clone instance? As far as I could test, getting a value from a list was a bit slower than getting a value from a text, but searching in a text was much slower than both. But I don't know the impact of processing 91 lists or text at the same time...
TL;DR: Is it more efficient to [text search], [text get] and [text set] 91 times in one [text] object, or to [text get] and [text set] 1 time in each of 91 [text] objects? or in 91 [list] objects?
Since you've gone through this long post and I gave a lot of context, I am of course very open to suggestions to do this in a completely different way :D
Thanks!

