 Hi, I'm James C. Davis, and I'm a professional programmer and an amateur songwriter. I'm going to talk to you today about something that I call Ember as Song. So let's start with an idea. There was a brainstorming session for Ember Comp proposals, where Melanie Sumner had thrown out this idea of composing a song alongside building up an Ember app. So building up the song piece by piece and the Ember app and then coinciding. So I really like this idea, but I wasn't really sure how to make it happen. So the idea grew, it just sat with me for a while. Like how best can I compare building an app with composing a song? Can I map the elements of a song to concepts in Ember? I wasn't really sure how to do that and make it work. And then it hit me. I could create an Ember app that is a song. And then this just led to a whole exploration into that. So I've long thought that programming and songwriting were very similar. They're both very creative endeavors. They're both complex and they share many fundamental concepts, like patterns and loops, conditionals, problem solving. It's often when you're creating music, you're trying to figure out how to get things to work together. And bug fixing, sometimes something's wrong and you have to figure out how to make it work. So what's in a song? A song is composed of sections. So you have like an intro and verse and a chorus and bridge. And these may repeat and be intermixed with each other. So what are sections composed of? Well, a section has instruments and the instruments play different parts. And the parts are made up of individual notes. Those notes are organized into measures and they can be strung together to create musical phrases. So like sentences or paragraphs. So when I map these concepts to Ember, so here's some of the mappings that I've done. Sections, I've mapped into routes because those are kind of like locations in the song. Instruments, I've mapped to services, which I'll demonstrate in a little bit. Parts are components because that's what makes it up. That's what makes up the song and that's what makes up the app, is the components. And then notes, I've mapped to contextual components. Specifically a contextual component within the part because it needs context. So a section mapped to a route. So it's a location of the song. It's composed of different instruments playing parts together. The same way a route, we'll have a route template where you have different things working together. It's really like the musical equivalent of a page. So an instrument, I've mapped to service. And this is because instruments are global. You have instruments that you use all throughout the song and they maintain state when moving through sections. They keep playing, so if there was a note that was sounding at the end of a section, it'll continue into the next section. Volume, you can control the volume of the instruments and that's a global control or effects that are applied on the instrument. So part, I've mapped to component because a part is made up of notes for one instrument and it's often a pattern that repeats within a section. And it could also be reused across multiple sections. So you might have a part in one section and use that same part later. The same way you would do a reusable component and number. So notes, I've made contextual components because they belong to a part, they need the context. They need to know which instrument that they go with and they need to know when to play relative to other notes. There's other globals as well, like tempo. Tempo is the speed that the song plays at. There's the master volume, so all the instruments together. There's a volume control that's global. There's also the playing state, such as start, pause, stop, and where we are on the timeline. These could be handled by a single or multiple services depending on how you want to group them together. So how do I take this concept of Ember as song into an actual implementation? So I started with the Web Audio API. The Web Audio API is extremely powerful, but it's a very low level. I wanted to start with something a little higher for making music. So I found tone.js, and tone.js uses the Web Audio API, it's built on top of it, but it provides primitives for making music, not just sounds, which is basically what the Web Audio API gives you. So I want to create a Hello World. So my goal here for Hello World was to create one instrument, a piano, let's say, and just play a single note, middle C. So middle C is the white key right in the middle of the piano keyboard. So I created a service, generated a service called a piano, and I went ahead and added a name, so we'd have something human readable. And so this service, I created a property called Inst for the instrument, and I use something called sample library, which is an extension to tone.js, that lets you play samples, and samples are just recorded instruments, little single note recordings of instruments. And so I load up the piano instrument, piano sample, and I send it to master. And so master is your output, basically, to your speakers. And so I wanted to be able to work with the instrument within the template. So tone.js is made for creating music and JavaScript. And I really wanted to create it in Ember, in Ember templates. And so what I did is I created a component to represent the instrument. And so you can see the component displays the title of the instrument. So you can see what it is, has a container parallel, I'll talk about later. But it yields a contextual component called part and passes through the instrument plus volume and humanized and things I'll talk about later to it. And it yields a part. Okay, so the part component. The part component is responsible for connecting notes to an instrument. It's responsible for scheduling notes to play. And I say scheduling because in tone.js you schedule notes to play at certain times. The timing is not exact enough and JavaScript to say just play this note right now. You actually schedule it to play at a certain time. Music it has to be very exact to sound right. It's also responsible for scheduling draws and draws are like anything where you manipulate the DOM and we'll see that a little bit later and also for looping. So any repeats. So those are all handled by the part component. So the template for the part component looks like this. And so we have the did insert element modifier we call an init part. And it yields a contextual component called note as I said earlier that I map notes to contextual components and it passes something called add note and something called active note to that component. So let's look at this note component. So the template's very simple has a local class. I'm using ever CSS modules here. And it has a conditional class on this dot active something called active and active gives it a background color. And then if we look at the backing class we can see there's a constructor that calls that add note that was passed in. It grabs a bunch of properties off the arguments and then active is a calculated getter. So let's play it. So here's how you would use it. You invoke the instrument component pass it the instrument. So this instrument is a service. We're now in a route template. So we need to create a controller so I create a controller and inject the piano service into the controller. And that's really all the controllers there for is to get the that's piano service into the template. So it yields I the contextual component part which yields P with the contextual component note. And here we say pitch equals C4. So C4 is middle C tone. Yes uses it's a standard way of naming the notes that starts all the way down at C0 goes CDEFG AB and then C1 because the notes repeat those seven notes repeat. So C4 is right in the middle. So let's see what that sounds like. And there you have it. You press middle C and you also saw that it lit up which we'll talk about visualization. So let's do a scale. A scale is a string of notes one after another can be ascending go up get higher or descending and pitch. And it's basically like for the C scale at least hitting all the white keys on the piano. So we can implement a scale like this. So we have our instrument we pass it a piano. And down here in the part I've actually divided things up into measures. The measure component there is really just for visual display. It just divides it up visually here and in the output. So you can see I have pitches studying at C4 and I'm ascending up CDEFG AB and then C5. That's the next octave. Once you wrap back around that's an octave. And here I've specified the time argument. So time in tone JS is defined with measures and beats. So standard time like a standard time signature is four four which is four beats per measure. So you see our four beats it starts at zero. So zero one two three then the second measure zero one two three. So let's see what that scale sounds like. There we go the C scale. Alright so how does this work? So here's our part component we looked at earlier. So you can see that it yields this note component. And then here's the backing class for that note component. So you can see that it's calling add note. That it was passed in and it's passing in basically the arguments. That's supposed to be RX there where it says this. Anyways so the part component. So let's take a look at this. We haven't seen this yet. So it defines an empty array of notes. Defines this action called add note takes a note calculates an ID for the note. So just the next one in the list just uses length for that pushes on to notes adding the ID and then returns the ID. So you can see down the lower left back to the part add note component where add notes called and returned with the ID which gets assigned to that note. Then we have trigger sent and trigger sent takes a time and a note and it calls trigger attack release which an attack and a release attack is basically hitting the key and releases releasing the key for a piano or any instrument on off. And so it just doesn't on and off. In tone.js there is attack and a separate release so that you could actually hold a note for a long time and do that. But we're just going to do one hit here. So what this is actually doing it's not actually playing the note when you call trigger attack release it's scheduling it for a certain time. And next we have a knit part. So the knit part action is what actually ties the notes together with trigger sent. So what it calls instantiates a new part and part capital P here is something from tone.js that the tone.js part. And you pass it a trigger trigger sent which is a callback and you pass it an array of notes and it goes through those array of notes and it calls trigger sent for each of them scheduling them all at the appropriate time. So let's talk about visualization for a minute. So if we look at the template for the note come component you can see we have this active class and we have a getter. This is in the backing class where we compare the active note argument to the ID of of the note and active sets of background color. It's that orangey color you can see when they light up. And so let's see how this actually works. So in part component you can see we set active note to negative one. There will never be a note with ID of negative one because it starts at zero. And trigger sent we've added a little bit more here. So you see this draw that schedule. So draw that schedule is something that tone.js gives us to be able to manipulate the DOM at a certain time in sync with the music. This is a little bit tricky because the DOM takes a little bit of time to update. So it actually factors that in to try to get it to line up real nicely. So what's happening here is we're actually saying at the time the same time that we've scheduled the note to play. We are setting the active note to the ID of the note that we scheduled to play at that time. So that will light it up. That will set the active note. It'll match the appropriate note component. Set that class to active and it'll light up orange. But then we wanted to turn off only release. And so the next draw that schedule right here is setting it back to negative one. And what we have to do here is we have to set the time in the future when we know that it's going to be released. So we have the duration and duration up there as you can see is four in four in is how you specify a quarter note and tone.js. So that's one quarter of a measure and four four. So time here has to be in seconds. So tone.js provides this time capital T here where you can pass a duration and convert it to seconds and then just add it to the time. So it knows when to turn off. Okay, so what if we want to do multiple instruments at the same time? So two instruments. So over on the left we have that's our piano scale we had before. And over on the right we've created something new, a violin. So these would actually be in the same template. It actually doesn't matter what order they go in as far as when things will play, but they will visually the one that is above the other will be above the other on the page. So the violin is another service very similar to the piano service. We inject it into the controller and use it here. Here we're using half notes. You can see a specified duration on the note instead of the default quarter note. So we have just two of them in a measure and then a little riff there. So let's see what that sounds like. And there you go piano and violin playing together. Okay, what about multiple parts? So you might have multiple parts for an instrument if you wanted some to repeat or you just wanted to break them up into different phrases. So here's where you can use start. So start schedules that part to happen that whole part a whole set of notes to happen at a certain time and that's specified in measures. So here we have the first part. We have flute. So another sample instrument service injected the controller. And we've started the first one at zero. And then we have two measures and then we started the next one at two. So that'll be the third and the fourth measure. So it'll play the first part and then the second part. Let's see what that sounds like in second part. All right, let's talk about loops. So a loop is just a repeat. It said parts are responsible for loops. So to specify a loop, you pass the loop argument and you specify a number of how many times to loop. But you also need to specify loop end. So that's actually how long to go before you loop. There's also a loop start if you don't want to loop all the way back to the beginning. But here we're just going to loop back to the beginning. We've defined two measures and we've said we want to loop after two measures. So just repeat the whole thing. So let's see what that sounds like. So you just played through it twice. All right, let's create a drum kit. So drums are pretty interesting because they're an instrument that's actually composed of multiple sub instruments. So what I've done here is I've created a drum service. And these are actually all just one thing. I've just broken it apart for display here. So I give it a name drum kit. And then instead of creating an end, I create a kick. So the kick drum is the big one down on the floor, the bass drum. Give it a name. I give it a default pitch. And what default pitch lets me do is define if I don't give it a pitch, just use this pitch. And it's a drum drums are tuned that they do have pitch. But here we've just given it a C1, a very low because it's a bass drum. C note. And for the end, we've created a membrane scent than this. This scent comes from tone JS and what a scent is as opposed to a sample. So while samples are recordings of instruments, a scent is actually completely generated by the computer. And you give it all these various parameters that could do a whole talk on oscillators and envelopes and how that works and different waveforms and combining them together. But basically it's computer generated music here. And then we send that to master. That's our output snare snare is actually pretty hard to synthesize. Well, so I'm actually using a sample here again with the default pitch and then the hi hat. And this one's a little more complicated because it uses this pan vol to get some effect. But this kind of demonstrates how you can chain things with tone JS together. You can create this pan vol effect, send that to master. And then you actually connect your hi hat sense to that. So you chain things together, chain instruments to effects to a master output. And it's a metal scent, which is just a different kind of sense. So how you use this is invoke instrument, pass it drums. But in the part, you specify the sub instrument that'll actually pull off that sub instrument off of the instrument. Because again, the instrument is passed to the contextual part component. And so we do that here. And then we have the snare part. The snare was a little bit loud. So I pass volume to it to turn it down a little bit. And then I've specified half notes here to let the snare ring a little while it sounds better. And finally down at the bottom, we have the hi hat and the hi hat was very loud. So I turned it down a good bit. I'm also passing this thing called human eyes. And what human eyes is in tone JS as it introduces a little bit of random variance instead of hitting right exactly on the beat. And that's because humans don't always hit exactly right on the beat. And it turns out computer generating music can feel sort of sterile sometimes because it's so precise. And so this is changing that up just a little bit. Now I've scheduled the snare to start at one and the hi hat to start at two. Because for this demonstration, I just want them to play one after the other kick drum. Okay, we have a drum kit. So let's loop it. So drum loops so often in a song you have a riff, like a drum riff that pattern that plays over and over again in a loop. So the way you do that is you can actually pass the loop argument to the instrument and it'll pass that down to all the parts. And then we're going to schedule these to all play simultaneously. So the default start is zero. So I haven't specified that here. But what I've done is I've specified some notes to play at various different times. So the kick is going to be on the first beat. The snare is going to be on the third beat and the hi hats on every beat. And this is actually a very standard rock beat. Let's see what that sounds like very standard beat. Cool. All right, let's put it all together. So I've actually composed a song with Ember, which I'm going to demonstrate in a minute. So I've created routes and controllers for these different sections, the intro, the verse and the chorus. And I've set it up to actually auto advance among the sections. So I'll actually do intro, a verse, a chorus, and then a final verse. The routes handle all the timing and advancing. So there's some timing about where to get these sections to play in relation to each other. It's all handled by the routes and then the advancing, which is just transitioning transition to the controllers are really there just to inject the instruments, the services to get them into the templates. And so I set this up with a parent route for the drums because I want those drums to loop all the way through the whole song and not have to redefine them for every section. And then we have child routes for each of these sections. So let's have a listen. So future plans. I want to write more songs. This was actually a lot of fun. Once I got things set up and going, it was fun to build that too. It was really fun to work with. I really want to turn this into an add-on and put it on the community. I think it would be great for other people to be able to play with this. I want to continue to add features. There's a lot more we could do and a lot more stuff I could get into the template and make it usable. And I want to try collaboratively writing songs using GitHub. I think that would be pretty cool. It's probably been done before, I'm sure. But I think this would be any way to do it. So I want to thank you all for listening to my talk. I'm going to put all of this up at jamesedavis.github.io. And if you want to follow me, I will tweet out when I release this as an add-on and do more work on it. It's jamesedavis on Twitter, without the E. And everywhere else, Discord and GitHub, it's jamesedavis. So thank you very much.