
Quick Links:
Background
Shimi is a project that I originally started working on several years ago, not long after my move to Canada. I'd done a pretty light move when coming over here, and my instruments were back home. I was actually kind of glad to have some space between myself and them though, because I'd felt like I was in a bit of a musical rut for a while, where I'd learnt to play a bunch of songs that I enjoyed, but I didn't feel like I was really able to use my instruments to actually express myself, or experiment.
Not wanting to straight away go out and buy some more instruments to repeat the same bad practice habits I'd built for myself up to that point, I instead decided that I should try building an instrument, one where I could easily and creatively map keyboard strokes, game controller wiggles, mouse movements, or even MIDI inputs into new MIDI output. The idea was that this would allow me to think about how I play music in a new way. From this, shimi was born, the idea being that it's a shim for all these separate inputs to themselves become MIDI controllers.
Development
The application was originally designed as a standalone desktop application using Vue + Electron, with an eye towards being a low-code tool, to be easily accessible for anyone to pick up and play around with. However, the deeper I got into the project, the more I realised that to unlock some of the truly creative possibilities, there was no alternative for having an actual fully-featured programming language, so I made the switch to making the project a javascript library instead. This not only made development much simpler, it also made it more portable, since now anyone with a web browser could play around with it.
Features
The project is currently in a state where it has components that support many common musical concepts, for example:
- - Metronomes, for representing the passing of time in terms of bars & beats.
- - Time Signatures, for defining how bars and beats are counted.
- - Clips, for holding melodic, or repeating musical ideas.
- - Arpeggios, for defining how a chord should be articulated.
- - Clip Recorders, for recording some musical input into a clip, which can then be played back.
There is also the companion project, shimi-wc, which is a collection of web components, aimed to support easy user-interaction with a number of shimi's objects. You can find this project here.
This also went through a fair bit of transformation to get to its current form. After I decided to redevelop the project as a library, the web components companion project got built using Vue, because apparently I just used Vue for everything back then. However, this had some downsides. Firstly, Vue isn't really meant for doing web components, and any time I wanted to use the web components library I had to also make sure that Vue was being imported, which just felt a little gross. Secondly, I found the build config for my Vue web components project to be an absolutely nightmare, where one day it just full on broke of its own accord and whatever I tried I wasn't able to get it back working again. So, after some research of good Web Component libraries, I made the switch to Lit which has been an absolute dream!
Usage
I included a link to the code playground up at the top of this page, where you can play around with and modify various examples, but I'll at least cover the philosophy of the design here. Shimi code will generally look something like this:
<script src="https://unpkg.com/shimi"></script>
<script>
function run() {
const midiOut = new shimi.WebAudioMidiOut(new AudioContext()).withDefaultChannels();
const keyboard = new shimi.Keyboard(new shimi.EventSubscriber(document));
keyboard.activate();
const metronome = new shimi.Metronome(120);
const clock = new shimi.Clock();
clock.children.push(keyboard, metronome, midiOut);
clock.start();
//Twinkle Twinkle Little Star
const clip = new shimi.Clip(8)
.addNote([0,1], 1, 'C4', 80)
.addNote([2,3], 1, 'G4', 80)
.addNote([4,5], 1, 'A4', 80)
.addNote(6, 2, 'G4', 80);
//Start a new playthrough of the clip each time the spacebar is pressed
keyboard.space.pressed.add(() => {
const clipPlayer = new shimi.ClipPlayer(clip, metronome, midiOut);
clipPlayer.beatCount = clip.duration;
clock.addChild(clipPlayer);
});
}
run();
</script>
In the above example we have a new playthrough of twinkle twinkle little star, which will get triggered every time you press the spacebar. For this, we create a MIDI output object, this is where we define what is going to handle actually playing the MIDI events which get generated. In this example that's a web MIDI player for the sake of portability, but this could just as easily be some synthesizer that's installed on your computer. We then define a keyboard object which gets activated to start listening for key events. You might be wondering why we have both a clock and a metronome set up after this. The clock is really the heartbeat of the entire program. It gets various objects added to it and makes sure they're regularly called for updates, passing in information to them about how much time has passed. It also automatically disposes of objects that are no longer needed. The metronome is one such object, which uses a key signature and tempo to convert the passing of time that it receives from the clock into information about the passing of musical time. Keeping track of where we are within a bar, how many bars have passed, etc. The finally we have a clip defined which holds information for our melody, and then we have a handler added to the spacebar pressed event so that every time it gets hit a new clip player object gets created, which lasts for the duration of the clip that it's going to play, and it gets added to the clock to start getting executed.
Future
While I'm happy with the stable state that shimi is currently in, my plans are to now to take it in a bit more of an experimental direction. I've always been fascinated by the idea of computer generated music. In 2017 I won an award at my university for Melodist, a system I was writing to generate new melodic ideas out of existing ones. I would love to incorporate some of the work from that into shimi.
Here's a video showing what melodist was, how you could have a bunch of melodies saved in a library, and drag different ones into different fields within a 'warp' panel, that would use specific aspects of a melody to contribute to a new output melody.
Park, Coach and Chemistry icons created by Freepik - Flaticon