Merge branch 'main' of https://github.com/Bubobubobubobubo/Topos into 58-support-for-external-midi-clock
This commit is contained in:
@ -235,6 +235,11 @@
|
|||||||
<input id="show-tips" type="checkbox" value="" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
<input id="show-tips" type="checkbox" value="" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
||||||
<label for="default-checkbox" class="ml-2 text-sm font-medium text-dark">Show Hovering Tips</label>
|
<label for="default-checkbox" class="ml-2 text-sm font-medium text-dark">Show Hovering Tips</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-center mb-4 ml-8">
|
||||||
|
<input id="load-demo-songs" type="checkbox" value="" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
||||||
|
<label for="default-checkbox" class="ml-2 text-sm font-medium text-dark">Load Demo Song</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Midi settings -->
|
<!-- Midi settings -->
|
||||||
<div id="midi-settings-container" class="rounded-lg bg-gray-300 pt-4">
|
<div id="midi-settings-container" class="rounded-lg bg-gray-300 pt-4">
|
||||||
|
|||||||
@ -56,6 +56,7 @@ export interface Settings {
|
|||||||
selected_universe: string;
|
selected_universe: string;
|
||||||
line_numbers: boolean;
|
line_numbers: boolean;
|
||||||
time_position: boolean;
|
time_position: boolean;
|
||||||
|
load_demo_songs: boolean;
|
||||||
tips: boolean;
|
tips: boolean;
|
||||||
send_clock: boolean;
|
send_clock: boolean;
|
||||||
midi_clock_input: string|undefined;
|
midi_clock_input: string|undefined;
|
||||||
@ -134,6 +135,7 @@ export class AppSettings {
|
|||||||
public send_clock: boolean = false;
|
public send_clock: boolean = false;
|
||||||
public midi_clock_input: string|undefined = undefined;
|
public midi_clock_input: string|undefined = undefined;
|
||||||
public midi_clock_ppqn: number = 24;
|
public midi_clock_ppqn: number = 24;
|
||||||
|
public load_demo_songs: boolean = true;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const settingsFromStorage = JSON.parse(
|
const settingsFromStorage = JSON.parse(
|
||||||
@ -154,6 +156,7 @@ export class AppSettings {
|
|||||||
this.send_clock = settingsFromStorage.send_clock;
|
this.send_clock = settingsFromStorage.send_clock;
|
||||||
this.midi_clock_input = settingsFromStorage.midi_clock_input;
|
this.midi_clock_input = settingsFromStorage.midi_clock_input;
|
||||||
this.midi_clock_ppqn = settingsFromStorage.midi_clock_ppqn || 24;
|
this.midi_clock_ppqn = settingsFromStorage.midi_clock_ppqn || 24;
|
||||||
|
this.load_demo_songs = settingsFromStorage.load_demo_songs;
|
||||||
} else {
|
} else {
|
||||||
this.universes = template_universes;
|
this.universes = template_universes;
|
||||||
}
|
}
|
||||||
@ -180,6 +183,7 @@ export class AppSettings {
|
|||||||
send_clock: this.send_clock,
|
send_clock: this.send_clock,
|
||||||
midi_clock_input: this.midi_clock_input,
|
midi_clock_input: this.midi_clock_input,
|
||||||
midi_clock_ppqn: this.midi_clock_ppqn,
|
midi_clock_ppqn: this.midi_clock_ppqn,
|
||||||
|
load_demo_songs: this.load_demo_songs,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,6 +208,7 @@ export class AppSettings {
|
|||||||
this.send_clock = settings.send_clock;
|
this.send_clock = settings.send_clock;
|
||||||
this.midi_clock_input = settings.midi_clock_input;
|
this.midi_clock_input = settings.midi_clock_input;
|
||||||
this.midi_clock_ppqn = settings.midi_clock_ppqn;
|
this.midi_clock_ppqn = settings.midi_clock_ppqn;
|
||||||
|
this.load_demo_songs = settings.load_demo_songs;
|
||||||
localStorage.setItem("topos", JSON.stringify(this.data));
|
localStorage.setItem("topos", JSON.stringify(this.data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export const makeExampleFactory = (application: Editor): Function => {
|
|||||||
) => {
|
) => {
|
||||||
const codeId = `codeExample${application.exampleCounter++}`;
|
const codeId = `codeExample${application.exampleCounter++}`;
|
||||||
// Store the code snippet in the data structure
|
// Store the code snippet in the data structure
|
||||||
application.api.codeExamples[codeId] = code;
|
application.api.codeExamples[codeId] = "bpm(120);\n" + code;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<details ${open ? "open" : ""}>
|
<details ${open ? "open" : ""}>
|
||||||
|
|||||||
@ -41,12 +41,13 @@ beat(.5) && snd('triangle').note([60,"F4"].pick()).out()
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
Chords can also played using different parameters:
|
Chords can also played using different parameters:
|
||||||
|
|
||||||
- <ic>chord(string||number[]|...number)</ic>: parses and sets notes for the chord
|
- <ic>chord(string||number[]|...number)</ic>: parses and sets notes for the chord
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Playing a named chord",
|
"Playing a named chord",
|
||||||
`
|
`
|
||||||
beat(1) && snd('triangle').chord(["C","Em7","Fmaj7","Emin"].beat(2)).out()
|
beat(1) && snd('triangle').chord(["C","Em7","Fmaj7","Emin"].beat(2)).adsr(0,.2).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
)}
|
)}
|
||||||
@ -54,7 +55,7 @@ ${makeExample(
|
|||||||
${makeExample(
|
${makeExample(
|
||||||
"Playing a chord from a list of notes and doing inversions",
|
"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()
|
beat(.5) && snd('triangle').chord(60,64,67,72).invert([1,-3,4,-5].pick()).adsr(0,.2).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
)}
|
)}
|
||||||
@ -152,8 +153,8 @@ These filters all come with their own set of parameters. Note that we are descri
|
|||||||
|
|
||||||
| Method | Alias | Description |
|
| Method | Alias | Description |
|
||||||
|------------|-----------|---------------------------------|
|
|------------|-----------|---------------------------------|
|
||||||
| cutoff | lpf | cutoff frequency of the lowpass filter |
|
| <ic>cutoff</ic> | <ic>lpf</ic> | cutoff frequency of the lowpass filter |
|
||||||
| resonance | lpq | resonance of the lowpass filter |
|
| <ic>resonance</ic> | <ic>lpq</ic> | resonance of the lowpass filter |
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Filtering a bass",
|
"Filtering a bass",
|
||||||
@ -165,8 +166,8 @@ ${makeExample(
|
|||||||
|
|
||||||
| Method | Alias | Description |
|
| Method | Alias | Description |
|
||||||
|------------|-----------|---------------------------------|
|
|------------|-----------|---------------------------------|
|
||||||
| hcutoff | hpf | cutoff frequency of the highpass filter |
|
| <ic>hcutoff</ic> | <ic>hpf</ic> | cutoff frequency of the highpass filter |
|
||||||
| hresonance | hpq | resonance of the highpass filter |
|
| <ic>hresonance</ic> | <ic>hpq</ic> | resonance of the highpass filter |
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Filtering a noise source",
|
"Filtering a noise source",
|
||||||
@ -178,8 +179,8 @@ ${makeExample(
|
|||||||
|
|
||||||
| Method | Alias | Description |
|
| Method | Alias | Description |
|
||||||
|------------|-----------|---------------------------------|
|
|------------|-----------|---------------------------------|
|
||||||
| bandf | bpf | cutoff frequency of the bandpass filter |
|
| <ic>bandf</ic> | <ic>bpf</ic> | cutoff frequency of the bandpass filter |
|
||||||
| bandq | bpq | resonance of the bandpass filter |
|
| <ic>bandq</ic> | <ic>bpq</ic> | resonance of the bandpass filter |
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Sweeping the filter on the same guitar sample",
|
"Sweeping the filter on the same guitar sample",
|
||||||
@ -245,12 +246,12 @@ The examples we have studied so far are static. They filter the sound around a f
|
|||||||
|
|
||||||
| Method | Alias | Description |
|
| Method | Alias | Description |
|
||||||
|------------|-----------|---------------------------------|
|
|------------|-----------|---------------------------------|
|
||||||
| lpenv | lpe | lowpass frequency modulation amount (negative or positive) |
|
| <ic>lpenv</ic> | <ic>lpe</ic> | lowpass frequency modulation amount (negative or positive) |
|
||||||
| lpattack | lpa | attack of the lowpass filter |
|
| <ic>lpattack</ic> | <ic>lpa</ic> | attack of the lowpass filter |
|
||||||
| lpdecay | lpd | decay of the lowpass filter |
|
| <ic>lpdecay</ic> | <ic>lpd</ic> | decay of the lowpass filter |
|
||||||
| lpsustain | lps | sustain of the lowpass filter |
|
| <ic>lpsustain</ic> | <ic>lps</ic> | sustain of the lowpass filter |
|
||||||
| lprelease | lpr | release of the lowpass filter |
|
| <ic>lprelease</ic> | <ic>lpr</ic> | release of the lowpass filter |
|
||||||
| lpadsr | | (**takes five arguments**) set all the parameters |
|
| <ic>lpadsr</ic> | | (**takes five arguments**) set all the parameters |
|
||||||
|
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
@ -265,12 +266,12 @@ ${makeExample(
|
|||||||
|
|
||||||
| Method | Alias | Description |
|
| Method | Alias | Description |
|
||||||
|------------|-----------|---------------------------------|
|
|------------|-----------|---------------------------------|
|
||||||
| hpenv | hpe | highpass frequency modulation amount (negative or positive) |
|
| <ic>hpenv</ic> | <ic>hpe</ic> | highpass frequency modulation amount (negative or positive) |
|
||||||
| hpattack | hpa | attack of the highpass filter |
|
| <ic>hpattack</ic> | <ic>hpa</ic> | attack of the highpass filter |
|
||||||
| hpdecay | hpd | decay of the highpass filter |
|
| <ic>hpdecay</ic> | <ic>hpd</ic> | decay of the highpass filter |
|
||||||
| hpsustain | hps | sustain of the highpass filter |
|
| <ic>hpsustain</ic> | <ic>hps</ic> | sustain of the highpass filter |
|
||||||
| hprelease | hpr | release of the highpass filter |
|
| <ic>hprelease</ic> | <ic>hpr</ic> | release of the highpass filter |
|
||||||
| hpadsr | | (**takes five arguments**) set all the parameters |
|
| <ic>hpadsr</ic> | | (**takes five arguments**) set all the parameters |
|
||||||
|
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
@ -285,12 +286,12 @@ ${makeExample(
|
|||||||
|
|
||||||
| Method | Alias | Description |
|
| Method | Alias | Description |
|
||||||
|------------|-----------|---------------------------------|
|
|------------|-----------|---------------------------------|
|
||||||
| bpenv | bpe | bandpass frequency modulation amount (negative or positive) |
|
| <ic>bpenv</ic> | <ic>bpe</ic> | bandpass frequency modulation amount (negative or positive) |
|
||||||
| bpattack | bpa | attack of the bandpass filter |
|
| <ic>bpattack</ic> | <ic>bpa</ic> | attack of the bandpass filter |
|
||||||
| bpdecay | bpd | decay of the bandpass filter |
|
| <ic>bpdecay</ic> | <ic>bpd</ic> | decay of the bandpass filter |
|
||||||
| bpsustain | bps | sustain of the bandpass filter |
|
| <ic>bpsustain</ic> | <ic>bps</ic> | sustain of the bandpass filter |
|
||||||
| bprelease | bpr | release of the bandpass filter |
|
| <ic>bprelease</ic> | <ic>bpr</ic> | release of the bandpass filter |
|
||||||
| bpadsr | | (**takes five arguments**) set all the parameters |
|
| <ic>bpadsr</ic> | | (**takes five arguments**) set all the parameters |
|
||||||
|
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
|
|||||||
@ -26,7 +26,7 @@ ${makeExample(
|
|||||||
"Using different mod values",
|
"Using different mod values",
|
||||||
`
|
`
|
||||||
// This code is alternating between different mod values
|
// This code is alternating between different mod values
|
||||||
beat([1,1/2,1/4,1/8].beat(2)) :: sound('bd').n(0).out()
|
beat([1,1/2,1/4,1/8].beat(2)) :: sound('hat').n(0).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
)}
|
)}
|
||||||
@ -34,24 +34,33 @@ beat([1,1/2,1/4,1/8].beat(2)) :: sound('bd').n(0).out()
|
|||||||
${makeExample(
|
${makeExample(
|
||||||
"Some sort of ringtone",
|
"Some sort of ringtone",
|
||||||
`
|
`
|
||||||
let blip = (freq) => {return sound('sine').sustain(0.1).freq(freq)};
|
// Blip generator :)
|
||||||
beat(1) :: blip(200).out();
|
let blip = (freq) => {
|
||||||
beat(1/3) :: blip(400).out();
|
return sound('wt_piano')
|
||||||
flip(3) :: beat(1/6) :: blip(800).out();
|
.gain(1)
|
||||||
beat([1,0.75].beat(2)) :: blip([50, 100].beat(2)).out();
|
.sustain(0.1)
|
||||||
|
.freq(freq)
|
||||||
|
.cutoff(1500)
|
||||||
|
.lpadsr(4, 0, .25, 0, 0)
|
||||||
|
};
|
||||||
|
beat(1) :: blip(200).pan(r(0,1)).vib(0.5).vibmod(2).out();
|
||||||
|
beat(1/3) :: blip(400).pan(r(0,1)).out();
|
||||||
|
flip(3) :: beat(1/6) :: blip(800).pan(r(0,1)).out();
|
||||||
|
beat([1,0.75].beat(2)) :: blip([50, 100].beat(2)).pan(r(0,1)).out();
|
||||||
`,
|
`,
|
||||||
false
|
false
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
- <ic>pulse(...n: number[])</ic>: faster version of the <ic>beat</ic> function. Instead of returning true for every beat, this function is returning true every _n_ clock ticks! It can be used to generate very unexpected results or to sequence by using your arithmetic ninja skills.
|
- <ic>pulse(...n: number[])</ic>: faster version of the <ic>beat</ic> function. Instead of returning true for every beat, this function is returning true every _n_ clock ticks! It can be used to generate very unexpected rhythms.
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Intriguing rhythms",
|
"Intriguing rhythms",
|
||||||
`
|
`
|
||||||
pulse(36) :: snd('east')
|
pulse([24,48].beat(2)) :: snd('hand')
|
||||||
.n([2,4].beat(1)).out()
|
.cut(1).room(0.9).size(0.9)
|
||||||
pulse([12, 36].beat(4)) :: snd('east')
|
.n([2,4].beat(2)).out()
|
||||||
|
pulse([48/2, 48/3].beat(4)) :: snd('hand')
|
||||||
.n([2,4].add(5).beat(1)).out()
|
.n([2,4].add(5).beat(1)).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
@ -71,8 +80,8 @@ ${makeExample(
|
|||||||
"Some simple yet detailed rhythms",
|
"Some simple yet detailed rhythms",
|
||||||
`
|
`
|
||||||
onbeat(1,2,3,4)::snd('kick').out() // Bassdrum on each beat
|
onbeat(1,2,3,4)::snd('kick').out() // Bassdrum on each beat
|
||||||
onbeat(2,4)::snd('snare').out() // Snare on acccentuated beats
|
onbeat(2,4)::snd('snare').n([0,2].beat(2.5)).out() // Snare on acccentuated beats
|
||||||
onbeat(1.5,2.5,3.5, 3.75)::snd('hat').out() // Cool high-hats
|
onbeat(1.5,2.5,3.5, 3.75)::snd('hat').gain(r(0.9,1.1)).out() // Cool high-hats
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
)}
|
)}
|
||||||
@ -80,10 +89,10 @@ onbeat(1.5,2.5,3.5, 3.75)::snd('hat').out() // Cool high-hats
|
|||||||
${makeExample(
|
${makeExample(
|
||||||
"Let's do something more complex",
|
"Let's do something more complex",
|
||||||
`
|
`
|
||||||
onbeat(0.5, 1.5, 2, 3, 3.75)::snd('kick').n(2).out()
|
onbeat(0.5, 2, 3, 3.75)::snd('kick').n(2).out()
|
||||||
onbeat(2, [1.5, 3].pick(), 4)::snd('snare').n(7).out()
|
onbeat(2, [1.5, 3, 4].pick(), 4)::snd('snare').n(8).out()
|
||||||
beat([.25, 1/8].beat(1.5))::snd('hat').n(2)
|
beat([.25, 1/8].beat(1.5))::snd('hat').n(2)
|
||||||
.gain(rand(0.4, 0.7))
|
.gain(rand(0.4, 0.7)).end(0.05)
|
||||||
.pan(usine()).out()
|
.pan(usine()).out()
|
||||||
`,
|
`,
|
||||||
false
|
false
|
||||||
@ -95,7 +104,9 @@ ${makeExample(
|
|||||||
"Using oncount to create more variation in the rhythm",
|
"Using oncount to create more variation in the rhythm",
|
||||||
`
|
`
|
||||||
bpm(120)
|
bpm(120)
|
||||||
z1('q (0 4 2 9)+(0 3 1 5)').sound('sawtooth').cutoff([400,500,1000,2000].beat(1))
|
z1('0.125 (0 2 3 4)+(0 2 4 6)').sound('sawtooth')
|
||||||
|
.cutoff([400,500,1000,2000].beat(1))
|
||||||
|
.lpadsr(2, 0, .2, 0, 0)
|
||||||
.delay(0.5).delayt(0.25).room(0.9).size(0.9).out()
|
.delay(0.5).delayt(0.25).room(0.9).size(0.9).out()
|
||||||
onbeat(1,1.5,2,3,4) :: sound('bd').gain(2.0).out()
|
onbeat(1,1.5,2,3,4) :: sound('bd').gain(2.0).out()
|
||||||
oncount([1,3,5.5,7,7.5,8],8) :: sound('hh').gain(irand(1.0,4.0)).out()
|
oncount([1,3,5.5,7,7.5,8],8) :: sound('hh').gain(irand(1.0,4.0)).out()
|
||||||
@ -133,11 +144,12 @@ beat(4) :: sound('cp').out()
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"And now for more interesting rhythmic constructions",
|
"And now something a bit more complex",
|
||||||
`
|
`
|
||||||
bpm(145); // Setting a faster BPM
|
bpm(145); // Setting a faster BPM
|
||||||
beat(.5) && euclid($(1), 5, 8) :: sound('bd').out()
|
beat(.5) && euclid($(1), 5, 8) :: sound('bd').out()
|
||||||
beat(.5) && euclid($(2), [1,0].beat(8), 8) :: sound('sd').out()
|
beat(.5) && euclid($(2), [1,0].beat(8), 8)
|
||||||
|
:: sound('ST03').n(3).room(1).size(1).o(1).out()
|
||||||
beat(.5) && euclid($(6), [6,7].beat(8), 8) :: sound('hh').out()
|
beat(.5) && euclid($(6), [6,7].beat(8), 8) :: sound('hh').out()
|
||||||
`,
|
`,
|
||||||
false
|
false
|
||||||
@ -172,10 +184,10 @@ ${makeExample(
|
|||||||
${makeExample(
|
${makeExample(
|
||||||
"rhythm is a beginner friendly rhythmic function!",
|
"rhythm is a beginner friendly rhythmic function!",
|
||||||
`
|
`
|
||||||
let speed = [0.5, 0.25].beat(8); bpm(140);
|
let speed = [1, 0.5].beat(8); bpm(140);
|
||||||
rhythm(speed, 5, 12) :: snd('east').n(2).out()
|
rhythm(speed, 5, 12) :: snd('linnhats').n(2).pan(noise()).out()
|
||||||
rhythm(speed, 2, 12) :: snd('east').out()
|
rhythm(speed, 2, 12) :: snd('east').out()
|
||||||
rhythm(speed, 3, 12) :: snd('east').n(4).out()
|
rhythm(speed, 3, 12) :: snd('linnhats').n(4).pan(noise()).out()
|
||||||
rhythm(speed, 7, 12) :: snd('east').n(9).out()
|
rhythm(speed, 7, 12) :: snd('east').n(9).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
@ -187,8 +199,9 @@ rhythm(speed, 7, 12) :: snd('east').n(9).out()
|
|||||||
${makeExample(
|
${makeExample(
|
||||||
"Change the integers for a surprise rhythm!",
|
"Change the integers for a surprise rhythm!",
|
||||||
`
|
`
|
||||||
beat(.5) && bin($(1), 34) && snd('kick').out()
|
bpm(135);
|
||||||
beat(.5) && bin($(2), 48) && snd('sd').out()
|
beat(.5) && bin($(1), 34) && snd('kick').n([1,3].beat(1)).out()
|
||||||
|
beat(.5) && bin($(2), 48) && snd('snare').n([1,4].beat(1)).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
)}
|
)}
|
||||||
@ -196,8 +209,13 @@ beat(.5) && bin($(2), 48) && snd('sd').out()
|
|||||||
${makeExample(
|
${makeExample(
|
||||||
"binrhythm for fast cool binary rhythms!",
|
"binrhythm for fast cool binary rhythms!",
|
||||||
`
|
`
|
||||||
binrhythm(.5, 13) && snd('kick').out()
|
let a = 0;
|
||||||
binrhythm(.5, 18) && snd('sd').out()
|
a = beat(4) ? irand(1,20) : a;
|
||||||
|
binrhythm(.5, 6) && snd(['kick', 'snare'].beat(0.5)).n(11).out()
|
||||||
|
binrhythm([.5, .25].beat(1), 30) && snd('wt_granular').n(a)
|
||||||
|
.cutoff(800).lpadsr(4, 0, 0.125, 0.5, 0.25)
|
||||||
|
.adsr(0, r(.1, .4), 0, 0).freq([50, 60, 72].beat(4))
|
||||||
|
.room(1).size(1).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
)}
|
)}
|
||||||
@ -205,31 +223,25 @@ binrhythm(.5, 18) && snd('sd').out()
|
|||||||
${makeExample(
|
${makeExample(
|
||||||
"Submarine jungle music",
|
"Submarine jungle music",
|
||||||
`
|
`
|
||||||
|
bpm(145);
|
||||||
beat(.5) && bin($(1), 911) && snd('ST69').n([2,3,4].beat())
|
beat(.5) && bin($(1), 911) && snd('ST69').n([2,3,4].beat())
|
||||||
.delay(0.125).delayt(0.25).end(0.25).speed(1/3).out()
|
.delay(0.125).delayt(0.25).end(0.25).speed(1/3)
|
||||||
|
.room(1).size(1).out()
|
||||||
beat(.5) && sound('amencutup').n(irand(2,7)).shape(0.3).out()
|
beat(.5) && sound('amencutup').n(irand(2,7)).shape(0.3).out()
|
||||||
`,
|
`,
|
||||||
false
|
false
|
||||||
)}
|
)}
|
||||||
|
|
||||||
${makeExample(
|
|
||||||
"Using tabla to play unpredictable rhythms",
|
|
||||||
`
|
|
||||||
beat(.5) && bin($(1), [123, 456, 789].beat(4))
|
|
||||||
&& snd('tabla').n($(2)).delay(0.5).delayt(0.25).out()
|
|
||||||
beat(1) && sound('kick').shape(0.5).out()
|
|
||||||
`,
|
|
||||||
false
|
|
||||||
)}
|
|
||||||
|
|
||||||
If you don't find it spicy enough, you can add some more probabilities to your rhythms by taking advantage of the probability functions. See the functions documentation page to learn more about them.
|
If you don't find it spicy enough, you can add some more probabilities to your rhythms by taking advantage of the probability functions. See the functions documentation page to learn more about them.
|
||||||
|
|
||||||
${makeExample(
|
${makeExample(
|
||||||
"Probablistic drums in one line!",
|
"Probablistic drums in one line!",
|
||||||
`
|
`
|
||||||
prob(60)::beat(.5) && euclid($(1), 5, 8) && snd('kick').out()
|
prob(60)::beat(.5) && euclid($(1), 5, 8) && snd('kick').out()
|
||||||
prob(60)::beat(.5) && euclid($(2), 3, 8) && snd('sd').out()
|
prob(60)::beat(.5) && euclid($(2), 3, 8) && snd('mash')
|
||||||
prob(80)::beat(.5) && sound('hh').out()
|
.n([1,2,3].beat(1))
|
||||||
|
.pan(usine(1/4)).out()
|
||||||
|
prob(80)::beat(.5) && sound(['hh', 'hat'].pick()).out()
|
||||||
`,
|
`,
|
||||||
true
|
true
|
||||||
)}
|
)}
|
||||||
@ -300,9 +312,10 @@ ${makeExample(
|
|||||||
"Clapping on the edge",
|
"Clapping on the edge",
|
||||||
`
|
`
|
||||||
flip(2.5, 10) :: beat(.25) :: snd('cp').out()
|
flip(2.5, 10) :: beat(.25) :: snd('cp').out()
|
||||||
flip(2.5, 75) :: beat(.25) :: snd('click').speed(2).end(0.2).out()
|
flip(2.5, 75) :: beat(.25) :: snd('click')
|
||||||
|
.speed(2).end(0.2).out()
|
||||||
flip(2.5) :: beat(.5) :: snd('bd').out()
|
flip(2.5) :: beat(.5) :: snd('bd').out()
|
||||||
beat(.25) :: sound('hh').out()
|
beat(.25) :: sound('hat').end(0.1).cutoff(1200).pan(usine(1/4)).out()
|
||||||
`,
|
`,
|
||||||
false
|
false
|
||||||
)}
|
)}
|
||||||
|
|||||||
53
src/main.ts
53
src/main.ts
@ -35,7 +35,7 @@ import { makeStringExtensions } from "./StringExtensions";
|
|||||||
const classMap = {
|
const classMap = {
|
||||||
h1: "text-white lg:text-4xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutral-900 rounded-lg py-2 px-2",
|
h1: "text-white lg:text-4xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutral-900 rounded-lg py-2 px-2",
|
||||||
h2: "text-white lg:text-3xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutral-900 rounded-lg py-2 px-2",
|
h2: "text-white lg:text-3xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutral-900 rounded-lg py-2 px-2",
|
||||||
h3: "text-white lg:text-2xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutoral-700 rounded-lg py-2 px-2 lg:mt-16",
|
h3: "text-white lg:text-2xl text-xl lg:ml-4 lg:mx-4 mx-2 lg:my-4 my-2 lg:mb-4 mb-4 bg-neutral-700 rounded-lg py-2 px-2 lg:mt-16",
|
||||||
ul: "text-underline pl-6",
|
ul: "text-underline pl-6",
|
||||||
li: "list-disc lg:text-2xl text-base text-white lg:mx-4 mx-2 my-4 my-2 leading-normal",
|
li: "list-disc lg:text-2xl text-base text-white lg:mx-4 mx-2 my-4 my-2 leading-normal",
|
||||||
p: "lg:text-2xl text-base text-white lg:mx-6 mx-2 my-4 leading-normal",
|
p: "lg:text-2xl text-base text-white lg:mx-6 mx-2 my-4 leading-normal",
|
||||||
@ -201,6 +201,11 @@ export class Editor {
|
|||||||
"midi-clock-ppqn-input"
|
"midi-clock-ppqn-input"
|
||||||
) as HTMLSelectElement;
|
) as HTMLSelectElement;
|
||||||
|
|
||||||
|
// Loading demo songs when starting
|
||||||
|
load_demo_songs: HTMLInputElement = document.getElementById(
|
||||||
|
"load-demo-songs"
|
||||||
|
) as HTMLInputElement;
|
||||||
|
|
||||||
// Editor mode selection
|
// Editor mode selection
|
||||||
normal_mode_button: HTMLButtonElement = document.getElementById(
|
normal_mode_button: HTMLButtonElement = document.getElementById(
|
||||||
"normal-mode"
|
"normal-mode"
|
||||||
@ -233,18 +238,10 @@ export class Editor {
|
|||||||
public hydra: any = this.hydra_backend.synth;
|
public hydra: any = this.hydra_backend.synth;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// ================================================================================
|
|
||||||
// Loading the universe from local storage
|
|
||||||
// ================================================================================
|
|
||||||
|
|
||||||
this.universes = { ...this.settings.universes, ...template_universes };
|
// ================================================================================
|
||||||
this.selected_universe = "Welcome";
|
// Loading the settings
|
||||||
this.universe_viewer.innerHTML = `Topos: ${this.selected_universe}`;
|
// ================================================================================
|
||||||
|
|
||||||
// Picking a random example to populate the landing page
|
|
||||||
let random_example = examples[Math.floor(Math.random() * examples.length)];
|
|
||||||
this.universes[this.selected_universe].global.committed = random_example;
|
|
||||||
this.universes[this.selected_universe].global.candidate = random_example;
|
|
||||||
|
|
||||||
this.line_numbers_checkbox.checked = this.settings.line_numbers;
|
this.line_numbers_checkbox.checked = this.settings.line_numbers;
|
||||||
this.time_position_checkbox.checked = this.settings.time_position;
|
this.time_position_checkbox.checked = this.settings.time_position;
|
||||||
@ -254,6 +251,29 @@ export class Editor {
|
|||||||
if (!this.settings.time_position) {
|
if (!this.settings.time_position) {
|
||||||
document.getElementById("timeviewer")!.classList.add("hidden");
|
document.getElementById("timeviewer")!.classList.add("hidden");
|
||||||
}
|
}
|
||||||
|
this.load_demo_songs.checked = this.settings.load_demo_songs;
|
||||||
|
|
||||||
|
// ================================================================================
|
||||||
|
// Loading the universe from local storage
|
||||||
|
// ================================================================================
|
||||||
|
|
||||||
|
this.universes = {
|
||||||
|
...this.settings.universes,
|
||||||
|
...template_universes
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.settings.load_demo_songs) {
|
||||||
|
let random_example = examples[Math.floor(Math.random() * examples.length)];
|
||||||
|
this.selected_universe = "Welcome"
|
||||||
|
this.universes[this.selected_universe].global.committed = random_example;
|
||||||
|
this.universes[this.selected_universe].global.candidate = random_example;
|
||||||
|
} else {
|
||||||
|
this.selected_universe = this.settings.selected_universe;
|
||||||
|
if (this.universes[this.selected_universe] === undefined)
|
||||||
|
this.universes[this.selected_universe] = structuredClone(template_universe)
|
||||||
|
}
|
||||||
|
this.universe_viewer.innerHTML = `Topos: ${this.selected_universe}`;
|
||||||
|
|
||||||
|
|
||||||
// ================================================================================
|
// ================================================================================
|
||||||
// Audio context and clock
|
// Audio context and clock
|
||||||
@ -509,7 +529,7 @@ export class Editor {
|
|||||||
button.addEventListener("click", () => {
|
button.addEventListener("click", () => {
|
||||||
this.setButtonHighlighting("clear", true);
|
this.setButtonHighlighting("clear", true);
|
||||||
if (confirm("Do you want to reset the current universe?")) {
|
if (confirm("Do you want to reset the current universe?")) {
|
||||||
this.universes[this.selected_universe] = template_universe;
|
this.universes[this.selected_universe] = structuredClone(template_universe);
|
||||||
this.updateEditorView();
|
this.updateEditorView();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -571,6 +591,7 @@ export class Editor {
|
|||||||
this.tips_checkbox.checked = this.settings.tips;
|
this.tips_checkbox.checked = this.settings.tips;
|
||||||
this.midi_clock_checkbox.checked = this.settings.send_clock;
|
this.midi_clock_checkbox.checked = this.settings.send_clock;
|
||||||
this.midi_clock_ppqn.value = this.settings.midi_clock_ppqn.toString();
|
this.midi_clock_ppqn.value = this.settings.midi_clock_ppqn.toString();
|
||||||
|
this.load_demo_songs.checked = this.settings.load_demo_songs;
|
||||||
|
|
||||||
if (this.settings.vimMode) {
|
if (this.settings.vimMode) {
|
||||||
let vim = document.getElementById("vim-mode-radio") as HTMLInputElement;
|
let vim = document.getElementById("vim-mode-radio") as HTMLInputElement;
|
||||||
@ -676,6 +697,12 @@ export class Editor {
|
|||||||
this.settings.midi_clock_ppqn = value;
|
this.settings.midi_clock_ppqn = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.load_demo_songs.addEventListener("change", () => {
|
||||||
|
let checked = this.load_demo_songs.checked ? true : false;
|
||||||
|
this.settings.load_demo_songs = checked;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
this.vim_mode_button.addEventListener("click", () => {
|
this.vim_mode_button.addEventListener("click", () => {
|
||||||
this.settings.vimMode = true;
|
this.settings.vimMode = true;
|
||||||
this.view.dispatch({
|
this.view.dispatch({
|
||||||
|
|||||||
Reference in New Issue
Block a user