Tuesday, 29 November 2011

Beams & Ligatures

Feels like the principle of iterating through the array of elements to be drawn now needs to become more comprehensive.

When drawing a note, you draw it’s stem and then any tails needed, except if the next note in the array has it’s ligatures (aka beams) extended back to this notes tail.

Also you don’t draw a notes tails if it is to extend back to the previous note but you do need to know what type of note the previous one is and where it’s stem is.

So a note needs to know the properties of the note to it’s right, and to it’s left in order to draw itself.

Now this light bulb has gone on, the approach of adding context through parameters to the paint() method could get quite clumsy. It may be better to allow each note access to read the manuscript it’s part of.

Following this approach would mean a note would fix up to the array of notes, find out it’s index in the array, then use that to access it’s neighbours. This could be quite expensive in terms of CPU cycles to perform array lookups as it’s a serial scan through an array to find it’s index.

Should we worry about CPU cost in this day and age? How much will performance be dragged down by if there’s 200 elements in the array?

A more performant approach would be to provide the references to the next and previous notes, and staff elements (you need to know if your neighbor is a bar line as that changes your drawing behavior too). This is what’s been implemented in the code today, for now, using some funky referencing while performing a single scan of the staff elements array.

My remaining concern is what else will we discover needs to be provided at paint() time in the way of context that will continue to extend complexity here? I wonder how long it will take me to get up to speed on this piece of code in 3 years time between this blog, documentation and source comments!

Saturday, 26 November 2011

Ties, Binds and Slurs

Not necessarily what you’re thinking! Supporting these in our data model, controller and view in the component is trickier than suspected.

Recent experience has taught me that traditional design approaches such as figuring out the data path requirements is a good way to approach figuring out how to implement functionality in the component. Firstly, we need to figure out which object is responsible for drawing these. Of course, it’s view in the component that will trigger this.

Our options seem to be:

  • Store an array of ties in the data model and have the view do the drawing at it’s level. If we only have a central list, this would mean the controller needs to create actions to build and amend the list, and also ensure if notes were deleted that were referenced in the list that we don’t break the data integrity in the model. The controller could use a keystroke on a selection to mean check the array, if tie exists then delete it, if not then create it. 
  • Have each note store a reference to the note at the other end of a tie it’s part of, and the second note in a tie is responsible for drawing the tie. The controller could work by taking a keystroke on a selection to mean toggle any tie between the first and last notes in the selection.

Another consideration is a tie could actually impact any future playback feature we build in and we want to think to the future, creating a good base now. If it’s an irregular grouping we need to know at the note level if it’s in such a grouping, eg ply 3 in the time of 2. I imagine playback will be executed by iterating the array of notes so the ability to ask the note if it’s the head of a tie binding could be useful. If it’s not an attribute of the note itself, it means an array scan of any central tie array for each note we process.

Doesn’t sound like a good idea from that perspective. Given we need to store an attribute which is unique to a tie, i.e. if it’s an irregular grouping, what’s the count,, e.g. 3, meaning 3 in the time of 2, 7 in the time of 6 and so on, it sounds like we need a class anyway. The tie class would store the head and tail notes of the class plus it’s irregular grouping factor. It’s probably appropriate that the tie knows how to draw itself. Whereever the drawing is triggered from, either at the component view level or while iterating through each individual notes draw routines, it’s good to separate that capability I think. Next let’s consider a note may be part of more than one tie, it’s not seen often but it’s possible, so need to cater for it. This suggests the concept of an array of ties would be a good way to store this. Given we now have a class, then a list of them isn’t too hard to implement, the question that remains for me is do we have a master list of ties, or do tie lists exist only within the notes themselves. In the latter case the note class would have a list of ties that the note is part of. While drawing the note would iterate this list, figure out if it’s the tail in the tie partnership and if so tell the tie to draw itself. So certainly each note needs a link to the ties it’s part of – that allows it to delete the tie should it be deleted itself and we protect ourselves against orphaned ties – there’s a concept!

Lastly, the note, with it's list of ties which link it to it's partner note, needs to cater for when the tie crosses between staff lines. It will be able to detect this by checking the y co-ords of the staff lines each note connects to but it won't know if they're more than one line apart. We somehow need to either get it a reference to the list of staff lines or get the controller to prevent ties being created across more than two lines. This could be close to impossible, given the user could drag a tied note down a couple of lines.

May need to find that reference to the staff array. It could be passed through the paint() calls, as today's thinking also says we need to either pass the list of notes through or at least a reference to the prior note in the array, when a note paints itself. This is so it can figure out where to draw beams back to. Oh, apparently beams are called ligatures too - hadn't heard that before but then again it's only the RSPBA exams I took on theory, nothing more comprehensive!

And something else, what I've been calling accidentals are better referred to as grace notes, as accidentals only seem to affect pitch - not something us simplistic drummers can do on a kevlar high tension surface...

Monday, 14 November 2011

To scale or not to scale ...

Doing well here, bar lines and notes of all different values but I've not really adopted a scaling model. I.E. if the user makes the staff line longer, do I make the notes wider? If they make it taller, do the notes get taller?

I'm thinking the right way is perhaps to offer a "point" model like fonts. You can set the notes to 9-point, 12-point etc - whatever that translates to in music notation rather than characters.

I deliberately didn't want to implement the component around a text font implementation. I wanted to be able to have total control over look and feel, which is ironic if I'm going back to treating this like a font problem. Not sure I'd have had the fine grained control over how to display that the note is a buzz not a tap using the systems underlying fonts though. Danger is I'm reinventing a round circular object, I think I'll call it a wheel!

Saturday, 12 November 2011

Data Model Optimisation

Going really well building out capability within the JMusicComponent, however as features are added, it becomes clear that a more experienced GUI programmer would have used a different data model. I can see now that adopting almost a traditional database approach would work, now that the access paths to the data become clearer to me.

I'm not stopping development now to rewrite the data model and access methods - don't get me wrong, I really feel like I should as when I was being taught programming, the most efficient was of doing things was a must, or the programme would potentially be useless, however in todays age of comparatively extremely powerful processors, I'm surprised at how responsive the programme still is despite lot's of serially scanning arrays on many keystrokes.

Because of that, and a statement I made this week that I'd have a working prototype up and running this winter, I must prioritise adding function rather than optimising what already works. I'm looking to get some basic, but enough functionality up to start using the keyboard drumpad idea as an input device, ie go straight from drumstroke to score. I think the way this code is structured it will really lend itself to multiple different solutions with it that really differentiate.

That needs proving, so onwards!!

Saturday, 5 November 2011

Something to show at last

Just to remind myself from time to time that progress is being made!

Selection Shmelection

I think I've got it now. I was getting too bogged down in how to integrate menus into managing the contents of the component. Ignoring all that now - as long as I use actions as the basis of all change then I can figure out menu integration with those later - just concentrate on the component itself and it's keyboard and mouse interface. May have to include a state table to manage whether the actions are disabled or not at any given point - parked!

I have a new found respect for properly trained software engineers who write GUI components. Wishing I'd actually taken some formal training on this, rather than trying to learn by just reading loads of articles on the web. There's actually so much to take in to do this properly, and as none of my formal programming training was in GUI / desktop / UI etc the right way to structure and approach the multitude of problems is very confusing to try and figure out.

I've still got to figure out Undo Manager integration with the component, that dreaded drag and drop API, CCP (copy cut paste), then there's the whole zoom scaling problem which Java provides broken support for too - you'd think if you scaled the drawing it would scale the mouse co-ord for you too, right? Any clues on that one mightily appreciated - when the time comes to tackle that again!

Onwards ...