adjust flip function for more natural behavior

This commit is contained in:
2023-10-06 09:42:40 +02:00
parent 9035c395d0
commit 583b5ec079
2 changed files with 118 additions and 116 deletions

View File

@ -1084,8 +1084,9 @@ export class UserAPI {
* @param ratio Optional ratio to influence the true/false output (0-100) * @param ratio Optional ratio to influence the true/false output (0-100)
* @returns Whether the function returns true or false based on ratio and time chunk * @returns Whether the function returns true or false based on ratio and time chunk
*/ */
let realChunk = chunk * 2;
const time_pos = this.app.clock.pulses_since_origin; const time_pos = this.app.clock.pulses_since_origin;
const full_chunk = Math.floor(chunk * this.ppqn()); const full_chunk = Math.floor(realChunk * this.ppqn());
// const current_chunk = Math.floor(time_pos / full_chunk); // const current_chunk = Math.floor(time_pos / full_chunk);
const threshold = Math.floor((ratio / 100) * full_chunk); const threshold = Math.floor((ratio / 100) * full_chunk);
const pos_within_chunk = time_pos % full_chunk; const pos_within_chunk = time_pos % full_chunk;
@ -1093,8 +1094,9 @@ export class UserAPI {
}; };
public flipbar = (chunk: number = 1): boolean => { public flipbar = (chunk: number = 1): boolean => {
let realFlip = chunk * 2;
const time_pos = this.app.clock.time_position.bar; const time_pos = this.app.clock.time_position.bar;
const current_chunk = Math.floor(time_pos / chunk); const current_chunk = Math.floor(time_pos / realFlip);
return current_chunk % 2 === 0; return current_chunk % 2 === 0;
}; };

View File

@ -29,7 +29,7 @@ ${makeExample(
beat([1,1/2,1/4,1/8].beat(2)) :: sound('hat').n(0).out() beat([1,1/2,1/4,1/8].beat(2)) :: sound('hat').n(0).out()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"Some sort of ringtone", "Some sort of ringtone",
@ -49,7 +49,7 @@ 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(); 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 rhythms. - <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.
@ -64,7 +64,7 @@ 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
)} )}
${makeExample( ${makeExample(
"pulse is the OG rhythmic function in Topos", "pulse is the OG rhythmic function in Topos",
` `
@ -72,7 +72,7 @@ pulse([48, 24, 16].beat(4)) :: sound('linnhats').out()
beat(1)::snd(['bd', '808oh'].beat(1)).out() beat(1)::snd(['bd', '808oh'].beat(1)).out()
`, `,
false false
)}; )};
- <ic>onbeat(...n: number[])</ic>: The <ic>onbeat</ic> function allows you to lock on to a specific beat from the clock to execute code. It can accept multiple arguments. It's usage is very straightforward and not hard to understand. You can pass either integers or floating point numbers. By default, topos is using a <ic>4/4</ic> bar meaning that you can target any of these beats (or in-between) with this function. - <ic>onbeat(...n: number[])</ic>: The <ic>onbeat</ic> function allows you to lock on to a specific beat from the clock to execute code. It can accept multiple arguments. It's usage is very straightforward and not hard to understand. You can pass either integers or floating point numbers. By default, topos is using a <ic>4/4</ic> bar meaning that you can target any of these beats (or in-between) with this function.
@ -84,7 +84,7 @@ onbeat(2,4)::snd('snare').n([8,4].beat(4)).out() // Snare on acccentuated beats
onbeat(1.5,2.5,3.5, 3.75)::snd('hat').gain(r(0.9,1.1)).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
)} )}
${makeExample( ${makeExample(
"Let's do something more complex", "Let's do something more complex",
@ -96,7 +96,7 @@ beat([.25, 1/8].beat(1.5))::snd('hat').n(2)
.pan(usine()).out() .pan(usine()).out()
`, `,
false false
)} )}
- <ic>oncount(beats: number[], meter: number)</ic>: This function is similar to <ic>onbeat</ic> but it allows you to specify a custom number of beats as the last argument. - <ic>oncount(beats: number[], meter: number)</ic>: This function is similar to <ic>onbeat</ic> but it allows you to specify a custom number of beats as the last argument.
@ -111,7 +111,7 @@ 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()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"Using oncount to create rhythms with a custom meter", "Using oncount to create rhythms with a custom meter",
@ -123,7 +123,7 @@ oncount([2, 3, 3.5, 6, 7, 10, 15],16) :: sound('hh').n(8).gain(0.8).out()
oncount([1, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16],16) :: sound('hh').out() oncount([1, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16],16) :: sound('hh').out()
`, `,
true true
)} )}
## Rhythm generators ## Rhythm generators
@ -144,7 +144,7 @@ beat(.25) && euclid($(3), 6, 8) && snd('shaker')
.speed(2).n(11).out() .speed(2).n(11).out()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"And now something a bit more complex", "And now something a bit more complex",
@ -156,7 +156,7 @@ beat(.5) && euclid($(2), [1,0].beat(8), 8)
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
)} )}
${makeExample( ${makeExample(
"Adding more rhythmic density", "Adding more rhythmic density",
@ -169,7 +169,7 @@ beat(.5) && euclid($(3), 6, 9, 1) && snd('dr').end(0.5).n(2).freq(200).speed(1)
beat(.25) && euclid($(4), 7, 9, 1) && snd('hh').out() beat(.25) && euclid($(4), 7, 9, 1) && snd('hh').out()
`, `,
false false
)} )}
Alternatively, you can <ic>oneuclid</ic> or <ic>rhythm</ic> without the _iterators_: Alternatively, you can <ic>oneuclid</ic> or <ic>rhythm</ic> without the _iterators_:
@ -183,7 +183,7 @@ ${makeExample(
oneuclid(7,16) :: snd('east').end(0.5).n(irand(3,5)).out() oneuclid(7,16) :: snd('east').end(0.5).n(irand(3,5)).out()
`, `,
false false
)} )}
- <ic>rhythm(divisor: number, pulses: number, length: number, rotate: number): boolean</ic>: generates <ic>true</ic> or <ic>false</ic> values from an euclidian rhythm sequence. This is another version of <ic>euclid</ic> that does not take an iterator. - <ic>rhythm(divisor: number, pulses: number, length: number, rotate: number): boolean</ic>: generates <ic>true</ic> or <ic>false</ic> values from an euclidian rhythm sequence. This is another version of <ic>euclid</ic> that does not take an iterator.
${makeExample( ${makeExample(
@ -196,7 +196,7 @@ 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
)} )}
- <ic>bin(iterator: number, n: number): boolean</ic>: a binary rhythm generator. It transforms the given number into its binary representation (_e.g_ <ic>34</ic> becomes <ic>100010</ic>). It then returns a boolean value based on the iterator in order to generate a rhythm. - <ic>bin(iterator: number, n: number): boolean</ic>: a binary rhythm generator. It transforms the given number into its binary representation (_e.g_ <ic>34</ic> becomes <ic>100010</ic>). It then returns a boolean value based on the iterator in order to generate a rhythm.
- <ic>binrhythm(divisor: number, n: number): boolean: boolean</ic>: iterator-less version of the binary rhythm generator. - <ic>binrhythm(divisor: number, n: number): boolean: boolean</ic>: iterator-less version of the binary rhythm generator.
@ -209,7 +209,7 @@ beat(.5) && bin($(1), 12) && snd('kick').n([4,9].beat(1.5)).out()
beat(.5) && bin($(2), 34) && snd('snare').n([3,5].beat(1)).out() beat(.5) && bin($(2), 34) && snd('snare').n([3,5].beat(1)).out()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"binrhythm for fast cool binary rhythms!", "binrhythm for fast cool binary rhythms!",
@ -223,7 +223,7 @@ binrhythm([.5, .25].beat(1), 30) && snd('wt_granular').n(a)
.room(1).size(1).out() .room(1).size(1).out()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"Submarine jungle music", "Submarine jungle music",
@ -235,7 +235,7 @@ beat(.5) && bin($(1), 911) && snd('ST69').n([2,3,4].beat())
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
)} )}
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.
@ -249,7 +249,7 @@ prob(60)::beat(.5) && euclid($(2), 3, 8) && snd('mash')
prob(80)::beat(.5) && sound(['hh', 'hat'].pick()).out() prob(80)::beat(.5) && sound(['hh', 'hat'].pick()).out()
`, `,
true true
)} )}
## Time Warping ## Time Warping
@ -274,7 +274,7 @@ flip(3) :: beat([.25,.5].beat(.5)) :: sound('dr')
beat(.25) :: warp([12, 48, 24, 1, 120, 30].pick()) beat(.25) :: warp([12, 48, 24, 1, 120, 30].pick())
`, `,
true true
)} )}
- <ic>beat_warp(beat: number)</ic>: this function jumps to the _n_ beat of the clock. The first beat is <ic>1</ic>. - <ic>beat_warp(beat: number)</ic>: this function jumps to the _n_ beat of the clock. The first beat is <ic>1</ic>.
@ -296,7 +296,7 @@ beat(.5) :: snd('arpy').note(
beat(1) :: beat_warp([2,4,5,10,11].pick()) beat(1) :: beat_warp([2,4,5,10,11].pick())
`, `,
true true
)} )}
## Larger time divisions ## Larger time divisions
@ -311,7 +311,7 @@ ${makeExample(
flip(4) :: beat(1) :: snd('kick').out() flip(4) :: beat(1) :: snd('kick').out()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"Clapping on the edge", "Clapping on the edge",
@ -323,7 +323,7 @@ flip(2.5) :: beat(.5) :: snd('bd').out()
beat(.25) :: sound('hat').end(0.1).cutoff(1200).pan(usine(1/4)).out() beat(.25) :: sound('hat').end(0.1).cutoff(1200).pan(usine(1/4)).out()
`, `,
false false
)} )}
${makeExample( ${makeExample(
"Good old true and false", "Good old true and false",
@ -335,7 +335,7 @@ if (flip(4, 75)) {
} }
`, `,
true true
)} )}
<ic>flip</ic> is extremely powerful and is used internally for a lot of other Topos functions. You can also use it to think about **longer durations** spanning over multiple bars. Here is a silly composition that is using <ic>flip</ic> to generate a 4 bars long pattern. <ic>flip</ic> is extremely powerful and is used internally for a lot of other Topos functions. You can also use it to think about **longer durations** spanning over multiple bars. Here is a silly composition that is using <ic>flip</ic> to generate a 4 bars long pattern.
@ -343,7 +343,7 @@ ${makeExample(
"Clunky algorithmic rap music", "Clunky algorithmic rap music",
` `
// Rap God VS Lil Wild -- Adel Faure // Rap God VS Lil Wild -- Adel Faure
if (flip(16)) { if (flip(8)) {
// Playing this part for two bars // Playing this part for two bars
beat(1.5)::snd('kick').out() beat(1.5)::snd('kick').out()
beat(2)::snd('snare').out() beat(2)::snd('snare').out()
@ -360,17 +360,17 @@ if (flip(16)) {
} }
`, `,
true true
)} )}
You can use it everywhere to spice things up, including as a method parameter picker: You can use it everywhere to spice things up, including as a method parameter picker:
${makeExample( ${makeExample(
"flip is great for parameter variation", "flip is great for parameter variation",
` `
beat(.5)::snd(flip(4) ? 'kick' : 'hat').out() beat(.5)::snd(flip(2) ? 'kick' : 'hat').out()
`, `,
true true
)} )}
- <ic>flipbar(n: number = 1)</ic>: this method works just like <ic>flip</ic> but counts in bars instead of beats. It allows you to think about even larger time cycles. You can also pair it with regular <ic>flip</ic> for writing complex and long-spanning algorithmic beats. - <ic>flipbar(n: number = 1)</ic>: this method works just like <ic>flip</ic> but counts in bars instead of beats. It allows you to think about even larger time cycles. You can also pair it with regular <ic>flip</ic> for writing complex and long-spanning algorithmic beats.
@ -389,7 +389,7 @@ flipbar(2) && a()
flipbar(3) && b() flipbar(3) && b()
`, `,
true true
)} )}
${makeExample( ${makeExample(
"Alternating over four bars", "Alternating over four bars",
` `
@ -398,7 +398,7 @@ flipbar(2)
: beat(.5) && snd(['east', 'east:2'].beat(1)).out() : beat(.5) && snd(['east', 'east:2'].beat(1)).out()
`, `,
false false
)}; )};
- <ic>onbar(bars: number | number[], n: number)</ic>: The second argument, <ic>n</ic>, is used to divide the time in a period of <ic>n</ic> consecutive bars. The first argument should be a bar number or a list of bar numbers to play on. For example, <ic>onbar([1, 4], 5)</ic> will return <ic>true</ic> on bar <ic>1</ic> and <ic>4</ic> but return <ic>false</ic> the rest of the time. You can easily divide time that way. - <ic>onbar(bars: number | number[], n: number)</ic>: The second argument, <ic>n</ic>, is used to divide the time in a period of <ic>n</ic> consecutive bars. The first argument should be a bar number or a list of bar numbers to play on. For example, <ic>onbar([1, 4], 5)</ic> will return <ic>true</ic> on bar <ic>1</ic> and <ic>4</ic> but return <ic>false</ic> the rest of the time. You can easily divide time that way.
@ -422,7 +422,7 @@ if (onbar([1,2], 4)) {
rhythm(.5, 2, 7) :: snd('snare').n(3).out(); rhythm(.5, 2, 7) :: snd('snare').n(3).out();
}`, }`,
true true
)} )}
## What are pulses? ## What are pulses?
@ -471,6 +471,6 @@ if((cbar() % 4) > 1) {
beat([.5, .5, 1, .25].beat(0.5)) :: sound('shaker').out() beat([.5, .5, 1, .25].beat(0.5)) :: sound('shaker').out()
`, `,
true true
)} )}
`; `;
}; };