Here’s my new tool called intervals
Learn about the theory behind it here.
The code for the tool.
What does it do?
Generates a random music interval, shows it on the musical staff. You try to guess it. Clicking on the staff reveals the answer. You can also play the interval.
How was it built?
It’s a React app. What’s React? Get the best React book and find out
But these days you don’t need to start a React app from scratch (as described in the book), you have create-react-app which generates a new app and sets up all auxiliary tools you need. Furthermore, you don’t need to start a new app from an empty canvas, you can start building off of a template, thanks to CRAFT.
The template used is flashcards.
So to get an app like this off the ground you go:
$ npm i -g create-react-app $ npm i -g craftool $ craft intervals http://ift.tt/2kITr79 $ cd intervals $ npm install . $ npm start
Tada! Sudden flashcard app, ready to go. All you need to do is implement the functions
This is a bit of a specialized app, so no need to go into the gory details of the Questions and Answers. But overall:
- generate a random first note. e.g. F♯ on the third octave
- generate a random interval, e.g. a perfect forth
- use teoria to give you the correct second note, given a start note and an interval
- draw the two on the staff using Vex
- play the notes
- random pretty-printing and conversion from my note conventions to teoria to vex
Weirdness and hacks
Vex wants to draw an SVG inside a DOM element. (AFAIK. There may be better APIs I did not uncover.)
So I draw the SVG in a hidden div then copy it over to React, like so:
<div dangerouslySetInnerHTML= />
Sometimes (rarely!) in all this randomness either
vex deserts me. I think I worked out most of the kinks but still… I have a try-catch that simply generates another random question. This is pretty bad as it can theoretically freeze the browser if it fails to generate a valid question but in my testing it hasn’t happened. And sometimes you gotta do what you gotta do
No WebAudio, just the ole
new Audio(url).play(). I play the first note, subscribe to its
ended event, play the second, subscribe to its
ended and play both. Awesome. Here it goes.
Except iPhone still refuses to play without human intervention, so I just play both together when iPhone is detected.
Thanks for reading!
via phpied.com http://ift.tt/2ldWyAK