teoria icon indicating copy to clipboard operation
teoria copied to clipboard

Make it possible to create interval from semitones

Open automata opened this issue 7 years ago • 3 comments

I was looking for a way to create an interval from number of semitones from a reference note, something similar with music.js's Interval.fromSemitones().

It's a bit verbose (please let me know if there's a better way), but it works as expected:

teoria.Interval().fromSemitones(0).name()  // => 'unison'
teoria.Interval().fromSemitones(1).name()  // => 'second'

I also added a helpful method to transpose a note without mutating it:

c = teoria.note('c')
c.name()  // => 'c'
c.transposeNew(teoria.Interval().fromSemitones(1)).name() // => 'd'
c.name()  // => 'c' (no changes on original note)

With the original Note.transpose() method we change the note itself:

c = teoria.note('c')
c.name()  // => 'c'
c.transpose(teoria.Interval().fromSemitones(1)).name() // => 'd'
c.name()  // => 'd' (note changed)

Please let me know if there's something I can improve on the PR. I'm actually using it on this live coding language where it's handy to create notes from intervals defined by semitones.

automata avatar Sep 05 '17 17:09 automata

Im currently working on a music theory library as well, and had to tackle the same issue.

A number of semitones is not enough to define an interval, because of the existence of enharmonic intervals (ex augmented fourth and diminished 5th both have a distance of 6 semitones).

If you only care about the pitch class or the frequency of the resulting notes, this is not a problem, and will indeed work, but this can not be implemented naively in a musical theory library imo

AtActionPark avatar Sep 22 '17 13:09 AtActionPark

AS @AtActionPark is saying, this isn't really possible to do "correctly", because an interval of 6 semitones can both be an #4 or b5, and 2 semitones can be M2 og d3. What I think is doable is to make a function that returns all possible intervals for a given semitone-defined interval. So:

Interval.fromSemitones(6) -> ['A4', 'd5']

ordered after what interval is most common. (M2 over d3, etc).

saebekassebil avatar Oct 07 '17 13:10 saebekassebil

I think i've already implemented something like that in https://github.com/saebekassebil/piu - maybe you could rip that functionality out, make it its own module, and I'd be happy to include it in teoria :)

saebekassebil avatar Oct 07 '17 13:10 saebekassebil