Forums > MaxMSP

newbie asks the hive: this works but, is there a better way?

April 18, 2008 | 11:08 pm

hello,

the following patch takes in a midi note (so far only set up for 70 and 70)
and depending on how it is set either lets the note play until a midi off comes, or it forces a set duration for the note.(which needs to be customisable for each different note)

this patch is going to go into a patch that drives a real world mechanical orchestra. some of the instruments like horns, need to sound as long as the note is open, others like xylophones are best played quick.

i’m not a newbie programmer but i’m a noob patcher, so there’s probably lots of really basic stuff i haven’t figured out how to use properly yet, such as encapsulation of patches within patches, so i’ve basically used the first things that got the job done that i found. and it works fine…

but

i can see that by the time i make this patch work for the full range of notes i need its going to be huge and repetitive.

and maybe there’s a much smarter way to get the job done.

anyone got any ideas?

cheers

mathew

max v2;
#N vpatcher 0 44 1280 796;
#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 491 492 52 196617 noteout 1;
#P button 533 438 15 0;
#P newex 491 450 35 196617 zl rev;
#B color 5;
#P newex 458 432 43 196617 route 0;
#P number 533 454 64 9 1 0 1 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 491 470 52 196617 makenote;
#P newex 533 420 62 196617 r power_on;
#P newex 429 473 35 196617 zl rev;
#B color 5;
#P newex 429 493 52 196617 noteout 1;
#P user gswitch2 429 399 39 32 1 0;
#P toggle 429 383 15 0;
#P newex 192 492 52 196617 noteout 1;
#P button 234 438 15 0;
#P newex 192 450 35 196617 zl rev;
#B color 5;
#P newex 159 432 43 196617 route 0;
#P number 234 454 64 9 1 0 1 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 192 470 52 196617 makenote;
#P newex 234 420 62 196617 r power_on;
#P newex 130 472 35 196617 zl rev;
#B color 5;
#P message 431 209 52 196617 $1 $2 $1;
#P newex 130 492 52 196617 noteout 1;
#P message 525 141 31 196617 71 0;
#P message 526 77 37 196617 71 90;
#P message 306 144 31 196617 70 0;
#P message 307 78 37 196617 70 90;
#P newex 431 245 64 196617 route 70 71;
#P message 132 46 14 196617 1;
#P message 58 46 40 196617 store 1;
#N vpreset 1;
#X append 1 2 0 383 130 toggle int 0 ; 1 399 130 GSwitch2 int 0 ; 15 454 234 number int 1000 ; 20 383 429 toggle int 1 ; 21 399 429 GSwitch2 int 1 ; 26 454 533 number int;
#X append 1 2 500 ;;
#P preset 58 113 19 19;
#P user gswitch2 130 399 39 32 0 0;
#P toggle 130 383 15 0;
#P connect 4 0 2 0;
#P connect 3 0 2 0;
#P connect 0 0 1 0;
#P connect 1 0 12 0;
#P connect 12 0 10 0;
#P connect 5 0 1 1;
#P connect 1 1 16 0;
#P connect 16 1 17 0;
#P connect 17 0 14 0;
#P connect 14 0 19 0;
#P connect 14 1 19 1;
#P connect 13 0 18 0;
#P connect 18 0 15 0;
#P connect 15 0 14 2;
#P connect 20 0 21 0;
#P connect 21 0 23 0;
#P connect 23 0 22 0;
#P connect 9 0 11 0;
#P connect 8 0 11 0;
#P connect 6 0 11 0;
#P connect 7 0 11 0;
#P connect 11 0 5 0;
#P connect 5 1 21 1;
#P connect 21 1 27 0;
#P connect 27 1 28 0;
#P connect 28 0 25 0;
#P connect 25 0 30 0;
#P connect 25 1 30 1;
#P connect 24 0 29 0;
#P connect 29 0 26 0;
#P connect 26 0 25 2;
#P pop;


April 19, 2008 | 2:32 am

this demonstrates one simple, but powerful, thing that took me a while
to fully comprehend.

