Skip to content

Commit

Permalink
Preserve unity when sorting by default
Browse files Browse the repository at this point in the history
  • Loading branch information
frostburn committed Jun 5, 2024
1 parent 7742232 commit dbd98f0
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
13 changes: 13 additions & 0 deletions src/__tests__/scale.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ describe('Scale', () => {
expect(scale.getFrequency(3)).toBeCloseTo(1875);
expect(scale.getFrequency(4)).toBeCloseTo(2000);
});
it('can be sorted (subunity lines)', () => {
const intervals = [
new Interval(ExtendedMonzo.fromFraction(new Fraction(2, 3), 3), 'ratio'),
new Interval(ExtendedMonzo.fromFraction(new Fraction(3, 2), 3), 'ratio'),
new Interval(ExtendedMonzo.fromFraction(new Fraction(5, 3), 3), 'ratio'),
new Interval(ExtendedMonzo.fromFraction(new Fraction(2, 1), 3), 'ratio'),
new Interval(ExtendedMonzo.fromFraction(new Fraction(5, 2), 3), 'ratio'),
new Interval(ExtendedMonzo.fromFraction(new Fraction(9, 5), 3), 'ratio'),
];
const baseFrequency = 1000;
const scale = Scale.fromIntervalArray(intervals, baseFrequency).sorted();
expect(scale.getFrequency(0)).toBeCloseTo(baseFrequency);
});
it('can be octave reduced', () => {
const intervals = [
new Interval(ExtendedMonzo.fromFraction(new Fraction(3, 5), 3), 'ratio'),
Expand Down
40 changes: 37 additions & 3 deletions src/scale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -670,10 +670,27 @@ export class Scale {

/**
* Sort the scale in-place.
* @param preserveUnity Keep the first entry in place and verify that it's 0 cents.
* @returns The scale with intervals sorted from smallest to largest without touching the equave.
*/
sortInPlace() {
sortInPlace(preserveUnity = true) {
let unity: Interval | undefined;
if (preserveUnity) {
unity = this.intervals.shift();
if (!unity) {
// Seems like an empty scale.
return this;
}
if (unity.totalCents()) {
throw new Error(
'Unrooted scales cannot be sorted while preserving unity.'
);
}
}
this.intervals.sort((a, b) => a.compare(b));
if (unity) {
this.intervals.unshift(unity);
}
return this;
}

Expand All @@ -689,16 +706,33 @@ export class Scale {
/**
* Construct a sorted copy of the scale. scale in-place.
* @param deep Create new copies of the intervals instead just a new array with the old instances.
* @param preserveUnity Keep the first entry in place and verify that it's 0 cents.
* @returns The scale with intervals sorted from smallest to largest without touching the equave.
*/
sorted(deep = false) {
sorted(deep = false, preserveUnity = true) {
let intervals: Interval[];
if (deep) {
intervals = this.intervals.map(interval => interval.clone());
} else {
intervals = [...this.intervals];
}
let unity: Interval | undefined;
if (preserveUnity) {
unity = intervals.shift();
if (!unity) {
// Seems like an empty scale.
return this.variant(intervals);
}
if (unity.totalCents()) {
throw new Error(
'Unrooted scales cannot be sorted while preserving unity.'
);
}
}
intervals.sort((a, b) => a.compare(b));
if (unity) {
intervals.unshift(unity);
}
return this.variant(intervals);
}

Expand Down Expand Up @@ -939,7 +973,7 @@ export class Scale {
* @returns A new scale with intervals from both without duplicates.
*/
merge(other: Scale) {
return this.concat(other).removeDuplicatesInPlace().sortInPlace();
return this.concat(other).removeDuplicatesInPlace().sortInPlace(false);
}

/**
Expand Down

0 comments on commit dbd98f0

Please sign in to comment.