Skip to content

Commit

Permalink
Keep unison in place when varying randomly
Browse files Browse the repository at this point in the history
  • Loading branch information
frostburn committed Mar 26, 2024
1 parent 764b72c commit 4753300
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
26 changes: 25 additions & 1 deletion src/__tests__/scale.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {describe, it, expect} from 'vitest';
import {ExtendedMonzo} from '../monzo';
import {Scale} from '../scale';
import {Interval, IntervalOptions} from '../interval';
import {arraysEqual, Fraction} from 'xen-dev-utils';
import {arraysEqual, Fraction, valueToCents} from 'xen-dev-utils';

describe('Scale', () => {
it('supports just intonation', () => {
Expand Down Expand Up @@ -1054,6 +1054,30 @@ describe('Scale', () => {
expect(scale.getMonzo(2).cents).toBeTruthy();
});

it('keeps the unison in place during random variance', () => {
const scale = Scale.fromIntervalArray([
new Interval(
ExtendedMonzo.fromEqualTemperament(
new Fraction(3, 15),
new Fraction(9),
2
),
'equal temperament',
undefined,
{preferredEtDenominator: 15, preferredEtEquave: new Fraction(9)}
),
new Interval(ExtendedMonzo.fromFraction(9, 2), 'ratio'),
]).vary(10, false);
expect(scale.intervals[0].totalCents()).toBe(0);
expect(scale.getCents(1)).toBeGreaterThanOrEqual(
(valueToCents(9) * 3) / 15 - 10
);
expect(scale.getCents(1)).toBeLessThanOrEqual(
(valueToCents(9) * 3) / 15 + 10
);
expect(scale.getCents(2)).toBeCloseTo(valueToCents(9));
});

it('respells the equave when approximated in equal temperament', () => {
const scale = Scale.fromIntervalArray([
new Interval(
Expand Down
4 changes: 3 additions & 1 deletion src/scale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,9 @@ export class Scale {
* @returns A new scale with variance added.
*/
vary(maxCents: number, varyEquave = false) {
const intervals = this.intervals.map(interval => interval.vary(maxCents));
const intervals = this.intervals.map((interval, i) =>
i ? interval.vary(maxCents) : interval.clone()
);
const result = this.variant(intervals);
if (varyEquave) {
result.equave = this.equave.vary(maxCents);
Expand Down

0 comments on commit 4753300

Please sign in to comment.