 Okay, I gotta get set up here, hold on. I actually got here at 7.30, but we were like too early, so we went to go and get food, and it took a while to find some food. We were looking for vegan food, which took some doing. There's vegans. Yes! Actually, we knew Awesome Place, which, where is it, where is it, where is it? Arrangements, aha! Okay, I win. We knew Awesome Place, but they were not open for breakfast. Watch, I win. Yeah! All right, so the first thing I wanna actually say, normally I don't think introductions are a good idea, but because the most important thing is just get to the point and introduce yourself later, but there's a few things I do wanna say to introduce myself or to talk about myself. And the first thing is, if you don't know why I'm wearing this hat, it's just because, I was out there, so I don't know how many of you were here in 2008, but it's an homage to 2008, so. Yay! All right, glad that some of you were. All right. The other thing is that I am not working with Ruby professionally. In fact, I have been for several years, but currently I work doing, like making videos and doing career coaching, and it's this kind of weird experiment, but I really like it because hopefully, it's going to enable me to write only the code that I'm interested in and none of the code that bores the hell out of me. And I don't mean to suggest that any of my employer's code has, you know, at any point, any employer bored the hell out of me, but I think you would be able to figure out that in fact this has happened once or twice, maybe. And this kind of gives an idea of what it feels like sometimes, you know, when they're like, you know, you're our rock star developer, you know, you're our ninja, our Batman, respond to the bat signal. It's like, no, I'd rather just play, you know, Dead Space or something. So the other thing is, you know, as I mentioned, this is a slide, and this is the website, which mentions no slides at all, where do I, there it is, right? Right there, no slides at all. And if you think about the fact that I am showing you slides now and that I said no slides at all, you may come to the conclusion that I am a liar. And in fact, here's a picture of me two years ago saying exactly the same thing. And this was, I had promised slides and delivered slides, it wasn't slides, it was, I thought Archaeopteryx was going to have a different feature set than it ended up having. So please just bear with me, if you were expecting, or even indeed demanding, no slides, I'm gonna make it quick, and so there's gonna be a lot of Q and A, because I do wanna do the whole discussion thing. So I'm gonna be talking about Archaeopteryx, and here's me attempting to give the presentation about Archaeopteryx with no slides, and this is kind of what it was like, right? Which is why I decided to go with slides. The other thing to know is that there's gonna be some math, but because math can get boring, there's lots of symbols and whatnot, there's also gonna be animals, including this scary, evil little turtle. The other thing is if you wanna ask questions, and please want to ask questions, because I'm trying to make this Q and A, and I'm trying to get through the slides fast, the way to do it is go on Twitter, and if your friends ask a good question, or you see somebody ask a good question, whether you know them or not, retweet the question, because if I go and look at Twitter, and it's like 300 retweets of the same question, then I'll be like, oh, that's the question, but there's also the old-fashioned way of yelling, and the old ways are good, right? So please, by all means, yell. Okay, so I don't know how many of you know what Archaeopteryx is, but it is basically a Ruby library for making music, essentially. So one of the major technologies that enables it is MIDI. Now, all you really need to know about MIDI is that it's like JSON or HTTP. It's a protocol which is unbelievably dead, dumb, simple. Basically, this is MIDI, on, off, and which note, right? So if you've got a synthesizer, you can send it MIDI saying play this note or play that note, right? Or if you've got, this is a soft synth that it's a drum machine on your computer, you can send it a note saying play this drum or that drum. And actually, let me just demonstrate that. Hold on one sec, because you'll need to see this. So it's gonna take forever to load, so I'll just show you some more stuff. There's more to MIDI, but, you know, I mean, if you want, you can like say, turn this knob like three degrees, you know, or something roughly equivalent to that in MIDI speak, but that's not so much what we're gonna talk about today. If you wanna work with MIDI, you need a pair of gems. Gem install MIDI Lib, gem install MIDIator. So the history with these is MIDI Lib was created like 2003 or something, it's really old school, and it allows you to work with MIDI files. MIDIator is basically, I created Archaeopteryx and I went around and promoted these conferences and I'm like, everybody, look how great this is. And somebody looked at the code and he was like, eh, I wanna make this better, and he did. So now it runs on this. And this is basically for doing live MIDI, right? If you're, you know, MIDI Lib is for files, MIDIator is for live MIDI. And to get Archaeopteryx, you can go to this URL, H-D-C-P, github.com, Giles Boquette, Archaeopteryx Tree MIDI files, or you can just Google Giles MIDI, which I would recommend, because the other way takes a lot of time. And the smart thing to do with Archaeopteryx or anything else is look at the branches on GitHub, because you can see that this MIDI files branch actually has like a lot more activity than master. Okay, so one of the things I wanna talk about, and I'm, again, gonna make this quick, is Lambda, okay? So Lambda is a feature of Ruby that a lot of people, you know, maybe they don't use so much. It's a very, very powerful feature. So here's some JavaScript in WebKit, okay? If you're going to JavaScript console in WebKit and you do foo new object, foo.bar equals function, right? You can just put a function on the object as a piece of data, as an attribute, as a key in the sort of hash that any JavaScript object is. And you can reference it as the object itself, right? Here we have a function object, foo.bar is a function object, foo.bar with the parentheses actually executes the function. Okay, so you can actually do almost exactly the same thing in Ruby if you want, and it's very, very simple, right? Here it is. You create foo equals object.new, obviously the same. This part is different. You do class, open, open foo, add our accessor bar, end, right? And then you can say foo.bar equals lambda return bar. And then if you do foo.bar, just like before, you get, you know, here you do foo.bar, you get the function object. Here you do foo.bar, you get a proc, which is essentially a function object. And then before, you can do foo.bar to execute that function. Here you can do foo.bar with the square parentheses I don't know what they're called, but the box. And it'll execute the code. So this is a very different way from writing Ruby from the way, you know, normally people do write Ruby. But the nub and the gist is if you wanna do this JavaScript thing in Ruby, it is extremely easy. Okay, I mean, it's right there. So we'll talk more about that a little bit later. So next thing I wanna explain is going to seem like a bit of a tangent, but I wanna tell you how Google PageRank works. So this is the original white paper on Google PageRank, right? And this is the algorithm, right? And here's where the math comes in. So this says that the page rank of a given page is equal to a dampening factor applied to the page rank. Well, this is iterating, right? When you have PRT1 yada yada to PRTN yada yada. What you're saying basically is for T1 through TN do this equation. So you're iterating over a collection and doing the same equation on it. And it sounds complicated, but here it is in 126 lines of Python, okay? We can do it a little bit better than that. I'm gonna explain, let me just go back here to, yeah. So we assume page A has pages T1 through TN which point to it, right? That's T1 and TN. The parameter of D is a damping factor and CA, that's C here and also here is defined as the number of links going out of page A, right? Which means, well, I'll just show you what it means. So you got the page rank of a given page is equal to a dampening factor applied to the page rank of a page linking in divided by the number of outbound links on the page linking in and then you iterate over all those pages, right? And if the math is too much, here is a hippo with a turtle, right? And you can see they're friends, right? This is a cozy picture, right? So here we have the page in question, yada, yada, yada, right? This actually works out to a very, very, very simple thing, right? Here it is in one line of code. This might be difficult to read because it's kinda small but page rank of page, one minus damper plus damper times and then you just do an inject into zero page, page rank of page divided by outgoing links from page. Not actually that complicated, it's almost one line and the power is in the probability matrix, right? Because what this does is it sets up a probability matrix. Now here's an example of what a probability matrix might be. It's a very simple one, right? You've got a thing and a probability, right? So we're saying that for some set, in some context, the probability of encountering an aardvark is 80%, what's that, a bird is 50, right? Cat is 90, this is some kind of bizarre zoo, right? I don't know what this is, I was just, you know, obviously these are in alphabetical order all the way down to hovercraft full of eels, igloo, and Jurassic Park. But the point is that you're simply associating things with probabilities, okay? So here's one way that this works, right? I've got this blog post here, it says config.gem, unpack, blah, blah, blah, this is obviously an error message, right? The whole post title is an error message, right? And here is the solution. Honestly, who would give a shit? Rails, vendor gem source, yada, yada, right? And if you encounter this cryptic, unhelpful, and deeply annoying error message that does not affect the running of your app in any way, shape, or form, all you need to do is Google it and you get the one liner solution, right? So these terms, if you were to make like a probability matrix that they link to my blog, this is actually what Google does, right? It forms this assessment of the probabilities that they link, and then because it's a high probability, if you put in the search term, you get the blog, right? So you notice that it contained like things like anything and whatever, right? Config.gem, unpack gem, whatever, right? Well, the reason that works is because these are terms with very high probability. You can also select a term with very low probability, like arizdif, right? You're not gonna see the term arizdif on the web very often, because it does not mean anything in any language, right? So its probability is zero, right? So if you search for config.gem, unpack gem, arizdif, you get dilly, right? So going back to this implementation of page rank, right? The page is inject, it's kind of a mistake. It's one of two mistakes in this code. It's mistaken that the variable name is not particularly clear, right? What we're really talking about when we say pages is the referring pages or the sources of inbound links. So a better way to write this thing is to fix that and also fix that I did memo wrong in that previous slide. I did the inject wrong, right? Page rank of page, here's the damper. Then into inbound links, you've got a collection of inbound links, right? Or pages containing inbound links, right? You know what, I'll just go forward here. Here's that diagram, which I know you guys got because it made sense. So here is it translated into code, right? So the page rank of a page, right? The damper, you find the page rank of the inbound link, you divide that by the number of links on the page containing the inbound link, and then you just iterate over all those links. So here we have the essential equation part where you are comparing the page rank of the inbound links to the page rank of the page containing the inbound link to the number of links on that page, right? And then you just iterate over it. That's where you're building a probability matrix because what a probability matrix really is is a probability distribution. And when it comes to distribution, there's a couple of slides here which are boring, so I'm just gonna skip them. Uh, however, it would be interesting if you were like shocked by the idea that Google is somehow imperfect. And if you were shocked by that idea, I include a picture of a hippo looking cute to like kinda ease that pain. And now it's gonna get even worse. We're gonna go from math to Python, you know? So brace yourselves, it's gonna hurt. I'm sorry, it's gonna hurt. The thing is, I did this great presentation where I'm like promoting Archieptrix, and I'm like Archieptrix is something to get excited about. And people are like, well, that's great, but how does it work? And I'm like, I just told you for an hour. And they're like, yeah, but three of those slides had code. So now I'm trying to give you the code. But I don't think it's actually what you want. I think it's actually what you say you want. But I'm thinking out loud here. Anyway, the Google page rank algorithm is 126 lines of Python, right? That's great, right? Here's how to write a spelling corrector in 21 lines of Python. So this is Peter Norvig, chief scientist at Google, and he's showing how, basically, he was talking to some friends of his, and they're like, oh my God, Google's spelling correction is amazing. And he's like, what? What's wrong with you? How don't you know that that's obvious, right? And here's his quote, right? What surprised me is that I thought Dean and Bill, his buddies, being highly accomplished engineers and mathematicians would have good intuitions about statistical language processing problems, such as spelling correction. He thought they knew it was easy, right? I figured that on the plane flight home, in less than a page of code, I could write a toy spelling corrector that achieves 80 or 90% accuracy at a processing speed of at least 10 words per second. So here it is in 10 lines, 21 lines of Python. And here are those 21 lines, right? And if you're not used to reading Python, and if you have no idea where I'm going with this, you might wonder which of these lines you should look at. It's these, these lines, right? And yes, it's 21 lines, but basically what these lines do is they go through a list of words and they compile basically frequency. And I think it also does something with the letters and the words, the misspellings, I don't know. But essentially it's just compiling a mapping of frequencies, right? And it's doing that in 21 lines, but the money shot is just five lines, right? And this here, our Ruby implementation and the page rank is again just five lines, right? So this probability matrix thing is a five line thing, right? People talk about Google and they're like, wow, you know, chief scientist Peter Norving wrote the book on Lisp and artificial intelligence, right? They think it's rocket science, it's not rocket science. Google is a post-it note, okay? All you need to do to understand like almost everything they do is understand how probability works. Things like a probability matrix, it's easy. Everyone in this room can do it, guaranteed, okay? Tangent, there's something very sick and wrong about the Python community. I'm talking about the lack of dick jokes, okay? I'm sorry, I don't mean to be like, you know, judgmental, but it is ridiculous to have people talking about Pythons day in and day out and not making one dick joke. It's just unreasonable, right? There isn't even like a web framework called Trousersnake, there's nothing. Seriously, what's wrong with these people? If you go to like a Python meetup, right? They're gonna be like, oh, yeah, how are you doing? No, your Python looks really good. And you're like, thank you. You know, I was like, oh, there's this Python. Look at this Python. What do you think of this as Python? Well, it's too long, you know? We're gonna have to trim that Python. I'm like, you're not trimming my Python, dude, whoa. You know, and they're like, if you tell someone, no, you know, don't trim my Python, trim your own Python, they'll be like, well, it is kind of hairy. Anyway, I just had to get that out of my system. I mean, I imagine meeting the guy, you know, who like got Python to work on Wang computers. I don't know if you remember these, they were around in the 80s. They're still kicking around somewhere. And I'm sure, I'm sure somebody got Python running on them. I bet if you went up to this guy, he would not make a dick joke. I bet if you were like, you got Python running on Wang computers, you'd just be like, waiting for the dick joke, and you could be waiting forever. You could drop them hints like, you know, I bet that was a big, hard project, you know? Nothing. So anyway, Python. I don't know what's up with those guys. I just don't see how they resist. Anyway, so here's some Python I wrote in 2005. It doesn't run. However, it ran in 2005. And back then I was on a Windows machine, and this is a Mac, so I don't know what happened. I guess Python is like not good enough for the Mac, but it was good enough for Windows. No, I'm kidding. Okay. Anyway, what this Python does is basically, it learns to play rock, paper, scissors, which is probably the most useless thing you could train a computer to do because they don't have hands. But I thought it would be cool. I thought it would be cool to train a computer to play rock, paper, scissors. And what it does basically, if you go rock, rock, rock, like 10 times in a row, the 11th time, it'll know that you're gonna do rock, right? So if you do, or if every time you do rock, rock, paper, it'll see that coming and it'll do scissors, right? So this is a Python program that learns how to beat you at rock, paper, scissors, right? And if you were going to program something that learned how to beat you at some real game, like chess or go or something like that, it would be much more complicated, right? This is just a toy that illustrates probability matrices, right? And basically this, well, there's a lot of code here. You might be wondering where the money shot is and I'm gonna say it's here and essentially this line down here where you say move probability equals sequence followed by move divided by overall frequency and that's 15 lines. But there's a reason for that. I'm not Peter Norvig, right? I'm not the chief scientist at Google and this was five years ago, right? And Python isn't my forte, but if I was to sit down and write it again, it would be less than 15 lines. And actually I should balance out all that trashing the Python community because there's something really cool about the Python community, which is there's a lot of work outside of the web in Python and you can talk to Python programmers who are doing non-linear fluid dynamics for special effects houses and stuff. That happens, I'm from LA, so that happens there. Anyway, let me explain how this stuff works, this rock, paper, scissors thing because I think it'll make the probability matrix somewhat clearer, okay? Here's what it does. It builds little matrices like this, right? Like if you play rock, paper, scissors with this thing 10 times, right? And eight times you just do rock, rock, rock, right? It says 80% of the time rock, rock is followed by rock and then it says 80%, right? If you say, if you do it like this, say you're playing it in a very unimaginative way where you do rock, rock, rock eight times, rock, rock, paper once and rock, rock, scissors once, right? Then it'll note that, right? And obviously if you do it eight times out of 10, that's 80%, one time out of 10, 10%, et cetera. That's all the probability matrix actually is, wait a minute, what happened? That, yeah, that's all the probability matrix actually is. Keynote is really hard, I don't know what's wrong with it. Anyway, what it is, is you could call it a probability distribution, that's another term you could have for it. Another thing is you could call it a frequency matrix, right? Your probability is essentially just your frequency divided by your total, right? So getting it to play rock, paper, scissors, you do this with the 0.8, yada, yada, yada. How the code handles inference and prediction is using something called Bayes's theorem. And since this has been a lot of math, here is a hippo chasing a perfectly innocent human being with the intention of eating it. See, I put these, I have this personal crusade to let the world know that hippos are not just cute, they are also dangerous. And here is an evil little turtle egging him on. Anyway, Bayes's theorem, okay? Here's the math with Bayes's theorem and it's already gotten boring, so here are the jaws of a hippo. Which is what you would see, this would be the last thing that you saw if a hippo ate you. And then when I was making these slides I got bored of the hippo meme, so here's a picture of Jessica Alba and she's wearing very blue eye shadow, if you notice. Here's a blue helicopter. It's almost exactly the same shade. Anyway, here's the math, right? And what this is, this is Bayes's theorem, but I got it from Wikipedia. And if you really want to understand something, Wikipedia is a stupid resource to go to. It's a great place to start, but it is not the place to find the real information. So this is, in my opinion, this is a really good place to go. This is one of the key books on Bayesian analysis, Bayesian networks. It is an extremely difficult book to read, but it is really good. It's called Probabilistic Reasoning in Intelligence Systems by Judea Pearl. And I showed you this code, it was like five lines, 10 lines, yada, yada, yada. Mathematicians write stuff that can be expressed in five to 10 lines of code that does amazing things. That makes these books fantastic, but this is like 600 pages of extremely dense math that shows you how to write five lines of code. So, caveat, don't go out and buy this and be like, dude, this is gonna be the most exciting thing to read ever. It's not, but it can lead to writing really interesting code. What's up? No, no, there are some, no, but he does talk about it raining. You know, rain, it's something. But that makes a perfect segue because one of the big examples he gives, and this is how he does the equation, is the probability that it rained last night if the ground is wet. Now, this is something that if a human figures it out, you're not gonna give them a Nobel Prize. But if a computer figures it out, that's pretty impressive. If a computer can figure out that it rained last night because the ground is wet, most computers, they can just get rained on. That's all they can do. Well, I mean, there's more that they can do, but that's a lot of thinking for a computer. So the math on this, right, is the probability that it rained if it's wet is the probability of it being wet if it rained times the probability of it raining, and then all of that divided by the probability of it being wet. And you could go into the source of this, but it's kind of an epic tangent. Reducing it to code is pretty easy, right? Like the probability of an event given some information is the probability of the information given the event times the probability of the event divided by the probability of the information, okay? There's just one problem with this. If you actually tried to use this code, right, it's, what is it doing? Sorry, there's real keynote problems. This here is a recipe for a stack trace, right? If you actually built that method, it would just go poof, you know, and your computer would just fail, right? It just, it takes a shit and you're done, right? So what you need to do instead is something different, and what I did in this code is I just used array indexes, and the result is kind of ghetto and inelegant, but whatever, right? So the probability of rock paper, right? Rock leading to paper is the probability of paper given rock times the probability one, there's just a, sorry, just an array or a hash with the probabilities in it, indexed, divided by another, you know, indexed probability. And another way you could put this is you could say infer rock paper based on, you know, the frequency of paper given rock, yada, yada, yada. And you use frequency because it's really what this code is about is about frequencies. This stuff here is about recording frequencies. It goes through this collection, right, and counts the features, right? And this here is going through these collections and making calculations based on the frequencies of these inbound links and the frequency of any link appearing on the page with the inbound link. Okay, so that's enough math. Now we're gonna talk about drum machines, okay? This part might be a little more fun. So I told you I was gonna show you a drum machine. Here it is. Now I gotta do the thing where I like code on one screen and look at the other screen. So, boom. So we're gonna create like a drum machine. And then this will probably freeze because my hard drive's kind of crappy, but what this is is, this is a program called Reason. It's got synths, drum machines, samplers. It's a virtual studio. Oh, and the samples are over here. Okay, so there's a base drum. All right, so if we get it running, I don't know if you can see, there's little dots that go across here. Can you see them? Little dots, okay. So then you put them like this, right? Okay, so then you got a base drum on every beat, right? So then we'll add like another drum, right? I'll throw a clap on there. Okay, so here's, turn the volume down on the clap a little and so it's pretty clear what this is doing, right? I'm just setting up the drum rhythm. And then this here is a hi-hat. I'm gonna turn the volume on down on that one too. Okay, and there you have like a very basic rudimentary drum rhythm, right, done in Reason. All right, so this basic model dates back to the Roland TR-808, which is like the best loved drum machine of all time. It's so well loved. People make pillows to look like it so that they can cuddle it at night when they go to sleep. It's a very well-loved drum machine. And this is the software drum machine I was just showing you. If you look at the structure, right, it's the same structure, right? You've got these columns up and down and then this little micro grid of one row at the bottom. Columns up and down, row at the bottom. Columns up and down, row at the bottom. Okay, so, and as you just saw, right, this column gives you a row for the hi-hat, this column and a row for the clap, and this column is a row for the kick, right? So what this actually is, if you're a programmer, you look at this, right, and you've been like working with these things, this is an array of arrays, right? Like the first element is the kick drum, which I guess it's a hash with, you know, kick drum mapped to an array of beats, clap mapped to an array of beats, and hi-hat mapped to an array of beats, right? So this is a matrix, right? You can represent it like this, right? You can see if you look at like where the yellows are and the greens and so on, it's the same thing, right? So this is basically a matrix of true and false, and this is the model the drum machines have run on since the late 70s, since the first drum machines. This is how they work, right? And you know, obviously if you can express it as true and false, you can also express it as ones and zeros, right? But I have been, you know, playing with drum machines like my whole life, and I'm reading all this stuff about probability matrices, and I think, well, I got Booleans and I got, you know, zeros and ones, why not put in floats, right? And this is what Archaeopteryx does. Here's some code from Archaeopteryx. This is a drum probabilities hash, right? And drum probabilities, you know, drum probabilities of 36 equals, and then you've got this array of floats. Drum probabilities of 41, and then an array of floats. So a little bit of background about how MIDI works really simply. When you're saying choose this note or that note, you're specifying a note number, okay? Now this, here's the kick drum. This is note number 36, right? Here's the clap 37, right? When you're saying drum probabilities of X number, you're just mapping directly to the MIDI note number. So what I'm doing here is I'm saying this drum has these floating point values assigned to it, right? And it's just like this, right, except that the values are probabilities. They are between zero and one, okay? So it's a probability matrix. And we're kind of like the way this works. You must be 45 inches tall to ride the crazy mouse, right? This kind of roller coaster thing, except it flips it upside down. It says you must be under this height to get through. It gives you a ceiling. Like for example, if you've got the number 0.8, you throw a random number at it. If there, you know, so there's a 0.8 and you throw a three at it, it gives you a green light, because it's good. If you got a 0.9, you throw an eight at it. I'm sorry, if you got the 0.8 and you throw a nine at it, it gives you a red light, because it's too high, right? So this is basically a series of gates through which you send numbers. And if the number gets through the gate, it becomes a note in the music. And if it doesn't get through the gate, then it doesn't become a note in the music. It doesn't become part of the drum pattern. So here's another blue helicopter. And now I'm out of slides, okay? So I'm gonna show you the code and I'm gonna do a little demo of Archaeopteryx. Let me get that up and running here. Okay, so over here, there we go. Try and make it nice and big, so it's easy to see. Okay, let's... Okay, so the first step is just to open up this utility. And this utility is like UNIX pipes for... Where is my mouse? Hold on, I'm gonna have to hide this. Oh, that's great. There's a black mouse on the background of a black terminal window. And I've improved it by making it a black mouse on the background of a black screen. Oh, there it is. Okay, so MIDI patch bay default, this is just a simple utility which is essentially UNIX pipes for MIDI, right? And this just says that you open a thing called ASDF. And, well, the variable names don't matter, actually. But you could type anything in there, and obviously I did. Anyway, here... Well, I'll use this one, because I think that's the... So then you just open up a Reason thingamajig, and here's... Oh, this is killing me, I don't know where anything is. Oh, there it is. Okay, so here's a Reason setup set up with a few more instruments. And one thing we need to do is set the preferences, which we'll also take a moment. Okay, so you wanna set your advanced MIDI preferences to whatever the variable name is. And then at that point you should be able to run something and get some music. The screen. Oh, and obviously there's a file though that says, God, I need specs in this motherfucker. That's actually a note to self, because I realized that I needed specs in there. Okay, so it's called Drums Live. Here it is. So you do Ruby, Drums Live, and let's see if it works. And judging by the way this presentation is going for me this morning, it probably won't, but let's find out. Yep. Oh, awesome. Okay, so that sounded like not so good. So the reason that I actually know exactly what went wrong there, if you go in here, and I'll open this up in TextMate, because it's easier to change the numbers. So here's the code in TextMate. And you remember that I said that, okay, I'm gonna have to change that one too, hold on. There we go. Okay. So you remember that I said that you are, basically you've got a series of gates and you throw numbers at that, and it just lets through whatever is lower than the gate. So if what you're throwing at the gate is zero, it's gonna be lower in every case. And what you have here, this right here, is 0.0. It's couched inside a lambda, which is, well, I'll talk about that in a sec. But say I do it differently. Say I move it up from 0.0 to 1.0, and I do that thing again. So every time I change the number, it should change the beat when I hit save, which I'll do like right about now. And if I change it like extremely down to zero, it'll sound bad again. But I can undo that. So that's kind of cool, right? It's really fun to be able to do that. Thank you. And what I hope is that you actually have a clearer understanding of what I was doing there than most of the people who have heard this and seen how it works. So here are the probabilities. And just so you know, this file is not actually the main, when I say Ruby Drums Live, this is not Ruby Drums Live. This is DV Drum Definition. Drums Live requires this file every four measures. And that's how if you change the file, you automatically get new music because it reevaluates the file on an ongoing basis. And you can, if you want, make it much faster than every four measures. You can make it like every two measures, every one measure. In practice, you don't generally want to be changed in the music that much. And in fact, in practice, I found that it is most useful generating MIDI files, which you can then chop up. Because a very common practice in producing this type of music is to have sample libraries or record collections or some source of existing, you know, content that you then, you know, reprocess or reorganize. What's that? Oh, really? Oh, God. Okay. Well, I better show you how Lambda is involved. And that would be relevant, right? Here, okay. So the most important place that a Lambda comes into the picture. And Lambda is used all over the place in this. So in five minutes, it's gonna be really difficult to tell you everything. But this here is a Lambda, right? Where generate beats is this method that generates beats, right? And then what you actually have to do is you're telling it later on to do that method again. So you store it as a Lambda to be invoked at a later time. But there's a bunch of other ways that it's used. For instance, down here, oh, I forgot to show you something very important. You might notice like right down here, it's got the Lambda where it's just a constant, right? Actually, I completely misused Lambda. God, I could show you the other Lambdas which are more interesting, but I don't think I have time. So this is real basic. But here, instead of giving it a 0.5 every time, I'm giving it Rand. So it's gonna be a different value each time, which means it's gonna sound different. It's gonna do a different loop each time. But that's different, but it's not different enough. So we're just gonna make it more different. See, now it'll start getting more different-er. So the way it does that is this Lambda is doing something a little more complicated, okay? Now, earlier, when I said that, you know, you can just set it up to do what JavaScript does where you put like a function in as a data object, you might have wondered, why on earth would that be useful in Ruby? Okay? Like, why would you ever wanna do that? You have all this metaprogramming capability anyway. Why would you bother? Okay? The reason is basically, if you know what a strategy pattern is in Java, right? It's this idea that you've sometimes got code that needs to make decisions about how it's going to do things. So if you just put a Lambda in an array and then you have another Lambda here, which is exactly what I'm showing you, which is a Lambda for choosing things from an array, right? That is like a meta-strategy pattern because it picks out strategies by working on the array. And you can like pop in different ones depending on what you want to do. And that is the major strength with it, although there are some other ones. To be honest, the main strength is it gave me incredible flexibility when I was building this thing. Just really, just incredible flexibility compared to like, you know, I've worked in Java and Python and Perl and it was as powerful as Perl but like much better organized, you know? So I was able to, you know, move these things around and create this. You could redo it today in Objective-C probably, but in order to find the structure, I needed that flexibility. And that's a massive, massive over-generalization but I'm really out of time so I should ask some questions or I mean, I should let you ask some questions if you have any, which I hope you do. Cause all I got is more babbling and a picture of a helicopter. Oh, awesome. Yeah. Yeah, well the way you change that is you go into this file here and you change these probabilities, right? Cause that's the array of floats that determines, you know, what, you know, if you're saying 0.8 and everything below 0.8 gets through, you know, you can bring it down to 0.1 or all the way up to 1.0 or indeed, you know, beyond that but 0.1 is supposed to represent 0% to 100%, right? So these are entirely arbitrary and you could set them up in a variety of, you know, different probabilities. I have them set up in such a way that they, you know, produce like typical rhythms for drum and bass. But actually I found that this system, if you wanna create like techno or house, you know, obviously this is focused on electronic music but there are other styles of electronic music that don't use break beats so much, right? This style of music is a lot about like, here's a beat and here's a variation on that beat. If you were to create like a style of music that was just like going forward and adding layers, this system works for that but you would have to change a few crucial parts which I was hoping to do for this presentation but did not. More questions? Pat, I have not, other people have, there's a guy called David Cope who's done really great work with this. He's got like a giant Lisp program that can basically do, you know, original compositions and classical music and there's people who've done it with analyzing stuff like, you know, I'll feed in a Rachmaninoff symphony and what emerges on the other side is, you know, a digital emulation of a Rachmaninoff symphony and you give it to a violinist and they're like, wow, you know, I love Rachmaninoff but I haven't heard this one before. You know, and these experiments have had like varying degrees of success because there is a real art to it, right? But it is essentially just a probability matrix, right? Is that a question? Exactly. No, I think, you know, God, on the one hand, I feel embarrassed to admit this especially with such an eminent audience but I am behind on Ruby 1.9 but I have seen like the new ways of doing lambdas which are much more powerful and I imagine that it could, yeah. I think that's absolutely the case. Yeah, yeah. Actually, there was a bass note in there which didn't come from the drum machine so it was driving multiple, put it, no, no, no. It was doing different notes but the bass line stuff is very unsophisticated yet but I mean, I've driven hardware with this at the same time as driving the software because MIDI is a universal protocol. MIDI is incredibly dumb but incredibly everywhere. It is ubiquitous. So, yeah. Yeah. With the software, yeah, yeah. All you would have to do like it's in here. Where is it? Choose bass note. It's got bass rhythm probabilities. All I basically do is I add a generation of notes, right? Section where it just goes through and creates notes but there's another way you can do it too. Where there's this concept of mixes and rhythms and I actually even have a fork which does things in multiple time signatures. It's quite messy but it works. Sorry, hey Mike. Oh, that's it, I'm done. Okay, thank you very much. Thanks for your patience.