diff --git a/packages/superdough/sampler.mjs b/packages/superdough/sampler.mjs index e7aee294f..d45e1050b 100644 --- a/packages/superdough/sampler.mjs +++ b/packages/superdough/sampler.mjs @@ -1,5 +1,5 @@ import { getBaseURL, getCommonSampleInfo } from './util.mjs'; -import { registerSound, registerWaveTable } from './index.mjs'; +import { registerSound, registerWaveTable, soundMap } from './index.mjs'; import { getAudioContext } from './audioContext.mjs'; import { getADSRValues, @@ -30,6 +30,29 @@ function humanFileSize(bytes, si) { return bytes.toFixed(1) + ' ' + units[u]; } +/** + * Returns the duration, in seconds, of the given sample. + * Has optional param `n` (for instance, the `2` in `s("casio:2")`) + * + * Note: `must` be called with await, otherwise you'll get a pending Promise object. + * + * @name getDuration,getDur + * @tag samples + * @param {string} sampleName + * @param {number} (optional) n + * + * @example + * // Set a patterns cycle length to exactly the length of the sample + * samples('github:tidalcycles/dirt-samples') + * let k = await getDuration('sax') + * s("sax").cps(1/k) + */ +export const getDuration = (s, n = 0) => { + return getSampleBufferSource({ s, n }, soundMap.get(s)[s].data.samples).then((x) => x.bufferDuration); +}; + +export const getDur = getDuration; + export function getSampleInfo(hapValue, bank) { const { speed = 1.0 } = hapValue; const { transpose, url, index, midi, label } = getCommonSampleInfo(hapValue, bank); diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 4ce8164bc..98d1fb67b 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -25,7 +25,7 @@ import { import { map } from 'nanostores'; import { logger } from './logger.mjs'; import { connectLFO, connectEnvelope, connectBusModulator } from './modulators.mjs'; -import { loadBuffer } from './sampler.mjs'; +import { getSampleBufferSource, loadBuffer } from './sampler.mjs'; import { getAudioContext } from './audioContext.mjs'; import { SuperdoughAudioController } from './superdoughoutput.mjs'; import { resetSeenKeys } from './wavetable.mjs'; diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 6576095c3..458904baf 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -5306,6 +5306,15 @@ exports[`runs examples > example "gain" example index 0 1`] = ` exports[`runs examples > example "gap" example index 0 1`] = `[]`; +exports[`runs examples > example "getDur" example index 0 1`] = ` +[ + "[ 0/1 → 1/1 | s:sax cps:null ]", + "[ 1/1 → 2/1 | s:sax cps:null ]", + "[ 2/1 → 3/1 | s:sax cps:null ]", + "[ 3/1 → 4/1 | s:sax cps:null ]", +] +`; + exports[`runs examples > example "grow" example index 0 1`] = ` [ "[ 0/1 → 1/10 | s:tha bank:mridangam ]", diff --git a/test/runtime.mjs b/test/runtime.mjs index 332e3caad..e06f91620 100644 --- a/test/runtime.mjs +++ b/test/runtime.mjs @@ -127,6 +127,7 @@ const loadSoundfont = () => {}; const loadCsound = () => {}; const loadCSound = () => {}; const loadcsound = () => {}; +const getDuration = () => {}; const midin = () => { return (ccNum) => strudel.ref(() => 0); // returns ref with default value 0 @@ -170,6 +171,7 @@ evalScope( loadCSound, loadCsound, loadcsound, + getDuration, setcps: id, setcpm: id, Clock: {}, // whatever