Gen patch-a-day
The MGraphics patch-a-day series was very successful, so it's time for a Gen patch-a-day! This time, though, a few things change. First of all, instead of doing these all myself, you will have a guest presenter each day. These presenters are the members of the Cycling team that develops educational content (internally called the Material Team), so you will get a variety of viewpoints, patching styles and levels of complexity. It is our desire to add some interesting and understandable Gen content to the mix.
Also, we will only be posting on weekdays - it is skiing season, and I want everyone to be able to hit the slopes...
I'm kicking this off with a very simple jit.pix patch that I use an awful lot: a patch that does threshold-based binary sampling, then provides offset and jittered feedback.
In other words, it uses my webcam to do creepy and flaming images of myself. I use pretty elementary techniques, so it should be pretty easy for everyone to follow. But I happen to really like feedback, and the results of this are pretty fun.
Enjoy!
[ddg]
Gen- patch-a-day! that's just what i was hoping for!! Will there also be some gen~'s these days?
Cheers!
Woah, this is *exactly* what I was hoping for!!! Brilliant.
"members of the Cycling team that develops educational content (internally called the Material Team)"
- is that tutorials, reference and help files and such? Or is there a whole aspect to this that I've been missing?
Looking forward to this, thanks Darwin!
woyteg: yes, we will be doing work with all three Gen variants (jit.pix, jit.gen and gen~).
Wetterberg: This is the group that works on (and is still working on) all of the things that you mention, but also works on some more things that have yet to be revealed... (mwah ha ha).
[ddg]
hehehe, it seemed that way, yeah. Cool. Alright. Alright.
:sits back and waits:
best possible timing! thank you very much!!
Darwin,
First of all, thanks for starting the Gen patch-a-day. I expect to learn a lot from it.
Second, I have a gripe. This patch brings up the documentation issues that seem to be lurking everywhere in Max 6. When I open the patch and examine the [jit.pix] object, I find this opening sentence: "The jit.pix object generates new Jitter mop objects from a patcher specifically for pixel processing."
What exactly is a "mop object"? If I go to help, I find no help for "mop." If I read all the gen documentation, I find no mention of "mop". When I scan through the jitter tutorials I read years ago, I find no mention of "mop."
Now, I'm pretty sure I know what "mop" designates, but how are relatively new users supposed to learn Max6 with undefined words in the documentation?
I think all the jit.pix, gen and so on have more documentation coming eventually, non?
Good morning, and welcome to the next in our Gen patch-a-day series. The super-secret Cycling '74 algorithm has chosen me today, and I'm going to throw another Jitter patch into the mix (A note to gen~ fans: It's just the luck of the draw that we started with two Jitter patches in a row. Don't despair - there is plenty of audio fun on the way). Today's jit.pix patch uses very simple means and makes extensive use of the fact that Jitter gen objects work with floating point data in the range of 0. - 1.0 when addressing the position of a pixel and sampling it. When combined with a few trig objects and the ability to sum, wrap, and fold data, there is room for all kinds of warpy fun. Please enjoy this patch responsibly.
with regards,
gregory
sooo cool... i don't understand a thing in Jitter but now i wish i had beginning to use it earlier, cause the magic of jitter's gen classes is beyond me...
@Wetterberg : i read somewhere that, yes, they are working on some proper Gen tutorials. Meanwhile you can mess with all the gen examples, in the cycling folder. There are some for msp's gen, and for jitter's gens, in jitter/gen.
@gregory
This is really fun! It's is a perfect patch for trying out the different precision modes. The default is auto, which maps char matrices to fixed precision. Try changing the precision to float32. You'll see a massive difference for many of the settings because of all of the trig ops.
Whoa. What an awesome suggestion!
Perhaps you may find the pair of Jitter gen tutorials that went up today to provide you with a little help in making sense of things. I tried to do some patching that more or less might be the way you thought of things if you weren't really familiar with the vector stuff that Jitter gen objects live and breathe, and then dedicated the second tutorial to trying to show what those same patches looked like in their more "proper" vectorized versions. I hope they help a little bit....
D'oh! I just realized that I said that Wesley's suggestion about experimenting with using 32-bit float precision in the jit.pix object without actually telling those of you who'd be curious HOW TO DO IT.
Sorry! It's an easy change. Just add an attribute to the jit.pix object so that it reads [jit.pix @precision float32], and you're good to go. Quite a lot of the adorable cruft that I found so fetching about the patch will be gone, but you may find the smooth results considerably more to your liking. In many cases, they *do* look more like a funhouse mirror.
This patch does a kind of gritty Buffershuffler-esque reordering of the last bar of audio.
I've hard coded it with crusty old drumLoop.aif to reduce clutter in the patch, but you'll be able to pretty easily open it out to other files or live input.
Next steps to take in its evolution could be
- adding variation to the amount of history being collected
- auto changing the number of steps
- adding an envelope to each step
- changing the direction of playback of a step
- copying out parts of audio history into other buffers so that you build up a more diverse history of audio
You'll need both Overdrive and SIAI on so that the phasor~ @lock is steady.
HAPPY PATCHING!!!!!!!
fantastiiiiiiixxxxxxxxxxxxxxrrrrrrrrrxxxxxxxck!
yay
Very nice intro's! Keep 'm coming...
I've run into a problem myself. I simply wanted to port Gregory's swizzle patch from jit.pix to jit.gl.pix but it won't compile. Am I missing something basic about jit.pix vs jit.gl.pix?
-- START GLSL INFO LOG: fp --
ERROR: 0:120: '
-- END GLSL INFO LOG: fp --
jit.gl.shader: GLSL program failed to compile.
-- START GLSL INFO LOG: fp --
ERROR: 0:120: '
-- END GLSL INFO LOG: fp --
jit.gl.shader: GLSL program failed to compile.
This is the same bug previously reported on the forum. There is no difference between jit.pix and jit.gl.pix in terms of how you compose a gen patcher. This will be fixed in the next update. Thanks for your patience.
OK, the algorithm says I'm up now. Here's my bunt for all the noobs in the house. This patch is so simple, don't even look inside! OK, you can look. You'll see how some really useful things can be super easy in gen.
If you're on the move with your camera, got your exposure set on your highlights, but the image is still too dark, here's a quick way to "brighten things up" that's safer than boosting brightness.
HP!<
@andrew:
i`ve tried your buffershuffler-esque gen~, but all i get is a lot of noisy crackling and anywhere in the back (with a lot of phantasy) i can hear the actually drums?
anybody with similar problems?
@stoersignal
Do you have "Scheduler in Overdrive" and "in Audio Interrupt" both checked in the Audio Status window?
Cheers
-A
thanks! that`S it
There is something wrong with the day 4 patch. It kills Max when I open it (Windows 7). The other patches work fine.
This patch explores the use of jit.gen to generate 3D matricies for use with jit.gl.isosurf. I've always had a soft spot for blobby, amorphous shapes, (http://en.wikipedia.org/wiki/Isosurface), but they tend to be hard to wrangle.
I ran across a web site (http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm) that has a handful of distance functions for some basic object primitives (sphere, torus, cone, etc), as well as some really cool distance and domain deformations.
The attached patch basically takes two primitives (cube and sphere) and throws them into the same data set, to create a morphing blobular shape, where the sphere is trying to "escape" from the grips of the cube. I wanted to keep it simple so you can see what is going on.
Since I put this patch together, I've gone ahead and implemented some of the other functions on the page. Can you? I particularly like the displacement deformation function.
jit.gl.isosurface is a touchy object, but once you find the right settings, you can get some really nice results. For me, jit.gen is a more immediate way to interact with the type of data sets that jit.gl.isosurface needs to compute the 3D object. Its really fun to just start throwing in different operators to see how they affect the outgoing matrix.
Enjoy!
-Ben
hi ben,
i get the following error message:
class max does not work in gen domain jit.gen
best,
kugelschreiber
Hi kugelschreiber,
Hmm, what version of Max are you running? What OS?
Can you try changing the 'max' object in the jit.gen patcher to 'maximum'? Or change it to 'expr max(in1, 0)'?
If you take the max operator out altogether, you can get some nice shapes too :)
-Ben
sexy time!
8)
Hey Everyone,
This is my first real gen patch and it was a lot of fun to make.
This patch implements the (simplified) equation used in jit.rota in the jit.gen environment. I use jit.rota all the time and was excited to see how a gen version would function. There are still some things that could stand a little fleshing out to prevent or smooth pixelation and add different bound modes, but it is pretty functional. I am also working on a version that implements the full equation with all the extra parameters, but this is a good starting point that I hope is less intimidating.
I included the equation from jit.rota inside the jit.gen patch so you can see how it was implemented.
Enjoy!
Cory
PS: I fixed a glitch, so if you grabbed this right when it went up, this is an updated version.
Some of you may have noticed that the jit.gen object in cory's patch has @precision float32. This is needed because the default precision for char matrices is @precision fixed. Fixed precision doesn't handle multiplying numbers that have a wide dynamic range very well. For example, the angle conversion from degrees to radians has a divide by 360 aka multiply by 0.0027777777777778. If you angle is 20 and you multiply by 0.0027777777777778, that's an approximately 4 orders of magnitude difference, which the fixed precision can't really handle. In this particular case, you can use the [radians] operator to convert degrees to radians with no issues in fixed point precision. Here's the patch:
Here's another version that folds some of the patch in, making use of the vector capabilities of jit.gen:
Cool stuff, Wesley. Thanks for extending the conversation!
This patch is an audio feedback network, similar routing-wise to Gregory's feedback network example in his Garden of Earthly Delays gen~ tutorial (https://cycling74.com/tutorials/gen-tutorial-1-the-garden-of-earthly-delays), but is more of the no-input variety (almost). It also differs in that it attempts to keep the sound moving through the tubes instead of allowing it to decay. That said, there's no real gain control happening, so watch out!
-Dave
Loving this gen stuff, but a long running 'patch a day' thing happening in a forum thread feels weird.
Rodrigo, if you prefer, we're also mirroring the Gen patches over here: https://cycling74.com/tutorials/gen-patch-a-day/
I love it. I sure hope someone will compile this into "Gen Recipes" or similar, but having this thread to follow is very thrilling :)
@ Ben :
>Since I put this patch together, I've gone ahead and implemented some of the other functions on the page. Can >you? I particularly like the displacement deformation function.
Both the repetition and the "twist" domain deformations have some great things about them.
This is the one place where I'd *really* like the most to place my efforts in gen, but I don't know at all how to translate what I see there into any sort of gen language. Might one resort to codebox for this, for instance:
--
float opTwist( vec3 p )
{
float c = cos(20.0*p.y);
float s = sin(20.0*p.y);
mat2 m = mat2(c,-s,s,c);
vec3 q = vec3(m*p.xz,p.y);
return primitive(q);
}
--
@Andrew
Yeah that's better. Why not have them on the main blog so they get pushed out with RSS feeds? (Like the "did you know?" stuff)
@wetterberg
This isn't exactly what you're asking about, but it's the same equation. I just put it on the end instead of the beginning and was really surprised at what came out. Try adjusting the warp factor.
Here's another version on the input side:
@Dave : amazing ! Do you know Klaus filip's ppooll patches ? There's an act called "beauty" that seems to be similar to your no-input stuff. I'm going to try a mix between those two patches !! In all cases, this is a very good starting point for those who want to make experimental synthesis with gen. Thanks !!
For my contribution, I slightly modified Gregory Taylor's awesome seven segment envelopes (included in the examples folder) to operate as a standard ADSR with adjustable curves per segment. I love this envelope, it'll replace all my envelope duties in my future Max work.
Not satisfied to merely rip of Gregory's envelope, I also adapted his MOD FM gen~ example as a sound source. The gen~ itself is unmodified in this instance, I merely built a lot of Max around it for modulation flexibility.
@matthieu
thanks! I'm not familiar with the 'beauty' patch, it would be interesting to see your mash up of the two. Another idea for expansion is to try different effects in the effects subpatcher. I imagine you could drop a lot of different things in there and fundamentally change the instrument each time.
In Ben's earlier patch, he did some manipulation of an isosurf - 'cuz that's what he is into. In my case, I'm getting a little obsessed with manipulation of matrices that contain meshes. In today's example, I'm creating an X-axis scanner, and using that to morph the duck model that comes with Max. Basically, if the X axis is near the current scanner location, the gen patcher forces all of the axes to push toward [0, 0, 0]. Sort of like putting a duck through the eye of a needle (or something).
Enjoy!
I loved Darwin's patch so much, I couldn't resist a little tweaking. In the following mod, the transformations only manipulate the position coordinates (taking advantage of the concat gen object), and I've applied the model's texture to the jit.gl.mesh, fun stuff!
i'm having great fun building upon dave's audio feedback network! with a bit of modding here and there plucked string sounds come out of it, decaying into endless feedback...
but i'm seeing some strangeness and i'm not sure it's expected behavior. when feeding back the main output into the gen objects audio stops and i get an multiple errors: "tapout~: no tapin~ object connected". audio comes back when i disconnect the feedback patch cord. i thought delaying it by one sample might solve it but no.
see patch below. will only sound after removing the feedback link.
This is a little patch that uses sin math to modulate a jit.gl.mesh. If you take a look inside the gen patch, you can see that the actual math is quite minimal but can produce quite complex forms. This kind of approach to working with OpenGL geometry is really exciting for me in that it provides really smooth results without the need to go through and animate every frame.
Cory
Hi dtr-
You'll need a tapin~/tapout~ pair in the feedback path between the gen~ objects. This isn't a gen~ specific requirement, just regular feedback handling in MSP.
@corymetcalf something went wrong while posting the patcher, can't open it..
it opens just fine here - fun, too!
Here is a copy compressed version for anyone that is having trouble opening the GenPADmultisine.maxpat file.
Inspired by Gregory's patch, I decided wanted to take things a little further "out", and it was an excuse to try some things in jit.gl.pix. This is another patch where the sample object is doing the heavy lifting, and aided by some simple noise matricies and the always useful jit.slide object.
What I really have been digging about patching in the gen world is that things are endlessly and easily tweakable. It is really quick to throw in different objects here and there into your gen patcher, and get rewarded instantly. Much more fun than staring at shader code, at least for me!
Enjoy,
-Ben
There are some issues with the patch I posted on Max 6.0.3 and lower.
When 6.0.4 is out, the previously posted patch should work fine, as there are some fixes for the usage of scale. Attached is a backwards compatible version to try in the meantime!
-Ben
6.0.4 is out :)
So many jitter patches........
This patch is an Lf-noise generator, similar to rand~ (and borrows from the gen.random example), but adds two things-- nonlinear ramping modes, and a ramp slope control.
The ramp slope control (called 'ramp value') let's you 'ramp up' the slope of interpolation such that the target random value arrives early and holds, creating a stepped component to the waveshape. This is useful if you like to have your parameters glide to a spot, hang out for a while, then glide again to another spot. At the extreme, it turns the waveform into a pure noise step function. It can also be modulated for added wildness.
awesome
A week or so ago we got an email from someone who had noticed that
onepole~ in Max 6 sounds different from onepole~ in Max 5 and it was
noticeable when listening to his patchers
Actually we've had a few of these - it's a by product of us having improved the sound
of MSP for Max 6, it's better, but it's different! Sometimes different trumps better.
So we had a look at the old onepole~ code. Tim Place had done an analysis of all the old
MSP code and especially the filters when he did the huge job of making them all use 64 bit
audio internally for Max 6.
Max 5's onepole~ actually has a cutoff freq mapping deal which clips the cutoff
frequency between 0 and SR/4, or about 11k Hz at 44.1 kHz SR (ahem). So if
you feed it a cutoff freq value higher than that, nothing changes.
Max 6's onepole~ on the other hand, responds all the way up to SR/2.
If you want the sound of Max 5's onepole~, it's gen~ to the rescue.
Today's patch has a comparison between the different onepole~ objects.
There's the one from the gen~.filters example, the Max 6 onepole~ object and
a recreation of the Max 5 onepole~
Cheers
-A
andrew, this is brilliant.
Here's a comb filter I implemented based on a paper from ICST. It uses allpass interpolation so it should be more accurate for high frequencies, and it also has built-in saturation. It can't do infinite sustain, but you can cascade them without too much insanity. The alpha parameter is the FF coeff.
We haven't seen much of the codebox during our patch-a-day tour of the Gen objects, so I thought I'd pitch one into the mix.
As you know, I'm particularly partial to the Navier-Stokes equation - from the days when I wrote my first Pluggo tutorial on the old Pluggo KnaveStories plug-in to my last Vizzie module. So I'd like to introduce you to the Navier-Stokes Trio.
No, it's not the smokin' jazz unit that has filled the gap in my grieving heart left by the sudden death of Esbjörn Svensson, but rather a set of three gen~ patches that map a progression of Gen patching to produce an audio-rate version of the classic Max chaos external based on Richard Dudas' original ChaosCollection and (more recently) Andre Sier's updated port of them (What? You don't have them? Click here right now).
The trio implements a Navier-Stokes equation in three slightly different dialects of gen~ - one that uses common gen~ operators (NS-operator), a version that has the Gen expr operator doing a little more of the heavy lifting (NS-expr), and a final codebox-based version that includes some inner bells and whistles (internal autoscaling!).
These three patches are all implementations of the same calculation (you'll find 'em inside the patch itself), so I hope you can get a sense of the progression of the patch.
gregory
P.S. I'd like to add a shout-out to my colleague Graham Wakefield on this one - he took a look at my original codebox workout and showed me how to include history operators inside the codebox and how to embed the autoscaling. (He also had some helpful suggestings about replacing my sah operators with the ? operator, too). He remains one of my heroes, and I owe him another pint.
I was playing with peter's implementation of the ladder filter (https://cycling74.com/forums/stilsons-moog-ladder-in-gen) and wanted to hear what it sounded like with a sawcloud feeding it, so I decided to implement a saw cloud with adjustable fatness in gen~
As a gennoob, I'm pretty sure this isn't the best or most efficient implementation (comments and suggestions welcome), but, you know, learn by doing. Don't think of it as fear of failure, think of it more as a 'floportunity'.
This is sweet!
Today, I decided to do something simple - but with unpredictable results - as my patch-a-day. I started with a simple "tartan generator", which just samples the input at the current x/x and y/y coordinates to build a grid. This is what you see when you first fire up the patch (and turn on your camera). I then wanted to see what feedback would do, and especially negative feedback. The patch goes from simple colored gridding to either fractal inversions or architectural blocking (in this case, I've got chunky set to 4, fbmix set to -1.267, x offset to .323 and y offset to 7.6). You can't easily predict the results, so it is one of those fun patches where you randomly twiddle the controls and enjoy the results.
Have fun!
morphing male 'ooo/ahh' formant filter
Three biquad filters in parallel.
Coefficients controlled with a single simple control.
I used filtergraph~ to produce the desired coefficients and then plugged the values into individual scale objects inside gen~ to morph the values.
oooooooo.
aaaaahhhh.
...and so on.
Today's gen~ is a simple sample playback engine that allows you to specify sample duplication, skipping, and shifting. For example, you could choose a duplication factor of 3, so then each sample in your signal stream is repeated 3 times until the next. Combinations of duplication/skip/shift settings will create more complex playback patterns.
This one is hardwired to loop a sample from the Max folder. From here I think the next step would be a version for live input. Also a stereo version where the duplication/skipping patterns on the two channels are related in some interesting way (e.g. phased)
A few weeks ago, Cycling '74's Wes Smith posted a patch on the forums after someone inquired about how to make an array of hexagons. Cool patch! What I've been finding is that a great way to learn Gen is to take some existing bit of code and try to see how it would be put together in Gen-land. Besides helping my Gen chops, it also gives me a better understanding of the underlying concepts involved.
This fairly simple patch uses jit.gen to create the necessary positioning matrix for the always classy jit.gl.gridshape->jit.gl.multiple combo. The next step for me is to figure out interesting ways to position the geometry in 3D space.
Enjoy!
-Ben
@Matthew
Here's a couple of fun mods on your supasaw: (now in stereo...)
Here's one for the gaffers and camera assistants in the house! By that I mean that this patch requires an image that is evenly-lit and properly exposed. That's why there's no jit.qt.grab, because it would be too easy to use your laptop's built-in camera with your face lit by the computer screen. Yuk!!! Also shooting at a fairly high resolution will make the details nicer.
The patch is based on the idea that all human skin, despite large differences in saturation and brightness, has approximately the same hue. We use that fact to apply a blur to the skin only, leaving details like eyes, nose, and mouth sharp. So the technique can be used to smooth out blemishes or–if you push it–create a cartoon effect.
In certain cases, for example very light or very dark complexions, you may find it easier to use the little gswitch object to look at the alpha channel while you adjust the threshold.
It's worth taking the time to dig into the jit.gl.pix objects for some useful tips. The blur uses the cell object to achieve sub-pixel displacement, regardless of image size. The technique for creating this cheap blur can also be used to do more specialized blurs. Our saturation boost is done in the hsl colorspace. We smooth the edges of our key with the smoothstep object.
If you have experience working with compositing/finishing applications like Shake, Nuke, Smoke, or even Da Vinci Resolve, you'll appreciate working with a nodal interface like Max. Now that gen brings that nodal interface to the world of openGL hacking, you can easily bring cool film techniques to your real-time video processing. Just don't forget to use your camera and lighting skills, too.
Ooops! It looks like I made a mistake. It turns out that if you want to use a param object with a vector, you have to declare it as a vector. See how it's done with the width param inside the blur abstraction.
Thanks to Andrew Benson for the original blur patch and to Andrew and Ben for finding the bug.
Thanks to Wes for showing the correct way of initializing a param object for vectors.
The other day I had an idea to try and make an audio generator which took an input and sampled it every N samples, then did some kind of interpolation between successive sampled values.
The picture might give you an idea.
Here's how it turned out. Because the "gap" in samples relates to the frequency of the incoming wave, its output varies all over the place as you change both its frequency and also the gap between successive sampled values.
This post is the last one in this patch a day series. We hope you've had fun playing along with us. On behalf of the members of the material group at c74, I'd like to thank Wes and Graham for all their help with these patches and for their work on this awesome addition to Max.
Cheers
-A
P.S. Thanks to Lilli, all of the Gen patch a day patchers are stored for posterity here
Hey I'm having problems with Bens Day 5 isosurface cube/sphere example , I loaded the patch turned it on and got this
not very qube or spherelike, is there something wrong with my max installation ?
Hi Sterling, check your Max 6 version and make sure you've got the latest installed. It could be that something in Ben's patch is relying on an updated Gen feature.
thanks for share the rotajitgen.maxpat
but if i compare under same condition (resolution, fps) and movie, it seems that this rota-gen use more cpu power than jit.rota!
jit.rota about 5%. rota-jit.gen about 25%!
Should gen not bee faster than normal jit??
great patches. one question while going through them: Andrew, I guess for the Buffershuffler-esque reordering (pad03) mono channel output is not the supposed outcome?
@TOBIAS ROSENBERGER. 8 years later, but still: there is an error in the patch: channels in poke are 0 based, which means that poke bucket 1 plays the right channel and not the left... Thanks for a nice collection of patches :)
Hello, and thank you all, 2 hours after starting to read this incredible article, I find myself with 18 Patches filled with knowledge and acquired experience, which you share with us with love and wisdom. Beginner in Max for 3 years, I learn a lot from Darwin Grosse with ten-year-old tutorials, and which in the eyes of the 48-year-old child that I am when I discover them, encourages me to learn still more to marvel the hearts of men. Darwin Grosse's generosity in sharing is enormous and I hope that in the Cycling '74 team, we will be able to find a worthy heir, to continue his work of sharing knowledge. I don't know if one day I will go to the United States, but if you pass by Auray in France, let me invite you for a beer, a coffee, and a huge smile to tell you how good it all is. Thank you, thank you all.
Sébastien Ruiz or sebairstein in my artist way of life :)
https://drive.google.com/drive/folders/1zGUvCL14nlfOb6saaGXA_MLhs6F3BLi5?usp=sharing
Hello, I have made a link to download all the patch. :)