Skip to content
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

Tonal.transpose() returns scale with notes in wrong register #50

Closed
heyaphra opened this issue Dec 8, 2017 · 7 comments
Closed

Tonal.transpose() returns scale with notes in wrong register #50

heyaphra opened this issue Dec 8, 2017 · 7 comments

Comments

@heyaphra
Copy link

heyaphra commented Dec 8, 2017

Working beautifully on my app in the key of C. Registral errors occurring when tranposing to other keys. Console logged some of these out:

Interval structure returned is correct.
myscale = Tonal.scale('major');
=>["1P", "2M", "3M", "4P", "5P", "6M", "7M"]

Great in the key of C.
myscale.map(Tonal.transpose('C2'));
=>["C2", "D2", "E2", "F2", "G2", "A2", "B2"]

We start to see registral problems when transposing to other keys.
myscale.map(Tonal.transpose('D2'));
=> ["D2", "E2", "F#2", "G2", "A2", "B2", "C#3"]

myscale.map(Tonal.transpose('E2'));
=> ["E2", "F#2", "G#2", "A2", "B2", "C#3", "D#3"]

etc...

Can't wait to introduce this functionality to my app! Thanks again!

@danigb
Copy link
Collaborator

danigb commented Dec 9, 2017

Hi @wildcat510

Thanks for reporting! 👍

But, as far as I know, this is the expected output. For example, "D2" transposed by a "7M" is "C#3"... The same can be applied to "E2" transposed by a "6M" or a "7M". In fact, "E2 major" is exactly the scale you obtained.

Am I missing something?

Regards,
Dani

@heyaphra
Copy link
Author

heyaphra commented Dec 9, 2017

A major 7th above D2 is C#2 in the same register— otherwise, we would be missing an entire note from the first octave of the scale. C major is correct because a major 7th above C2 is B2 in the same octave. If I'm transposing a C scale (or any scale) in octave register 2 to another key, the whole scale should stay in the same octave register unless I'm using the wrong method for transposing keys. All scales should be played linearly, steps 1 through 7, not steps 1-6 and then 7 an octave higher, or 1-5 with 6 and 7 and octave higher as this leaves the scale registers disjointed and incomplete. After all, in common practice scales are played 1-2-3-4-5-6-7 in the same octave. If you want supporting audio to demonstrate I can provide.

So just like myscale.map(Tonal.transpose('C2')); produces ["C2", "D2", "E2", "F2", "G2", "A2", "B2"], a uniform linear scale played from scale degree 1 to 7, I would expect the same of other keys.

Unless I'm missing something. Is this the right way to go about transposing scales as an entire unit to a different key?

@mrjacobbloom
Copy link
Contributor

The cutoff for register number is always C no matter what key you're in. C# above D2 is higher than the C that follows D2 so it's in the 3rd register. C#2 is the note below D2

@heyaphra
Copy link
Author

heyaphra commented Dec 9, 2017

So is there any way I can have scales in keys other than C laid out in a register theoretically consistent with the same way a musician would notate and play it? What is the reason for the cutoff at C if it produces scales inconsistent with common practice?

@danigb
Copy link
Collaborator

danigb commented Dec 9, 2017

Hi!

Yes, I think @mrjacobbloom is right here. In western music theory we use always C as the cutoff registry.

Another way to think about it is using interval sizes. For example, 7M is 11 semitones up. That's exactly the distance from D2 to C#3 (and the distance from D2 to C#2 is 1 semitone down).

I don't understand very well your explanation, @wildcat510 but It would help to have some external references or resources.

Anyway, you can always use pitch classes (note names without octave number) to avoid this problem:

["1P", "2M", "3M", "4P", "5P", "6M", "7M"].map(Tonal.transpose("D")) // => ["D", "E", "F#", "G", "A", "B", "C#"]

And you can use Tonal.Note.props to coerce to an octave: scale.map(note => Tonal.Note.props({ oct: 2 }, note)) or, if you are sure they are all pitch classes, a simple string concatenation: scale.map(note => note + "2")

Hope it helps
Regards
Dani

@heyaphra
Copy link
Author

heyaphra commented Dec 9, 2017

Looks like I misunderstood the transpose function's application. Concatenating pitch classes works.
Thanks guys!
-Nate

@danigb
Copy link
Collaborator

danigb commented Dec 9, 2017

Great! I'm going to close this issue, but feel free to reopen if something is not clear.

@danigb danigb closed this as completed Dec 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants