Skip to content

Commit

Permalink
Merge branch 'tidalcycles:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
edcrub authored Aug 5, 2024
2 parents e8787a6 + d40e4da commit b175aba
Show file tree
Hide file tree
Showing 42 changed files with 1,306 additions and 74 deletions.
12 changes: 12 additions & 0 deletions packages/core/controls.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,17 @@ export const { compressorRelease } = registerControl('compressorRelease');
*
*/
export const { speed } = registerControl('speed');

/**
* Changes the speed of sample playback, i.e. a cheap way of changing pitch.
*
* @name stretch
* @param {number | Pattern} factor -inf to inf, negative numbers play the sample backwards.
* @example
* s("gm_flute").stretch("1 2 .5")
*
*/
export const { stretch } = registerControl('stretch');
/**
* Used in conjunction with `speed`, accepts values of "r" (rate, default behavior), "c" (cycles), or "s" (seconds). Using `unit "c"` means `speed` will be interpreted in units of cycles, e.g. `speed "1"` means samples will be stretched to fill a cycle. Using `unit "s"` means the playback speed will be adjusted so that the duration is the number of seconds specified by `speed`.
*
Expand All @@ -1393,6 +1404,7 @@ export const { speed } = registerControl('speed');
* @superdirtOnly
*
*/

export const { unit } = registerControl('unit');
/**
* Made by Calum Gunn. Reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter. The SuperCollider manual defines Squiz as:
Expand Down
3 changes: 1 addition & 2 deletions packages/core/evaluate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import { isPattern } from './index.mjs';

export const evalScope = async (...args) => {
const results = await Promise.allSettled(args);
const modules = results.filter((result) => result.status === 'fulfilled').map((r) => r.value);
Expand Down Expand Up @@ -39,6 +37,7 @@ function safeEval(str, options = {}) {

export const evaluate = async (code, transpiler, transpilerOptions) => {
let meta = {};

if (transpiler) {
// transform syntactically correct js code to semantically usable code
const transpiled = transpiler(code, transpilerOptions);
Expand Down
19 changes: 15 additions & 4 deletions packages/core/pattern.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1423,6 +1423,9 @@ export function fastcat(...pats) {
result = result._fast(pats.length);
result.tactus = pats.length;
}
if (pats.length == 1 && pats[0].__tactus_source) {
pats.tactus = pats[0].tactus;
}
return result;
}

Expand Down Expand Up @@ -1566,7 +1569,11 @@ export function register(name, func, patternify = true, preserveTactus = false,
// There are patternified args, so lets make an unpatternified
// version, prefixed by '_'
Pattern.prototype['_' + name] = function (...args) {
return func(...args, this);
const result = func(...args, this);
if (preserveTactus) {
result.setTactus(this.tactus);
}
return result;
};
}

Expand Down Expand Up @@ -2612,8 +2619,7 @@ export function s_cat(...timepats) {
}
if (timepats.length == 1) {
const result = reify(timepats[0][1]);
result.tactus = timepats[0][0];
return result;
return result.withTactus((_) => timepats[0][0]);
}

const total = timepats.map((a) => a[0]).reduce((a, b) => a.add(b), Fraction(0));
Expand Down Expand Up @@ -2706,6 +2712,10 @@ export const s_sub = stepRegister('s_sub', function (i, pat) {
return pat.s_add(pat.tactus.sub(i));
});

export const s_cycles = stepRegister('s_extend', function (factor, pat) {
return pat.fast(factor).s_expand(factor);
});

export const s_expand = stepRegister('s_expand', function (factor, pat) {
return pat.withTactus((t) => t.mul(Fraction(factor)));
});
Expand Down Expand Up @@ -2919,7 +2929,8 @@ export const splice = register(
);

export const { loopAt, loopat } = register(['loopAt', 'loopat'], function (factor, pat) {
return new Pattern((state) => _loopAt(factor, pat, state.controls._cps).query(state));
const tactus = pat.tactus ? pat.tactus.div(factor) : undefined;
return new Pattern((state) => _loopAt(factor, pat, state.controls._cps).query(state), tactus);
});

/**
Expand Down
7 changes: 7 additions & 0 deletions packages/core/signal.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,13 @@ export const pickRestart = register('pickRestart', function (lookup, pat) {
* @param {Pattern} pat
* @param {*} xs
* @returns {Pattern}
* @example
* p1: "<a b c d>".pickRestart({
a: n("0 1 2 3"),
b: n("4 5 6 7"),
c: n("8 9 10 11"),
d: n("12 13 14 15")
}).scale("C:major").s("piano")
*/
export const pickmodRestart = register('pickmodRestart', function (lookup, pat) {
return _pick(lookup, pat, true).restartJoin();
Expand Down
5 changes: 5 additions & 0 deletions packages/core/test/pattern.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1248,4 +1248,9 @@ describe('Pattern', () => {
);
});
});
describe('loopAt', () => {
it('maintains tactus', () => {
expect(s('bev').chop(8).loopAt(2).tactus).toStrictEqual(Fraction(4));
});
});
});
4 changes: 2 additions & 2 deletions packages/mini/mini.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const applyOptions = (parent, enter) => (pat, i) => {
const ast = parent.source_[i];
const options = ast.options_;
const ops = options?.ops;

const tactus_source = pat.__tactus_source;
if (ops) {
for (const op of ops) {
switch (op.type_) {
Expand Down Expand Up @@ -69,7 +69,7 @@ const applyOptions = (parent, enter) => (pat, i) => {
}
}
}

pat.__tactus_source = pat.__tactus_source || tactus_source;
return pat;
};

Expand Down
2 changes: 2 additions & 0 deletions packages/mini/test/mini.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,14 @@ describe('mini', () => {
});
it('supports ^ tactus marking', () => {
expect(mini('a [^b c]').tactus).toEqual(Fraction(4));
expect(mini('[^b c]!3').tactus).toEqual(Fraction(6));
expect(mini('[a b c] [d [e f]]').tactus).toEqual(Fraction(2));
expect(mini('^[a b c] [d [e f]]').tactus).toEqual(Fraction(2));
expect(mini('[a b c] [d [^e f]]').tactus).toEqual(Fraction(8));
expect(mini('[a b c] [^d [e f]]').tactus).toEqual(Fraction(4));
expect(mini('[^a b c] [^d [e f]]').tactus).toEqual(Fraction(12));
expect(mini('[^a b c] [d [^e f]]').tactus).toEqual(Fraction(24));
expect(mini('[^a b c d e]').tactus).toEqual(Fraction(5));
});
});

Expand Down
Loading

0 comments on commit b175aba

Please sign in to comment.