diff --git a/src/pitch.ts b/src/pitch.ts index 579290e7..4fed6cdd 100644 --- a/src/pitch.ts +++ b/src/pitch.ts @@ -571,7 +571,7 @@ export class Pitch extends prebase.ProtoM21Object { } else { this.octave = p.octave; } - return p; + return this; } /** @@ -591,7 +591,38 @@ export class Pitch extends prebase.ProtoM21Object { getLowerEnharmonic(inPlace=false) { return this._getEnharmonicHelper(inPlace, -1); } - /* TODO: isEnharmonic, getEnharmonic, getAllCommonEnharmonics */ + + getEnharmonic(inPlace=false): Pitch { + let post = this; + if (!inPlace) { + post = this.clone(); + } + + if (post.accidental !== undefined) { + if (post.accidental.alter > 0) { + // we have a sharp, need to get the equivalent flat + post.getHigherEnharmonic(true); + } else if (post.accidental.alter < 0) { + post.getLowerEnharmonic(true); + } else { + // assume some direction, perhaps using a dictionary + if (['C', 'D', 'G'].includes(this.step)) { + post.getLowerEnharmonic(true); + } else { + post.getHigherEnharmonic(true); + } + } + } else { + if (['C', 'D', 'G'].includes(this.step)) { + post.getLowerEnharmonic(true); + } else { + post.getHigherEnharmonic(true); + } + } + + return post; + } + /* TODO: isEnharmonic, getAllCommonEnharmonics */ protected _nameInKeySignature(alteredPitches: Pitch[]) : boolean { for (const p of alteredPitches) { // all are altered tones, must have acc diff --git a/tests/moduleTests/pitch.ts b/tests/moduleTests/pitch.ts index 4019f5df..35f6f6da 100644 --- a/tests/moduleTests/pitch.ts +++ b/tests/moduleTests/pitch.ts @@ -107,7 +107,8 @@ export default function tests() { assert.equal(dis.octave, 5, 'Pitch octave set to 5'); // inPlace - dis.getHigherEnharmonic(true); // inPlace + const same = dis.getHigherEnharmonic(true); // inPlace + assert.equal(same, dis, 'inPlace=True returns same object'); assert.equal(dis.nameWithOctave, es.nameWithOctave); const cDblSharp = new music21.pitch.Pitch('C##5'); @@ -131,6 +132,32 @@ export default function tests() { // assert.equal(bSharp.octave, undefined, 'octave should be undefined'); // assert.equal(bSharp.name, 'B#'); + // getEnharmonic (not inPlace) + const start1 = new music21.pitch.Pitch('E-5'); + const expectedFirst1 = new music21.pitch.Pitch('D#5'); + const expectedSecond1 = new music21.pitch.Pitch('E-5'); + + const first1 = start1.getEnharmonic(); + assert.notEqual(first1, start1, 'should not return the same (modified) object'); + assert.equal(first1.nameWithOctave, expectedFirst1.nameWithOctave); + + const second1 = first1.getEnharmonic(); + assert.notEqual(second1, first1, 'should not return the same (modified) object'); + assert.equal(second1.nameWithOctave, expectedSecond1.nameWithOctave); + + // getEnharmonic (inPlace) + const start2 = new music21.pitch.Pitch('F-3'); + const expectedFirst2 = new music21.pitch.Pitch('E3'); + const expectedSecond2 = new music21.pitch.Pitch('F-3'); + + const first2 = start2.getEnharmonic(true); + assert.equal(first2, start2, 'should return the same (modified) object'); + assert.equal(first2.nameWithOctave, expectedFirst2.nameWithOctave); + + const second2 = first2.getEnharmonic(true); + assert.equal(second2, first2, 'should return the same (modified) object'); + assert.equal(second2.nameWithOctave, expectedSecond2.nameWithOctave); + }); test('music21.pitch.Pitch To String', assert => {