From: Tom B. (Tehom) <te...@pa...> - 2013-09-24 16:32:16
|
> (On the broader issue, I can't find anything in Rosegarden that makes me think we handle importing triplets from MIDI correctly. I'm dealing with triplets that aren't triplets, with all kinds of superfluous and incorrect properties. I despair of fixing it short of a marathon session hand hacking the XML. Blah.) > [And from your wiki edit] > I tried to turn all the triplet 8th notes into > quarter notes with Ctrl+4. They all became dotted quarter notes! (It's worth > noting that no 3 show up in the interface anywhere, but the events have duration > 320, so they are triplet 8th notes. This file seems to have confused Rosegarden > mightily. It's basically a piece in 9/8 that everybody writes in 3/4 with a solid > wall of triplets for some reason. I thought to just put the piece in 9/8, but that > didn't work out either. I have bumped into that too. It's basically due to the way we represent triplets and other tuplets. We have this hybrid representation that we don't really keep in sync. A triplet is both some properties in the note (tupletbase, tupletcount) and an indication-type event, which shows the triplet span, the thing that says [3]. That would be perfect if you never edited a note after it was inserted. We do some stuff to extend the triplet indication if you insert a note after it, but IIUC that's about all we do to keep it in sync. So your quarter notes still "know" they are triplets, and represent themselves accordingly. MIDI import probably never sets those properties. ISTM all of the event time-changing operations should erase the tupletbase and tupletcount properties (or reset them, for triplet/tuplet). MIDI import and note-/rest-merging ought to be smarter about those properties too. Some beaming problems come from that hybrid representation. If you re-beam anything about tuplet group, you destroy the indication, so the note will still think it's a tuplet but there won't be an indication. We do something to shorten them when contrasting notes are added, but it ends up fairly messy. I have some true abominations in my files, eg whole note rests that think they are septuplets. Towards fixing it? ISTM the cleanest way is to completely redo tuplet indications whenever they might be munged. Make the note properties the Real Thing and make the indications follow them. This could be a dirty region in a Segment. We'd dirty that when we place a note, and at some point before we redisplay we would erase all the tuplet indications in the dirty region and put appropriate indications in place according to note properties. For tough cases (2 against 3 on the same staff) we'd need to make sure every vertically-aligned note had the same tupletbase and tupletcount. Shifting a segment by a fraction of a bar should dirty the whole Segment. Then we have to deal with tuplet indications that are halfway in a dirty region. We could either: * make dirty regions begin and end on bar lines. It doesn't handle "Everything's Coming Up Roses" and the occasional Chopinesque run of 23-in-2-measures. * expand the dirty region to cover existing tuplet indications. We also have problems with editing in the presence of other notes. Something about tuplets erases the following note. I once thought it was because they don't have neat end-times divisible by 480, but it sometimes happens even for triplets. Tom Breton (Tehom) |
From: D. M. M. <ros...@gm...> - 2013-09-24 22:29:12
|
On 09/24/2013 12:32 PM, Tom Breton (Tehom) wrote: > I have bumped into that too. It's basically due to the way we represent > triplets and other tuplets. I kind of slowly halfway started to figure that out. > We have this hybrid representation that we don't really keep in sync. A > triplet is both some properties in the note (tupletbase, tupletcount) and > an indication-type event, which shows the triplet span, the thing that > says [3]. I guess it's more like a specialized beam group, even for notes that can't be beamed. There's a beam group, and there's a different sort of beam group just for tuplets that results in the 3 (etc.) being drawn. What you end up with all the time is notes that have tupletbase/tupletcount but they aren't part of one of these groups. This is apparently a common enough problem that an old way of dealing with it exists, which is to use the Make Tuplet dialog and [x] timing is already correct. That fixes up the events. The problem is, it takes a segment and an event start time, and it computes time plus duration_of_thing_I'm_making and stops there. If you disable the stop, it will run to the end of the segment making tuplets out of everything in sight. The other problem is when everything else is mostly correct already (eg. these very precise triplets that have the properties but aren't part of a tuplet group) the dialog is just nuts to use that many times in a row. I actually dealt with this by hacking the source temporarily to make that checkbox checked by default, and even then I had to go wiggle various controls 102 times (or will have once I finish the B part). Barf. > So your quarter notes still "know" they are triplets, and represent > themselves accordingly. MIDI import probably never sets those properties. It apparently does. All these notes had the tupled/untupled properties set, and were mostly tuplets, which is why I got all the weird results trying to change the durations. Using the Untuple function clears all that crap out, but a typical user would never know they're even tupled, unless we want to extend the definition of "typical" to mean a user familiar with the extremely dangerous advanced event editor, also known as the make Rosegarden crash dialog, or one familiar with reading XML in the .rg file. Yeesh. > ISTM all of the event time-changing operations should erase the tupletbase > and tupletcount properties (or reset them, for triplet/tuplet). MIDI > import and note-/rest-merging ought to be smarter about those properties > too. The Ctrl+2 (for example) Make Half Notes or whatever and its various kin should probably clear out the tuplet nonsense, or perhaps just ask the user. "Hey mate, I found some tuplet nonsense. Were you wanting to keep that, or what?" > Some beaming problems come from that hybrid representation. If you > re-beam anything about tuplet group, you destroy the indication, so the > note will still think it's a tuplet but there won't be an indication. Right. Just changing the beaming arrangement around fundamentally alters this, which is very bad, since LilyPond export won't know what to do with these notes unless the tuplet groups are set properly. They export as non-tupled versions of themselves, and everything goes all to hell. I suppose if we can't make the data stream less full of garbage, the least we could do is make the LilyPond export smarter about looking for the properties, and using them to determine whether a note is a tuplet or not. > Towards fixing it? ISTM the cleanest way is to completely redo tuplet > indications whenever they might be munged. Make the note properties the > Real Thing and make the indications follow them. Some kind of automatically applied go back and fix up the events that have tupled/untupled but aren't in a tuplet group seems like the path of least resistance, if not the cleanest solution. There's the whole problem of many years of legacy cruft floating around out there to consider, which makes it harder to get really inventive. > This could be a dirty region in a Segment. We'd dirty that when we place a > note, and at some point before we redisplay we would erase all the tuplet > indications in the dirty region and put appropriate indications in place > according to note properties. For tough cases (2 against 3 on the same > staff) we'd need to make sure every vertically-aligned note had the same > tupletbase and tupletcount. Shifting a segment by a fraction of a bar > should dirty the whole Segment. I'm thinking this is probably one of those things where it turns out trying to do it automatically is too much wishful thinking, because of all the edge cases where it doesn't work out right. An equivalent of Ctrl+N to go back and normalize the mutilated rests in a slightly quirky segment might be appropriate here. Some function users can run manually, "Recognize and group tuplets" or something. Maybe run this automatically in certain contexts too. I don't know, I might not be thinking big enough. You're the mad genius, and I tend to be more conservative and much less bold. > Then we have to deal with tuplet indications that are halfway in a dirty > region. We could either: > > * make dirty regions begin and end on bar lines. It doesn't handle > "Everything's Coming Up Roses" and the occasional Chopinesque run of > 23-in-2-measures. > > * expand the dirty region to cover existing tuplet indications. > > > We also have problems with editing in the presence of other notes. > Something about tuplets erases the following note. I once thought it was > because they don't have neat end-times divisible by 480, but it sometimes > happens even for triplets. It depends how you create the tuplets, I think. It's cleanest to enter new ones putting the editor into triplet insert mode before you put any notes there. (I'm not sure off the top of my head if there's a generic tuplet insert mode. Probably is.) When you do this, the notes are born correctly. The alternative is to take existing normal full length notes and make a tuplet out of them, which pulls them back and leaves odd holes in time. (This does not work if the "normal" notes are actually munged tuplets with missing groups.) I've found in practice the latter method never produces good results. Nothing will ever fall neatly around tuplets manufactured in this fashion, and you're better off erasing everything and drawing it from scratch using the tuplet insert mode. Same thing used to be true of grace notes. You made them by drawing normal notes, and then grace-ifying them, which just never fell well with anything, and resulted in notation that was constantly messed up in subtle ways. The original grace note implementation was such crap it was almost impossible to use. The new implementation, off the top of my head, consists of making the things by inserting them that way from the beginning. There's a lesson there, but grace notes are rare, and tuplets common as mud. We need something that doesn't break a million existing compositions, except to the extent it might show up problems like your septupletified whole rests and other garbage that was always there but never visible before. OK, just writing off the cuff here, not thinking deeply. There could be big holes in my thinking. -- D. Michael McIntyre |
From: Tom B. (Tehom) <te...@pa...> - 2013-09-25 02:37:45
|
> I guess it's more like a specialized beam group, even for notes that > can't be beamed. There's a beam group, and there's a different sort of > beam group just for tuplets that results in the 3 (etc.) being drawn. Yes. For some reason I thought that was an indication, but a quick look at BaseProperties shows me that you are right, it's a specialized beam group. >> So your quarter notes still "know" they are triplets, and represent >> themselves accordingly. MIDI import probably never sets those >> properties. > > It apparently does. All these notes had the tupled/untupled properties > set, and were mostly tuplets, which is why I got all the weird results > trying to change the durations. Hmm. That stuff isn't set in MidiFile or Segment::insert, so I wonder what's going on. Probably a quantizer is working on it after that. Yes, createDocumentFromMIDIFile uses EventQuantizeCommand. So ISTM whatever MIDI import weirdness is happening is due to a quantizer. Bad news: Looks to me like NotationQuantizer is already doing it kinda the way I described. It erases all those properties and recalculates tuplet groups. Obviously it's not working so well. There are some comments suggesting that the tuplet code there is not entirely right. > There's the whole > problem of many years of legacy cruft floating around out there to > consider, which makes it harder to get really inventive. Yes. I just searched thru the source for BEAMED_GROUP_TUPLET* and what I found is frightening. NotationQuantizer and SegmentNotationHelper each try to do everything, and Segment, NoteRestInserter, NoteInsertionCommand, and TupletCommand all fiddle with those properties. ISTM there should be only one module that handles the tricky stuff (group ID, etc), and everything else should call it. > I'm thinking this is probably one of those things where it turns out > trying to do it automatically is too much wishful thinking, because of > all the edge cases where it doesn't work out right. Yes, it could be. There are a ton of edge cases. OTOH, it might be the trick that allows us to separate concerns. Anyways, that might be moot. If the quantizer is buggy (and it clearly is) and we fix it, it can fix groupings - which it *thinks* it's doing now. Then there's much less need to do it automatically. >> We also have problems with editing in the presence of other notes. >> Something about tuplets erases the following note. I once thought it >> was >> because they don't have neat end-times divisible by 480, but it >> sometimes >> happens even for triplets. > > It depends how you create the tuplets, I think. It's cleanest to enter > new ones putting the editor into triplet insert mode before you put any > notes there. (I'm not sure off the top of my head if there's a generic > tuplet insert mode. Probably is.) When you do this, the notes are born > correctly. Yes, I find that's cleanest way to do it. With larger tuplet groups, if a note follows it I have to find an empty bar, insert everything there, then copy it to where it is supposed to be. Tom Breton (Tehom) |
From: D. M. M. <ros...@gm...> - 2013-09-25 11:03:26
|
On 09/24/2013 10:37 PM, Tom Breton (Tehom) wrote: > Yes. For some reason I thought that was an indication, but a quick look > at BaseProperties shows me that you are right, it's a specialized beam > group. Hairpins, ottavas, slurs, things like that are indications. They have a beginning time, an end time, but no pitch. Tuplets have pitch, and they're often grouped together, so I suppose that's why Chris decided to hang that functionality off of the beaming logic. > Hmm. That stuff isn't set in MidiFile or Segment::insert, so I wonder > what's going on. Probably a quantizer is working on it after that. Yes, > createDocumentFromMIDIFile uses EventQuantizeCommand. Now I remember. > Bad news: Looks to me like NotationQuantizer is already doing it kinda the > way I described. It erases all those properties and recalculates tuplet > groups. Obviously it's not working so well. There are some comments > suggesting that the tuplet code there is not entirely right. It's getting the tupled/untupled just fine in THIS case, which is probably one of the more optimistic ones. I'm pretty sure this file I snagged was machine-generated. So what's missing is the grouping. The best case is Chris almost had it figured out, and we just have to bridge a little tiny gap. The worst case is we have to tear down the walls and rethink everything. > Yes. I just searched thru the source for BEAMED_GROUP_TUPLET* and what I > found is frightening. NotationQuantizer and SegmentNotationHelper each > try to do everything, and Segment, NoteRestInserter, NoteInsertionCommand, > and TupletCommand all fiddle with those properties. ISTM there should be > only one module that handles the tricky stuff (group ID, etc), and > everything else should call it. I wholeheartedly agree that's how it should be. Whether it's worth the effort to refactor all of it is another matter, I suppose. > Anyways, that might be moot. If the quantizer is buggy (and it clearly > is) and we fix it, it can fix groupings - which it *thinks* it's doing > now. Then there's much less need to do it automatically. Fix the quantizer, and we solve a lot of problems. The first thing I did trying to resolve this mess automatically was try the quantizer. The notes were obviously lined up with perfect mathematical precision, and it should have been an easy job to sort it out. This rabbit hole may or may not get tied up with automatic beaming. If it does, that's something that has been on my list of most hated bugs for nigh on 10 years now. Automatic beaming has a lot of bugs, and frequently does an awful job. I scarcely know where to begin on that one though. I've looked into it once or twice, and always slammed the lid shut and walked away. I bet they're closely related, but that's just a hunch. > Yes, I find that's cleanest way to do it. With larger tuplet groups, if a > note follows it I have to find an empty bar, insert everything there, then > copy it to where it is supposed to be. If it makes you feel any better--and it does me--I ran into a situation like that with MuseScore. I really want to love it so much I ditch Rosegarden and switch teams, but every time I get into some tricky situation I realize that doing notation with computer is just a bitch no matter what you do, and no matter who you are. Rosegarden is a big ball of quirks, hacks, and workarounds at this point, but it still has the home team advantage. Incidentally, now that I've spent some time with the development tree of MuseScore, I think it's appropriate to start taking Rosegarden in a direction where we work with LilyPond more closely instead of fighting against LilyPond. We have been heading down that road for a long time, but instead of implementing native versions of a bunch of things, I think we should just add more non-native things, and make it all easier to work with. I'm starting to get funky ideas, like a dialog where you can zoom in on an individual note, and it shows up like a character in a video game with little slots where you can put things from a palette. There are six slots where you can put a fingering, you can toggle every kind of mark, flip the stem, and whatever else comes to mind; all closely coupled to LilyPond in the end, with our on-screen display just essentially a crude rough draft that doesn't even attempt to show a lot of these things. We might have been better off on micro-positioning of various notation elements coupling it more closely to LilyPond, for example. What we've got in practice now attempts to translate across two totally different and unrelated scales, and it's quirky. MuseScore has taught me that you can have 500,001 excellent features that allow massive precision in positioning and tweaking everything, and you can have all that and your printed notation still looks crappy compared to LilyPond. -- D. Michael McIntyre |
From: Tom B. (Tehom) <te...@pa...> - 2013-09-25 22:01:05
|
> On 09/24/2013 10:37 PM, Tom Breton (Tehom) wrote: > >> Yes. For some reason I thought that was an indication, but a quick look >> at BaseProperties shows me that you are right, it's a specialized beam >> group. > > Hairpins, ottavas, slurs, things like that are indications. They have a > beginning time, an end time, but no pitch. Tuplets have pitch, and > they're often grouped together, so I suppose that's why Chris decided to > hang that functionality off of the beaming logic. I get that beaming and tupleting often go together, but it brings in so many edge and corner cases. I was just looking at BeamCommand and BreakCommand, which bring in yet more issues. In many ways our work would probably be simpler if beaming and tupleting were treated separately. But then display would be trickier, since NotationGroup wants to handle both types of grouping and tuplet groups use the beam line when it's available. So how to separate concerns? We really have three concerns: * Display-wise beaming, just what BEAMED_GROUP_ID indicates now, what NotationGroup understands as beaming. * Groups of notes that want real, honest beams, or that don't. * An individual note's or rest's notation-wise duration, including an idea of M-in-time-of-N. This is just one note's time, ignoring other notes. Basically what {NOTE_TYPE, BEAMED_GROUP_UNTUPLED_COUNT, BEAMED_GROUP_TUPLED_COUNT, BEAMED_GROUP_TUPLET_BASE} indicate now. We could separate the concerns as follows: * Something (NotationQuantizer or SegmentNotationHelper) has the responsibility to create and maintain coherent display-wise groupings. It must maintain tupleted notes in properly time-aligned groups, and is allowed to split and tupletize notes and rests to do so. It is the only thing that may set BEAMED_GROUP_ID. It is allowed to ignore or punt impossible requests for real beaming, eg requests to beam tuplets of incompatible ratios together. * NotationGroup and ?? that feeds it are allowed to read all those things but not allowed to change them. It is allowed to give priority to BEAMED_GROUP_ID rather than do tricky things. Eg if given a quintuplet that wants to physically beam notes 1&2 and 4&5, it could display it as one beamed group of five. * BeamCommand, BreakCommand, etc can request real beaming to their heart's content, regardless what tupleting is in place. * Inserters, squashing, duration-changes, etc can change the notation-wise duration freely, regardless of beaming or lack of it. What do you think? Does that seem like a reasonable separation of concerns? >> Bad news: Looks to me like NotationQuantizer is already doing it kinda >> the >> way I described. It erases all those properties and recalculates tuplet >> groups. Obviously it's not working so well. There are some comments >> suggesting that the tuplet code there is not entirely right. > > [NotationQuantizer] is getting the tupled/untupled just fine in THIS case, which is > probably one of the more optimistic ones. I'm pretty sure this file I > snagged was machine-generated. So what's missing is the grouping. Hmm. When I wrote that, I had just tried the quantizer on some hand-made triplets, and it turned them into a chaos of dotted notes. There's something that it's not doing right. It's not simply ignoring grouping, though. NotationQuantizer erases and resets BEAMED_GROUP_ID and the tuplet properties. >> Yes, I find that's cleanest way to do it. With larger tuplet groups, if >> a >> note follows it I have to find an empty bar, insert everything there, >> then >> copy it to where it is supposed to be. > > If it makes you feel any better--and it does me--I ran into a situation > like that with MuseScore. I really want to love it so much I ditch > Rosegarden and switch teams, but every time I get into some tricky > situation I realize that doing notation with computer is just a bitch no > matter what you do, and no matter who you are. FWIW, I found exactly where that happens, in NoteRestInserter::doAddCommand. In order to fix other bugs, we added code that first places a double-duration rest. I'm not at all sure that fix was worth it, for many reasons. Tom Breton (Tehom) |
From: D. M. M. <ros...@gm...> - 2013-09-25 23:13:41
Attachments:
evil-rhythm.png
|
On 09/25/2013 06:00 PM, Tom Breton (Tehom) wrote: > I get that beaming and tupleting often go together, but it brings in so > many edge and corner cases. I was just looking at BeamCommand and > BreakCommand, which bring in yet more issues. I dreamed up an evil edge case I've never encountered in the real world, and rendered it in LilyPond. [See evil-rhythm.png] It should have worked, and it did, because the bar counts perfectly well, even though that would be really awkward to count in practice. In principle, entering this figure into Rosegarden ought to work like: 1. Go to triplet insert mode 2. Click 8th note duration 3. Click 8th note into existence 4. Leave triplet insert mode 5. Click quarter note duration 6. Click quarter note into existence 7. Repeat 1-6 until finished What actually happens is: 3. Click 8th note into existence You get the 8th note, a triplet spanner, and two 8th triplet rests. (MuseScore does the same thing). 6. Click quarter note into existence You get a triplet quarter note of duration 640. I think this example says a lot about how Rosegarden is thinking, and why this is all such a mess. My made up example is not an important benchmark in of itself, but striving to be able to enter a figure like this seems like a good use case. Tupletness and beamedness would have to exist independently of each other, which would simplify some of our work and make other work harder. > What do you think? Does that seem like a reasonable separation of concerns? Yes no maybe. I think you've about got it right, but I've got some ideas trying to coalesce that just won't form right at the moment. I want to give my head time to simmer. I'll come back to this. -- D. Michael McIntyre |
From: D. M. M. <ros...@gm...> - 2013-09-26 22:55:28
|
On 09/25/2013 06:00 PM, Tom Breton (Tehom) wrote: > What do you think? Does that seem like a reasonable separation of concerns? Yes. I've had time to ponder on it, and you've just about got it laid out. The big sea change we need is the ability for the individual, isolated note to be a triplet note and carry a 3 on itself independently of its surroundings. (How that scales to a note from a 22:2 tuplet is a question I'm not sure I can entirely get my head around. Would it have to show 22:2? I suppose so.) In my example project, all the properties are already set except the beam group. No beam group, no 3. Recognize the properties, and now the 3 comes. No changes to existing data necessary. Grouping them together ought to just be done automatically by the layout engine, with nothing to export. We could indeed do new tuplet brackets as indications, like you thought they were to start with, but these indications wouldn't be of much use in LilyPond export. LilyPond does a fine job of providing such brackets automatically. We'd want something so people can mostly play a score off the screen, but having it look good in LilyPond is the greater concern. If they could be 100% generated visible entities with no representation as any kind of events, it would greatly simplify keeping them in sync as edits are made. Recalculate. No crufty vestiges left over where a tuplet spanner indication is lingering in a now inappropriate area. Now my head is starting to hurt again imagining all the myriad possibilities, and the implementation details. If I were going to dive into this myself, I guess I'd start at the layout engine and start displaying a 3 on notes that are really triplet notes, even if they have no group ID. A lot of the rest of the code may not be perfect, and there's a lot to be said for consolidating all the tuplet-related nonsense in one unified manipulator, but on the whole I think most of it is basically working. The big limitation is needing to be in a group to display correctly. ALSO, to EXPORT correctly, which is a much bigger thing. The project in question, the durations were all just right, the groups were missing, and they didn't come out as triplets at all, or LilyPond would have fixed that stuff up. I'm thinking once that was possible, a lot of the rest of it would become more self-evident. This note should be taking a 3, but it isn't. Why not? Why are we getting funky dots here when it should be a 3? Meh, I'm late to work again, so I have to leave off. You're left with another unedited brainstorm. -- D. Michael McIntyre |
From: Tom B. (Tehom) <te...@pa...> - 2013-09-27 01:50:32
|
> On 09/25/2013 06:00 PM, Tom Breton (Tehom) wrote: > >> What do you think? Does that seem like a reasonable separation of >> concerns? > > Yes. I've had time to ponder on it, and you've just about got it laid > out. > > The big sea change we need is the ability for the individual, isolated > note to be a triplet note and carry a 3 on itself independently of its > surroundings. (How that scales to a note from a 22:2 tuplet is a > question I'm not sure I can entirely get my head around. Would it have > to show 22:2? I suppose so.) It can actually display tuplet marks on isolated notes - our display code doesn't try to count how many notes in a tuplet, so feeding it a "tuplet" of one event works. It's the rest of the code that believes that N-tuplets mean N events (or N events with distinct starting times) > Grouping them together ought to just be done automatically by the layout > engine, with nothing to export. We could indeed do new tuplet brackets > as indications, like you thought they were to start with, but these > indications wouldn't be of much use in LilyPond export. I've kinda abandoned the idea that they should be like indications because the display code is locked onto the idea that they are just funky beaming. > LilyPond does a > fine job of providing such brackets automatically. Yes, I was looking at how LilyPond handled tupleting. It can handle some pretty crazy bracketing. > If they could be 100% > generated visible entities with no representation as any kind of events, > it would greatly simplify keeping them in sync as edits are made. > Recalculate. No crufty vestiges left over where a tuplet spanner > indication is lingering in a now inappropriate area. There is a certain wisdom in that, especially since part of the complexity is driven by NotationGroup's need to be spoon-fed about beaming. But on the balance, I have reservations. * Rests are a big problem. They can't be display-only. So if we want rests to accomodate tupleting, as they do in eighth-note+quarter-rest triplets, we still have to understand and manage tuplets well before we display them. * If we can get it to work right, then I'd like to be able to feed the same organized information to the various other outputs (Lilypond, etc), rather than making them re-code all that functionality. Worst case, the various outputters would have all different bugs and so the user can have a document that looks perfect in notation and inexplicably won't work in the other outputs. > Meh, I'm late to work again, so I have to leave off. You're left with > another unedited brainstorm. Thanks for the evil example. It helped clarify what this stuff needs to do. Tom Breton (Tehom) |
From: Chris C. <ca...@al...> - 2013-09-27 10:13:52
|
On Fri, Sep 27, 2013, at 02:50 AM, Tom Breton (Tehom) wrote: > of one event works. It's the rest of the code that believes that > N-tuplets mean N events (or N events with distinct starting times) There shouldn't be any code that wants N events for an N-tuplet -- things like crotchet-quaver triplets would have been a normal use case from the start. (Though who knows what cruft has grown over the years.) Might be worth going over some of the early docs for this stuff, which can still be found in Subversion at e.g. https://svn.code.sf.net/p/rosegarden/code/branches/obsolete/docs/data_struct/tuplets.txt (there are various other interesting antiquities in that directory... they're mentioned on the wiki but with broken links to SVN). As usual, much of this springs from trying to make a sequencer-with-notation rather than a score editor. Some salient points: * The initial idea was that you should be able to play the notes and get the right results even if you didn't know about tuplets, so the base timings stored were for the performed rather than notated tuplets * It was a deliberate compromise to have tuplets as a kind of beamed group, even though they aren't always beamed. At the time it seemed worthwhile to get only one overarching type of structure even though it wouldn't allow some more sophisticated arrangements * and of course there are no group "objects", only group properties on events in a structure organised by time only. The group objects are invented on the fly from the properties by the notation engine when it renders something. A problem of course with this, particularly the final point, is that there's no way to mark the start and end of a group in a way that remains consistent "by itself" when events inside the group are added or edited. Also, the whole mechanism for beamed groups suffered from being adapted to try to pick up multiple simultaneous groups (with different group ids) in different "voices" in the same segment -- this was before we resolved the display of multiple segments on a staff. The code could have been much cleaner without this confusion. So although the basic design in terms of properties isn't great, it can be made to work better than it does and I doubt if it's worth trying to change it now. But the code that does all the crazy stuff is crazy. Chris |
From: D. M. M. <ros...@gm...> - 2013-09-27 12:11:42
|
On 09/27/2013 06:13 AM, Chris Cannam wrote: > But the code that does all the crazy stuff is crazy. That needs to be printed on a t-shirt. I hadn't thought about all the terrible stuff from trying to resolve polyphony. We may have figured out a way to work with overlapping voices in a more or less reasonable way, but somebody still has to go through imported/recorded MIDI and resolve all of this by hand. I wonder if anybody is clever enough to write an algorithm to resolve the individual voices and split them out automatically. Short answer: No. That little research project didn't last long. ScoreCleaner looks interesting. You know, after 11 years of this, spending $140 on a piece of software actually seems cheap. Now to talk them into producing a Linux version. Har dee har har. -- D. Michael McIntyre |
From: Tom B. (Tehom) <te...@pa...> - 2013-09-27 17:11:27
|
> > On Fri, Sep 27, 2013, at 02:50 AM, Tom Breton (Tehom) wrote: >> of one event works. It's the rest of the code that believes that >> N-tuplets mean N events (or N events with distinct starting times) > > There shouldn't be any code that wants N events for an N-tuplet -- > things like crotchet-quaver triplets would have been a normal use case > from the start. (Though who knows what cruft has grown over the years.) When you add another tripletted note to that crotchet-quaver triplet, RG believes that the new note is the third note in the triplet. Gives it the same group id, so display groups it all as one triplet. > Might be worth going over some of the early docs for this stuff, which > can still be found in Subversion at e.g. > https://svn.code.sf.net/p/rosegarden/code/branches/obsolete/docs/data_struct/tuplets.txt Thanks for that link! It filled in some of the missing pieces. > * The initial idea was that you should be able to play the notes and > get the right results even if you didn't know about tuplets, so the > base timings stored were for the performed rather than notated tuplets Right, that makes complete sense. Separating performance and notation times was a great idea. I mentally group tupleting information with the notation time information. > A problem of course with this, particularly the final point, is that > there's no way to mark the start and end of a group in a way that > remains consistent "by itself" when events inside the group are added or > edited. Right. That was the indication issue. Michael's evil example showed me that it's tricky to delineate them neatly. It could be done, splitting innocent untupleted notes to fully populate the tuplets. If there are only rests and one type of tuplet, the splitting points are fairly natural. It'd be considerably nastier if other counterpointing tuplets were present. What if we have 3-against-5? Split into 15-lets? Another nasty case is 4-in-3 groupings (or 8-in-7, 7-in-5, almost anything where the denominator isn't a power of 2). 4-in-3 quarter-notes in 4/4 could start on beat 1 ending on beat 4, or start on beat 2 ending on the bar line. We don't (can't, shouldn't) require the user to say where a tupleted group starts and ends. In a similar vein, it's possible for tuplets to just start at a bad place. Make a tuplet, cut it, put an eighth-note rest at the start of the bar, and paste the tuplet after it. Where should the tupleted group start, displaywise? There I don't think we have much choice but to display a bizarrely-timed tupleted group. Some of the evil examples are just the user's own fault and if they look bizarre in the display, so be it. All that leads us in the direction of complete ~laissez faire~, but ISTM that's not ideal. Reasonable tupleted groups ought to start neatly on beats no matter how they came to exist. Tuplets ought to be enterable normally regardless what else is in the Segment. So ISTM we should do more work to figure out healthy tuplets and less micro-management of them in the various other code. I've sketched some code but I'm not satisfied with it yet. Tom Breton (Tehom) |
From: D. M. M. <ros...@gm...> - 2013-09-27 22:02:28
|
On 09/27/2013 01:11 PM, Tom Breton (Tehom) wrote: > When you add another tripletted note to that crotchet-quaver triplet, RG > believes that the new note is the third note in the triplet. Gives it the > same group id, so display groups it all as one triplet. Enter as 8-4 in a triplet, and all behaves well. Enter as 4-8 in a triplet, and you always get the spanner encompassing a spurious dotted rest, and if you enter a note where that rest is, it becomes part of the "triplet" of a totally incorrect duration. I tested entering with the I-II-III keyboard shortcuts to ensure that "hold your mouth right when you click" wasn't a factor. The insertion point should be moving with mathematical precision, and the numbers are skewed in this case. If you avoid that rest, you can enter anything to the side of this figure, but you can't delete compress or quantize that rest away. Noticing this entry pattern might lead to a clue. What happens when you place the triplet 4 and then the triplet 8 that doesn't happen going the other way? > In a similar vein, it's possible for tuplets to just start at a bad place. > Make a tuplet, cut it, put an eighth-note rest at the start of the bar, > and paste the tuplet after it. Where should the tupleted group start, > displaywise? There I don't think we have much choice but to display a > bizarrely-timed tupleted group. Some of the evil examples are just the > user's own fault and if they look bizarre in the display, so be it. Moving segments, cutting out a range, pasting a range... All kinds of ways to shift things by a fraction of a something and send the whole thing cascading all to hell. This is one of the huge thorny things about notation-on-sequencer, but there is no easy to answer to a lot of this but the undo and quantize functions. > All that leads us in the direction of complete ~laissez faire~, but ISTM > that's not ideal. Reasonable tupleted groups ought to start neatly on > beats no matter how they came to exist. Tuplets ought to be enterable > normally regardless what else is in the Segment. Ought to be, within the limitation that users will still be expected to tread carefully. A notation-driven application would have more options for subtly shifting everything by 1/3 beat somewhere, but our start times are anchored to absolute MIDI time. If you overrun your gap, or don't fill your gap, you get into the same consequences as moving a segment or myriad other subtle things that can knock everything out of whack. > So ISTM we should do more work to figure out healthy tuplets and less > micro-management of them in the various other code. I've sketched some > code but I'm not satisfied with it yet. I've gotten busy at work again, so any hope I had of getting involved with that particular code is diminishing rapidly. I still plan to twiddle a few things, and I have a mind to push the release back to December and make it an interesting one this time. -- D. Michael McIntyre |