Merge pull request #112 from tidalcycles/more-functions

`.brak()`, `.inside()` and `.outside()`
This commit is contained in:
Alex McLean 2022-05-09 20:09:46 +02:00 committed by GitHub
commit 9588272639
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 25 deletions

View File

@ -67,7 +67,7 @@ export class Pattern {
* @param {Function} func the function to apply * @param {Function} func the function to apply
* @returns Pattern * @returns Pattern
*/ */
withQueryTime(func) { withQueryTime(func) {
return new Pattern((state) => this.query(state.withSpan((span) => span.withTime(func)))); return new Pattern((state) => this.query(state.withSpan((span) => span.withTime(func))));
} }
@ -88,7 +88,7 @@ export class Pattern {
* @param {Function} func the function to apply * @param {Function} func the function to apply
* @returns Pattern * @returns Pattern
*/ */
withHapTime(func) { withHapTime(func) {
return this.withHapSpan((span) => span.withTime(func)); return this.withHapSpan((span) => span.withTime(func));
} }
@ -97,7 +97,7 @@ export class Pattern {
* @param {Function} func * @param {Function} func
* @returns Pattern * @returns Pattern
*/ */
_withHaps(func) { _withHaps(func) {
return new Pattern((state) => func(this.query(state))); return new Pattern((state) => func(this.query(state)));
} }
@ -106,7 +106,7 @@ export class Pattern {
* @param {Function} func * @param {Function} func
* @returns Pattern * @returns Pattern
*/ */
_withHap(func) { _withHap(func) {
return this._withHaps((haps) => haps.map(func)); return this._withHaps((haps) => haps.map(func));
} }
@ -193,7 +193,7 @@ export class Pattern {
/** /**
* see {@link Pattern#withValue|withValue} * see {@link Pattern#withValue|withValue}
*/ */
fmap(func) { fmap(func) {
return this.withValue(func); return this.withValue(func);
} }
@ -231,7 +231,7 @@ export class Pattern {
* as its `part` timespan. * as its `part` timespan.
* @returns Pattern * @returns Pattern
*/ */
onsetsOnly() { onsetsOnly() {
// Returns a new pattern that will only return haps where the start // Returns a new pattern that will only return haps where the start
// of the 'whole' timespan matches the start of the 'part' // of the 'whole' timespan matches the start of the 'part'
// timespan, i.e. the haps that include their 'onset'. // timespan, i.e. the haps that include their 'onset'.
@ -696,6 +696,14 @@ export class Pattern {
return this._fast(Fraction(1).div(factor)); return this._fast(Fraction(1).div(factor));
} }
_inside(factor, f) {
return f(this._slow(factor))._fast(factor);
}
_outside(factor, f) {
return f(this._fast(factor))._slow(factor);
}
_ply(factor) { _ply(factor) {
return this.fmap((x) => pure(x)._fast(factor))._squeezeJoin(); return this.fmap((x) => pure(x)._fast(factor))._squeezeJoin();
} }
@ -822,6 +830,16 @@ export class Pattern {
return slowcatPrime(...pats); return slowcatPrime(...pats);
} }
/**
* Returns a new pattern where every other cycle is played once, twice as
* fast, and offset in time by one quarter of a cycle. Creates a kind of
* breakbeat feel.
* @returns Pattern
*/
brak() {
return this.when(slowcat(false, true), (x) => fastcat(x, silence)._late(0.25));
}
rev() { rev() {
const pat = this; const pat = this;
const query = function (state) { const query = function (state) {
@ -979,7 +997,7 @@ function _composeOp(a, b, func) {
} }
// Make composers // Make composers
(function() { (function () {
const num = (pat) => pat._asNumber(); const num = (pat) => pat._asNumber();
const numOrString = (pat) => pat._asNumber(false, true); const numOrString = (pat) => pat._asNumber(false, true);
@ -1390,6 +1408,14 @@ Pattern.prototype.compress = function (...args) {
args = args.map(reify); args = args.map(reify);
return patternify2(Pattern.prototype._compress)(...args, this); return patternify2(Pattern.prototype._compress)(...args, this);
}; };
Pattern.prototype.outside = function (...args) {
args = args.map(reify);
return patternify2(Pattern.prototype._outside)(...args, this);
};
Pattern.prototype.inside = function (...args) {
args = args.map(reify);
return patternify2(Pattern.prototype._inside)(...args, this);
};
// call this after all Patter.prototype.define calls have been executed! (right before evaluate) // call this after all Patter.prototype.define calls have been executed! (right before evaluate)
Pattern.prototype.bootstrap = function () { Pattern.prototype.bootstrap = function () {

View File

@ -41,6 +41,7 @@ import {
tri2, tri2,
id, id,
ply, ply,
rev
} from '../index.mjs'; } from '../index.mjs';
import { steady } from '../signal.mjs'; import { steady } from '../signal.mjs';
@ -277,10 +278,7 @@ describe('Pattern', function () {
); );
}); });
it('can SqueezeOut() structure', () => { it('can SqueezeOut() structure', () => {
sameFirst( sameFirst(sequence(1, [2, 3]).keepifSqueezeOut(true, true, false), sequence([1, [2, 3]], [1, [2, 3]], silence));
sequence(1, [2, 3]).keepifSqueezeOut(true, true, false),
sequence([1, [2, 3]], [1, [2, 3]], silence),
);
}); });
}); });
describe('sub()', function () { describe('sub()', function () {
@ -439,6 +437,20 @@ describe('Pattern', function () {
// mini('eb3 [c3 g3]/2 ') always plays [c3 g3] // mini('eb3 [c3 g3]/2 ') always plays [c3 g3]
}); });
}); });
describe('inside', () => {
it('can rev inside a cycle', () => {
sameFirst(sequence('a', 'b', 'c', 'd').inside(2, rev),
sequence('b', 'a', 'd', 'c')
);
});
});
describe('outside', () => {
it('can rev outside a cycle', () => {
sameFirst(sequence('a', 'b', 'c', 'd')._slow(2).outside(2, rev),
sequence('d', 'c')
);
});
});
describe('_filterValues()', function () { describe('_filterValues()', function () {
it('Filters true', function () { it('Filters true', function () {
assert.equal( assert.equal(
@ -589,6 +601,11 @@ describe('Pattern', function () {
); );
}); });
}); });
describe('brak()', () => {
it('Can make something a bit breakbeaty', () => {
sameFirst(sequence('a', 'b').brak()._fast(2), sequence('a', 'b', fastcat(silence, 'a'), fastcat('b', silence)));
});
});
describe('timeCat()', function () { describe('timeCat()', function () {
it('Can concatenate patterns with different relative durations', function () { it('Can concatenate patterns with different relative durations', function () {
assert.deepStrictEqual( assert.deepStrictEqual(