Juce Tutorial 50- Creating a Metronome Pt 1 (Concept of Playing and Stopping)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up everybody I'd like to welcome you into another juice tutorial and in this tutorial what we're going to do is we're going to build a metronome from scratch so there's a question of okay if I have a blank project how can we start developing a concept of time and tempo and beats per minute and playing and stopping States how can we develop these from scratch and I'm gonna show you how to do this so this is going to be part one of maybe a two or three part series so before we get started just got a couple announcements first thing is as always we have the patreon set up so if you'd like to support the channel it's much appreciated because it gives me a lot of motivation to do more videos like these and we have a number of different rewards for different contributions so we have t-shirts we have hoodies we also have time like consulting time if you want to talk about code or if you want to talk about your career you can also contribute and I'm available to set up a meeting for that so you can find that on the patreon on patreon.com slash the audio programmer another thing is that I'm very excited that we're going to be offering some premium courses so these are going to be courses that are going to be a little bit more in-depth than the ones that I've been doing here on the YouTube channel and we're also going to expand that out so that there are going to be other contributors that are going to be giving lessons and and packages that are going to be a little bit more interactive so you're going to be able to speak to tutors and get kind of real-time help on the lessons that you're doing and they'll also be a little bit more in depth on various subjects such as C++ juice web audio Maximus piece on and so forth so to find out more about that you can sign up on the audio programmer so the audio programmer comm slash sign up so let's go ahead and get started so what I'm gonna do is I'm going to create this from a blank audio application and I'm just gonna call this metronome and I'm going to create this here so first thing that we're gonna do is we're going to create a new class so to do this I need another cpp and header file so if we just click on this plus button here and what I'm gonna do is I'm gonna do add a new sepia new CPP and header file so make sure it's not add a new component class because we it's not gonna be a component it's just going to be a metronome itself so what we're gonna do is we're just gonna call this metronome with a capital M because that's convention and then we're just gonna save it I'm just gonna take these I'm gonna move these into my main source folder and as you can see it's just a blank it's just a blank header file here and CPP file and we're going to go ahead and open that up in our Xcode so here we are in our Xcode by the way if you find this video helpful be sure to LIKE and subscribe if you're not already liking and subscribing to it so here we are in our blank header file here and what I'm gonna do is I'm just gonna go to the main component and I'm just going to get this include here this include hash tag that gives us all of our juice all of our juice methods and functionality here and we're just going to put that here in our class okay so we're going to go through this step-by-step this first video is just going to get the very basics kind of set up and then the second and third video will be going into a little bit more detail so first thing we're going to do is we're just gonna create a class so we could just do that called class metronome with a capital M and then what I do is I just give it some brackets there make sure you put the semicolon at the end now we're gonna have certain methods that we're gonna want to access from other header files that are other CPP files when we created when we created metronome object so we're gonna have public access we're gonna have certain things that are gonna have private access so things that we just want to keep to ourselves in this class that we don't need the our main component to be able to see okay so let's see so let's go ahead and so we've done that so now the first thing that we're gonna do for me is we're gonna jump over to our main component here and we're going to just stop and we're just gonna have a little think about the concept of what we're gonna do here so the main thing that I'm that I'm thinking in my head so there are there a number of different ways that we can probably do this but the the way that I'm gonna do it is that I want to have so so we're going to have a concept of time so that so when something starts it's going to start counting and then when it stops it's going to stop so so I'm thinking that we need to have two different states two different application states so we need to have a play state where the song or the timer or the metronome is doing its thing and then we're going to have it where it stops and then it stops counting okay so to do this they're like I said there are a number of different ways that we could probably do this I'm just gonna change my formatting really quick to four spaces there we go and so the way I'm going to do this I'm going to do this using a enum class I'm just gonna call this play state and then I'm going to we're going to have to application states with so one will be playing and one will be stopped so the first one will be playing like this and then we just put a comma and then we have another application state called stopped okay and now what we could do is we can go in here erase this boilerplate code and then what we what we want to do now is we want to start we want to have a button right that'll probably when we when we click it it's going to play and when we click stop is going when we click the stop button it's going to stop so we need two buttons so we'll just call this text button and then play I'll call this play button and we can put an argument in here of what we want the text to say so we could say play and then you can do another one here we can call the stop button and I'm just gonna put that as stop now we can jump over to our CPP here and I'm just going to get rid of all this business here so actually I'll keep that there I'm going to change this size of this here - let's just say 200 200 because we just want something that's small and here we go I'm just gonna erase some of this other boilerplate here and then I'm going to erase this here and here we gonna go down here and we're actually just going to actually we're gonna go back up here and I'm going to start creating the buttons here so let me just go ahead and open up the Jews API so here we go so text button and here we are sorting the text button class this is a class we've used in a number of tutorials before so check some of the past tutorials if you don't if you're not familiar with it okay so I'm gonna fly a little bit through this because this is something that we've done so many times before okay so so first thing that we're gonna do is we're going to say text button dots so let's see here so we got so we got set toggle state so we can do set toggle state or this called play button play button set toggle state so we don't want it to be playing when the application starts so we want it to just be off when it starts so I'm gonna put this to false the notification type we don't need to send any sort of notification so it's going to be a notification type don't send a notification and then I'm gonna add and make visible and then I'm going to do play button so this is making this a child component of the main component I'm also going to do this this method here where it is let's see where are we so if we go down to button public public metric member functions mmm I can't seem to find it maybe it's in component it's called set radio ID yeah so rate set radio group ID so this just means that what we could do is we could set it where when one button is on the other button is off and vice versa okay so that's what we want to have happen here so we got play button set radio group ID I'm just gonna put this in Group one okay and then I'm gonna start doing this for the stop button as well set radio group ID this is gonna be group one play button that set toggle state and then this will be true because this is gonna be on when the other one is off and vice versa right and then notification type doesn't send notification okay and now we could do this we could do a lambda function here which allows us when we when we click the button we want it to do something right so we say play button dot on click equals and now we have this lambda and we will say we'll leave this blank for the moment and then we're going to go to our header file here and now I'm going to create a function and I'm just going to call it play let's just call it play right void play now what I'm gonna do is I'm just gonna put this in here play make sure you put a semicolon in there so this is just a very kind of small function so it's just saying when I kill it the button that I want it that I want the action to happen to this component and that I wanted to execute the play function and what is the play function well we haven't written it yet but we're going to write it right now so we've got void main component play and now here is where we go back to our our play state right so we have these two play States and one is playing and one is stopped and I can just say we could just say play place they oh we need to go back actually so what we need to do is we need to create an object of this of this class okay so I could say play state place date okay so that's just an object of this enum class here okay and now I'm going to go down here and I'm just going to say play state equals and then capital play state playing okay so so I hope that I hope that I didn't do that too quickly there so I'm just gonna go through and explain this very quickly again so I so I have two buttons called play and stop and that obviously when I click one I want it to execute a function called play so we need to so we have this enum class that's called play state so we're gonna want to have certain things happen when the application is in a plain state right so the first thing that we want to happen is that if we hit the play button that we change the play state to playing okay and that actually that actually gives me a reminder what I need to do is I need to give this this place state a default value okay which we're going to say play state stopped so we're starting so so we're starting the application in this state called stopped right and this is just like this is just kind of an abstract concept that I've just made up right so we're just saying hey we have we have certain things that we want to happen when things are playing and certain things that are happening when when things are stopped and that this an enum class just allows me to define what those things actually are and say okay when it's plain I want these things to happen I want the metronome to be going I want the song to be playing and when stopped then I want everything to be stopped I want things to reset go back to some type of initial state so on and so forth and that's what play state stopped is about okay so so now so we're going to start this very simply and we have a function called play where we change the place state the playing and now we're gonna do a function called stop okay and then here we're going to define what that means like I say play state equals play state stopped okay and now we can go back up here to our constructor and we can just define this you can just define these things so we could set up our stop button on click equals then once again when an action that executes to when we click on this on the actual stop button and we want it to stop right make sure your pet semicolon there because this is just like it's like a little function right there okay and we want to add and make it visible and we've got a stop button and there we are okay so let me see what else so we got to make these buttons visible now so what I'm gonna do is I'm gonna go down here to resized I'm gonna set up a flexbox I'm gonna call this flexbox now I'm gonna add the play and the stop button items to the Flex box okay so I have tutorials on this if you're not sure what I'm doing here so we got flex box items add and then we've got flex item and then we could just say here we got so our our size the size of our of our actual component is 200 200 so we could say that this is going to be 100 100 and then this will be our play button okay so that because that's our component there and then we got flexbox items add flex item and then we're gonna set the bounds to 100 100 it's gonna be stop button so the main reason that I'm flying through all these without actually explaining them all is because I've done these in past tutorials so I don't want to kind of go over old ground so to speak so if you're not sure what's happening with with this flex box be sure to check out the flex box tutorial and then we could do flex so we need to set a variable called bounds so we can use that using a rectangle class of type int this called bounds and then what we're doing is we're getting the actual area of our of the component that were in which is the main component which is 200 200 so now I'm gonna do flexbox perform layout and we can see that the argument that we need there is the is the rect is is a rectangle integer object okay so then I can just say bounds here and now I'm just going to execute this and actually before up before I do that what I'm gonna do is I'm gonna I'm gonna go here to my audio block and we'll do we'll do something here real quick just to show how this application now has a place to eat and a stop state so what I can do is I can just say now normally you aren't supposed to console anything out in the audio block because if you had audio going then it could lock it could block the audio if the the audio callback causing the the audio to actually stop or stutter or do something that you don't want it to do but since we don't actually have any audio actually happening at the moment this is okay just for demonstrations demonstrations sake okay so I'm just gonna put an if placed 8 equals play state playing and what I could do is I could use this DB G which is like kind of like a see out console out and then I'll just what I'll do is I'll just put playing printout playing to the console and then else and then I could put DB g and stopped okay so now we're going to try this out this shouldn't take too long to actually compile for us hopefully and so this is just going to demonstrate what happens how we're going to switch between these two application states okay okay here we are we're linking and here we go so waiting for the application to pop up here so here we are so we have this this little app here that has two buttons has a play button and a stop button we can see that the that it's constantly out stopped and now I could hit play and now we see that it says playing and now I hit stopped and it stopped okay so that's how that UNAM class kind of connects into the play and stop function and gives us this concept of something playing and something stopping okay so that's good there so that's fine great so now what we're going to do is we're going to jump over to the metronome side and so now once again we're just going to take a take a moment and just really think about this concept of audio and what it means for something to be playing so we have so so when when we have an audio callback what's happening is that it's playing at a sample rate so we should know by now about a sample rate and what it is and as how many samples that were playing of of audio a second so normally that would either be 44100 or 48,000 48,000 samples per second so now when we think about it what we could do is we could actually measure that because what we could do is we could actually say okay well if I look at the audio callback and I know that my buffer size is let's say 512 I know that when that 512 gets up to 44,000 1/100 values that one second of audio has passed if I'm if I'm operating at a sample rate of 44100 all right so that's pretty valuable because what we could do is we could actually go into the audio callback and we could look at the at the at the at the buffer size and we can use that to calculate how much time has actually elapsed so that's what we're going to do so the first thing that we're gonna do is we're going to look at this concept of time so the first thing that I'm going to do is I'm going to actually implement a timer because what we're going to need to do is update we're going to need to update how much how many more values we need until we're at our next measure or at our next beat okay actually you know I'm not gonna worry about that for now I'm just going to do one simple function and we can call this let's say void count samples okay and this is just going to be something that counts how many samples we've had since things have since we started the song okay so if we go back to our main component and we go into our audio call back so we could we have this this object called audio source channel info and this is where we could get our buffer information so what we could do is I could say auto auto buffer equals buffer to fill dot num samples okay so that gives us what our buffer size is how many how many samples that we have in our buffer so it would probably be something like 512 samples something like that okay so if I go in here so if I if I click num samples and I go to jump the definition I can see that this is of type int the number of samples okay so what I could do is I can now go back to my metronome and here in count samples I want to count how many samples have elapsed so what I could say is int num samples right or int will just call it int buffer size okay and now I'll do a function like this and I'll go void metronome that's the class that we're in now and it's counts samples and it's int buffer size and now what we need is we need something that captures this number when it comes in so what I could do is I could just create a private a private variable here we can say int let's just say samples elapsed or actually let's call it turtle samples and what I'm going to do is I'm just going to initialize that to zero and then what I could say is now I'm going to do turtle samples plus equals buffer size okay and what that's going to do is that's going to take and put our add our buffers at our buffer size as as the buffer values are coming in so each time it does each time the audio does a call back it's going to add another 512 512 samples or however many samples there are and our buffer size to the number of total number of samples okay so then what we could do is we could console out turtle samples just to see what happens there okay now what we could do is I can go back here and I can get rid of this stuff because we do not want any sort of counseling out happening in our audio callback and I can say if play state YZ equals playing then what we need to do is we first need to create a metronome object okay so we have this class called metronome so now we need to get this into our main component so what I could do is I could go up here to our main component header file I could do include metronome dot H and now what I need to do is I need to create a metronome object so I could say metronome metronome with a lowercase M and then what I could do is I could go back to the main component here and I could say metronome dot count is it gonna complete for me I'll just complete it so I'm just do count samples and what do we need in here we need our buffer in here ok so just gonna walk you through that again ok so we've created a public function called count samples and then what I've done is I'm just adding I'm just adding the the total sample the the the buffer size to a variable a private variable called total samples and then I'm just consoling out how many samples there are okay so let's go ahead and see if that works okay so if so then I've implemented that here this count samples function and it's gonna build take a second to build here we go so if this is working properly when we hit the play button we should see we should see a number going up here in the console and we can see that that that's happening right so now if I hit stop we can see that it stops right and then I play and then it starts again but we can see that it doesn't reset when we when we stop okay so but we can we can just fix that really quickly right so hit play and that makes sense right because when we're when we're playing we want we want our song to be playing we want to be filling it we want to be filling the buffer with samples we want to be processing audio doing our thing and when it stopped we don't want it to be doing anything right so that's so that's what's happening there so now we can just start adding some little helper functions here so let's do like a void reset and then I will just implement this here so we'll do this void metronome already set and then what do we want to happen here so at the moment what's happening is that we have the we have the samples they're counting and when we hit stop it stops but it doesn't reset to zero so we want it to reset to zero right so what I could do is I could just say turtle samples equals zero and that should do this so so if we do else if actually yeah yeah we need to do it we just need to do an else not an if sometimes I feel like it's if I do else if it it makes it more clear what's actually happening but I was talking with some people that were a lot more experienced in C++ and just developing than me and they they were saying that to be kind of brief and as concise as possible just make it else and so we could say play state equals stopped or placed eighth stopped and then what we could do is we could actually so okay so I'm just thinking I'm just thinking here equality comparison unused oops I just want this so I'm just thinking whether to put the timer the met the reset here or whether to put it in the stop I think I think that I'm going to just put it here in the stop in the stop method here so I will do metronome dot reset okay and actually when I'm what I'm thinking as well is that I am going to get rid of this here so I don't need that there so the only time the only thing that we need to happen is if it's in a playing state that we're counting the samples and then when we hit stop the metronome should reset okay so we're just gonna try that now so here we are and now we're gonna hit play samples are playing I had stopped now hit play again and we can see that it starts from zero so we're at 40 49 60 now and now and now if I start again it just starts from zero again so that's that's what we're gonna do for now you know we might want to have a separate reset button that just resets it back to zero maybe we want an application where we have a play button a stop on a reset button that all have those different functions where the where if it if we hit stop and then we hit play again it plays from wherever we were at but if we hit stop and we hit reset then it goes back to zero but we don't have to worry about now so I think that that's a good place to end this that's that's a good place to end it now what I'll do is I'll do one more function here let's do a prepare to play function and what this will enable us to do is find out what sample rate that were that we're playing at because we need to know whether we're at 44100 values a second or 48,000 values a second or 96,000 values a second and so what we need to do is we need to have some place where we're able to to take that in for later processing because we're gonna need to do some calculations to find out our beats per minute so I'm going to do another mathematical void prepare to play and here so once again we'll go back to our main component I will look at what the sample rate expects it expects a number of type double so in here I'm going to put type double it's a double sample rate and then I could go into the CPP here I could be void metronome prepare to play and then double sample rate and then we're going to probably need to pass the sample rate around two different functions to do our calculations so I can make a private variable called double m sample rate so I'm going to do this and then I'm going to change total samples to M because that's just a member global variable M total samples in M sample rate so I could do M total samples and total samples and then I could do M sample rate so that's our global sample rate is equal to whatever number comes in there that we call sample rate and then here I can put total samples then I could go back into the main component I could go in to prepare to play and I could do metronome dot prepare to play and we have a double sample rate and I could just put my double sample rate here okay so this is just kind of the first kind of getting everything set up just getting kind of two application States playing state a stopping state and actually getting the the actual values from the audio callback coming in so there we are so we have a play state stop state and now we're counting samples so that's where I'm going to end this tutorial and then in the next tutorial we're actually going to start calculating beats per minute and start looking at bars and beats and how to calculate those so I hope you enjoy this tutorial and I will see you next time
Info
Channel: The Audio Programmer
Views: 3,131
Rating: undefined out of 5
Keywords: juce, juce framework, c++, audio, tutorial, audio programming, creative programming, creative coding, dsp, digital signal processing, vst, create vst, create plugin, audio plugin, oscillator, synthesizer, maximilian, openframeworks, software development, beginner, easy, max msp, metronome, transport
Id: z3XDvYmTarE
Channel Id: undefined
Length: 37min 45sec (2265 seconds)
Published: Sat Apr 13 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.