first, save this as "sub_patch":

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 112 143 52 196617 noteout 1;
#P button 154 89 15 0;
#P newex 112 101 35 196617 zl rev;
#B color 5;
#P newex 79 83 43 196617 route 0;
#P number 154 105 64 9 1 0 1 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 112 121 52 196617 makenote;
#P newex 154 71 62 196617 r power_on;
#P newex 50 124 35 196617 zl rev;
#B color 5;
#P newex 50 144 52 196617 noteout 1;
#P user gswitch2 50 50 39 32 1 0;
#P inlet 79 30 15 0;
#P inlet 50 30 15 0;
#P connect 7 0 6 2;
#P connect 10 0 7 0;
#P connect 5 0 10 0;
#P connect 6 1 11 1;
#P connect 6 0 11 0;
#P connect 9 0 6 0;
#P connect 8 1 9 0;
#P connect 2 1 8 0;
#P connect 1 0 2 1;
#P connect 4 0 3 0;
#P connect 2 0 4 0;
#P connect 0 0 2 0;
#P window clipboard copycount 12;

then, in the same directory, save this as "main_patch":

#P toggle 317 443 15 0;
#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 317 459 55 196617 sub_patch;
#P toggle 489 443 15 0;
#P message 491 269 52 196617 $1 $2 $1;
#P message 585 201 31 196617 71 0;
#P message 586 137 37 196617 71 90;
#P message 366 204 31 196617 70 0;
#P message 367 138 37 196617 70 90;
#P newex 491 305 64 196617 route 70 71;
#P message 192 106 14 196617 1;
#P message 118 106 40 196617 store 1;
#N vpreset 1;
#P preset 118 173 19 19;
#P newex 489 459 55 196617 sub_patch;
#P window linecount 5;
#P comment 552 460 100 196617 < -- double-click to see your subpatch. as
you edit that file , it will get updated here as well;
#P connect 5 1 1 1;
#P connect 10 0 5 0;
#P connect 9 0 10 0;
#P connect 8 0 10 0;
#P connect 6 0 10 0;
#P connect 7 0 10 0;
#P connect 11 0 1 0;
#P connect 5 0 12 1;
#P connect 13 0 12 0;
#P connect 4 0 2 0;
#P connect 3 0 2 0;
#P window clipboard copycount 14;

now when you open "main_patch" you will find two instances of your
"sub_patch". obviously you can make hundreds of instances as needed. the
cool part is that if you need to change something in "sub_patch", you
just need to open that file and do it once. every instance will be
updated in "main_patch"

this is just one encapsulation method, but it’s very handy. if you look
at some of the more complex patches in the "examples" folder you will
see this practiced widely.

hth,
david


April 19, 2008 | 3:09 am

Here’s how I would do it. It starts with David’s abstraction approach (make sure you understand that first!) but instead of separate abstractions is uses a single poly~ to handle all 128 MIDI note values without creating a ton of objects.

The pattr system is used to manage all your settings (including saving and loading them to disk – read up on pattstorage for how to do that).

In programming terms, this is how you would make an array of objects in Max.

Try selecting MIDI note number 70 and changing the sustain and and duration settings. If you go to 71 and then come back, it remembers your settings. Pretty cool, right?

Save this as midi-note-output.pat

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 22 89 114 196617 if $i1==0 then 2 else 1;
#P message 22 34 14 196617 1;
#P message 125 129 14 196617 1;
#P newex 125 151 73 196617 pattr duration;
#X prestore 1 0 1;
#P objectname duration;
#N in 1;
#P newobj 50 111 25 196617 in 1;
#P newex 22 67 68 196617 pattr sustain;
#X prestore 1 0 1;
#P objectname sustain;
#P newex 22 133 38 196617 gate 2;
#P newex 83 197 52 196617 noteout 1;
#P newex 50 154 43 196617 route 0;
#P newex 83 175 52 196617 makenote;
#P newex 22 197 52 196617 noteout 1;
#P window linecount 2;
#P comment 39 25 169 196617 set defaults , pattr will remember this value when the patch reopens;
#P connect 10 0 6 0;
#P connect 6 0 11 0;
#P connect 11 0 5 0;
#P connect 5 0 1 0;
#P connect 7 0 5 1;
#P connect 5 1 3 0;
#P connect 3 1 2 0;
#P connect 2 0 4 0;
#P connect 2 1 4 1;
#P connect 9 0 8 0;
#P connect 8 0 2 2;
#P window clipboard copycount 12;

