Granular Synthesis: Building a granular synth with Max, part 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

thanks partner

👍︎︎ 2 👤︎︎ u/breakfastsquid 📅︎︎ Aug 21 2021 🗫︎ replies

You had me at Half assed? This will help me allot , I just started pulling apart that granular package , THANKS

👍︎︎ 1 👤︎︎ u/rustingeezer 📅︎︎ Aug 21 2021 🗫︎ replies

I think you should mention that with the final patch if you trigger a new grain you end the playback of the currently playing one when grainTime < grainLength. That's why it has such a 'clipped' sound at the end and where poly~ would come into handy to solve such an issue.

👍︎︎ 1 👤︎︎ u/seismo93 📅︎︎ Aug 21 2021 🗫︎ replies
Captions
when we think of the sound of a synthesizer we're probably thinking of something simple an instrument bill on top of a basic periodic waveform an oscillator now you could generate all kinds of sounds from this one basic design from simple waveforms like signs triangles saw pulse whatever all the way up to more complex sounds like FM or wavetable synthesis but today we're going to look at a completely different approach to synthesis one that isn't based around any constant waveform at all but instead on tiny microscopic particles of sound we're going to be looking at granular synthesis where we take an atomic approach to sound so what is granular synthesis well the approach develops out of the work of physicist Dennis Gabor in the 1940s and it examines the audio signal as a small series of a series of small grains of sound so grain being something approximately less than 50 milliseconds now according to Tom Holmes in contrast to thuria's analysis of sound Gabor looked at developing to quote a mathematical principle for representing sound as being composed of minut grains each with its own wave form envelope duration density and position in space end quote now today we're going to be looking at this approach from the perspective of electronic music but it's an instrumental composer Yanis Linnaeus who's generally considered to be the kind of pioneer of developing a compositional approach to working with grains of sound here stochastically composing with tiny percussive sounds of orchestral instruments and then over in the electronic music kind of realm Kurtis Rhodes is the figure who developed one of the earliest approaches to translating de Bourgh's theories into a practical programming environment for creating electronic music now Rhodes is a really important figure here whenever we talk about granular synthesis I mean he literally wrote the book on granular synthesis which is called my croissant a lot of what we talk about today is kind of gonna lift lift out of that now granular synthesis at its most basic uses many many many small fragments of sounds and we're calling these grains and we're gonna piece together a complex stream of these grains so rather than any constant waveform like a regular oscillator it's easier to think of this as a stream of many sounds so many sounds rather than just one sound and each of these grains each of these sounds has its potential for having its own unique character so from there we can control these grains in different ways we can allow them to develop or shift we can synthesize sounds that just wouldn't be possible with any kind of regular oscillator so think about each grain could have its own sound its own pitch its own Tambora duration even its position in the stereo field before we get ahead of ourselves let's start with that fundamental element what is a grain well a grain is a short wave form the grains content shaped by an amplitude envelope there's two parts there the wave form and the envelope now in granular synthesis we can use a variety of envelopes we can use anything from a simple envelope attack sustained-release up to things like Gaussian curves which we'll look at today the grains duration can be constant random or dependent on frequency so shorter grain durations for higher frequency sounds longer durations for lower frequency sounds something like that it could be really really sure giving very little indication of the grains content so something short and percussive like an impulse or a click or something a bit longer so that we can really hear more of that grains content more of that waveform now the waveform within the grain the sound content could be either synthetic so something synthesized like a bunch of sine waves or something sampled today we're going to look at building a granular sampling synthesizer a synthesizer that plays grains of sampled sounds from an audiophile so how's that instrument gonna look well we're going to start with a sound file we'll have something loaded into a buffer now you could use a live SiC and all kind of constantly recording into a live buffer but the ease of use we're just going to work with a pre-recorded sample preloaded sample and from that buffer so we've got a buffer here we're gonna pull out individual tiny grains and they'll be triggered back as kind of these little isolated envelopes so to play multiple grains so overlapping grains we're going to have to use some polyphony so we'll use the poly object in max now what I would say is that if you have not used max before or you haven't used it in a little while don't worry we're going to patch along together so hopefully it should be fine but just to kind of a brief a brief note there because this is the kind of unfamiliar approach for a lot of people to synthesis might seem like we're working kind of ass backwards in in some instances we're gonna be starting by building the envelope before we've built the content and things like that so just bear with us isn't it all kind of come to pass so where do we start first things first we need to make our buffer and our grain generator in Max and then the grain generator is the heart of the whole operation really it's easy to get kind of caught up in you know how clouds swarm around us and you know all of the strange and complex behavior of things but really the grain generator is the star of the show here and it doesn't matter if we're dealing with a single grain or an entire cloud of grains the grain generator is fundamentally always going to be the SIPP it always going to be the same it's an amplitude envelope and that's going to be applied to a waveform so a grain generator also gives you control of individual parameters of each grain so amplitude duration frequency panning all sorts of things this is a simple grain generator that we're going to be working with and it's given in Kurt Rhoda's book my croissant so at the top of this image we have an envelope generator and that's going to be used to shape the oscillator or waveform note the pitch control here and that will be sent out to the output so we're going to follow this design broadly and start building our envelope so I've talked a creating adsr envelopes in earlier videos and if you want you could do what we're about to do with an adsr or you could explore using Max's function objects to make a nice kind of break point line chart but today I'm going to look at building a Gaussian envelope and that will give us a nice smooth bell-shaped curve okay fading in and then fading back out now because our grain is going to have a variable duration we can change how long each grain is we need a really efficient way of applying a scalable envelope so envelope can change for each grain now adsr or a function line could do this fine but what I'm gonna do today is I'm gonna actually use a buffer to make this now if you don't understand exactly what I'm doing or perhaps why I'm doing it and particularly the kind of nitty-gritty of a lot of the maths don't worry too much what I would suggest is you try and patch along with me here because a lot of this process is gonna be about you kind of exploring and experimenting with stuff and kind of learning as we go so a lot of this might not make sense initially but as it falls into the larger instrument I really hope that it will kind of all start to make sense with you now I've got a new max object here now eventually this is going to end up as a sub patch of a much larger instrument but we don't need to worry about for that for the time being we're just going to start we're just going to focus on making this nice little envelope generator and what we need is we need whenever this instrument first load loads it needs to initialize our envelope it needs to make our envelope straight away so I'm going to do that with a loud bang message and what that's going to do is that's going to send a bang when this patch is first loaded and that is going to be attached to what we call an oozy object now Susy is going to rattle off when it receives a bang a list of 512 numbers so for its current index so I wonder if all of a sudden when I click that when I initialize this is going to rattle off from 0 to 512 now what we're actually going to do is we're going to pass this through an expression and what that's going to do is that's going to scale those digits from 0 to 5 1 2 to give us a kind of Gaussian window now the maths of this expression look horrendous I'm not going to bother reading it out to you what I will do is I will post this line in the comments of the video so you can just copy and paste this in because that's what we're going to be working with right now don't worry too much about how and why you kind of get this value at the moment you'll see what it does in in a second now what's going to happen here is this is going to run through and it's going to give us a list of values that create this nice bell-shaped curve bell-shaped curve but what we're going to do is we're going to pack them together so I need to pack into a 0 it so that's an integer and a 0 decimal so let's say decimal number so what we get is on the right Inlet here we get this floating number and on the left Inlet we get the index the values 0 2 5 1 2 and we're going to pack this all into a buffer and we're going to use the peak object to do this now I appreciate that if you're watching this you're probably thinking what the hell is a peak object where did he find Izzie what's expert expert for a busy road point-five and I've been doing this for a few years so I kind of know what some of these objects are and don't worry if you don't know about them yet as we start to use them you'll figure out why we're doing it and what do now peak is a really lovely object and all its going to allow us to do is record in into a buffer sample by sample so it effectively imagined stepping through each sample of a buffer of audio and saying okay step one that's going to have a value of this step two that's going to have a value of this and we're just sort of punching in a buffer sample by sample I'm going to come back to the hash zero in just a second but effectively what this is going to do when I initialize the patch it's going to rattle off numbers from zero to five one two that is going to form the index so we're in the buffer and then it's also going to run through this expression which will give us that Gaussian curve we also need a buffer object that would help and so I'm gonna call this hash zero green and of and I'm going to specify that it is 512 samples long there we go so we've got our buffer actually idea what I could do this would make it nicer I'm gonna give this P [Music] right now wait for me that's alright and with a little luck that will give us our wave form so I think is crossed here AE there we go so you can see now this this kind of gives us a nice helpful thing you can see each of those 512 steps not quite but you can imagine 512 steps each one of them has a gauzy and kind of curve value there so there's a nice envelope curve it's recording it into a buffer so handily we can kind of call this wherever we need it and all we're gonna do to use this is kind of play through that buffer speed that we need and that's going to give us that nice kind of curve if you can imagine like amplifying this against a signal it'll give us that nice smooth in and out now I just want to talk very briefly about this hash Zero thing in max this is a symbol for creating a unique identifier so in an argument you can use that hash Zero symbol to give you a kind of unique ID for whatever patcher or sub patcher it you're in now I'm just doing it now because it'll save me time later you'll understand why we're doing it later on basically when we start to look at kind of polyphonically generating grains each one of those grains needs to have its only unique ID right otherwise the volume would just be set for all grains and you might be using thousands of them so instead by using hash 0 each time a grain is generated that's going to be represented as a unique number I think it's like four or six digits unique digits each time so it might look a little bit strange now but it's a it's a it's a lifesaver later on and just so I don't forget it if anyone is doing this with Max for live Ableton uses a slightly different syntax so instead of hash 0 I believe it's three hyphens but maybe check that okay moving on now at this point we could just create a really simple sine wave and multiply that sine wave by our envelope and that would give us a nice kind of synthesized grain waveform okay we would just have a short kind of curve in but we're going for something a little bit more ambitious here we're wanting to build a sampling granular synthesizer so to do that we're going to need a an audio file kind of buffer now what I want to do I'm just going to encapsulate this so I'm going to copy everything and I'm gonna hold command shift and E on Mac and that's just gonna drop all of this into a little sub patcher so I if I wanted that I could open it back up and sure enough we've got a little sub Pacha it's the time being I can just Bob this over into a corner down here so if we think back to the grain generator we've currently got one of the two components we've got the envelope what we haven't got is the the content we haven't got the waveform yet so we need that we need our buffer so first of all let's create a buffer and this one's gonna be a kind of main sample buffer so I'm gonna call this hash zero using that again I'm just gonna call this grain buffer there we go and I can create as I just did a wave form give it the buffer name grain buffer and then I can load in an audio file so I have loaded the 21st century masterpiece Pony by Ginuwine as I kind of test material here so this is going to make up the content of each grain so we're building the grain generator now so the way that this is gonna work is we've got our waveform on the one hand and we've got the envelope that's going to be used to shape that waveform what we're gonna do to make that is we're going to use the the wave object and essentially what that allows us to do is to read through a buffer by index so in the same way that we use the peak objects before to kind of specify the value of each step on that Gaussian curve now what we're going to do we're going to use the wave object to kind of read out of that buffer step by step so if I put in the same grain nforce the name of our now I can do is I can use the line object which we've used in the past to kind of step through and what I'm going to do is just for kind of sake of argument I'm going to set it to five one two so it's going to set step through each number from zero to five one to feed in here now that's just very quickly I built a little scope here hold on I just make this window a little bigger here and I'm going to set this to automatic so it should be if I step through if I trigger this line will read through the envelope so just to remind you read through that shape over time so let's have a very quick kind of audio test of this you don't have to patch them long what I'm gonna do is I'm very quickly I can copy it in so here I've just copied in the groove object which just plays back from our buffer in a constant loop given speed so I'm gonna do is this is just going to play back constantly and what we'll do is we'll apply this envelope to the output so we'll use that when I trigger the the envelope it will use up to shape our kind of curve so there we go now this is very very quick it's just 512 kind of milliseconds or so it's it's stepping through that buffer we could set this a bit longer if you wanted to just kind of check what's going on we could set this to maybe a second a thousand milliseconds and we'll hear back grain content now in granular synthesis we're actually going to be working with much shorter durations we're gonna be working with things from fifty to a hundred or something like that say so we'd be working with very short very quick envelopes notice how we don't hear any you know kind of recognizable sounds we kind of get little hints of the kind of timbre and it's much more subtle now what we actually want is not this we rather want the waveform to be played back at specific kind of points so we want to specify where our sample starts and where it ends from the main audio file so what we're going to do is we're not going to use grooves to just play a constant stream of sounds we're going to specify which elements of our audio file we want to play so we're going to use the play object to play back specific elements of our audio file and then we're going to use the wave object to shape the amplitude envelope of that so let's create play and we're going to call again the kind of sample so in this case Ginuwine's pony I probably could have given this a better name like hash zero sample or something instead of grain buffer but what it is if you want to change yours maybe do it now now all I'm gonna do let me line them up so that it makes sense is I'm gonna use the same kind of argument that I was using for the amplitude envelope I'm going to use this line object to kind of scan through that that audio buffer and play back that now we want to do this at the same time so what I'm gonna do is I'm just going to use a button or a bang here to trigger these at the same time so when I click this button what we should get is playing back through our sample and at the same time playing back through our amplitude envelope and then applying those multiplying them here to kind of give shape to to to the to the grain now there's gonna be a problem though that problem is that I was just doing this from a very kind of short tiny section so if you think to back to how line works and we've looked to that in previous videos but if not just hold alt on the object and it will bring up the help file up here and if I look at this list input you'll see that the way that this works is we're going from a value 0 to a value 1 over a period of time in this case 2000 so what we're saying here is go from 0 sample 0 to sample 1 over 50 milliseconds now from 0 to 1 is it's kind of useless for our audio sample so maybe we would be say go from zero to a thousand over 50 milliseconds then we should hear something ah okay maybe let's make it a bit longer just so we can hear let's take it back to five one two as I generation now because we're saying play from the start of this sample sample zero to a thousand samples in and do it all in five hundred twelve milliseconds everything is being squashed up so it's being played too fast it's not being played at a kind of realistic speed or a normal speed so if we're gonna start and and you know similarly if we wanted to say okay well we don't want to play from the start we want to play a hundred milliseconds in fact actually as a kind of example let's say 500 milliseconds because we're now playing instead of from zero to a thousand four to five hundred to a thousand which should be half the speed so we need to think about some various kind of parameters that we want to control in our grade generator we need to think about where we're gonna play from in our audio sample and we're going to play - and how long that's going to take so we need to think about kind of stretching the sound so what we need to do is a little bit of kind of argument - juggling at this point and to do that I'm going to use the pack object and I'm also going to use the dollar argument basically dollar so here for instance let's do this as dollar one what that's basically saying is if you take this value as being whatever that number is so if this was here if this was set to 512 he's gonna play a 512 milliseconds if it was set to a thousand or longer we end up with a longer amplitude envelope okay so that dollar argument is going to allow us to pass variables through so we're going to use that quite a bit so I've had a little think about the parameters that I need to be able to control in my grain generator now for every grain I need to be able to control the start point from that sample from the sample buffer so in this case Ginuwine's pony I need to control where we're gonna start how long the grain is going to be and what the grains pitch is so let's make those so I'm just gonna create an integer number here I'm going to create another integer and then my interval ratio is going to be a decimal floating number now let me just tidy this up I'm gonna get rid of this now the wave and the envelope keepers together but I'm just gonna move those down here get rid of this for the time being this these just die off the way I'm just gonna give us a bit of space because what we're gonna have to do is a little bit of like I said juggling just kind of making sure that some numbers don't go bigger than others and some are less than others and things like that now as I said we're going to pack these objects up and what we're gonna need here is we're gonna need three values okay and they're all going to go into this argument here so this is going to need to be dollar one dollar two and dollar three so what that is sentence essentially is going to be doing is telling the line object that we're going to take from here so that's that first inlet of the pack object ooh the second valuable over the time of this one so let's say that grain duration is going to be going here and we know our start duration is going to be here so what else do we need we need our playback well where does that go okay so the interval ratio is actually going to be multiplying the duration by the speed that we want so I'm gonna take multiply one decimal remember to put the decimals in because otherwise it will kind of just turn this into a integer number so that's going to go from our duration we're going to multiply it by our interval ratio and then we're gonna use that to offset from our starting sample or something like that we'll pull out there now what I'm going to do is I'm just gonna give us some numbers here just so we can kind of monitor the situation so that's gonna just check what that is yeah now this was something a bit more helpful than a negative number let's say we were going to start from 1022 we want to play it for 500 milliseconds and we want to play it at regular speed of 1 now because this has all been I've set these in different orders they're not being triggered neatly which is kind of a pain so what I want to do is I want to make sure that these are all and at the same time that duration also needs to be set down here there we go okay so what we can do is we can now play back a single grain from a given point so it could be over here to a given duration so in this case 500 at a given rate now let's just check this let's just play around so I'm just going to create a really simple metro object it's just gonna trigger every let's say every yeah every half second this is kind of a good way of just making sure that you're kind of triggering constant grains and you can kind of play around with checking them there we go okay so playing around with our start point playing around without generation but there's something interesting happening here because I'm triggering a new grain every half second if I set it to longer it's gonna get cut off so if I have it to be careful about that why don't we have a kind of single train of frames here if I have very short grain and then I can also change the pitch or the rate at which I'm playing back each of these grains so it seems like we have what kind of very basic mono single train line green generator now I'm generating a series of grains and I'm able to control where in our audio sample they play back from how long they last another nice thing that we could play around with at the moment we've just got mono grains but wouldn't it be cool if we could use some stereo panning so all I'm going to do here is I'm going to just take a very simple the pan to object I'm just going to stick this in down here and now we can use this inlet here so MIDI panning so this is just a an integer from zero which is left to 127 which is right and then we could start to pan things around or even I could use the dial object and set oh it's already there so what I could do let me just turn back yes that's kind of nice because I can make these kind of spatial sort of drifts of sound which would could be interesting but what I want to think about and this is where the real power of granular synthesis comes in is what if every single grain had a different spatial location okay so that's really simple to do all we'd have to say is every time we generate a grain so in our train that's every time we we bang a grain I just want to generate a random number between 0 and 1 to it or 1/2 so and what that will do is every time a new grain is generated it's gonna have a different position in the stereo image let's have a lesson now already that's way more interesting it's really dynamic when we start to look up overlapping grains hundreds of thousands of grains this can be a really beautiful sensation particularly few listening headphones but what I would say is why stop there why does it just have to be the stereo image what if we started to play around with generating different starting points or different durations or even different pitches and we can take the same very very basic sort of system here just generating a random number each time a grain is generated to specify a new start point duration or pitch one thing we have to be careful of though is defining our boundaries now for instance I know because I've used this little info buffer object up here I know that my sample of Ginuwine's pony is this long in milliseconds now the reason that I've I've added that info object to find that out is because if I start generating random start points or random durations I need to be sure that I'm not going to specify an impossible starting point I can't start my grain right you know past the end of the sample so I need to be able to define kind of limits there and what we need to do then is to start to be very careful about what random numbers we generate and how far they go and where they go similarly some of them are not problems of you know is this impossible some of it is about tuning it so it works for you maybe just having a bunch of random pitches is just going to sound absolutely awful but if we start to have random pitches that were all tuned to an octave so changing our interval ratio from one to two to four or 0.5 you know having it tuned in maybe harmonic series or something like that could be really really beautiful or just having tiny fluctuations zero point zero zero one shifting and having kind of this nice kind of dynamic fluctuation of pitch at the moment my patches is a bit of a mess so what I'm going to do is I'm going to clean this up a little bit I might encapsulate a few things and then we can look at some simple and effective ways of setting boundaries on our random generators okay so things up a little bit I've tried to space things out a little bit more so you'll see that I've got the wave form of a sample up here I've got the amplitude envelope down here and then I've labeled up the parameters that we're currently using so as just a reminder this is the sound that we've got so that is starting 2,000 milliseconds into our sample the grain duration is a hundred milliseconds and the grain rate the playback speed is one and I'm just randomly generating stereo sort of positioning now I thought a nice thing to play around with and just to move around is that grain start position now what if instead of just playing the same point each time always 100 milliseconds what if we just sort of nudged it around a little bit so to do that what I'm going to do is I'm going to specify a - two locations I'm going to specify a possible start point and a possible end point okay so in the current example this would be starting say at well let's just say let's start at a hundred milliseconds in and let's possibly move it 100 milliseconds on so let's say it could go up to 200 now what I'm gonna do here is I'm gonna sorry is I'm going to create a random number every time we generate a new grain as we did with the stereo positioning and I'm gonna offset it by a start point that basically means every time I'm just gonna add this number so I'll put that here so that's going to go into the right Inlet of this value and then I'll just connect these up so every time I manage ping that number and that number so what we're currently saying is I'm going to generate a random number and I'm going to offset it by at the moment 100 now what is that random number what's the limits there well we don't want to say 200 because then that would actually give us too +100 which would say 300 so what we're gonna do is we're going to subtract start maximum that's going to go into the left inlet from you know so that's gonna go into the right Inlet note that they're switched here because you're saying it's 200 - 100 rather than 100 - 200 that's gonna give us hopefully 100 I'll take that off as that random number now well being well this should start generating random numbers between 100 and 200 now let me just move this up here so let's I'm going to do is I'm going to get rid of this I'm going to connect up I'll start it playing back for us and then I'll connect this up when you can hear the difference so that's a static starting point actually let's just so we're using the same place let's say I will start at 2000 we'll go up to you two so we get some unpredictability coming here we could really you know make this a lot more subtle but we could take this down so there's just a 45 millimeter millisecond margin here that we can just move sounds around and we start to end up with something that has a little bit more kind of development to it it feels like there's more fluctuation there's something interesting happening here it's a little bit unpredictable it's quite nice now you could very easily from this point play around with this this mechanism of instead of defining a low point and a high point you could for instance say okay I'm gonna define a central point and give me a width so you could say all right let's say let's start 2000 milliseconds and play 10 milliseconds above or 10 milliseconds below and generate a random number between those two we could do the same thing for our grain duration so each grain in fact actually that's let's try that let's let's just encapsulate and get rid of this I can just think caps you like this to keep it clean and let's just try this for each of the value so I'm gonna get rid of those okay we'll just keep a great rate in this name so instead I can now play around with my green duration so let's say that could go from 100 to 150 let's see what we end up with here but what have I done wrong wow I haven't triggered it now we just got something that we can play around with a little bit more I mean much shorter we can make it a much wider choice similarly we could do the same thing with our start position so while it might sound a bit more chaotic we've got a real wide margin of possibility here you know these could be samples playing from anywhere within that whole sample remember up here in the top right we've got our total length or it could be playing from a very very short duration to a very long duration and you know we've really got a lot of a lot of scope to play around with here now for the time being this is going to this is going to sort us for a single line kind of grain train so if we can only play a single grain at any one time and that's kind of you know limited really it's effectively like kind of just playing or triggering a series of very short samples where granular synthesis really becomes to begins to kind of come into its own is when we start building layers and we can work with kind of polyphonic layers of these samples so in the next video we're going to look at taking a very basic grain generator that we've made today and making it so that we're able to trigger hundreds if not thousands of these grains that all overlap and form these really kind of luscious clouds of grains and we'll start to play around with other ways of controlling them and kind of making them a little bit more interesting okay see you next time [Music]
Info
Channel: oliver thurley
Views: 11,979
Rating: undefined out of 5
Keywords: granular synthesis, computer music, music technology, Max, Max/MSP, music programming, synths, modular synthesizer, electronic music, studio, presentation, UI, user interface, panel, design, layout, music lesson, grains
Id: g3nAeDWgf9Y
Channel Id: undefined
Length: 45min 44sec (2744 seconds)
Published: Wed Apr 22 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.