UNPKG

mosfez-xen-types

Version:

Basic xen number types for microtonal scale representation and manipulation with TypeScript / JavaScript.

1 lines 12.6 kB
{"version":3,"file":"xen-types.mjs","sources":["../src/xen-types.ts"],"sourcesContent":["//\n// internal predicates\n//\n\nexport const isNumber = (input: unknown): input is number =>\n typeof input === \"number\";\n\nexport const isString = (input: unknown): input is string =>\n typeof input === \"string\";\n\n//\n// type conversions\n//\n\nexport const stringToNumber = (str: string): number => {\n const result = Number(str);\n if (isNaN(result) || str === \"\") {\n throw new Error(`\"${str}\" is not a number`);\n }\n return result;\n};\n\n//\n// utils\n//\n\nexport const toDecimal = (value: number, places: number): number => {\n const m = 10 ** places;\n return Math.round(value * m) / m;\n};\n\nexport const toDecimalString = (value: number, places: number): string => {\n return `${toDecimal(value, places)}`.replace(/(?:\\.0+|(\\.\\d+?)0+)$/, \"$1\");\n};\n\n//\n// xen types\n//\n\nexport class Cents {\n public value = 0;\n\n constructor(cents: number);\n constructor(stringToParse: string);\n constructor(ratio: Ratio);\n constructor(ed2: Ed2);\n constructor(input: number | string | Ratio | Ed2) {\n if (isNumber(input)) {\n this.value = input;\n } else if (isString(input)) {\n this.value = Cents.parse(input);\n } else if (input instanceof Ed2) {\n this.value = Cents.fromEd2(input);\n } else if (input instanceof Ratio) {\n this.value = Cents.fromRatio(input);\n }\n }\n\n static parse(str: string): number {\n const trimmed = str.trim().replace(/c$/g, \"\");\n return stringToNumber(trimmed);\n }\n\n static fromEd2(ed2: Ed2): number {\n return Math.log2(ed2.toMultiplier()) * 1200;\n }\n\n static fromRatio(ratio: Ratio): number {\n return Math.log2(ratio.numerator / ratio.denominator) * 1200;\n }\n\n toString(): string {\n return `${this.value}c`;\n }\n\n toDecimal(places: number): number {\n return toDecimal(this.value, places);\n }\n\n toDecimalString(places: number): string {\n return `${toDecimalString(this.value, places)}c`;\n }\n\n toScl(places: number): string {\n const str = toDecimalString(this.value, places);\n return str.indexOf(\".\") === -1 ? `${str}.` : str;\n }\n\n toMultiplier(): number {\n return 2 ** (this.value / 1200);\n }\n}\n\nexport class Ratio {\n public numerator = 1;\n public denominator = 1;\n\n constructor(numerator: number, denominator: number);\n constructor(stringToParse: string);\n constructor(a: string | number, b?: number) {\n if (isNumber(a) || b !== undefined) {\n this.numerator = a as number;\n this.denominator = b as number;\n } else {\n const [n, d] = Ratio.parse(a);\n this.numerator = n;\n this.denominator = d;\n }\n }\n\n static parse(str: string): [number, number] {\n const split = str.trim().split(\"/\");\n if (split.length > 2)\n throw new Error(`ratio \"${str}\" must contain a single slash (/)`);\n const n = stringToNumber(split[0]);\n const d = split.length > 1 ? stringToNumber(split[1]) : 1;\n return [n, d];\n }\n\n get value(): [number, number] {\n return [this.numerator, this.denominator];\n }\n\n toMultiplier(): number {\n return this.numerator / this.denominator;\n }\n\n toString(): string {\n return `${this.numerator}/${this.denominator}`;\n }\n\n toScl(): string {\n return this.toString();\n }\n}\n\nexport class Ed2 {\n public steps = 1;\n public divisions = 1;\n\n constructor(steps: number, divisions: number);\n constructor(stringToParse: string);\n constructor(a: string | number, b?: number) {\n if (isNumber(a) || b !== undefined) {\n this.steps = a as number;\n this.divisions = b as number;\n } else {\n const [s, d] = Ed2.parse(a);\n this.steps = s;\n this.divisions = d;\n }\n }\n\n static parse(str: string): [number, number] {\n const split = str.trim().split(\"\\\\\");\n if (split.length !== 2)\n throw new Error(`ed2 \"${str}\" must contain a single backslash (\\\\)`);\n const s = stringToNumber(split[0]);\n const d = stringToNumber(split[1]);\n return [s, d];\n }\n\n get value(): [number, number] {\n return [this.steps, this.divisions];\n }\n\n toString(): string {\n return `${this.steps}\\\\${this.divisions}`;\n }\n\n toScl(places: number) {\n return cents(this).toScl(places);\n }\n\n toMultiplier(): number {\n return 2 ** (this.steps / this.divisions);\n }\n}\n\nexport type Pitch = Cents | Ratio | Ed2;\n\nexport function cents(cents: number): Cents;\nexport function cents(centsInstance: Cents): Cents;\nexport function cents(stringToParse: string): Cents;\nexport function cents(ratio: Ratio): Cents;\nexport function cents(ed2: Ed2): Cents;\nexport function cents(a: number | string | Ratio | Ed2 | Cents): Cents {\n if (a instanceof Cents) return a;\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return new Cents(a);\n}\n\nexport function ratio(ratio: Ratio): Ratio;\nexport function ratio(stringToParse: string): Ratio;\nexport function ratio(numerator: number, denominator: number): Ratio;\nexport function ratio(a: Ratio | string | number | Ed2, b?: number): Ratio {\n if (a instanceof Ratio) return a;\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return new Ratio(a, b);\n}\n\nexport function ed2(ed2: Ed2): Ed2;\nexport function ed2(stringToParse: string): Ed2;\nexport function ed2(steps: number, divisions: number): Ed2;\nexport function ed2(a: Ed2 | string | number, b?: number): Ed2 {\n if (a instanceof Ed2) return a;\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return new Ed2(a, b);\n}\n//\n// parsing\n//\n\nexport const parse = (input: string): Pitch | \"ignore\" | \"invalid\" => {\n input = input.trim();\n\n const catchAndError = (cb: () => Pitch) => {\n try {\n return cb();\n } catch (e) {\n return \"invalid\";\n }\n };\n\n if (input === \"\" || \"!#\".indexOf(input[0]) !== -1) {\n return \"ignore\";\n }\n\n if (input.indexOf(\"\\\\\") !== -1) {\n return catchAndError(() => ed2(input));\n }\n\n if (input.indexOf(\".\") !== -1 || input.slice(-1) === \"c\") {\n return catchAndError(() => cents(input));\n }\n\n return catchAndError(() => ratio(input));\n};\n"],"names":[],"mappings":"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"}