and here’s the main patch (save in same directory and then reopen):

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 333 93 48 196617 loadbang;
#P number 493 246 35 9 1 0 1 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 493 224 73 196617 pattr duration;
#X prestore 1 0 1;
#P objectname duration;
#P toggle 333 245 15 0;
#P newex 493 192 150 196617 sprintf bindto out.%d::duration;
#P newex 333 192 145 196617 sprintf bindto out.%d::sustain;
#P newex 333 147 27 196617 + 1;
#P number 333 124 35 9 0 127 3 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 333 221 68 196617 pattr sustain;
#X prestore 1 0 1;
#P objectname sustain;
#P button 527 56 26 0;
#P newex 115 142 27 196617 + 1;
#P newex 115 119 58 196617 unpack 0 0;
#P message 115 168 53 196617 target $1;
#P newex 98 95 27 196617 t l l;
#P message 192 51 31 196617 71 0;
#P message 154 50 37 196617 71 90;
#P message 78 53 31 196617 70 0;
#P message 36 52 37 196617 70 90;
#P message 527 86 69 196617 clientwindow;
#P newex 527 109 67 196617 pattrstorage;
#X client_rect 40 104 680 344;
#X storage_rect 0 0 640 240;
#P objectname u570000007;
#P newex 98 194 135 196617 poly~ midi-note-output 128;
#P objectname out;
#P window linecount 2;
#P comment 179 139 144 196617 Midi goes from 0-127 but poly~ targets go from 1-128;
#P comment 554 57 72 196617 check state of variables;
#P window linecount 4;
#P comment 374 124 100 196617 Select a MIDI note number and change the settings for that number below;
#P window linecount 2;
#P comment 509 131 173 196617 pattrstorage can save and load presets and save them to an XML file;
#P connect 6 0 5 0;
#P connect 15 0 6 0;
#P connect 22 0 23 0;
#P fasten 23 0 22 0 498 266 488 266 488 217 498 217;
#P connect 20 0 22 0;
#P fasten 18 0 19 0 338 182 338 182;
#P fasten 18 0 20 0 338 183 498 183;
#P connect 16 0 21 0;
#P fasten 21 0 16 0 338 264 326 264 326 215 338 215;
#P connect 19 0 16 0;
#P connect 17 0 18 0;
#P connect 24 0 17 0;
#P connect 14 0 12 0;
#P connect 13 0 14 0;
#P connect 11 1 13 0;
#P connect 12 0 4 0;
#P connect 11 0 4 0;
#P connect 7 0 11 0;
#P connect 8 0 11 0;
#P connect 9 0 11 0;
#P connect 10 0 11 0;
#P window clipboard copycount 25;


April 19, 2008 | 8:52 am

ah such nice people on these forums.

thank you,
this looks really good,

will plunge in an see what i can do

cheers
mat


April 20, 2008 | 6:25 pm

i would suggest putting each instrument on a different MIDI channel. then, filter the incoming notes by channel (using some trivial gates and logic that don’t seem to be beyond your grasp). For the trumpet channel, just pass the notes through and wait for the note-off. For the xylophone channel, set a duration using the makenote object. See below:

max v2;
#N vpatcher 10 59 671 660;
#P window setfont "Sans Serif" 9.;
#P window linecount 3;
#P comment 59 277 86 196617 send notes through with 100ms duration;
#P comment 405 271 66 196617 send notes through unmodified;
#P window linecount 1;
#P newex 388 317 29 196617 t i 2;
#P newex 240 320 29 196617 t i 1;
#P newex 264 448 43 196617 noteout;
#P newex 340 269 58 196617 unpack 0 0;
#P newex 156 272 58 196617 unpack 0 0;
#P newex 156 296 94 196617 makenote 127 100;
#P newex 246 157 48 196617 pack 0 0;
#P newex 301 192 40 196617 gate 3;
#P newex 271 127 40 196617 notein;
#P window linecount 2;
#P comment 347 195 167 196617 < -- will direct notes from MIDI channels 1 , 2 , and 3.;
#P connect 2 0 5 0;
#P connect 5 0 4 0;
#P connect 5 1 4 1;
#P connect 4 1 8 0;
#P connect 1 0 3 0;
#P connect 6 0 7 0;
#P connect 4 0 7 0;
#P connect 9 0 7 1;
#P connect 8 0 7 1;
#P connect 1 1 3 1;
#P connect 9 1 7 2;
#P connect 8 1 7 2;
#P connect 1 2 2 0;
#P fasten 3 0 2 1 251 182 336 182;
#P connect 2 1 6 0;
#P connect 6 1 9 0;
#P pop;


April 20, 2008 | 11:25 pm

thats a very sensible idea,

and one i think it would have been great to use.

unfortunately all the instruments are controlled on a single midi channel (10) and the builder has been getting people to compose works just using channel one, using his note mapping.

but perhaps i should create a note remapping that maps from general midi mapping (where the instrument exists in the machine) to the one channel mapping, then i could incorporate your idea?

thanks

mathew


Viewing 6 posts - 1 through 6 (of 6 total)