Renamed root level note() to midi(). midi() & sound() now accepts object as parameter. + merge
This commit is contained in:
@ -99,6 +99,8 @@
|
|||||||
<p rel="noopener noreferrer" id="docs_time" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Time</p>
|
<p rel="noopener noreferrer" id="docs_time" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Time</p>
|
||||||
<p rel="noopener noreferrer" id="docs_sound" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Sound</p>
|
<p rel="noopener noreferrer" id="docs_sound" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Sound</p>
|
||||||
<p rel="noopener noreferrer" id="docs_samples" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Samples</p>
|
<p rel="noopener noreferrer" id="docs_samples" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Samples</p>
|
||||||
|
<p rel="noopener noreferrer" id="docs_synths" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Synths</p>
|
||||||
|
|
||||||
<p rel="noopener noreferrer" id="docs_midi" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">MIDI</p>
|
<p rel="noopener noreferrer" id="docs_midi" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">MIDI</p>
|
||||||
<p rel="noopener noreferrer" id="docs_functions" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Functions</p>
|
<p rel="noopener noreferrer" id="docs_functions" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Functions</p>
|
||||||
<p rel="noopener noreferrer" id="docs_shortcuts" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Shortcuts</p>
|
<p rel="noopener noreferrer" id="docs_shortcuts" class="pl-2 pr-2 lg:text-xl text-sm hover:bg-neutral-800 py-1 my-1 rounded-lg">Shortcuts</p>
|
||||||
|
|||||||
@ -255,6 +255,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
this.MidiConnection.sendSysExMessage(data);
|
this.MidiConnection.sendSysExMessage(data);
|
||||||
};
|
};
|
||||||
|
sy = this.sysex;
|
||||||
|
|
||||||
public pitch_bend = (value: number, channel: number): void => {
|
public pitch_bend = (value: number, channel: number): void => {
|
||||||
/**
|
/**
|
||||||
@ -277,6 +278,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
this.MidiConnection.sendProgramChange(program, channel);
|
this.MidiConnection.sendProgramChange(program, channel);
|
||||||
};
|
};
|
||||||
|
pc = this.program_change;
|
||||||
|
|
||||||
public midi_clock = (): void => {
|
public midi_clock = (): void => {
|
||||||
/**
|
/**
|
||||||
@ -298,6 +300,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
this.MidiConnection.sendMidiControlChange(control, value, channel);
|
this.MidiConnection.sendMidiControlChange(control, value, channel);
|
||||||
};
|
};
|
||||||
|
cc = this.control_change;
|
||||||
|
|
||||||
public midi_panic = (): void => {
|
public midi_panic = (): void => {
|
||||||
/**
|
/**
|
||||||
@ -1034,7 +1037,7 @@ export class UserAPI {
|
|||||||
*/
|
*/
|
||||||
return this._euclidean_cycle(pulses, length, rotate)[iterator % length];
|
return this._euclidean_cycle(pulses, length, rotate)[iterator % length];
|
||||||
};
|
};
|
||||||
ec = this.euclid;
|
eu = this.euclid;
|
||||||
|
|
||||||
_euclidean_cycle(
|
_euclidean_cycle(
|
||||||
pulses: number,
|
pulses: number,
|
||||||
|
|||||||
@ -81,6 +81,13 @@ A set of files is called a _universe_. Topos can store several universes and swi
|
|||||||
Switching between universes will not stop the transport nor reset the clock. You are switching the context but time keeps flowing. This can be useful to prepare immediate transitions between songs and parts. Think of universes as an algorithmic set of music. All scripts in a given universe are aware about how many times they have been runned already. You can reset that value programatically.
|
Switching between universes will not stop the transport nor reset the clock. You are switching the context but time keeps flowing. This can be useful to prepare immediate transitions between songs and parts. Think of universes as an algorithmic set of music. All scripts in a given universe are aware about how many times they have been runned already. You can reset that value programatically.
|
||||||
|
|
||||||
You can clear the current universe by pressing the flame button on the top right corner of the interface. This will clear all the scripts and the note file. **Note:** there is no shortcut for clearing a universe. We do not want to loose your work by mistake!
|
You can clear the current universe by pressing the flame button on the top right corner of the interface. This will clear all the scripts and the note file. **Note:** there is no shortcut for clearing a universe. We do not want to loose your work by mistake!
|
||||||
|
|
||||||
|
# Sharing your work
|
||||||
|
|
||||||
|
Click on the Topos logo in the top bar. Your URL will change to something much longer and complex. The same URL will be copied to your clipboard. Send this link to your friends to share the universe you are currently working on with them.
|
||||||
|
|
||||||
|
- The imported universe will always get a randomly generated name such as: <icode>random_silly_llama</icode>.
|
||||||
|
- Topos will automatically fetch and switch to the universe that was sent to you. Your previous universe is still there, don't worry.
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const time: string = `
|
const time: string = `
|
||||||
@ -346,6 +353,51 @@ ${injectAvailableSamples()}
|
|||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const synths: string = `
|
||||||
|
# Synthesizers
|
||||||
|
|
||||||
|
Topos comes with a small number of basic synthesizers. These synths are based on a basic [WebAudio](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) design. For heavy synthesis duties, please use MIDI and speak to more complex instruments.
|
||||||
|
|
||||||
|
# Substractive Synthesis
|
||||||
|
|
||||||
|
The <icode>sound</icode> function can take the name of a synthesizer as first argument.
|
||||||
|
- <icode>sine</icode>, <icode>sawtooth</icode>,<icode>triangle</icode>, <icode>square</icode> for the waveform selection.
|
||||||
|
- <icode>cutoff</icode> and <icode>resonance</icode> for adding a low-pass filter with cutoff frequency and filter resonance.
|
||||||
|
- <icode>hcutoff</icode> or <icode>bandf</icode> to switch to a high-pass or bandpass filter.
|
||||||
|
- <icode>hresonance</icode> and <icode>bandq</icode> for the resonance parameter of these filters.
|
||||||
|
|
||||||
|
Here is a simple example of a substractive synth:
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
mod(.5) && snd('sawtooth')
|
||||||
|
.cutoff(pick(2000,500)) + usine(.5) * 4000)
|
||||||
|
.resonance(0.9).freq(pick(100,150))
|
||||||
|
.out()
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
|
||||||
|
# Frequency Modulation Synthesis (FM)
|
||||||
|
|
||||||
|
The same basic waveforms can take additional methods to switch to a basic two operators FM synth design (with _carrier_ and _modulator_). FM Synthesis is a complex topic but take this advice: simple ratios will yield stable and harmonic sounds, complex ratios will generate noises, percussions and gritty sounds.
|
||||||
|
|
||||||
|
- <icode>fmi</icode> (_frequency modulation index_): a floating point value between <icode>1</icode> and <icode>n</icode>.
|
||||||
|
- <icode>fmh</icode> (_frequency modulation harmonic ratio_): a floating point value between <icode>1</icode> and <icode>n</icode>.
|
||||||
|
|
||||||
|
And here is a simple example:
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
mod(.25) && snd('sine')
|
||||||
|
.fmi(pick(1,2,4,8))
|
||||||
|
.fmh(divseq(2, 1,2,4,8))
|
||||||
|
.freq(pick(100,150))
|
||||||
|
.sustain(0.1)
|
||||||
|
.out()
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
**Note::** you can also set the _modulation index_ and the _harmonic ratio_ with the <icode>fm</icode> argument. You will have to feed both as a string: <icode>fm('2:4')</icode>. If you only feed one number, only the _modulation index_ will be updated.
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
const about: string = `
|
const about: string = `
|
||||||
# About Topos
|
# About Topos
|
||||||
|
|
||||||
@ -561,6 +613,7 @@ export const documentation = {
|
|||||||
time: time,
|
time: time,
|
||||||
sound: sound,
|
sound: sound,
|
||||||
samples: samples,
|
samples: samples,
|
||||||
|
synths: synths,
|
||||||
midi: midi,
|
midi: midi,
|
||||||
functions: functions,
|
functions: functions,
|
||||||
reference: reference,
|
reference: reference,
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
|
|
||||||
constructor(sound: string | object, public app: Editor) {
|
constructor(sound: string | object, public app: Editor) {
|
||||||
super(app);
|
super(app);
|
||||||
if (typeof sound === 'string') this.values = { 's': sound, 'dur': 0.5 };
|
if (typeof sound === "string") this.values = { s: sound, dur: 0.5 };
|
||||||
else this.values = sound;
|
else this.values = sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
sound = (value: string): this => {
|
sound = (value: string): this => {
|
||||||
this.values['s'] = value
|
this.values["s"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -123,31 +123,37 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
this.values["cutoff"] = value;
|
this.values["cutoff"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
lpf = this.cutoff;
|
||||||
|
|
||||||
resonance = (value: number): this => {
|
resonance = (value: number): this => {
|
||||||
this.values["resonance"] = value;
|
this.values["resonance"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
lpq = this.resonance;
|
||||||
|
|
||||||
hcutoff = (value: number): this => {
|
hcutoff = (value: number): this => {
|
||||||
this.values["hcutoff"] = value;
|
this.values["hcutoff"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
hpf = this.hcutoff;
|
||||||
|
|
||||||
hresonance = (value: number): this => {
|
hresonance = (value: number): this => {
|
||||||
this.values["hresonance"] = value;
|
this.values["hresonance"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
hpq = this.hresonance;
|
||||||
|
|
||||||
bandf = (value: number): this => {
|
bandf = (value: number): this => {
|
||||||
this.values["bandf"] = value;
|
this.values["bandf"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
bpf = this.bandf;
|
||||||
|
|
||||||
bandq = (value: number): this => {
|
bandq = (value: number): this => {
|
||||||
this.values["bandq"] = value;
|
this.values["bandq"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
bpq = this.bandq;
|
||||||
|
|
||||||
coarse = (value: number): this => {
|
coarse = (value: number): this => {
|
||||||
this.values["coarse"] = value;
|
this.values["coarse"] = value;
|
||||||
@ -183,11 +189,13 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
this.values["delayfeedback"] = value;
|
this.values["delayfeedback"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
delayfb = this.delayfeedback;
|
||||||
|
|
||||||
delaytime = (value: number): this => {
|
delaytime = (value: number): this => {
|
||||||
this.values["delaytime"] = value;
|
this.values["delaytime"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
delayt = this.delaytime;
|
||||||
|
|
||||||
orbit = (value: number): this => {
|
orbit = (value: number): this => {
|
||||||
this.values["orbit"] = value;
|
this.values["orbit"] = value;
|
||||||
@ -208,6 +216,7 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
this.values["velocity"] = value;
|
this.values["velocity"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
vel = this.velocity;
|
||||||
|
|
||||||
modify = (func: Function): this => {
|
modify = (func: Function): this => {
|
||||||
const funcResult = func(this);
|
const funcResult = func(this);
|
||||||
@ -223,13 +232,24 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
this.values["dur"] = value;
|
this.values["dur"] = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
sus = this.sustain;
|
||||||
|
|
||||||
update = (): void => {
|
update = (): void => {
|
||||||
if(this.values.key && this.values.pitch && this.values.parsedScale && this.values.octave) {
|
if (
|
||||||
const [note,_] = noteFromPc(this.values.key, this.values.pitch, this.values.parsedScale, this.values.octave);
|
this.values.key &&
|
||||||
|
this.values.pitch &&
|
||||||
|
this.values.parsedScale &&
|
||||||
|
this.values.octave
|
||||||
|
) {
|
||||||
|
const [note, _] = noteFromPc(
|
||||||
|
this.values.key,
|
||||||
|
this.values.pitch,
|
||||||
|
this.values.parsedScale,
|
||||||
|
this.values.octave
|
||||||
|
);
|
||||||
this.values.freq = midiToFreq(note);
|
this.values.freq = midiToFreq(note);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
out = (): object => {
|
out = (): object => {
|
||||||
return superdough(
|
return superdough(
|
||||||
@ -238,5 +258,4 @@ export class SoundEvent extends AudibleEvent {
|
|||||||
this.values.dur
|
this.values.dur
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -559,6 +559,7 @@ export class Editor {
|
|||||||
"time",
|
"time",
|
||||||
"sound",
|
"sound",
|
||||||
"samples",
|
"samples",
|
||||||
|
"synths",
|
||||||
"midi",
|
"midi",
|
||||||
"functions",
|
"functions",
|
||||||
"reference",
|
"reference",
|
||||||
|
|||||||
Reference in New Issue
Block a user