-
-
Notifications
You must be signed in to change notification settings - Fork 291
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
Improve instance/group assignment + "." group-member operator #249
Comments
This is working as expected. The rules of instance and group assignment are a bit complicated, but I feel like they should hopefully work the way one might expect. The question is, what do/should one expect? To explain what's happening in each of the above scenarios: Example 1:
Example 2:
Example 3:
Now both piano instances are named, so they are both forced to be new instances. This makes perfect sense to me, but I admit that it's complicated, and might not make perfect sense to other people who use Alda. I can understand how in Example 2, one might expect "piano" to be available again as a new instrument instance after you named another piano, but the question is, is that the way it should work? |
The way I expected it was that an unnamed instrument was treated as its own instrument instance that was just called by the name of the instrument itself. so in the case of the code
what I expected was that But what happens when we modify the code slightly?
According to my expectations, all these instruments would play together. However, with the way things are now there's ambiguity as to which piano EDIT: oh, and also
this plays normally for some reason... |
Yeah, that does make a lot of sense. I think we should change it to make it On Jul 20, 2016 10:25 AM, "elyisgreat" [email protected] wrote:
|
I am going to refine my expectations into the following logic. I think it should be pretty intuitive, although I'd love to hear your thoughts on it an instrument call takes the form
|
Makes sense to me! 👍 On Jul 20, 2016 11:20 AM, "elyisgreat" [email protected] wrote:
|
Ok. I changed the blocking a bit to make it more readable. |
OK, so, after re-familiarizing myself with the code... One wrinkle about doing it the way you're proposing is that it would make it cumbersome to define new named instrument groups using all new instrument instances. The way it works currently:
If we made this change:
It's been a long time (years!) since I designed this system of instance assignment, but I believe this may have been my reasoning for making it work the way it does. Basically, the idea is that a "stock instrument" like |
Oh. I must admit I completely forgot about grouped instruments. I think for ungrouped instruments the logic I'm proposing makes the most sense. This, however is the problem:
This makes it very easy to make new instances of stock instruments within groups. There are problems with this, though, besides having a less intuitive instrument system. 1: You can't separate new instances of stock instruments created in groups. Consider:
Currently creates a new clarinet and flute, but what if you want to extract just the clarinet somewhere else? There's no way to refer to it unambiguously. 2: Recall that you can name instruments after other stock instruments. I'd imagine this is highly recommended against, however my proposed system would have no problem handling it. This creates a problem, though, because if one were to do something like this...
They would expect that no new instrument instances are created. But they would end up with a violin and a clarinet that they did not want. Personally, I think it's more intuitive that instrument grouping does not create new instances, as I see it more as bringing instruments together. However I can see why it may be desirable to do so. |
Separating instruments from a group could be achieved, if the implicit instrument name were a mix of the group name plus the instrument. e.g.
The second issue, where explicit names are created that might match implicit names, is a matter for the score writer. If you declare any instrument called "piano", any declaration of a new instrument with the same name should throw an error - whether that new declaration were implicit or explicit. The error helps the score writer discover what they've done wrong :-)
|
Hm. I'm not a huge fan of either of those ideas; the first one because many stock instruments have a The second one is a problem because I don't believe we should disallow users from naming instruments after other instruments, mainly because in the future plugins will allow more instruments and this could break alda scores when played in a separate alda client that has those plugins. I don't actually think it makes sense to ever create new instrument instances when grouping. when I think of grouping I think of bringing instruments together, not creating new ones. Unfortunately, this leads to some awkward code:
I don't know if most people would expect this. But it seems like the most intuitive behaviour to me. |
@jimcheetham said:
I like this idea. As @elyisgreat mentioned, there is some potential for naming conflicts, so I think what we would do is add a special operator for accessing members of a group. I think
I like this because it provides the new ability of accessing (previously "anonymous") members of a named group, but still keeps the syntax concise and elegant. I'm not sure yet what we should do (if anything) about the possibility of naming instrument instances after stock instruments and other instance names, but my gut feeling is that we should throw an informative error in both cases, like @jimcheetham said. I think that stock instrument names should always be available for creating new instances of that instrument, and if a score writer gives a name to an instance (or group of instances), then that name should always refer to that instance or group. @elyisgreat: One important thing to remember is that when you use a group, e.g.
This creates one piano and one violin. The piano plays On the other hand, if you give a name to the group, the semantics are different; it will create new instances for any stock instruments described in the group. Consider this score:
This creates two pianos and one violin. The second piano was created in order to be a part of this new group, Basically the idea is that if you're giving a name to a group, it's going to be its own entity with its own instrument instances, so as not to conflict with other instances that are doing their own thing. This is my fault for not making it clearer in the documentation / examples, but my general recommendation is that you can't go wrong if you name every instrument and instrument group that you use, the first time you use it, and then use the names from then onward. Mixing and matching named and unnamed things is a recipe for confusion. So, continuing with the same example, take a look at this score:
Like the last example, this also creates two pianos and one violin, but now it's extra clear that the first piano is a separate piano. Now from this point onward in the score, you are working with two separate entities, "piano1" and "piano2-and-violin," and it's easy to keep them separate in your mind as you're writing the score. So then, what if you wanted to break the violin out of the "piano2-and-violin" group and have it play something by itself? If we added an operator, you would have an operator like
I know this is a little awkward-looking, but maybe this is a good example of a situation where a "member of group" operator could help make the code cleaner and more concise:
I'm still open to altering the way this works, it's just difficult to adjust such a complicated system without unexpected consequences. It might end up being easier to fix this issue with a combination of better documentation and useful error-throwing when score writers attempt to do things that aren't recommended. |
All this is just making the system even more complicated than it already is. I think we should use my system, and just disallow any new instances to be created as part of groups. Otherwise I think we need a new, simpler system. |
Now that I think about it, instrument instance calling needs to be not only refined, but completely overhauled. Alda will eventually support waveforms, non-MIDI instruments, and plugins that may add even more instruments, and piling that on top of an already confusing instrument instance system will just add more confusion. |
I'm not opposed to radically changing the instrument assignment/reference I've played around with a syntax that was more explicit about creating a On Jul 23, 2016 10:26 PM, "elyisgreat" [email protected] wrote:
|
I think the way it works currently is intuitive, we just need to explain it better in the documentation. The first key thing that perhaps isn't clear enough in the docs is that assigning an alias is something you do when you create an instance or group. After that, you always use the alias to refer to the instrument. The second key thing is that you should not use a combination of named and unnamed things; if you name one thing, you should name all of them. Does that make sense? I'd like to talk about this and figure out where exactly the confusion lies, and improve our documentation so that it doesn't confuse other people. |
not sure. there's still the problem of plugin instruments though... |
I'm not sure what you mean by "plugin instruments" -- can you elaborate on that? |
Alda will eventually have plugins, which may add more instruments. so for example:
If a plugin is added that adds a stock instrument |
Oh, I see what you're saying. I don't think that will be problematic, though. Take the following score, for example:
The first line creates a piano and names it "violin" -- now
In this score, a piano called "violin" is instantiated on the first line, and continued on the second line. On the third line, the same instrument is continued again and nicknamed "violin-2". On the fourth line, it is continued again. *unless you use the stock instrument's full name The same logic will apply to any new stock instruments that get added as available instruments in Alda scores. For example, if we add a |
That doesn't make sense... In fact I would imagine that |
Here, on the first line, a piano is created and named "violin". On the second line, the same instance is reused along with a new guitar instance, to form the group named "piano-and-guitar." So, if the |
No, as it seems to violate this part of the instances doc:
Also, it seems confusing that two names can refer to the same instrument instance. |
Here's your problem:
You have the same problem with variable naming too - by insisting on an Madness: What would happen to instance names if you always required the "double piano "violin": c d e If you wanted the mix you suggested earlier, you'd do If you also signalled user's variable names with a marker, you wouldn't $hook = a b >c< As a programmer, I'm used to seeing that sort of syntax. -jim |
Ok; I think I have a pretty good compromise that should be pretty intuitive.
|
It seems like that's fairly close to what we have now, but with a couple of differences:
Re: the first point, I do like the idea of defining a behavior for that scenario, but I'm not sure if "most recently used instance of that stock instrument" is the behavior we want. That would mean that, in a score where you have multiple named piano instances, if you choose to use What if, instead of referring to the instance most recently called, the call would create (and then refer back to) a new instance? That would allow for one "anonymous" piano instance, alongside the named ones. For example:
That behavior seems it might be easier for newcomers to understand, and could possibly be more useful. Although, I would still recommend NOT mixing and matching named vs. unnamed instances; if you find yourself naming one instance, you should name them all. As for the second point, we would still have the problem of being forced to use an awkward syntax in order to create a named group of new instances:
Whereas currently you can just do:
|
I think the current system is intuitive as long as you don't mix and match named and unnamed things. What if we threw a descriptive error whenever you tried to do that? That way, newcomers to Alda would learn early how this works. |
Making mixing named and unnamed stock instruments of the same type illegal is probably the most intuitive and least ambiguous solution. One thing I would add is that I like the idea of calls of the form |
Here's the latest system more formalized: Two important points:
|
Another thing to mention; I'm assuming nested group operators would work; if you had code of the form
I would assume that And what happens if the stock instruments in a new group are the same? |
Nested group operators seems like an obscure use case, but I see no reason not to allow it. Seems like |
Yes, however consider this:
I reckon the second case should be made illegal, as it doesn't make sense to have the same instrument in a group twice. However the case of |
Sure, I could see it being useful to define a group of the same instrument playing in unison, for example if you wanted to emulate a chorus effect. I'm not sure how we should handle the
Now we're back to the awkward syntax where you have to define and name instances without giving them any notes to play, but maybe this situation is rare enough that it's acceptable. |
Agreed. Probably could update the ruleset for group calling stating that group calls to the same stock instrument or named instrument are not allowed. |
Sounds good to me. Updated. |
I should also note that in the case of unnamed groups, it is still possible to encounter a case where only some instruments are being created anew:
Should this throw an ambiguity error? |
No, that should re-use the same |
rules look good then! I'm interested in how the progress is going on the implementation... |
I've been very busy lately, and this issue is not a priority. A PR would be much appreciated, otherwise I'll get to it when I can. I think it will be a while. |
How would that work? |
The logic for determining which instrument instances to use/create when calling a part is all in the alda.lisp.score.part namespace -- |
If you're wanting general info about how to create a PR to a project on GitHub: https://help.github.com/articles/creating-a-pull-request/ |
Thanks! If I can figure out the clojure, I'll take a look. |
Awesome, sounds good! I realize it's a lot to ask of anybody to learn a new language just to contribute to an OSS project, and I feel bad that I don't have more time to tackle all of these Alda issues, but I'm basically working on Alda by myself, and there's only so much one person can do :) |
The clojure still goes over my head for me (although even if I knew the language it would probably be faster to write it yourself than me ask about all the contextual information). I could, if you'd like, write some java pseudocode to simulate calling instruments to a score. You might want to assign this to a contributor with some time who actually knows the language :P |
No worries! This shouldn't be hard for myself or another Clojure-savvy contributor to knock out -- the only obstacle for me is finding a pocket of free time :) |
Still interested in the pseudocode? |
Sure, that could be helpful -- I would just put it in a gist or pastebin or something so this issue doesn't get too noisy. |
The code started turning into a mess rather quickly, so I think I'm going to leave it up to you. sorry about that. |
Not a problem - we'll see what we can do!
|
1.0.0-rc46 is out, incorporating the changes described above. I've updated the docs as well, summarizing the rules in what I hope is an intuitive way, with examples. I'm pleased with the state of part and group assignment in Alda now, but I'm happy to discuss further if anyone has any questions or points of confusion going forward! |
Consider the following code:
When played, it plays normally. However, if I switch the declaration of the instruments at the top
piano1
does not start playing untilpiano
has finished its melody. The order of the melodies at the bottom does not matter, sowill play
piano1
first and then playpiano
.And if they're both named, there is no problem. both of the scores below play normally.
The text was updated successfully, but these errors were encountered: