[00:00.000 --> 00:12.680] Now let's have some music with Melrose, a program and play music by Ernest. [00:12.680 --> 00:13.680] Yes. [00:13.680 --> 00:23.800] Yeah, thank you all for waiting, it took me a bit more time to set things up, but I'm [00:23.800 --> 00:30.600] glad you're here at the end of the day, full room, and I'd like to share with you a result [00:30.600 --> 00:34.240] of an open source project I've been working on for a couple of years now. [00:34.240 --> 00:40.480] My name is Ernest Mikleij, I'm a Go developer, but my day job is actually being a manager, [00:40.480 --> 00:47.880] so this is how I program in my spare time, and yeah, so in a couple, in this presentation [00:47.880 --> 00:52.680] I want to show you what it is, what you can do with it, and if we have time I can also [00:52.680 --> 00:54.880] show you demos. [00:54.880 --> 00:57.240] So why did I start this project? [00:57.240 --> 01:04.040] So I'm also a piano player, and I noticed, as you do probably, that music is really a [01:04.040 --> 01:09.040] structured language right, so we have all kinds of patterns, and Bach is one of the [01:09.040 --> 01:15.320] famous ones, and I wanted to explore those expressions in some kind of a program language, [01:15.320 --> 01:21.920] and I took up the challenge to find the right functions, abstractions to actually program. [01:22.440 --> 01:28.000] Now I told you I'm a Go programmer, so initially I thought, okay, I'm just going to write a [01:28.000 --> 01:34.240] library and create all these function abstractions, but then I realized, okay, each time I create [01:34.240 --> 01:39.520] something like a music or a pattern, I have to compile it and restart it, listen to it, [01:39.520 --> 01:46.000] no it's not good, change it, compile it, restart it, so I quickly skipped that whole idea, [01:46.000 --> 01:52.040] and then I realized I need to offer quick feedback, and so I started thinking about [01:52.040 --> 01:59.040] a different language, and then use Go as an interpreter of that language. [01:59.040 --> 02:00.680] So what is Melrose Ndient? [02:00.680 --> 02:06.720] It's actually a combination of a language, my abstraction of how to write music, and [02:06.720 --> 02:10.880] it's also a runtime to play those things. [02:10.880 --> 02:21.960] Well, for instance, if I go here, where is it, yeah, that works, okay. [02:21.960 --> 02:28.720] So yeah, this is just a glimpse, and I will talk to you through it what it actually means, [02:28.720 --> 02:34.480] and I put this presentation in four parts, we'll talk about the language, a bit about [02:34.480 --> 02:41.400] the tool, very short part about Go, perhaps, and of course, where you all want to hear [02:41.400 --> 02:43.920] something, right? [02:43.920 --> 02:50.040] So about the language, so I decided this would be my note presentation, a note consists of [02:50.040 --> 02:55.600] several components, just a simple thing here, you can see the C and you can put length information [02:55.600 --> 03:02.000] in front of it, you can change the sharp or make it flat, change the octave by adding [03:02.000 --> 03:07.240] a number at the end, and then put in some dynamics, and I chose to use minus, minus, [03:07.240 --> 03:11.120] plus, plus to make it louder and shorter. [03:11.120 --> 03:16.840] So this is how I represent a note in the language. [03:16.840 --> 03:24.360] And these are just examples of how to express them, but I hope you already see that this [03:24.360 --> 03:30.720] is not really a good way or easy way to compose music, because then I have to type a lot of [03:30.720 --> 03:37.680] notes, right, put them together, and so very quickly, of course, I needed some another abstraction, [03:37.680 --> 03:44.480] I call it sequence, and a sequence also is typically a collection of notes, and I also [03:44.480 --> 03:53.360] added a notation to have grouping, so we can have chords, right? [03:53.360 --> 04:00.480] And this is just an example of a sequence, and this is an arrest, this is an eighth note, [04:00.480 --> 04:11.400] and so on, and I was hoping I could actually play it here, I think I can, it doesn't work, [04:11.400 --> 04:21.120] of course it doesn't work, why not, and there it is, ah, it doesn't know where to find it, [04:22.080 --> 04:37.760] I have to set the output device, you see, sorry about that, give me a minute, just restart [04:37.760 --> 04:46.840] the tool, let's see what kind of media devices there are, I think there it is, so one, [04:52.120 --> 05:19.040] still not, why not, this is the demo effect guys, I'm sorry, it happens, I think it is missing [05:20.000 --> 05:31.200] this one, so, yep, are you still with me? [05:31.200 --> 05:52.520] Something wrong with my setup guys, I don't know what, maybe I should do this, it doesn't see my synthesizer, [05:53.520 --> 05:59.400] and of course I can play it myself, but that's not really what I'm trying to sell to you, right? [05:59.400 --> 06:07.120] So maybe I will continue with, ah, there it is, I see it, [06:29.400 --> 06:48.280] sorry about that, thank you, thank you, thank you, any questions, no, so, yeah, this is just one of [06:48.280 --> 06:54.920] them, and soon I realized I need more abstractions, because, yeah, the sequence, still have to write [06:54.920 --> 07:01.840] all those notes, right, so I also have the progressions, and this is a progression, [07:01.840 --> 07:21.040] yeah, this is a chord sequence, so, yeah, the real power in the language, I think, [07:21.360 --> 07:27.360] comes from composition, so I managed to find all kinds of functions that take groups and [07:27.360 --> 07:33.800] transform it into something else, so, you need to read from right to left, so we start [07:33.800 --> 07:40.360] with a chord, which is the same as the sequence CEG, right, and then I engroup it, so I get [07:40.360 --> 07:46.640] separate notes, then I reverse it to get this, then transposes, I get that, and I repeat [07:46.640 --> 08:03.280] it four times, yes, so I can do this as well, so it takes the sequence, and it changes the [08:03.280 --> 08:08.640] number of notes by this pattern, I just came up with that pattern, and make it shorter [08:08.640 --> 08:17.640] notes, fraction, and eight, so shorter, and I repeat in a join, and the nice thing is, [08:17.640 --> 08:37.160] you can also change, I will come to that later how that works, and then I realized, ah, so [08:37.160 --> 08:42.680] I can have sounds, but I really also want to express rhythms, and then I came up with the [08:42.680 --> 08:51.360] pattern consisting of dots and bangs, so every bang and a dot represents a kick, and if it's [08:51.360 --> 09:00.360] centered to channel 10, which is the standard for drums, I shoot, pray again, if that works, [09:00.360 --> 09:22.120] now it doesn't, why not, maybe it's this channel, no, that doesn't work, for some reason, and [09:22.120 --> 09:32.920] then this doesn't work either, that's too bad, see if we can make that channel 10, no, you [09:32.920 --> 09:38.360] have to bear with me, that should work, maybe I will figure out later, let me explain how [09:38.360 --> 09:44.920] this works, so I made some variables, I extended the language to have variables, because you [09:44.920 --> 09:49.520] can reference them, that's easy, in normal program languages, and then you see a note [09:49.520 --> 09:54.880] map here, where I map the kick on all the bangs and the snare, and then there's a function [09:54.880 --> 10:00.960] called merge, that squeezes everything into one sequence, but because every note has a [10:00.960 --> 10:08.680] different instrument, they won't go all together, they each will send to the right instrument, [10:08.680 --> 10:14.240] and I'm using BPM, I can change the beat per minute, obviously, and I send the whole thing [10:14.240 --> 10:22.760] to channel 10, which for some reason doesn't work now, I don't know, okay, and there's [10:22.760 --> 10:29.600] lots more out there, so I showed you fraction, merge, and repeat, and I realized when trying [10:29.600 --> 10:35.400] to compose music like that, oh I need something that has a transpose map, and I need something [10:35.400 --> 10:45.640] random, and I need something pitch, and so the language grew and grew, like you see now, [10:45.640 --> 10:52.960] so a bit about the tool, so Melrose, the program, it doesn't produce any sound, it just uses [10:52.960 --> 11:00.280] MIDI, and MIDI, there's lots of MIDI devices out there, and so that's why I brought my [11:00.280 --> 11:05.160] synthesizer here, it's just one of those devices that we can talk to and send MIDI to, [11:06.040 --> 11:10.960] and it's very, yeah, I think most of you know MIDI, so I won't go into detail of that, [11:10.960 --> 11:18.960] and so Melrose comes actually with a binary and a web version, so the one, the binary version is [11:18.960 --> 11:24.920] running currently with my machine, just a little interpreter you just saw for changing the devices, [11:24.920 --> 11:34.120] and it actually has an HTTP interface such that each tool can talk to Melrose using HTTP, [11:34.760 --> 11:42.520] so that's the reason why my presentation sent the data to my Melrose program from my web page, [11:42.520 --> 11:50.320] right, and also have a web version that uses Wasm, web assembly, so you can play it in the [11:50.320 --> 11:55.880] browser, if your machine has some local MIDI device you can try it in the playground, [11:55.880 --> 12:03.640] and this is the whole setup, so there's this Melrose program, and I could also create it [12:03.640 --> 12:11.400] with Visual Studio Extension, so if you load your script.mel file in Visual Studio Code, [12:11.400 --> 12:17.600] you can actually have some shortcuts to talk to Melrose, and this is how I actually compose music [12:17.600 --> 12:25.680] using the tool, and because I'm actually using the MIDI, Melrose can talk to any MIDI device, [12:25.680 --> 12:31.920] it can be hardware, software such as this one, and so you can also combine multiple devices. [12:31.920 --> 12:42.040] Playing music, so you already saw BPM, and of course we have a loop, so the loop can take a [12:42.040 --> 12:47.560] sequence and just loop it, and it's very nice, I thought, because once you have a kind of a [12:47.560 --> 12:52.520] sequence and you start looping, then using a MIDI device you can find the right instrument that [12:52.520 --> 13:03.200] matches the loop, so that's how I interact with it. A bit of a behind the scenes, so if you [13:03.200 --> 13:09.440] write a program in Melrose, and you ask it to evaluate it, to play it, it will actually pass, [13:09.440 --> 13:15.240] of course the language, so you get a music object tree, and it will translate it in a [13:15.240 --> 13:20.840] bunch of note events, and it needs to schedule those events, but because each note should start [13:20.840 --> 13:27.400] at a certain moment in time, so you create a timeline, and then you play the timeline by [13:27.400 --> 13:35.400] sending all the MIDI notes to a device, and another picture that demonstrates the same thing is this [13:35.400 --> 13:40.720] is the timeline, it's actually implemented as a linked list for the programmers that know what [13:40.720 --> 13:48.680] that is, and so each time I say this is a sequence, I create this timeline and send it, and this is [13:48.680 --> 13:54.360] done in parallel, so while the music is playing, I can send more sequence to the same timeline, [13:54.360 --> 14:04.920] so I can start doing composition real-time as well. Okay, already mentioned that one, [14:04.920 --> 14:13.200] so this is where you can find my goat, and where you can download the binary, I have a Mac version [14:13.520 --> 14:20.720] and a Windows version, I created a documentation site on Melrose, and just a little note, so I [14:20.720 --> 14:29.680] choose to use the O with a dash on top of it, and because it looks like a note, but it also makes the, [14:29.680 --> 14:34.320] sorry, it also makes the whole name unique in the on the web, so if you type in this name, [14:34.320 --> 14:46.640] you'll find exactly my sign, it's nice, so now let me try to come up with another example, [14:46.640 --> 14:58.960] so let's app it, E-Piano, [14:58.960 --> 15:03.760] Taser, Taser, now we already had that one, right? [15:04.640 --> 15:14.080] So just kill it, control K, this is fine from the bells, [15:18.160 --> 15:19.280] how am I doing on time? [15:21.760 --> 15:28.400] Oh thank you, so I'm just going to show you, no I'm not showing you, I'll let you hear stuff, [15:28.400 --> 15:35.360] right? So I changed the instrument here, and this is Visual Studio Code using my extension, [15:40.240 --> 15:45.280] try to read what's happening, so there are four sequences, I joined them, [15:49.840 --> 15:51.520] but I can change of course the speed, [15:51.680 --> 16:01.040] I have to wait for the loop to end it, you see, [16:03.200 --> 16:07.920] and there's also, so I can also change, I won't do it because it will screw up the sound, [16:08.480 --> 16:16.160] I can also change the characters, and I, thank you, and I evaluate again and it will pick up [16:16.160 --> 16:21.120] the changes, and that's what I mean by the audio feedback, so without compiling the whole thing, [16:21.600 --> 16:29.200] I can just let it loop and then change, and then find another instrument, [16:32.080 --> 16:38.480] and this is how I killed the loop, okay, let me jump to this one, [16:38.640 --> 16:45.440] piano, four, and this one, [16:47.440 --> 16:52.880] yeah, thank you, oh this is a heavy one, I'm not going to do that one, [16:57.600 --> 17:01.440] so can you read it by the way, I hope so, [17:02.400 --> 17:06.400] so, [17:11.440 --> 17:17.760] ah, drum is working, you see, I already mentioned it, so it's actually doing this, [17:19.200 --> 17:26.240] and it loops the drums, as you can see, and I start another loop, [17:26.320 --> 17:32.560] I hope, yeah, there it is, [17:35.360 --> 17:40.400] yeah, and it uses the tap notation, one of the additions I did recently, [17:42.000 --> 17:47.760] so yeah, so now our two loops are running at the same time, but I can add more, and send one loop [17:47.760 --> 17:54.560] to this device, and the other one to the other device, and change it, and I'll change the text, [17:55.120 --> 17:56.800] and so on, [18:02.800 --> 18:06.800] one more, okay, okay, okay, [18:07.680 --> 18:08.800] and [18:24.880 --> 18:27.360] now ends, it's doing program, [18:36.400 --> 18:36.800] thank you, [18:55.280 --> 19:06.400] yes, yes, that's possible, the question is, can you do other MIDI things like changing program, [19:07.200 --> 19:14.000] right, yeah, so pedal support as well, and changing programs, yeah, the only thing I cannot do is [19:14.000 --> 19:21.520] change the beats per minute while it's playing, that's design decision, yeah, sorry, yeah, [19:25.520 --> 19:36.640] yes, and no, so I'm working on that to read MIDI and try to find the expression that matches the MIDI, [19:37.360 --> 19:42.240] and then start from there, but that's difficult, maybe chat GPT knows, but [19:44.800 --> 19:45.520] yeah, [19:45.520 --> 19:50.800] can you consider also using open sound control, OSC, OSC, [19:54.960 --> 19:59.200] can't remember any, I think it's using, I started out with port MIDI, [20:00.800 --> 20:05.280] when I thought about that, and then I changed it to something else, I have to look at the library, [20:05.280 --> 20:09.600] can't remember, so I didn't look at it, but no, yeah, yeah, [20:10.400 --> 20:11.840] can you get MIDI CC in? [20:13.280 --> 20:23.200] MIDI CC, oh, as an input, yeah, I skipped that whole part, but you can actually listen to MIDI [20:23.200 --> 20:30.720] events, and then trigger it by keys as well, but also make changes to it, yeah, yeah, that would [20:30.720 --> 20:38.880] be a nice demo for next time, yeah, yeah, [20:48.960 --> 20:54.720] yes, it runs on the triplet, yeah, so Go can compile to multiple platforms, so like I said, [20:54.720 --> 21:01.200] I have pre-compiled binaries, so for Windows and for Mac, but you can just grab the Go code [21:01.200 --> 21:06.400] and compile it yourself, and if you want to know the library, yeah, have a look at the source code, [21:07.920 --> 21:16.000] yes, yes, there's a function called export, and then your whole MIDI is exported, yeah, [21:16.320 --> 21:19.280] does the debugger work with breakpoints? [21:23.120 --> 21:29.680] yeah, I stole the feature to trigger the loop, so yeah, that's a nice part of the Visual Studio Code [21:29.680 --> 21:36.320] expression, sorry, good, yeah, what about the other tools, do you consider things like Sonic Pi? [21:37.920 --> 21:43.840] no, not at all, because, oh, so the question is, did I consider using Sonic Pi, but that already [21:43.840 --> 21:50.880] exists, and it, yeah, but that produces actually sounds, right, and not, I really wanted to use the [21:50.880 --> 21:57.680] MIDI and focus on composition language, yeah, have you looked at a lily pond suit? [21:57.680 --> 22:05.520] yes, I did, what do you think about it, so that's a lily pond suit? [22:05.520 --> 22:13.360] yeah, I know, yeah, I personally found it too complex, and also part of me thought, hey, [22:13.360 --> 22:21.840] let's try something else, to be honest, yes, is there a, what if the binary is running, [22:21.840 --> 22:29.440] is there like a input for Melrose, like, that you can programmatically send, like Melrose expressions? [22:31.200 --> 22:38.720] by HTTP, by sending HTTP, you set the source to Melrose, and then it gets evaluated immediately, [22:38.720 --> 22:44.400] that's how the tools interact, so you could write a program that generates Melrose, yes, yes, [22:44.400 --> 22:51.360] you could, send me the submission, yes, okay, so it's interesting that there's a crazy guy that [22:51.360 --> 22:57.520] must have the same idea you had, okay, represent music in a way that they equal handle code, [22:57.520 --> 23:01.520] so you could do diffs and stuff like that, and it's called earmuff, and the guy's called crazy, [23:01.840 --> 23:10.640] you might get along, oh, yeah, so there's another guy, just as crazy as he is doing, [23:13.680 --> 23:23.520] earmuff, oh, okay, code to MIDI, oh, I would like to see that, yeah, yeah, [23:24.080 --> 23:30.800] it's more bar-oriented, oh, okay, I would like to have a look at that, thank you, thank you, [23:30.800 --> 23:37.760] yes, one more, how suitable do you think it is for live coding where you compose as you're doing, [23:38.960 --> 23:47.680] yeah, so the question is how suitable is it for live coding, try out, I don't know, [23:48.240 --> 23:55.120] I did, as a performer, I didn't come too far that yet, but I would love to try it, [23:55.120 --> 23:59.760] really, yeah, and also because, yeah, it gives you direct audio feedback, right, so I can start [23:59.760 --> 24:03.280] multiple loops, and at the same time do all the other things, and then start the loop, [24:03.280 --> 24:09.680] or kill the loop, and, yeah, sounds interesting experiments, yeah, yeah, very good, yeah, okay, [24:10.560 --> 24:22.800] more questions, oh, yeah, thank you, you should start your show with this, I invite you, more [24:22.800 --> 24:34.560] questions, yes, melody, I thought about it, and then, yeah, nice rose, and then, [24:35.520 --> 24:41.600] and I knew about this trick from someone else that uses it, and then, ah, I'm going to register [24:41.600 --> 24:47.040] this name, that's the third thing you need to do, right, is it free, and then, no, rose, it's stuck, [24:49.120 --> 24:55.520] last question, last question, okay, you mentioned that it will generate a music object tree, [24:55.520 --> 25:01.120] yeah, is this, will you be planning on allowing other software to capture that tree so that, [25:01.520 --> 25:13.040] oh, yeah, yeah, so the question was, in my, in my, one of my slides, I showed you the music tree [25:13.040 --> 25:17.680] object, and the question was, could that be, yeah, accessible from, for other programs, [25:19.200 --> 25:23.600] yeah, yes, so can it be used for other programs, yeah, I would love to have this, this interface, [25:23.600 --> 25:30.080] yeah, I already have some kind of a visualization, so if you, you can show in the browser the whole [25:30.080 --> 25:35.680] pattern of the sequence, sometimes you need visual feedback, so sometimes I miss Ableton, yes, [25:36.640 --> 25:47.680] and, ah, well, it's another way, yeah, thank you, thank you all for joining.