-
-
Notifications
You must be signed in to change notification settings - Fork 286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Javascript implementation of REPL + Web Audio API #72
Comments
Whoops -- didn't see this issue before I made #73 :P I'm definitely interested in doing what I'm proposing in #73, for the full-on Alda experience in the browser, but this would probably be a little easier. As luck would have it, the Clojure parsing library that we're using, Instaparse, has a cljs port, so it would at least be very easy to port the actual grammar/parsing part to ClojureScript. Clojure and ClojureScript are very similar, so I think we could reuse a lot of the same code. This is a really interesting idea... I might take a stab at this over the next few days, time permitting. |
Awesome, let me know if I can provide any assistance! When it comes to matters of timing you'll have to rewrite some parts to use the dance of the clocks, which I would be more than happy to tackle with you. |
I'm no stranger to the dance of the clocks -- I've actually already written a ClojureScript library that is essentially a port of WAAClock, a scheduling library that uses a combination of setTimeout and the WebAudio API clock to get more precise scheduling. I'll get cracking on this soon -- will keep you posted! |
Heh. 👌 |
I went ahead and took an initial stab at this: https://github.com/alda-lang/alda-cljs It doesn't do much yet, but I've got a basic parser set up with Instaparse, and a public function that will parse a string of Alda code and return & print the parse tree: The It occurred to me when I got to this stage that ClojureScript doesn't have (Aside from not being able to use |
For replacing eval, you could use the bootstrapped compiler in Should be able to execute without eval for regular |
This looks awesome! Once the parser (emitting JS code) is in place, I would be happy to hook this up with http://mudcu.be/midi-js/ in order to provide a MIDI playback. Midi.js supports multiple outputs, including Web MIDI and Web Audio (via mp3/ogg samples). |
@daveyarwood what do you think about creating a |
@ondras Awesome! This is really exciting, and makes me want to get the score-emitting piece in place as soon as possible. Once that's done, you and @kylestetz can team up on hooking it up to MIDI.js. @crisptrutski I'm very much in favor of that idea. It would be good for the two versions to share as much code as possible. |
If you have some sample data in the form of those emitted JS arrays (i.e. a JSON representation of the AST), feel free to post it somewhere. I can start transforming those into a set of midi.js commands, without having an access to the full cljs alda/parser port... |
@ondras here you go, bonus points if you identity it :P
Using http://www.freeformatter.com/javascript-escape.html#ad-output is quite convenient to just paste example scores into the console, then just used |
Thanks a lot! I will give it a shot hopefully tomorrow, if I find some time. As far as identification goes, the JSON is too abstract for me :-) I will have to wait until I have something that actually plays music before I can identify it. Also my general MIDI knowledge is not great, so I will have to study some more (the timing is still puzzling me - I am supposed to periodically schedule playback of some notes, wait a bit, check the time, schedule more notes, rinse & repeat ... ?). |
@ondras the timing can fortunately all be dealt with in advance... the way the alda REPL works is by executing a line at a time, so you'd be able to schedule that entire line to play. The |
Right, I understand this. But once I have a JS state machine that interprets those arrays, I am not sure if I am free to buffer all notes to midi.js at once (before the playback actually starts), or if I shall batch those "play on"/"play off" commands using some time windows and setTimeout calls. (Of course, this question belongs more to the midi.js project, but I was curious how this stuff is handled in general.) |
I would advocate for sending it all in advance and letting midi.js deal with the timing (since it does that already). |
I will definitely try that as a first attempt :) |
So, @crisptrutski , I have a very first testing version available at http://tmp.zarovi.cz/midi/. It kinda works in latest FF and Chrome, other browsers are untested. I apparently somehow screwed with timing -- the default tempo seems to be too fast. That's why I introduced -- for debugging purposes -- the Duration multiplier input. When slowed 5x (or 10x), the sound sounds appropriate, although I am still unable to identify the piece :-) Also, many features are not supported or implemented at all. Volume/velocity is weird, only one instrument (grand piano) is supported, only default rest durations are available. What next? Shall I create an alda-lang/... repo and push my player code there? I would appreciate some more consultations re. alda syntax / semantics to fix my code as well; do we have an IRC / discussion group? |
@ondras exciting! Will check it out later, bit tied up right now. I'very also been thinking a it would be nice to get a discussion group going, but my preference is for gitter or slack. This repo is accumulating stars quickly, and curious to hear more voices 😄 |
For a mailing list, might be worth trying ou clojureverse |
Ha, the tempo issues has been probably solved -- the |
@ondras checked it out, sounding good! @daveyarwood what do you think of a PR to bring the JS straight into https://github.com/alda-lang/alda-cljs for now, and we can port it to CLJS "in the open" for people who're interested in seeing the process |
I would suggest creating a separate repo instead: this JS player has little relation to the alda language itself; it also depends on the midi.js code (preferrably as a git submodule). Finally, the player repo could leverage GitHub pages hosting, providing a live demo/player page... |
@ondras That sounds right! Looks and sounds awesome, btw! 👍 I like the sound of what you're proposing -- we could make this a separate repo within the alda-lang org. We should make it clear that this feature is in alpha, since it will be improving a lot in the near future. I think you'll be able to greatly simplify your JS player code once we port more of Alda to ClojureScript. The parser will basically hand you a JavaScript object representing the score, which will contain an array of instruments with config info (the MIDI patch number, etc.) and an array of objects representing note events with precise pitches, durations, etc. which should be easier to hook up to MIDI.js, I think. |
✋ Officially declaring my interest in designing and helping to build the demo site. Can't do it right this minute, but over the next month I can put it together (collaboratively, with lots of help!). |
Cool, what repo name do you suggest?
Yes, this might simplify things. There are still several points (both in alda and midi.js) which are not completely clear to me:
I will be attending the Web Audio Hackday as part of the jsconf.eu extravaganza. This will give me one full day to hack on this project, potentially improving the web playback client -- adding support for more instruments, working on performance, visualizing the score using traditional notation via |
One more question:
Having some kitchen-sink example of all language features would be very cool for testing and improving on the player. |
Maybe To answer your questions:
If I have a minute, I might throw together a little demo .alda file that uses all of the available features -- would be handy for testing new implementations like this. |
Why not; I will wait till Monday (some other names might come in) and create the repo then.
If a song has four tracks (as in the sample JS data), these are all to be played via the same MIDI channel? (I am really not sure what the MIDI channel really means.) Consider no
Understood. Is the velocity "set once, use for all further notes" (similar to duration)?
Is the rest duration propagated to all following rests? Or even to all following notes? Are rest lengths also influenced by duration of the notes played before rests? |
Re:
Patches have to be set per-channel -- to my knowledge, it is not possible to have multiple notes played by different instruments in the same channel, at the same time. Re: velocity, yes, it is a "set once, use for all further notes until you set it again" kind of thing, just like pitch and duration. In terms of the JS score object, it will contain pitch, duration, volume, etc. information for every note, which should simplify things once we're at that stage. Re: rests: they work interchangeably with notes. They are influenced by the duration of notes and rests played before them, and they influence the duration of the notes and rests following. |
Actually, the JavaScript score object will also simplify things significantly so that we don't have to include the If you run |
Makes sense. And what about multiple parts/voices using the same instrument? Can these fit into one channel, or is it always "one channel per part/voice"? Generally, having a completely prepared score/note data sounds cool, but I do not require it. I believe some level of abstraction -- such as a JSONified AST -- might be generally useful, not particularly for my use case. Also, midi.js already provides the instrument <-> patch number mapping, so I can do this myself. Having "acoustic grand piano" in the intermediate format looks far more readable than "1" :-) |
Cool! I think what I'll do is make it so that the exported "parse" can take Channels are divided up by instrument part, not voice. So if you have a On Sat, Sep 12, 2015, 1:40 PM Ondřej Žára [email protected] wrote:
|
*the exported "parse" function On Sat, Sep 12, 2015, 2:21 PM Dave Yarwood [email protected] wrote:
|
The initial code has been uploaded to https://github.com/alda-lang/web-demo. I suggest closing this issue and using the repo's issue tracker for further progress. |
Added support for multiple (different) instruments. Not sure if the sample data sounds right ;-) |
@ondras That sounds right to me -- awesome! 🎻 🎶 I think since we've gotten cracking on this, we should close this issue and move this discussion to issues on the |
I am loosely aware of the ability, via clojurescript, to get clojure running in native javascript. If it's possible for the parser to be ported to javascript I would be happy to build the website that surrounds it and plug in the web audio API so folks can aldajam in the browser.
Any idea what would be involved in porting the parser to JS?
The text was updated successfully, but these errors were encountered: