Added scientific pitch notation and named chords for sound
This commit is contained in:
@ -1,3 +1,4 @@
|
|||||||
|
import { noteNameToMidi } from "zifferjs";
|
||||||
import { type UserAPI } from "./API";
|
import { type UserAPI } from "./API";
|
||||||
import { Player } from "./classes/ZPlayer";
|
import { Player } from "./classes/ZPlayer";
|
||||||
export {};
|
export {};
|
||||||
@ -30,6 +31,7 @@ declare global {
|
|||||||
z14(): Player;
|
z14(): Player;
|
||||||
z15(): Player;
|
z15(): Player;
|
||||||
z16(): Player;
|
z16(): Player;
|
||||||
|
note(): number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +81,7 @@ export const makeStringExtensions = (api: UserAPI) => {
|
|||||||
String.prototype.z = function (options: {[key: string]: any} = {}) {
|
String.prototype.z = function (options: {[key: string]: any} = {}) {
|
||||||
return api.z(this.valueOf(), options);
|
return api.z(this.valueOf(), options);
|
||||||
};
|
};
|
||||||
|
|
||||||
String.prototype.z0 = function (options: {[key: string]: any} = {}) {
|
String.prototype.z0 = function (options: {[key: string]: any} = {}) {
|
||||||
return api.z0(this.valueOf(), options);
|
return api.z0(this.valueOf(), options);
|
||||||
};
|
};
|
||||||
@ -148,6 +150,13 @@ export const makeStringExtensions = (api: UserAPI) => {
|
|||||||
return api.z16(this.valueOf(), options);
|
return api.z16(this.valueOf(), options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
String.prototype.note = function () {
|
||||||
|
try {
|
||||||
|
return parseInt(this.valueOf());
|
||||||
|
} catch (e) {
|
||||||
|
return noteNameToMidi(this.valueOf());
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type SpeechOptions = {
|
type SpeechOptions = {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { type Editor } from "../main";
|
import { type Editor } from "../main";
|
||||||
import { AudibleEvent } from "./AbstractEvents";
|
import { AudibleEvent } from "./AbstractEvents";
|
||||||
import { midiToFreq, noteFromPc } from "zifferjs";
|
import { chord as parseChord, midiToFreq, noteFromPc, noteNameToMidi } from "zifferjs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
superdough,
|
superdough,
|
||||||
@ -230,13 +230,42 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
// Frequency management
|
// Frequency management
|
||||||
|
|
||||||
public sound = (value: string) => this.updateValue("s", value);
|
public sound = (value: string) => this.updateValue("s", value);
|
||||||
public chord = (value: object[]) => this.updateValue("chord", value);
|
public chord = (value: string|object[]|number[]|number,...kwargs: number[]) => {
|
||||||
|
if(typeof value === "string") {
|
||||||
|
const chord = parseChord(value);
|
||||||
|
value = chord.map((note: number) => { return {note: note, freq: midiToFreq(note) } });
|
||||||
|
} else if(value instanceof Array && typeof value[0] === "number") {
|
||||||
|
value = (value as number[]).map((note: number) => { return {note: note, freq: midiToFreq(note) } });
|
||||||
|
} else if (typeof value === "number" && kwargs.length > 0) {
|
||||||
|
value = [value, ...kwargs].map((note: number) => { return {note: note, freq: midiToFreq(note) } });
|
||||||
|
}
|
||||||
|
return this.updateValue("chord", value);
|
||||||
|
}
|
||||||
|
public invert = (howMany: number = 0) => {
|
||||||
|
if(this.values.chord) {
|
||||||
|
let notes = this.values.chord.map((obj: { [key: string]: number }) => obj.note);
|
||||||
|
notes = howMany < 0 ? [...notes].reverse() : notes;
|
||||||
|
for (let i = 0; i < Math.abs(howMany); i++) {
|
||||||
|
notes[i % notes.length] += howMany <= 0 ? -12 : 12;
|
||||||
|
}
|
||||||
|
const chord = notes.map((note: number) => { return {note: note, freq: midiToFreq(note) } });
|
||||||
|
return this.updateValue("chord", chord);
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
public snd = this.sound;
|
public snd = this.sound;
|
||||||
public nudge = (value: number) => this.updateValue("nudge", value);
|
public nudge = (value: number) => this.updateValue("nudge", value);
|
||||||
public cut = (value: number) => this.updateValue("cut", value);
|
public cut = (value: number) => this.updateValue("cut", value);
|
||||||
public clip = (value: number) => this.updateValue("clip", value);
|
public clip = (value: number) => this.updateValue("clip", value);
|
||||||
public n = (value: number) => this.updateValue("n", value);
|
public n = (value: number) => this.updateValue("n", value);
|
||||||
public note = (value: number) => this.updateValue("note", value);
|
public note = (value: number|string) => {
|
||||||
|
if(typeof value === "string") {
|
||||||
|
return this.updateValue("note", noteNameToMidi(value));
|
||||||
|
} else {
|
||||||
|
return this.updateValue("note", value);
|
||||||
|
}
|
||||||
|
};
|
||||||
public speed = (value: number) => this.updateValue("speed", value);
|
public speed = (value: number) => this.updateValue("speed", value);
|
||||||
public spd = this.speed;
|
public spd = this.speed;
|
||||||
|
|
||||||
|
|||||||
@ -22,16 +22,43 @@ beat(.5) && snd(['sine', 'triangle', 'sawtooth', 'square'].beat()).freq(100).out
|
|||||||
|
|
||||||
Two functions are primarily used to control the frequency of the synthesizer:
|
Two functions are primarily used to control the frequency of the synthesizer:
|
||||||
- <ic>freq(hz: number)</ic>: sets the frequency of the oscillator.
|
- <ic>freq(hz: number)</ic>: sets the frequency of the oscillator.
|
||||||
- <ic>note(note: number)</ic>: sets the MIDI note of the oscillator (MIDI note converted to hertz).
|
- <ic>note(note: number|string)</ic>: sets the MIDI note of the oscillator (MIDI note converted to hertz).
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Selecting a pitch or note",
|
"Selecting a pitch",
|
||||||
`
|
`
|
||||||
beat(.5) && snd('triangle').freq([100,200,400].beat(2)).out()
|
beat(.5) && snd('triangle').freq([100,200,400].beat(2)).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
${makeExample(
|
||||||
|
"Selecting a note",
|
||||||
|
`
|
||||||
|
beat(.5) && snd('triangle').note([60,"F4"].pick()).out()
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)}
|
||||||
|
|
||||||
|
Chords can also played using different parameters:
|
||||||
|
-<ic>chord(string||number[]|...number)</ic>: parses and sets notes for the chord
|
||||||
|
|
||||||
|
${makeExample(
|
||||||
|
"Playing a named chord",
|
||||||
|
`
|
||||||
|
beat(1) && snd('triangle').chord(["C","Em7","Fmaj7","Emin"].beat(2)).out()
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)}
|
||||||
|
|
||||||
|
${makeExample(
|
||||||
|
"Playing a chord from a list of notes and doing inversions",
|
||||||
|
`
|
||||||
|
beat(.5) && snd('triangle').chord(60,64,67,72).invert([1,-3,4,-5].pick()).out()
|
||||||
|
`,
|
||||||
|
true
|
||||||
|
)}
|
||||||
|
|
||||||
## Vibrato
|
## Vibrato
|
||||||
|
|
||||||
You can also add some amount of vibrato to the sound using the <ic>vib</ic> and <ic>vibmod</ic> methods. These can turn any oscillator into something more lively and/or into a sound effect when used with a high amount of modulation.
|
You can also add some amount of vibrato to the sound using the <ic>vib</ic> and <ic>vibmod</ic> methods. These can turn any oscillator into something more lively and/or into a sound effect when used with a high amount of modulation.
|
||||||
|
|||||||
Reference in New Issue
Block a user