Github site | source documentation | change notes | application
Thanks to Nenad Strangar we now have nested tuplets!
This is the first major UI reboot. Originally, I didn’t even want to have a UI, I only wanted to focus on rendering and optimization, and let other people adapt the UI to their taste.
But at the same time, I didn’t make it so obvious how to do this. And it’s hard to get people to try Smoosic out if they have to first memorize a bunch of keyboard commands. Also, my own vanity doesn’t like having an ugly interface on my pet project.
Here are some highlights:
On the development side:
Where to start…Smoosic has been disassembled and reassembled multiple times. A project like this is never ‘complete’, but pretty much everything that I intended to do with Smoosic is now working, to some extent:
I have rewritten the SVG rendering so that each page is its own SVG element (Renderer context, in VexFlow terminology). This allows us to edit large scores more quickly, since each SVG element is smaller. The renderer will only update pages that have changed music.
I added basic part features like transposing score, part-specific text, multi-measure rests.
Music playback is sample-based. Original samples come from Electronic Music Studios and Sonatina Symphonic Orchestra.
Change to the way proportionality (softmax) is computed:
Merged latest vexflow (4.0.1) with Smoosic. There are some changes in the API signatures for note modifiers (accidentals, etc.) that will break against earlier versions of Smoosic. But the formatting improvements for Vexflow 4.0.1 over 3.0.x are worth it.
Also fix a few bugs with copy/paste.
Fix issues persisting part-specific layout, formatting, and key. Fix issues transposing in import/export musicXML.
I am trying to simplify and canonize the rules for what the configuration file needs to contain, in the process reducing hard-coded magic that happens when the library or application is bootstrapped.
These configuration parameters apply to both application and library mode:
scoreDomContainer
must specify the DOM element where the music is to be rendered, either string ID or HTMLElement.The changes to remote loader basically mean you no longer need to do any promise/waiting to render a score.
These apply in application mode:
The configuration file is no longer a global. It is passed as a parameter where needed - I thought this would help with support of multiple editing regions in the DOM - think CKEditor.
I removed the concept of ‘actions’ to record editing macros. I burrowed this from a DAW called Reaper. Reaper lists the actions you have performed so you can copy them and apply them to other tracks/channels etc. But this didn’t really work in Smoosic - the action is so dependent on the current selection that it wasn’t deterministic. It’s also probably not required - since this is a javascript application, you can do what you want to the score whenever you want.
I also removed all the instance details from the configuration object. Only DOM and configurable parameters are in the config object. The global Smo.SuiApplication.instance
object contains hooks to the global instance.
I’ve been going through the MusicXML samples and testing for round trip, features missing etc. Also comparing against MuseScore. There was some XML we were emitting that wasn’t correct according to the spec, and some which was just wrong or missing. Tempo, repeats, slurs, time signatures.
Round trip XML will always be a little bit ‘lossy’ since Smoosic does things a little bit differently than Finale.
I replaced the midi parsing function with the one from https://github.com/NHQ/midi-file-parser/. This code seems to handle running status correctly. I did some comparisons to MuseScore input and it is…comparable. I added variable quantization to different note lengths, and basic triplet support. It doesn’t support instruments so much, but instrument support in Smoosic in general is pretty raw.
I had hoped to finish MIDI import this week, but as usual I misunderestimated how hard it would be. The files exported from Smoosic import OK, except for tuplets. But any MIDI file from a performance or exported by another program is a crapshoot. I will need some logic dedicated to inferring the correct rhythms from the midi ticks.
All of the project files have been rewritten in Typescript. The UI, particularly the dialog and menus, have been redone in a more component-friendly way. I expect to create new pens that describe how to create new UI elements, and modify existing ones.
Smoosic now supports parts. Parts can consist of 1-2 adjacent staves. They can contain their own measure formatting, text, and page/layout settings.
There are a few different score-organization concepts that could get confusing:
Typescript migration underway. Most SMO files are already migrated. Pens have been updated to reflect the new build target. This is merged to main branch.
If you are using the library, the biggest change will be mangling the ‘Smo’ namespace in your references to Smoosic types.
2 ways to do a thing, right and over. Some aspects of Smoosic need a fresh iteration before I can go much further.
First big change, moving from concat to webpack. I realize now why people use it. There’s no other way to check for defined/unused symbols with a bunch of scripts that don’t know about each other.
Once I am in webpack-land, I can start moving the SMO music files to typescript. Right now it is too easy to pass an Ornament when an Articulation is expected, etc.
While doing this, I expect to revisit the object model. 2 things that I did not consider in the first go-round:
Out of consideration for those who use Smoosic currently, and fear that it won’t work out, I’m doing this work on a separate branch. I expect existing Smoosic files will be backwards-compatible. I will try to minimize the impact on existing codes.
Background Rendering, Lyrics/Multi-Voice/Scrolling improvements and bug fixes.
Rendering longer scores, even just a page or 2, was frustrating. It can take several seconds to re-render the entire score. We now render in the background, with a progress bar, allowing one to edit while the score is rendering. Full re-render timer is pro-rated on render time, so you get more editing time.
Fixed some bugs with xml import/export.
Added measure-add dialog, for multiple measures.
I’ve been thinking lately. My goal was to create a flexible music creation API that works in a variety of contexts. In some ways, the application is just a demo of the API. As the application gets more complicated, it becomes less customizable and embeddable. So I need to distinguish between Smoosic the application and Smoosic the API.
In some ways, Smoosic is similar to technologies like Vue or Angular, in that they update a DOM view based on changes to a document state, and visa-versa. In this case, the document is SMO, the JSON structure that represents the score. The DOM is the rendered music in the SVG. You can map events from the DOM and map them to artifacts in your musical model, and make changes to the model and have it rendered.
Therefore…Introducing the Smoosic API. I’ve made a few minor tweaks in the initialzaiton that make it possible to create a library version of Smoosic. This has no native GUI, so you can create your own, or just call the API and render some music.
I created the following pens to help demonstrate how to use it.
Smoosic API This creates a simple HTML container, and renders a score in it. It demonstrates the mimimal objects you need to create, and how to update the model in such a way that your changes get rendered.
Load Score This demonstrates how to load a pre-made score and render it.
Load Music XML Similar to the above, but with an Music XML score (finale format).
Simple Music Editor I’ve been asked how to embed the editor in CKEditor or some other application that has its own event model This example shows that. It implements a very minimal music editor, and shows how keyboard and mouse events are handled.
I have made a number of changes to the way Smoosic works, based on some feedback:
You can see Smoosic in action here:
Note: unit tests have been removed for now. Editor actions will be used to create a new set of unit tests for the modern age.
Instructions on how to use smoosic: Smoosic Wiki
If you want to contribute or hack, there is source-code auto-generated documentation