JUCE 6 Tutorial 10 - State Variable Filter and the DSP Module

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up everybody i'd like to welcome you to another juice tutorial and in this tutorial we're going to use the juice dsp module to build a state variable filter and this is a great way if you're just getting started with audio programming and just getting started with juice to actually get something up running up and running fairly quickly without a whole lot of work so we're going to go through that today and this will be a multi-part series so in this first one we'll just show you the very basic implementation of the filter so before we get started i'd like to remind you about our audio programmer community so it's a place where audio programmers from around the world gather and network and get to ask and answer audio programming questions so we help each other out we're from all different backgrounds all different skill levels and we welcome you to join and it's free and you can join via the audio programmer dot com forward slash community also we have the patreon for people that would like to see more tutorials like these and the various events that we do and you can actually contribute to our patreon for various of rewards on patreon.com forward slash the audio programmer so we will go ahead and get started and by the way both of those links are below in the description so we'll go ahead and get started we've created a juice project so this is just a plug-in project where we have our regular source files here and what we want to do first is we want to add the dsp module to the list of modules that we're going to be using and so to do this we just go to the plus and then add a module the global juice modules path and then juice dsp and now we can see the juice dsp module is in our list of modules and now we will go ahead and save and open this up in xcode and by the way i have a presentation that i did not long ago on the basics of the juice dsp module so i won't be going through all of that again uh i would just rather direct you to that video where it shows you the basic concepts of the juice dsp module um but you'll see that we will implement many of those concepts today so now we're in our header file and what we can do is we can actually create a filter object first so what we'll need to do is we will need to create an object of this long thing here okay and now we'll show you how to do that now so since this is a juice object first thing that we do is we pre-seed juice objects with the juice namespace and it's in the dsp namespace in our dsp module so it's juice dsp and then we just declare the object type here which is state variable tpp filter and then we have this angle brackets where we put the type the sample type that we want so this would be like if you wanted to process and float or in uh double uh double um the double values and so we'll just do float for this time around and so we want state variable tpt filter and now we have to put the type that we want let's type float i'll just call this filter and there we are and now what i'm going to do is i'm just going to build this make sure that i've declared the object correctly and we can see that we have so build succeeded there so far so good now we'll just take a look at some of the other methods that we have in our state variable filter class and just taking a look at the description very quickly we see that we can do low band and high pass filtering and that this is based on vadim z i won't say his lap try to try to say his last name but vadim is actually a dsp engineer quite well known engineer in the industry that works for native instruments and he has written a book on uh modern analog analog modeling practices for filters and it's pretty math heavy but it's a pioneering book for uh for filter design and so this is based on some of his some of his work so let's go ahead and go down to some of the methods that we have here so we have a set type method where we can set the type of filterings that this filter is so we have type i'll just open this up in another tab and we will see that we have an enum here where we can select between low pass band pass and high pass filters and i'll show you how to implement that in a bit we also set the cutoff frequency set the resonance so pretty typical methods that we would see for a filter and then we have the typical methods that we would see in any juice dsp or for that matter any sort of dsp method or algorithm so normally you'd have like a prepare method where you have to pass in the sample rate the buffer size the number of channels that you want to process you would normally have a reset method that so you know that these filters are going to have some complex mathematics inside of them and the reset method just takes all of those all those different variables within the filter and just resets them back to their initial state then we're going to have a process method so we can process two different ways we can either process using what's called a process context which i will show you how to do in this tutorial or if you wanted to do a sample by sample processing process you can do that as well using the method process sample where you give it a sample from the audio buffer and it's able to process it so uh so yeah so that's how that's how it works so let's go ahead and start getting some of the setup done first thing that we'll need is the reset method so the juice audio processor already has a reset method that we can override so we're just going to do that now so we'll create a method called reset since it's a method that is declared in our juice audio processor class and we're inheriting from the audio processor class right here then what we want to do is we want to mark that with the override keyword or else it will give us a warning so then we will just implement this down in our pluginprocessor.cpp and so this is void we need the class type here and then it's reset and that's crossed out because that's a private we've we've put it in our private methods so that's the reason that you see it crossed out but since we're in the same class we can actually use this use this method and in here we just want to say filter which is our filter object that we created just a few minutes ago and reset and there we go so now we can implement this in our prepare to play function so prepare to play is a great place where we can implement this this is going to be called uh whenever the audio is going to begin to or get ready to start playing into the plugin and we want to make sure that our our filter is ready to take in those value values and that it doesn't have any sort of junk values left from the last time that it was playing audio so we'll call reset in there while we're in the prepare to play method we also have this uh the prepare method that we need to implement and we can see that it takes this process spec object so if you're not sure about what process spec is you may want to take a look at the juice module juice dsp module presentation that i did i'll put that in the description below and the process spec is essentially an object that allows us to hold the sample rate of our plug-in the buffer size and the number of channels so this is information that your dsp algorithm will need in order to properly process your dsp so what we could do is we could just create a ds a process spec object here in prepare to play so this would be juice bsp process spec and i'll just call this spec and now what we could do is we just want to declare all of these things so we got our sample rate maximum block size and number of channels so we got spec dot maximum block size will equal our samples per block so this is a way that when our ma when when our plug-in is getting ready to start playing it just passes all this information back into your dsp algorithm okay because it needs to know this information spec sample rate equals sample rate spec num channels equals uh get total num output channels which should be two because we're going to be working in a stereo setting here and then what we could say is filter dot prepare we just pass in that spec object that we've created and we are good to go so next thing you know next thing we need to do is we need to go back to our state variable class and look at what else we need to do so we have the set type so the type of filter that we want to set so we will implement a ui a little bit later before this but uh what we'll do is we will start preparing the filter or plug-in for uh when we actually implement a ui so what what i'll do so the way i'm thinking to do this is that we could maybe make an enum class and we will just call this filter type and then i will just say that we'll have three different types of filters we'll have a low pass band pass high pass so these are essentially like like ins almost where you can just select between these three different types and now we just need to actually put what those actual types mean and actually create our functionality there so what i will do now is i'll create a filter type object so i will say filter type filter type and then i will initialize it with filter type and we'll initialize it with low pass argument there okay and then let's create a let's create a method where we can actually select the filter type that we want so we can say void set set type and then what we will do is we will go into our cpp and we'll say void then we need our class name and then set set type and then let's see so we have this uh the state variable filter class we have this method set type so we're going to need to now associate our enum with setting the type of our filter to lowpass pass and high pass so that's what we'll do here we can do this using i'm thinking the best way to do it is using a switch a switch statement here so let's go ahead and implement this so we can say switch and what we want in here is we want our our filter type right so so we will just put that in as what our expression is and now we want to say okay if the filter type is this then we want this we want the filter to set the type to low pass and so on and so forth so so first one is filter type make sure you use capital f there and we could say filter type low pass so if our filter type is low pass then we want filter set type and now we just need to put our type in there so what we want to do is we need to declare this type of object here dsp state variable tpt filter type and then lowpass okay so it's like a knee numb inside of an enum so we got juice dsp sorry i forgot the name state variable tpt filter type state variable there we go state variable tpt filter type and then low pass okay so that's that's a bit of a handful there right so that feels quite long to type out all the time so maybe what i'll do is i will pull this out and let's just make for readability let's just say using uh f type is equal to all of this uh all this stuff here and then what i could do is i can go in here i could say f type like that that makes it a little bit more readable so we don't have to continue to type all of this every single time so now we just need to make cases for all of our other types so i'll just copy this twice and then we just need to change this to bandpass and high pass and then in here same thing band pass i pass and then we'll make a default or we will just set it back to low pass oh wrong place so this is in anticipation that at some point in the future we'll have a ui where we have a set of buttons and we'll be able to click into one of those buttons and that will change what the filter type is okay so that's uh that's where we just set the type so we're all good there i can close that out and close spec out and now what we'll do is we will just do a real kind of hack hello world of of filter uh setting setting this filter to actually do something so i can just get rid of all this commenting here we can actually get rid of all this stuff and so what i'm going to do is i'm going to show you how to use the audio block class to actually do this okay so uh so let's see so let's duplicate this so i stay on the same site and then we will go to audio block so here we go and now we're in our audio block class so audio block is so as you remember going back to the state variable filter process method here we have this thing called a process context that we need to pass in okay so this is a little bit this is a little bit confusing and i think i don't know if uh if this is the easiest way to to go about doing this but uh but this is the way to actually make this work so first thing is you have this dsp audio block class which is a way of passing in uh our our audio buffer into this filter algorithm and normally when you're so there's a video that i did in the past about one of the one of the biggest mistakes that people make in dsp processing which is that normally when you're creating a dsp process from scratch you normally have to create a dsp process for each channel of audio that you're processing so if you were doing a filter in this situation you were creating a filter from scratch you would need to have a filter on for your left channel and a filter for your right hand channel so the dsp class and the audio block and the way that this is processing is actually is actually an effort from juice to actually eliminate all of that complexity and just say okay you can just pass in this audio block and it will tell and it will actually do all of this kind of internally for you so they've abstracted that out okay and uh there's just a little bit of setup to actually do this so we have this audioblock object and we see that so this can be a little bit difficult to read but i will walk you through it so what we can do is we can create an audio block from an audio buffer so we can see that the documentation here actually says creates an audio block that points to the data in an audio buffer so an audio block is not a whole separate uh set of memory that is holding all of your audio data the audio block just simply points to the audio buffer okay so that's uh so what we could say is we could say audi auto we'll do an auto and audio block equals and we'll oh we need to do all of our name spacing again juice dsp audio block and once again we need to set a sample type sample type will be float and then like we saw in the documentation what i need to do is i need to just pass it in this audio buffer uh i just need to pass in our audio buffer from process block and so now we've created an audio block so audio block is essentially an alias for your audio buffer okay so it's just an so it is your audio buffer essentially uh then what we need is we have this we have this method or this object that is called process process context not replacing or process context non-replacing so we want process context replacing so what does this actually mean process context replacing means that when you have audio that's actually coming in uh from the outside in your daw it's coming into the plug-in that what happens is process context replacing means that i'm going to take a piece of audio i'm going to perform this dsp algorithm on it and then i'm going to replace what was previously there with the with the new audio okay with the processed audio after the filter i should have pulled out my ipad to to actually write this down but i think you get the idea if you've seen my last tutorial on the audio buffers okay so we're actually writing new information into the audio buffer so what i can say is i can declare an object that's going to be called i'll call it context and then equals juice dsp process context replacing because we want to replace the audio that's coming in with the audio with the processed data that will be run through our dsp algorithm once again we need to give it a type and we will do float and i think that we just need to pass in our audio block object so let me just make sure that i have that right so there are a couple different ways that we can that we can do this and let's see so we have our audio buffer and we have our audio block so oh i'm looking at the wrong thing that's that could be a problem so we want process context replacing and we want our audio block type okay so that's that's what we created here our audio block okay let me make sure that i have everything that i need here and that should be fine okay then from there we can go back to our process method and we can actually just uh put our context into this process method okay so let's just do that and we can say filter dot process and then we give it the context method and that's that's how you do it like that okay now let's let's set our filter to actually do something so we will set our sample type so we have this set cutoff frequency and we can set our frequency that we want so we have a set as a default to low pass so what i could do is i could say filter dot set cutoff frequency and then i will give it a new frequency so let's do something where we can hear that it's actually filtering and i would just put it at 150 hertz right so that is how we will do that and so that's fine and i think we will be ready to go so now we just need to actually build this in a doll i didn't do a new tutorial that actually shows you how to hook this up to a doll but i will in the very near future so oh i forgot to put a semicolon after the enum here so there we go and what i'll do is i'll show you that very quickly so if you go to what's called your build targets so that's this little space here at the very top here where you see the actual type of uh the type of thing that you're building what i can do is i can go into edit scheme i'll click in there and then what i can do is i can set an executable for my daw to actually launch when i want to when i actually build this plugin so i've just clicked in other and then i go to i'm just going to go to ableton so i got macintosh hard drive applications and i got ableton and i will choose that and close and so this ableton will actually launch when this is actually done building so we see that we got a build succeeded we're just building for vst3 right now and now we have ableton launching and so able 10 is launching okay now we're back in ableton and what we could do is we could look into our plugin look for our plugin the default is your company and then our plugin is called basic sbf we'll just put this on our audio channel 3 and we see that we don't even have a ui for it yet so all we'll hear when this plug-in turns on is just the actual filtering that'll be happening at 150 hertz so should sound low pass filtered when we actually do this so i will put a sample in here so we will go with this little loop just turn this down slightly and i will turn it off here so you can hear the unfiltered so we hear that that filter actually works our plugin is actually working and we've built a filter so this is a good place for us to stop this tutorial i just wanted to show you how to do that very basic implementation and actually get all of this running so in the next tutorial what we'll do is we will actually set up an audio process or value tree state and actually connect this up with the filter and actually get a ui going where we can select the filter type set the filter frequency and the resonance so i hope you enjoyed this tutorial and if you found this helpful please give it a thumbs up and subscribe and i'll see you next time
Info
Channel: The Audio Programmer
Views: 1,987
Rating: undefined out of 5
Keywords: Juce Framework, framework, juce audio, creative programming, audio coding, vst development, vst, software development, c++, audio programming, juce, plugin development, svf, state variable filter, filter, low pass filter, high pass filter, band pass filter, dsp, digital signal processing
Id: CONdIj-7rHU
Channel Id: undefined
Length: 26min 58sec (1618 seconds)
Published: Thu Oct 29 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.