Closed jcard0na closed 5 months ago
Hi Javier, as someone who plays alto more than tenor, I'd like to take a look at the transposition function - but I had an idea for an alternative user interface. Rather than having to step up or down a semitone at a time, it'd be nice to be able to jump to a particular key - e.g. to switch to alto you'd enter transposition mode and then play an Eb. That'd be much easier than counting semitones.
The downside is that it makes the "menu" system more complicated. Instead of entering Mode::Control
and pressing up or down buttons (like your suggestion), you'd have to enter another mode. To prevent the user getting lost in the menu system, I think it'd make sense for transposition mode to be independent of control mode, so rather than
# Not this
Play Mode -> (Low Bb + draw air) -> Control Mode -> (Button?) -> Transpose Mode -> ....
You'd instead do
Play Mode -> (Low B + draw air) -> Transpose Mode -> Press keys for Eb + blow air (sets offset) -> Play Mode
What do you think? I'd be happy to have a go at the implementation once we've worked out the UI
I like your proposal a lot, definitely better than my first draft. Two things that come to mind:
Some people will probably want to change the transposition permanently. Currently the way to do this is by changing the default notemap. If one has a different notemap installed, selecting a transposition using absolute notes (e.g. Eb) will be trickier. The offset would have to be calculated relative to some note in the current notemap, and that note might have a different fingering. But I'm jumping into implementation details here.
Can you post your proposed approach as a poll in haxo-hw? There are some musicians that should have valuable feedback on your proposed interface.
Thanks!
Thanks Javier. I hadn't thought about the interaction with notemaps. I think there could be three options then
Keep notemaps as the main way of changing between different "instruments" (tenor vs alto) and keep this transposition option for simple things like +/- a semitone
Keep notemaps as is (i.e. the default is tenor), but use my proposal for changing the transposition. To calculate the offset, this would probably mean assuming the user hasn't changed the notemap
Redefine the concept of the notemap so the note output by the notemap is the "written note". I.e. fingering for Bb -> note map outputs a Bb. Then it would be up to the transpose offset to deal with the conversion from "written note" to "sounding note". This would mean there would be a single notemap for bari / tenor / alto / soprano, and you'd use my suggestion above for changing the transposition. We could then add a command line argument for the default transposition (so a user could configure their own haxophone to boot as a tenor or alto, etc)
I think (3) is the best option, but would be a breaking change for people that have written their own notemaps. They could get the old functionality by setting the "transposition" to zero on the command line, though.
Sorry to delve into implementation details a bit, but I though it worth running (3) by you first. I'll post a poll to haxo-hw if you agree that those are the three options I should mention in my post.
Thanks!
Hi Peter (and happy new year!),
Yes, I like your 3rd option above. Let me capture my thinking to explain why I like it. I see the following use cases for transposition:
UC1 A user wants to boot by default into their default transposition (e.g. Bb instrument) UC2 A user wants to temporarily change transposition until next change or reboot, for instance to play along a recording in an unfamiliar key
Considerations:
With that perspective, your 3rd proposal is an improvement in most fronts:
haxo.service
(e.g. --transposition -2
) instead of (1) the full contents of the notemap file and (2) the path argument (--notemap-file
) to haxo.service
Low B + draw air
for 1s to enter Transpose Mode
Eb
) that will be the new C
(hear the new C
)Transpose Mode
low B
with Transpose
. Since this might not be a frequently use feature, I can imagine people forgetting (i.e "Was it B, Bb, C#?"). But maybe someone out there can propose a mnemonic or even a different fingering to enter Transpose Mode
(Oh, I just realized that in English solfeggio, "B" is "Ti", so that might work as a good mnemonic. "Transpose" -> Starts with "T" -> Pronounce "Ti" -> "...sol-la-Ti-do" -> "B"... thoughts?)Thanks Javier, started a discussion here: https://github.com/cardonabits/haxo-hw/discussions/60
I don't have any better ideas about the mnemonic (and never learnt solfeggio)
I've got the first step working in a branch here: https://github.com/petermoz/haxo-rs/tree/transpose
In that, I changed the notemap to be in concert pitch (added 14 to everything), and then added the --transpose
CLI option (default to -14). So you can get an alto by changing to -9, bari with -21 etc. The impl details were pretty easy: I added a transpose offset to notemap.rs which is set from the CLI (and could be changed dynamically).
I'll still give some time for feedback on the discussion before trying to merge anything
I'm on the road for the next 24 hours, with limited laptop time, but I'll certainly take a look at this after that.
One quick question, though... If you switch from alto to bari sound in the pre-installed sound font, I think the sound is transposed by an octave already (based on my recollection, can't confirm right now). But if that is the case, wouldn't we just need to pick the relative transposition, without picking the octave? i.e. couldn't we just use --transpose -2
for all Bb instruments and --transpose 3
for all Eb, letting the soundfont pick the right octave? I suppose I need to dig deeper, just floating the question now in case that is something you had already ruled out before deciding we need -14, -9, -21, etc. values.
Thanks!
I tried out the different patches in the sound font and I'm pretty convinced there's no octave transposition going on. i.e. you hear exactly the same octave when playing the bari or alto patches. That makes sense to me, when sending a given pitch via MIDI you'd expect to hear the same octave regardless of what instrument is playing it.
So I'm pretty sure you need the separate -9 / -21 for alto / bari and -2 / -14 for soprano / tenor. Open to be convinced otherwise though, let me know what you think once you've had time to try (no rush)!
OK, back home, with some time to look at this. Yes, you are right, I just confirmed that the octaves do not change between instruments, just the timbre. My memory failed me. So 👍 for the -2, -9, ... proposal.
I also looked at the code and it looks clean and straightforward. Don't feel you need a lot more feedback before pushing your changes... so far you have unanimous support for your proposed approach! 💪
BTW, just a question that hit me as I was retiring for the day... In temporary transposition, how would one distinguish between alto and bari? Using the octave key? (i.e. low Eb for bari, mid Eb for alto (i.e. octave key), and even high Eb for sopranino (i.e. palm Eb)?) Sounds like the most intuitive approach, but wanted to confirm if that is what you had in mind as well.
Hi Javier, thanks for confirming -2, -9 etc.
I have a draft of some code that implements the "transpose mode" here: https://github.com/petermoz/haxo-rs/tree/transpose-mode It's not ready for a code review yet, but it works for testing out the concept.
Per the discussion above, play Low B and draw in air to enter transpose mode (haxo will do a double beep), then press appropriate keys and blow air to set the transposition (haxo will play concert "high C" and transposed "high C"), then the three left palm keys to exit.
Regarding the Low Eb for bari etc, yes that's exactly what I've done. "High C" is treated as the reference pitch, and then the transpose offset is set based on distance from the reference pitch. So playing a "High Bb" will set the tranpose to -2 (soprano), "Mid Eb" will give you alto, "Mid Bb" tenor and "Low Eb" bari. To set the haxophone to produce notes at concert pitch, you just play the reference pitch ("High C")
The one thing I don't like about this approach is that to achieve the full range of soprano to bari, it means the reference pitch has to be quite high (High C). So if your reason to use the transpose function is not to emulate a different kind of saxophone, but it's because you want to e.g. "put this chart up 1 whole step" then it feels a little weird that the reference is so high.
This makes me think that haxo might eventually end up with two different types of "transpose mode" - one for setting the type of saxophone, and then another one for nudging the pitch up or down one semitone at a time (like your original suggestion) that would be used when you want to "transpose this chart to a different key"
For now, though, I think this is a step in the right direction, so I think we should continue with this approach.
I'd probably separate the code into at least a separate function before doing a PR, but I'd be interested in feedback about the actual mechanism (e.g. which notes to "beep", what pressure to use as a play note threshold, etc). So please try my branch and let me know what you think!
Thanks Peter
Hi @petermoz
I just tried your branch. I did not look at the code, just trying to get the user experience. And it is great!
Things that I tried:
Regarding:
This makes me think that haxo might eventually end up with two different types of "transpose mode" - one for setting the type of saxophone, and then another one for nudging the pitch up or down one semitone at a time (like your original suggestion) that would be used when you want to "transpose this chart to a different key"
To me the simplest approach could be to use R1/R3
keys without requiring to blow a note (like for changing instruments) while in the current transpose mode. So, in transpose mode, one could:
R1
or R3
without blowing for +1/2 | -1/2 tone "fine" transposition. Same double beep feedback as 1.Implementing both in transpose mode should be feasible because R1
nor R3
alone are valid fingerings. In the remote possibility that someone defines those as fingerings on their notemap.json
, their definition would take precedence and shadow (disable) the "fine" transposition key. So, "fine" transposition would only be active if neither standalone R1
nor standalone R3
are defined in the notemap.
Probably the biggest risk I see is that while releasing a valid note, one could fleetingly press R1
or R3
and throw the transposition off by 1/2 a tone. Definitely not something one wants to experience live... :blush:
To prevent that, we would need to require a minimum press duration on those.
What do you think?
At any rate, I agree that fine tuning it can be implemented later, at your discretion. What you have now is a big improvement already. Great work!
Thanks Javier, "fine transpose" seems like a good idea. I'll have a look at that before submitting a PR for the transpose mode. In the meantime, I think it's worth submitting just the first part (notemap changes and --transpose
argument). So I'll send a PR now
Hi I'd like to offer some thoughts on "fine transpose" from the EWI world. It's not uncommon, rather it's a feature, for EWI fingerings to use the palm keys and left hand pinky keys for instant transposing +1or -1. Let's say on the Haxophone I have set R2
to be +1 and R3
to be -1, I can use any standard fingering on the notemap, and when I use any fingering in combination with R2
(and only in combination with R2
), the Haxophone would send the intended MIDI note +1. The same, but -1 for R3
. There is no feedback other than the fact that the user chose to hit that key, and the resulting sound. This should maybe not be enabled by default.
From this perspective, my suggestion for the "fine transpose" on the Haxophone is to use it in a momentary sense. Inside haxo.service
the user could define --fine-transpose
arguments according to their preferences. I suggest a format in the style of --fine transpose R2:+1 R3:-1 L2:+1 L6:-1
. The engine would not necessarily limit the user on how many of these transposing keys can be used, and using one +1 key in combination with another +1 key would result in a "fine transposition" of +2.
There is from this starting point the possibility of giving the user the option if they want to use momentary "fine transpose" or if they want to use it as a latching, incrementing mode - akin to what was originally suggested. That is, when I press a +1 key, the whole instrument transposes up +1 even when I let go of the "fine transpose" key. This could result in a haxo.service
argument that looks like --fine-transpose R2:+1:MOM R3:-1:LATCH L2:+1:LATCH L6:-1:MOM
or something like it.
Furthering on this, why limit ourselves to +1 and -1? What about something radical like --fine-transpose R0:+12:LATCH
and R4:-12:LATCH
? Why should the engine limit to only transposing in half steps, could this be arbitrary instead?
As an even further thought ahead, at point I'm dreaming: What if the Haxophone had a small vibration motor? That way, if the user wanted "latching" fine transpose, the instrument could give off a light vibration as feedback. So if the user is performing, this would not be interrupted or disturbed by the instrument beeping. Of course usable for the instrument selection mode and transpose mode as well.
There's a more in-depth article from Bret Pimentel about AKAI EWI fingerings. The rough idea of how something like it can be implemented on the Haxophone can be summarized by this comment. The AKAI EWI fingerings get a bit more specific in it's possibilities and it's basic principles, though.
Would love to hear some thoughts, cheers!
Hi @Ekolide - all interesting ideas, thanks for the link to the EWI article. Certainly the great thing about the haxophone is that all these things are possible.
For the "momentary" modifiers, it seems like you could achieve this with the notemap.json
. The notemap is just defining the mapping from a set of keys to a note, and a "set of keys plus a modifier" is really just "a different set of keys", so this could be mapped directly in the notemap. Obviously it would be painful to have to manually write a notemap that includes "keys" -> "note" and "keys + R2" -> "note + 1" for every set of keys, but you could write script to do that for you.
In any case, these are good ideas, but I don't plan to implement any of that here. I see the transposition for different saxophone types, plus (maybe) the fine transposition as the things I'm trying to achieve in this piece of work, and I'll leave the other modes you described to a future change.
Cheers Peter
Hey @petermoz! Thanks for a good and clear answer.
I certainly do not expect to get any or all of that implemented, but rather thought that voicing an adjacent idea is better than not voicing it. My current solution is, as you suggested, using the notemap. It is indeed painful to do it manually, but it's been effective once the notemap has been generated.
For what it's worth, I do think this sort of way of working with "fine transposition" is a serious solution for the problem that has been presented here. Certainly not a perfect solution, and I'd love to get some feedback on improvement, but it would be flexible and user-centric. I understand that I'm not developing the solution, of course the final say goes to whoever does that.
Thanks!
Suggested here:
https://github.com/cardonabits/haxo-hw/discussions/41#discussioncomment-7915720
This would be relatively simple:
Choose an unused control key combination like the ones used for changing instruments. For instance, table G# and table Bb for +1/2 and -1/2
Add transposition value to the function that translates fingering to midi note, see here