Merge branch 'main' into glossing/fmsss
This commit is contained in:
commit
d28c8dac8e
32 changed files with 1065 additions and 210 deletions
|
|
@ -1366,6 +1366,8 @@ export const { fanchor } = registerControl('fanchor');
|
|||
*
|
||||
* @name lprate
|
||||
* @param {number | Pattern} rate rate in hertz
|
||||
* @example
|
||||
* note("<c c c# c c c4>*16").s("sawtooth").lpf(600).lprate("<4 8 2 1>")
|
||||
*/
|
||||
export const { lprate } = registerControl('lprate');
|
||||
|
||||
|
|
@ -1374,6 +1376,8 @@ export const { lprate } = registerControl('lprate');
|
|||
*
|
||||
* @name lpsync
|
||||
* @param {number | Pattern} rate rate in cycles
|
||||
* @example
|
||||
* note("<c c c# c c c4>*16").s("sawtooth").lpf(600).lpsync("<4 8 2 1>")
|
||||
*/
|
||||
export const { lpsync } = registerControl('lpsync');
|
||||
|
||||
|
|
@ -1382,8 +1386,23 @@ export const { lpsync } = registerControl('lpsync');
|
|||
*
|
||||
* @name lpdepth
|
||||
* @param {number | Pattern} depth depth of modulation
|
||||
* @example
|
||||
* note("<c c c# c c c4>*16").s("sawtooth").lpf(600).lpdepth("<1 .5 1.8 0>")
|
||||
*/
|
||||
|
||||
export const { lpdepth } = registerControl('lpdepth');
|
||||
/**
|
||||
* Depth of the LFO for the lowpass filter, in HZ
|
||||
*
|
||||
* @name lpdepthfrequency
|
||||
* @synonyms
|
||||
* lpdethfreq
|
||||
* @param {number | Pattern} depth depth of modulation
|
||||
* @example
|
||||
* note("<c c c# c c c4>*16").s("sawtooth").lpf(600).lpdepthfrequency("<200 500 100 0>")
|
||||
*/
|
||||
|
||||
export const { lpdepthfrequency } = registerControl('lpdepthfrequency', 'lpdepthfreq');
|
||||
|
||||
/**
|
||||
* Shape of the LFO for the lowpass filter
|
||||
|
|
@ -1433,6 +1452,19 @@ export const { bpsync } = registerControl('bpsync');
|
|||
*/
|
||||
export const { bpdepth } = registerControl('bpdepth');
|
||||
|
||||
/**
|
||||
* Depth of the LFO for the bandpass filter, in HZ
|
||||
*
|
||||
* @name bpdepthfrequency
|
||||
* @synonyms
|
||||
* bpdethfreq
|
||||
* @param {number | Pattern} depth depth of modulation
|
||||
* @example
|
||||
* note("<c c c# c c c4>*16").s("sawtooth").lpf(600).bpdepthfrequency("<200 500 100 0>")
|
||||
*/
|
||||
|
||||
export const { bpdepthfrequency } = registerControl('bpdepthfrequency', 'bpdepthfreq');
|
||||
|
||||
/**
|
||||
* Shape of the LFO for the bandpass filter
|
||||
*
|
||||
|
|
@ -1479,7 +1511,20 @@ export const { hpsync } = registerControl('hpsync');
|
|||
* @name hpdepth
|
||||
* @param {number | Pattern} depth depth of modulation
|
||||
*/
|
||||
export const { hpdepth } = registerControl('hpdepth');
|
||||
export const { hpdepth, hpdepthfreq } = registerControl('hpdepth');
|
||||
|
||||
/**
|
||||
* Depth of the LFO for the hipass filter, in hz
|
||||
*
|
||||
* @name hpdepthfrequency
|
||||
* @synonyms
|
||||
* hpdethfreq
|
||||
* @param {number | Pattern} depth depth of modulation
|
||||
* @example
|
||||
* note("<c c c# c c c4>*16").s("sawtooth").lpf(600).hpdepthfrequency("<200 500 100 0>")
|
||||
*/
|
||||
|
||||
export const { hpdepthfrequency } = registerControl('hpdepthfrequency', 'hpdepthfreq');
|
||||
|
||||
/**
|
||||
* Shape of the LFO for the highpass filter
|
||||
|
|
@ -1892,12 +1937,12 @@ export const { nudge } = registerControl('nudge');
|
|||
* Sets the default octave of a synth.
|
||||
*
|
||||
* @name octave
|
||||
* @synonyms oct
|
||||
* @param {number | Pattern} octave octave number
|
||||
* @example
|
||||
* n("0,4,7").s('supersquare').octave("<3 4 5 6>").osc()
|
||||
* @superDirtOnly
|
||||
* n("0,4,7").scale("F:minor").s('supersaw').octave("<0 1 2 3>")
|
||||
*/
|
||||
export const { octave } = registerControl('octave');
|
||||
export const { octave, oct } = registerControl('octave', 'oct');
|
||||
|
||||
// ['ophatdecay'],
|
||||
// TODO: example
|
||||
|
|
@ -1905,6 +1950,7 @@ export const { octave } = registerControl('octave');
|
|||
* An `orbit` is a global parameter context for patterns. Patterns with the same orbit will share the same global effects.
|
||||
*
|
||||
* @name orbit
|
||||
* @synonyms o
|
||||
* @param {number | Pattern} number
|
||||
* @example
|
||||
* stack(
|
||||
|
|
@ -1912,7 +1958,7 @@ export const { octave } = registerControl('octave');
|
|||
* s("~ sd ~ sd").delay(.5).delaytime(.125).orbit(2)
|
||||
* )
|
||||
*/
|
||||
export const { orbit } = registerControl('orbit');
|
||||
export const { orbit } = registerControl('orbit', 'o');
|
||||
// TODO: what is this? not found in tidal doc Answer: gain is limited to maximum of 2. This allows you to go over that
|
||||
export const { overgain } = registerControl('overgain');
|
||||
// TODO: what is this? not found in tidal doc. Similar to above, but limited to 1
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import {
|
|||
stringifyValues,
|
||||
} from './util.mjs';
|
||||
import drawLine from './drawLine.mjs';
|
||||
import { logger } from './logger.mjs';
|
||||
import { errorLogger, logger } from './logger.mjs';
|
||||
|
||||
let stringParser;
|
||||
|
||||
|
|
@ -414,7 +414,7 @@ export class Pattern {
|
|||
try {
|
||||
return this.query(new State(new TimeSpan(begin, end), controls));
|
||||
} catch (err) {
|
||||
logger(`[query]: ${err.message}`, 'error');
|
||||
errorLogger(err, 'query');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -2234,7 +2234,7 @@ export const brak = register('brak', function (pat) {
|
|||
});
|
||||
|
||||
/**
|
||||
* Reverse all haps in a pattern
|
||||
* Reverse all cycles in a pattern. See also `revv` for reversing a whole pattern.
|
||||
*
|
||||
* @name rev
|
||||
* @memberof Pattern
|
||||
|
|
@ -2266,6 +2266,23 @@ export const rev = register(
|
|||
true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Reverse a whole pattern. See also `rev` for reversing each cycle.
|
||||
*
|
||||
* @name revv
|
||||
* @memberof Pattern
|
||||
* @returns Pattern
|
||||
* @example
|
||||
* // This is the same as `<[g e] [d c]>`. If `rev()` is used, you get
|
||||
* // the same as `<[d c] [g e]>`, where each cycle reverses, but the order of
|
||||
* // cycles stays the same.
|
||||
* note("<[c d] [e g]>").revv()
|
||||
*/
|
||||
export const revv = register('revv', function (pat) {
|
||||
const negateSpan = (span) => new TimeSpan(Fraction(0).sub(span.end), Fraction(0).sub(span.begin));
|
||||
return pat.withQuerySpan(negateSpan).withHapSpan(negateSpan);
|
||||
});
|
||||
|
||||
/** Like press, but allows you to specify the amount by which each
|
||||
* event is shifted. pressBy(0.5) is the same as press, while
|
||||
* pressBy(1/3) shifts each event by a third of its timespan.
|
||||
|
|
|
|||
|
|
@ -152,9 +152,9 @@ export function repl({
|
|||
// allows muting a pattern x with x_ or _x
|
||||
return silence;
|
||||
}
|
||||
if (id === '$') {
|
||||
if (id.includes('$')) {
|
||||
// allows adding anonymous patterns with $:
|
||||
id = `$${anonymousIndex}`;
|
||||
id = `${id}${anonymousIndex}`;
|
||||
anonymousIndex++;
|
||||
}
|
||||
pPatterns[id] = this;
|
||||
|
|
@ -215,8 +215,19 @@ export function repl({
|
|||
let { pattern, meta } = await _evaluate(code, transpiler, transpilerOptions);
|
||||
if (Object.keys(pPatterns).length) {
|
||||
let patterns = [];
|
||||
let soloActive = false;
|
||||
for (const [key, value] of Object.entries(pPatterns)) {
|
||||
patterns.push(value.withState((state) => state.setControls({ id: key })));
|
||||
// handle soloed patterns ex: S$: s("bd!4")
|
||||
const isSolod = key.length > 1 && key.startsWith('S');
|
||||
if (isSolod && soloActive === false) {
|
||||
// first time we see a soloed pattern, clear existing patterns
|
||||
patterns = [];
|
||||
soloActive = true;
|
||||
}
|
||||
if (!soloActive || (soloActive && isSolod)) {
|
||||
const valWithState = value.withState((state) => state.setControls({ id: key }));
|
||||
patterns.push(valWithState);
|
||||
}
|
||||
}
|
||||
if (eachTransform) {
|
||||
// Explicit lambda so only element (not index and array) are passed
|
||||
|
|
@ -227,14 +238,13 @@ export function repl({
|
|||
pattern = eachTransform(pattern);
|
||||
}
|
||||
if (allTransforms.length) {
|
||||
for (let i in allTransforms) {
|
||||
pattern = allTransforms[i](pattern);
|
||||
for (const transform of allTransforms) {
|
||||
pattern = transform(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isPattern(pattern)) {
|
||||
const message = `got "${typeof evaluated}" instead of pattern`;
|
||||
throw new Error(message + (typeof evaluated === 'function' ? ', did you forget to call a function?' : '.'));
|
||||
pattern = silence;
|
||||
}
|
||||
logger(`[eval] code updated`);
|
||||
pattern = await setPattern(pattern, autostart);
|
||||
|
|
|
|||
|
|
@ -524,7 +524,7 @@ export const wchoose = (...pairs) => wchooseWith(rand, ...pairs);
|
|||
* @example
|
||||
* wchooseCycles(["bd",10], ["hh",1], ["sd",1]).s().fast(8)
|
||||
* @example
|
||||
* wchooseCycles(["bd bd bd",5], ["hh hh hh",3], ["sd sd sd",1]).fast(4).s()
|
||||
* wchooseCycles(["c c c",5], ["a a a",3], ["f f f",1]).fast(4).note()
|
||||
* @example
|
||||
* // The probability can itself be a pattern
|
||||
* wchooseCycles(["bd(3,8)","<5 0>"], ["hh hh hh",3]).fast(4).s()
|
||||
|
|
|
|||
|
|
@ -586,6 +586,18 @@ describe('Pattern', () => {
|
|||
.map((a) => a.value),
|
||||
).toStrictEqual(['c', 'b', 'a']);
|
||||
});
|
||||
it('Does not reverse the order of cycles', () => {
|
||||
expect(fastcat('a', 'b', 'c', 'd').slow(2).rev().fast(2).sortHapsByPart().firstCycle()).toStrictEqual(
|
||||
fastcat('b', 'a', 'd', 'c').firstCycle(),
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('revv()', () => {
|
||||
it('Does reverse the order of cycles', () => {
|
||||
expect(fastcat('a', 'b', 'c', 'd').slow(2).revv().fast(2).sortHapsByPart().firstCycle()).toStrictEqual(
|
||||
fastcat('d', 'c', 'b', 'a').firstCycle(),
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('sequence()', () => {
|
||||
it('Can work like fastcat', () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue