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...
    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.-- [ddg]

    Day 1

    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.

    Day 2

    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.
    To experiment with using 32-bit float precision in the jit.pix object, 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. Please enjoy this patch responsibly. -- gregory

    Day 3

    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.You'll need both Overdrive and SIAI on so that the phasor~ @lock is steady. HAPPY PATCHING!!!!!!! -- Andrew
    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

    Day 4

    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! < -- Les

    Day 5

    This patch explores the use of jit.gen to generate 3D matricies for use with I've always had a soft spot for blobby, amorphous shapes, but they tend to be hard to wrangle.
    I ran across a web site 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. 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 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

    Day 6

    This is my first real gen patch and it was a lot of fun to make. It 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

    Day 7

    This patch is an audio feedback network, similar routing-wise to Gregory's feedback network example in his Garden of Earthly Delays gen~ tutorial, 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

    Day 8

    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. -- matthew

    Day 9

    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). -- [ddg]

    Day 10

    This is a little patch that uses sin math to modulate a 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

    Day 11

    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 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

    Day 12

    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. -- Dave

    Day 13

    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 -- Andrew

    Day 14

    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

    Day 15

    I was playing with Peter's implementation of the ladder filter 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'. -- matthew

    Day 16

    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! -- [ddg]

    Day 17

    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. -- matthew

    Day 18

    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) -- Dave

    Day 19

    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> combo. The next step for me is to figure out interesting ways to position the geometry in 3D space. Enjoy! -- Ben

    Day 20

    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 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. -- Les

    Day 21

    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. -- Andrew

    • Feb 21 2012 | 3:31 am
      hello, I am quit new to jitter, I like very much the first tutorial Day 1. But I don't understand how you find the messages that can go to the jit.pix object. In the example you have used xwiggle, thresh, fbamt how did you find them? Thank you very much
    • Feb 21 2012 | 7:55 am
      These messages/parameters are defined within the jit.pix object (double-click it to see the code). You define any "params" you want, then send messages from the main patcher.
    • Feb 21 2012 | 10:04 am
      Thank you very much for you reply, i found it :)
    • Feb 27 2012 | 9:36 pm
      Thank you for the patchers, this is great.
    • Mar 01 2012 | 6:38 am
      Great stuff! But i seem to have a problem with the patch of day 16. I get no output whatsoever in the jit.pwindow. Am i missing something.
    • Feb 26 2014 | 10:24 am
      Thanks for these interesting examples, but I whish they will be better organized : names with the right numbers in order to relate the patches to the texts. In addition, they do not all refer to gen and gen~ but to different stuff. Not very easy to follow that wigly tutorial !
    • Jun 27 2014 | 4:29 pm
      Hello, I have a few questions (just kidding, I have dozens but I'll start with those): why in the day 11 patch you multiply the noise by PI and then you make the sin? And why there is a "+" object in the end with the second inlet empty?
      Thank you!
    • May 29 2015 | 7:01 am
      Hi, I'm interested in isosurf and followed the link provided in the day 5 patch ( ; but I don’t understand how to write such equations in jit.gen ; i’m ok with the sphere and the box but don’t succed with others shapes (I don’t want to use gridshape here). In fact I don’t understand how to convert notations such as "length(p.xz)" or "max(d.x, d.y)" …. Do you have some tips ? Thanks !