Merge branch 'main' of github.com:Bubobubobubobubo/topos into tonnetz-docs
This commit is contained in:
@ -37,13 +37,13 @@
|
|||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"showdown": "^2.1.0",
|
"showdown": "^2.1.0",
|
||||||
"showdown-highlight": "^3.1.0",
|
"showdown-highlight": "^3.1.0",
|
||||||
"superdough": "^0.9.11",
|
"superdough": "^0.9.12",
|
||||||
"tailwind-highlightjs": "^2.0.1",
|
"tailwind-highlightjs": "^2.0.1",
|
||||||
"tailwindcss": "^3.3.3",
|
"tailwindcss": "^3.3.3",
|
||||||
"tone": "^14.8.49",
|
"tone": "^14.8.49",
|
||||||
"unique-names-generator": "^4.7.1",
|
"unique-names-generator": "^4.7.1",
|
||||||
"vite-plugin-markdown": "^2.1.0",
|
"vite-plugin-markdown": "^2.1.0",
|
||||||
"zifferjs": "^0.0.51",
|
"zifferjs": "^0.0.54",
|
||||||
"zyklus": "^0.1.4",
|
"zyklus": "^0.1.4",
|
||||||
"zzfx": "^1.2.0"
|
"zzfx": "^1.2.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -146,6 +146,7 @@ export class UserAPI {
|
|||||||
: (this.app.selectedExample as string);
|
: (this.app.selectedExample as string);
|
||||||
}
|
}
|
||||||
this.stop();
|
this.stop();
|
||||||
|
this.resetAllFromCache();
|
||||||
this.play();
|
this.play();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -168,6 +169,7 @@ export class UserAPI {
|
|||||||
this.stop();
|
this.stop();
|
||||||
this.play();
|
this.play();
|
||||||
this.app.exampleIsPlaying = true;
|
this.app.exampleIsPlaying = true;
|
||||||
|
this.resetAllFromCache();
|
||||||
evaluateOnce(this.app, code as string);
|
evaluateOnce(this.app, code as string);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -139,13 +139,17 @@ export const showDocumentation = (app: Editor) => {
|
|||||||
document.getElementById("documentation")?.classList.remove("hidden");
|
document.getElementById("documentation")?.classList.remove("hidden");
|
||||||
// Load and convert Markdown content from the documentation file
|
// Load and convert Markdown content from the documentation file
|
||||||
let style = createDocumentationStyle(app);
|
let style = createDocumentationStyle(app);
|
||||||
let bindings = Object.keys(style).map((key) => ({
|
|
||||||
type: "output",
|
function update_and_assign(callback: Function) {
|
||||||
regex: new RegExp(`<${key}([^>]*)>`, "g"),
|
let bindings = Object.keys(style).map((key) => ({
|
||||||
//@ts-ignore
|
type: "output",
|
||||||
replace: (match, p1) => `<${key} class="${style[key]}" ${p1}>`,
|
regex: new RegExp(`<${key}([^>]*)>`, "g"),
|
||||||
}));
|
//@ts-ignore
|
||||||
updateDocumentationContent(app, bindings);
|
replace: (match, p1) => `<${key} class="${style[key]}" ${p1}>`,
|
||||||
|
}));
|
||||||
|
callback(bindings)
|
||||||
|
}
|
||||||
|
update_and_assign((e: Object) => updateDocumentationContent(app, e));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -166,15 +170,28 @@ export const updateDocumentationContent = (app: Editor, bindings: any) => {
|
|||||||
* @param app - The editor application.
|
* @param app - The editor application.
|
||||||
* @param bindings - Additional bindings for the showdown converter.
|
* @param bindings - Additional bindings for the showdown converter.
|
||||||
*/
|
*/
|
||||||
|
let loading_message: string = "<h1 class='border-4 py-2 px-2 mx-48 mt-48 text-center text-2xl text-white'>Loading! <b class='text-red'>Clic to refresh!</b></h1>";
|
||||||
const converter = new showdown.Converter({
|
const converter = new showdown.Converter({
|
||||||
emoji: true,
|
emoji: true,
|
||||||
moreStyling: true,
|
moreStyling: true,
|
||||||
backslashEscapesHTMLTags: true,
|
backslashEscapesHTMLTags: true,
|
||||||
extensions: [showdownHighlight({ auto_detection: true }), ...bindings],
|
extensions: [showdownHighlight({ auto_detection: true }), ...bindings],
|
||||||
});
|
});
|
||||||
const converted_markdown = converter.makeHtml(
|
console.log(app.currentDocumentationPane);
|
||||||
app.docs[app.currentDocumentationPane],
|
|
||||||
);
|
function _update_and_assign(callback: Function) {
|
||||||
document.getElementById("documentation-content")!.innerHTML =
|
const converted_markdown = converter.makeHtml(
|
||||||
converted_markdown;
|
app.docs[app.currentDocumentationPane],
|
||||||
};
|
);
|
||||||
|
callback(converted_markdown)
|
||||||
|
}
|
||||||
|
_update_and_assign((e: string)=> {
|
||||||
|
let display_content = e === undefined ? loading_message : e;
|
||||||
|
document.getElementById("documentation-content")!.innerHTML = display_content;
|
||||||
|
})
|
||||||
|
if (document.getElementById("documentation-content")!.innerHTML.replace(/"/g, "'") == loading_message.replace(/"/g, "'")) {
|
||||||
|
setTimeout(() => {
|
||||||
|
updateDocumentationContent(app, bindings);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -525,18 +525,25 @@ export const installInterfaceLogic = (app: Editor) => {
|
|||||||
"loading_samples",
|
"loading_samples",
|
||||||
].forEach((e) => {
|
].forEach((e) => {
|
||||||
let name = `docs_` + e;
|
let name = `docs_` + e;
|
||||||
document.getElementById(name)!.addEventListener("click", async () => {
|
|
||||||
if (name !== "docs_sample_list") {
|
// Check if the element exists
|
||||||
app.currentDocumentationPane = e;
|
let element = document.getElementById(name);
|
||||||
updateDocumentationContent(app, bindings);
|
if (element) {
|
||||||
} else {
|
element.addEventListener("click", async () => {
|
||||||
console.log("Loading samples!");
|
if (name !== "docs_sample_list") {
|
||||||
await loadSamples().then(() => {
|
|
||||||
app.docs = documentation_factory(app);
|
|
||||||
app.currentDocumentationPane = e;
|
app.currentDocumentationPane = e;
|
||||||
updateDocumentationContent(app, bindings);
|
updateDocumentationContent(app, bindings);
|
||||||
});
|
} else {
|
||||||
}
|
console.log("Loading samples!");
|
||||||
});
|
await loadSamples().then(() => {
|
||||||
|
app.docs = documentation_factory(app);
|
||||||
|
app.currentDocumentationPane = e;
|
||||||
|
updateDocumentationContent(app, bindings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("Could not find element " + name);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
} from "zifferjs";
|
} from "zifferjs";
|
||||||
import { SkipEvent } from "./SkipEvent";
|
import { SkipEvent } from "./SkipEvent";
|
||||||
import { SoundParams } from "./SoundEvent";
|
import { SoundParams } from "./SoundEvent";
|
||||||
|
import { centsToSemitones, edoToSemitones, ratiosToSemitones } from "zifferjs/src/scale";
|
||||||
|
|
||||||
export type EventOperation<T> = (instance: T, ...args: any[]) => void;
|
export type EventOperation<T> = (instance: T, ...args: any[]) => void;
|
||||||
|
|
||||||
@ -294,7 +295,9 @@ export abstract class AudibleEvent extends AbstractEvent {
|
|||||||
value = Array.isArray(value) ? value.concat(kwargs) : [value, ...kwargs];
|
value = Array.isArray(value) ? value.concat(kwargs) : [value, ...kwargs];
|
||||||
}
|
}
|
||||||
this.values["pitch"] = value;
|
this.values["pitch"] = value;
|
||||||
if (this.values.key && this.values.parsedScale) this.update();
|
this.values["originalPitch"] = value;
|
||||||
|
this.defaultPitchKeyScale();
|
||||||
|
this.update();
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -309,7 +312,7 @@ export abstract class AudibleEvent extends AbstractEvent {
|
|||||||
if (kwargs.length > 0) {
|
if (kwargs.length > 0) {
|
||||||
value = Array.isArray(value) ? value.concat(kwargs) : [value, ...kwargs];
|
value = Array.isArray(value) ? value.concat(kwargs) : [value, ...kwargs];
|
||||||
}
|
}
|
||||||
this.values["octave"] = value;
|
this.values["paramOctave"] = value;
|
||||||
if (
|
if (
|
||||||
this.values.key &&
|
this.values.key &&
|
||||||
(this.values.pitch || this.values.pitch === 0) &&
|
(this.values.pitch || this.values.pitch === 0) &&
|
||||||
@ -337,6 +340,12 @@ export abstract class AudibleEvent extends AbstractEvent {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
defaultPitchKeyScale() {
|
||||||
|
if (!this.values.key) this.values.key = 60;
|
||||||
|
if (!(this.values.pitch || this.values.pitch === 0)) this.values.pitch = 0;
|
||||||
|
if (!this.values.parsedScale) this.values.parsedScale = safeScale("major");
|
||||||
|
}
|
||||||
|
|
||||||
scale = (
|
scale = (
|
||||||
value: string | number | (number | string)[],
|
value: string | number | (number | string)[],
|
||||||
...kwargs: (string | number)[]
|
...kwargs: (string | number)[]
|
||||||
@ -354,12 +363,43 @@ export abstract class AudibleEvent extends AbstractEvent {
|
|||||||
} else if (Array.isArray(value)) {
|
} else if (Array.isArray(value)) {
|
||||||
this.values.parsedScale = value.map((v) => safeScale(v));
|
this.values.parsedScale = value.map((v) => safeScale(v));
|
||||||
}
|
}
|
||||||
if (this.values.key && (this.values.pitch || this.values.pitch === 0)) {
|
this.defaultPitchKeyScale();
|
||||||
this.update();
|
this.update();
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
semitones(values: number|number[], ...rest: number[]) {
|
||||||
|
const scaleValues = typeof values === "number" ? [values, ...rest] : values;
|
||||||
|
this.values.parsedScale = safeScale(scaleValues);
|
||||||
|
this.defaultPitchKeyScale();
|
||||||
|
this.update();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
steps = this.semitones;
|
||||||
|
|
||||||
|
cents(values: number|number[], ...rest: number[]) {
|
||||||
|
const scaleValues = typeof values === "number" ? [values, ...rest] : values;
|
||||||
|
this.values.parsedScale = safeScale(centsToSemitones(scaleValues));
|
||||||
|
this.defaultPitchKeyScale();
|
||||||
|
this.update();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ratios(values: number|number[], ...rest: number[]) {
|
||||||
|
const scaleValues = typeof values === "number" ? [values, ...rest] : values;
|
||||||
|
this.values.parsedScale = safeScale(ratiosToSemitones(scaleValues));
|
||||||
|
this.defaultPitchKeyScale();
|
||||||
|
this.update();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
edo(value: number, intervals: string|number[] = new Array(value).fill(1)) {
|
||||||
|
this.values.parsedScale = edoToSemitones(value, intervals);
|
||||||
|
this.defaultPitchKeyScale();
|
||||||
|
this.update();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
protected updateValue<T>(key: string, value: T | T[] | null): this {
|
protected updateValue<T>(key: string, value: T | T[] | null): this {
|
||||||
if (value == null) return this;
|
if (value == null) return this;
|
||||||
this.values[key] = value;
|
this.values[key] = value;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { AudibleEvent } from "./AbstractEvents";
|
import { AudibleEvent } from "./AbstractEvents";
|
||||||
import { type Editor } from "../main";
|
import { type Editor } from "../main";
|
||||||
import { MidiConnection } from "../IO/MidiConnection";
|
import { MidiConnection } from "../IO/MidiConnection";
|
||||||
import { noteFromPc } from "zifferjs";
|
import { resolvePitchClass } from "zifferjs";
|
||||||
import {
|
import {
|
||||||
filterObject,
|
filterObject,
|
||||||
arrayOfObjectsToObjectWithArrays,
|
arrayOfObjectsToObjectWithArrays,
|
||||||
@ -84,31 +84,32 @@ export class MidiEvent extends AudibleEvent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
update = (): void => {
|
update = (): void => {
|
||||||
// Get key, pitch, parsedScale and octave from this.values object
|
|
||||||
const filteredValues = filterObject(this.values, [
|
const filteredValues = filterObject(this.values, [
|
||||||
"key",
|
"key",
|
||||||
"pitch",
|
"pitch",
|
||||||
|
"originalPitch",
|
||||||
"parsedScale",
|
"parsedScale",
|
||||||
"octave",
|
"addedOctave"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const events = objectWithArraysToArrayOfObjects(filteredValues, [
|
const events = objectWithArraysToArrayOfObjects(filteredValues, [
|
||||||
"parsedScale",
|
"parsedScale",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
events.forEach((event) => {
|
events.forEach((soundEvent) => {
|
||||||
const [note, bend] = noteFromPc(
|
const resolvedPitchClass = resolvePitchClass(
|
||||||
(event.key as number) || "C4",
|
(soundEvent.key || "C4"),
|
||||||
(event.pitch as number) || 0,
|
(soundEvent.originalPitch || soundEvent.pitch || 0),
|
||||||
(event.parsedScale as number[]) || event.scale || "MAJOR",
|
(soundEvent.parsedScale || soundEvent.scale || "MAJOR"),
|
||||||
(event.octave as number) || 0,
|
(soundEvent.addedOctave || 0)
|
||||||
);
|
);
|
||||||
event.note = note;
|
soundEvent.note = resolvedPitchClass.note;
|
||||||
if (bend) event.bend = bend;
|
soundEvent.pitch = resolvedPitchClass.pitch;
|
||||||
|
soundEvent.octave = resolvedPitchClass.octave;
|
||||||
});
|
});
|
||||||
|
|
||||||
const newArrays = arrayOfObjectsToObjectWithArrays(events) as MidiParams;
|
const newArrays = arrayOfObjectsToObjectWithArrays(events) as MidiParams;
|
||||||
|
|
||||||
this.values.note = newArrays.note;
|
this.values.note = newArrays.note;
|
||||||
if (newArrays.bend) this.values.bend = newArrays.bend;
|
if (newArrays.bend) this.values.bend = newArrays.bend;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
arrayOfObjectsToObjectWithArrays,
|
arrayOfObjectsToObjectWithArrays,
|
||||||
objectWithArraysToArrayOfObjects,
|
objectWithArraysToArrayOfObjects,
|
||||||
} from "../Utils/Generic";
|
} from "../Utils/Generic";
|
||||||
import { midiToFreq, noteFromPc } from "zifferjs";
|
import { midiToFreq, resolvePitchClass } from "zifferjs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
superdough,
|
superdough,
|
||||||
@ -22,10 +22,13 @@ export type SoundParams = {
|
|||||||
note?: number | number[];
|
note?: number | number[];
|
||||||
freq?: number | number[];
|
freq?: number | number[];
|
||||||
pitch?: number | number[];
|
pitch?: number | number[];
|
||||||
|
originalPitch?: number | number[];
|
||||||
key?: string;
|
key?: string;
|
||||||
scale?: string;
|
scale?: string;
|
||||||
parsedScale?: number[];
|
parsedScale?: number[];
|
||||||
octave?: number | number[];
|
octave?: number | number[];
|
||||||
|
addedOctave?: number | number[];
|
||||||
|
pitchOctave?: number | number[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export class SoundEvent extends AudibleEvent {
|
export class SoundEvent extends AudibleEvent {
|
||||||
@ -387,27 +390,36 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
const filteredValues = filterObject(this.values, [
|
const filteredValues = filterObject(this.values, [
|
||||||
"key",
|
"key",
|
||||||
"pitch",
|
"pitch",
|
||||||
|
"originalPitch",
|
||||||
"parsedScale",
|
"parsedScale",
|
||||||
|
"addedOctave",
|
||||||
"octave",
|
"octave",
|
||||||
|
"paramOctave"
|
||||||
]);
|
]);
|
||||||
const events = objectWithArraysToArrayOfObjects(filteredValues, [
|
const events = objectWithArraysToArrayOfObjects(filteredValues, [
|
||||||
"parsedScale",
|
"parsedScale",
|
||||||
]);
|
]);
|
||||||
events.forEach((event) => {
|
events.forEach((soundEvent) => {
|
||||||
const [note, _] = noteFromPc(
|
const resolvedPitchClass = resolvePitchClass(
|
||||||
(event.key as number) || "C4",
|
(soundEvent.key || "C4"),
|
||||||
(event.pitch as number) || 0,
|
(soundEvent.originalPitch || soundEvent.pitch || 0),
|
||||||
(event.parsedScale as number[]) || event.scale || "MAJOR",
|
(soundEvent.parsedScale || soundEvent.scale || "MAJOR"),
|
||||||
(event.octave as number) || 0,
|
(soundEvent.paramOctave || 0)+(soundEvent.addedOctave || 0)
|
||||||
);
|
);
|
||||||
event.note = note;
|
soundEvent.note = resolvedPitchClass.note;
|
||||||
event.freq = midiToFreq(note);
|
soundEvent.freq = midiToFreq(resolvedPitchClass.note);
|
||||||
|
soundEvent.pitch = resolvedPitchClass.pitch;
|
||||||
|
soundEvent.octave = resolvedPitchClass.octave;
|
||||||
});
|
});
|
||||||
|
|
||||||
const newArrays = arrayOfObjectsToObjectWithArrays(events) as SoundParams;
|
const newArrays = arrayOfObjectsToObjectWithArrays(events) as SoundParams;
|
||||||
|
|
||||||
this.values.note = newArrays.note;
|
this.values.note = newArrays.note;
|
||||||
this.values.freq = newArrays.freq;
|
this.values.freq = newArrays.freq;
|
||||||
|
this.values.pitch = newArrays.pitch;
|
||||||
|
this.values.octave = newArrays.octave;
|
||||||
|
this.values.pitchOctave = newArrays.pitchOctave;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
out = (orbit?: number | number[]): void => {
|
out = (orbit?: number | number[]): void => {
|
||||||
|
|||||||
@ -186,9 +186,12 @@ export class Player extends AbstractEvent {
|
|||||||
"freq",
|
"freq",
|
||||||
"note",
|
"note",
|
||||||
"pitch",
|
"pitch",
|
||||||
|
"originalPitch",
|
||||||
"key",
|
"key",
|
||||||
"scale",
|
"scale",
|
||||||
"octave",
|
"octave",
|
||||||
|
"pitchOctave",
|
||||||
|
"addedOctave",
|
||||||
"parsedScale",
|
"parsedScale",
|
||||||
) as SoundParams;
|
) as SoundParams;
|
||||||
|
|
||||||
@ -205,9 +208,12 @@ export class Player extends AbstractEvent {
|
|||||||
"freq",
|
"freq",
|
||||||
"note",
|
"note",
|
||||||
"pitch",
|
"pitch",
|
||||||
|
"originalPitch",
|
||||||
"key",
|
"key",
|
||||||
"scale",
|
"scale",
|
||||||
"octave",
|
"octave",
|
||||||
|
"pitchOctave",
|
||||||
|
"addedOctave",
|
||||||
"parsedScale",
|
"parsedScale",
|
||||||
);
|
);
|
||||||
}) as SoundParams[];
|
}) as SoundParams[];
|
||||||
@ -236,10 +242,13 @@ export class Player extends AbstractEvent {
|
|||||||
const obj = event.getExisting(
|
const obj = event.getExisting(
|
||||||
"note",
|
"note",
|
||||||
"pitch",
|
"pitch",
|
||||||
|
"originalPitch",
|
||||||
"bend",
|
"bend",
|
||||||
"key",
|
"key",
|
||||||
"scale",
|
"scale",
|
||||||
"octave",
|
"octave",
|
||||||
|
"pitchOctave",
|
||||||
|
"addedOctave",
|
||||||
"parsedScale",
|
"parsedScale",
|
||||||
) as MidiParams;
|
) as MidiParams;
|
||||||
if (event instanceof Pitch) {
|
if (event instanceof Pitch) {
|
||||||
@ -258,11 +267,34 @@ export class Player extends AbstractEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scale(name: string) {
|
scale(name: string|number[]) {
|
||||||
if (this.atTheBeginning()) this.ziffers.scale(name);
|
if (this.atTheBeginning()) this.ziffers.scale(name);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
semitones(values: number|number[], ...rest: number[]) {
|
||||||
|
values = typeof values === "number" ? [values, ...rest] : values;
|
||||||
|
if (this.atTheBeginning()) this.ziffers.semitones(values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
cents(values: number|number[], ...rest: number[]) {
|
||||||
|
values = typeof values === "number" ? [values, ...rest] : values;
|
||||||
|
if (this.atTheBeginning()) this.ziffers.cents(values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ratios(values: number|number[], ...rest: number[]) {
|
||||||
|
values = typeof values === "number" ? [values, ...rest] : values;
|
||||||
|
if (this.atTheBeginning()) this.ziffers.ratios(values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
edo(value: number, scale: string|number[] = new Array(value).fill(1)) {
|
||||||
|
if (this.atTheBeginning()) this.ziffers.edo(value, scale);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
key(name: string) {
|
key(name: string) {
|
||||||
if (this.atTheBeginning()) this.ziffers.key(name);
|
if (this.atTheBeginning()) this.ziffers.key(name);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@ -122,7 +122,6 @@ beat(1)::sound(['kick', 'fsnare'].dur(3, 1))
|
|||||||
|
|
||||||
## Manipulating notes and scales
|
## Manipulating notes and scales
|
||||||
|
|
||||||
|
|
||||||
- <ic>pitch()</ic>: convert a list of integers to pitch classes
|
- <ic>pitch()</ic>: convert a list of integers to pitch classes
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
@ -136,7 +135,62 @@ beat(0.25) :: snd('sine')
|
|||||||
true,
|
true,
|
||||||
)}
|
)}
|
||||||
|
|
||||||
- <ic>scale(scale: string, base note: number)</ic>: Map each element of the list to the closest note of the slected scale. [0, 2, 3, 5 ].scale("major", 50) returns [50, 52, <ic>54</ic>, 55]. You can use western scale names like (Major, Minor, Minor pentatonic ...) or [zeitler](https://ianring.com/musictheory/scales/traditions/zeitler) scale names. Alternatively you can also use the integers as used by Ian Ring in his [study of scales](https://ianring.com/musictheory/scales/).
|
- <ic>semitones(number[], ...args?)</ic>: Create scale from semitone intervals.
|
||||||
|
|
||||||
|
${makeExample(
|
||||||
|
"Play pitches from scale created from semitone intervals",
|
||||||
|
`
|
||||||
|
beat(1) :: sound('gtr').pitch([0, 4, 3, 2].beat()).key(64)
|
||||||
|
.semitones(1, 1, 3, 1, 1, 2, 3).out()
|
||||||
|
`,
|
||||||
|
true,
|
||||||
|
)}
|
||||||
|
|
||||||
|
- <ic>cents(number[], ...args?)</ic>: Create scale from cent intervals.
|
||||||
|
|
||||||
|
${makeExample(
|
||||||
|
"Play pitches from scale created from cent intervals",
|
||||||
|
`
|
||||||
|
rhythm([0.5,0.25].beat(1),14,16) :: sound('pluck')
|
||||||
|
.stretch(r(1,5)).pitch(r(0,6)).key(57)
|
||||||
|
.cents(120,270,540,670,785,950,1215).out()
|
||||||
|
`,
|
||||||
|
true,
|
||||||
|
)}
|
||||||
|
|
||||||
|
- <ic>ratios(number[], ...args?)</ic>: Create scale from ratios.
|
||||||
|
|
||||||
|
${makeExample(
|
||||||
|
"Play pitches from scale created from ratios",
|
||||||
|
`
|
||||||
|
rhythm([0.5,0.25].beat(0.25),5,7) :: sound('east:3')
|
||||||
|
.pitch([0,1,2,3,4,5,6,7,8,9,10,11].beat(0.25)).key(67)
|
||||||
|
.ratios(2/11,4/11,6/11,8/11,10/11,11/11).out()
|
||||||
|
`,
|
||||||
|
true,
|
||||||
|
)}
|
||||||
|
|
||||||
|
- <ic>edo(number, scale?: string|number[])</ic>: Create scale from equal divisions of the octave. Creates chromatic scale by default.
|
||||||
|
|
||||||
|
${makeExample(
|
||||||
|
"Play pitches from scale created from equal divisions of the octave",
|
||||||
|
`
|
||||||
|
z0("e bd bd <bd bd [bd bd] [bd bd bd bd]>").sound().out()
|
||||||
|
flipbar(1) :: rhythm(.25,14,16) :: sound("ST10:30").stretch(3).gain(0.5)
|
||||||
|
.pitch([0,10,r(20,40),r(100,200),r(-200,200),r(200,300),200,r(3,666)].beat([1.0,0.5,0.25].bar(6)))
|
||||||
|
.octave(r(-6,6))
|
||||||
|
.edo(666,"rocritonic")
|
||||||
|
.out()
|
||||||
|
rhythm(2.0,26,32) :: sound("ST20").n([22,5,24,34,31,5,11,19].pick()).stretch(rI(1,6))
|
||||||
|
.pitch(rI(127,300))
|
||||||
|
.edo(666)
|
||||||
|
.out()
|
||||||
|
`,
|
||||||
|
true,
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
- <ic>scale(scale: string, base note: number)</ic>: Map each element of the list to the closest note of the slected scale. [0, 2, 3, 5 ].scale("major", 50) returns [50, 52, <ic>54</ic>, 55]. You can use western scale names like (Major, Minor, Minor pentatonic ...) or [zeitler](https://ianring.com/musictheory/scales/traditions/zeitler) scale names. Alternatively you can also use the integers as used by Ian Ring in his [study of scales](https://ianring.com/musictheory/scales/).
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Mapping the note array to the E3 major scale",
|
"Mapping the note array to the E3 major scale",
|
||||||
|
|||||||
16
yarn.lock
16
yarn.lock
@ -3455,10 +3455,10 @@ sucrase@^3.32.0:
|
|||||||
pirates "^4.0.1"
|
pirates "^4.0.1"
|
||||||
ts-interface-checker "^0.1.9"
|
ts-interface-checker "^0.1.9"
|
||||||
|
|
||||||
superdough@^0.9.11:
|
superdough@^0.9.12:
|
||||||
version "0.9.11"
|
version "0.9.12"
|
||||||
resolved "https://registry.yarnpkg.com/superdough/-/superdough-0.9.11.tgz#3a3842a47d6340477f77d39077303f05e15274dd"
|
resolved "https://registry.yarnpkg.com/superdough/-/superdough-0.9.12.tgz#455f8860bc13cffbe1d8f391919e8f1dba1ff0b5"
|
||||||
integrity sha512-s0SNSg/EJHwp2sUnE2A7pTZ0G2luiSEq9NVKJvodjJw11Tn0fOp9XcnegNXINYz3U6mAsUYRoeaj4NmuTL13fA==
|
integrity sha512-rsdCoYk5rLYster4tE5mSGjotf/TNP3gPpsuK4hxTZNxL92TkdEcbPFLnJfky5oMQJtpRY1XqAXUx3htLbHEZA==
|
||||||
dependencies:
|
dependencies:
|
||||||
nanostores "^0.8.1"
|
nanostores "^0.8.1"
|
||||||
|
|
||||||
@ -4028,10 +4028,10 @@ yaml@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b"
|
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b"
|
||||||
integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==
|
integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==
|
||||||
|
|
||||||
zifferjs@^0.0.51:
|
zifferjs@^0.0.54:
|
||||||
version "0.0.51"
|
version "0.0.54"
|
||||||
resolved "https://registry.yarnpkg.com/zifferjs/-/zifferjs-0.0.51.tgz#567efb39a1675fa622a1edc54d671318b58c43c7"
|
resolved "https://registry.yarnpkg.com/zifferjs/-/zifferjs-0.0.54.tgz#2dd4b43820f85d797c13dd35d933476ecacdb146"
|
||||||
integrity sha512-0uYFZNsdUL4wOv8x37HLenoEOKmcMi1hVpZIWXQwx9AsTeGvZqgVak0y02MSne5S5dMFmAO5s5ZXokc4kzbCeQ==
|
integrity sha512-vo1I12VvW4yFdVJTVnrfOxeOpWq7tIMZ67BfXxcK0t9GveLi+3GrF1zjowq8WCDssVgw+lQHEjdGVhO5FbK3RA==
|
||||||
|
|
||||||
zyklus@^0.1.4:
|
zyklus@^0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
|
|||||||
Reference in New Issue
Block a user