mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 13:48:34 +00:00
Merge pull request #301 from tidalcycles/support-freq-in-sampler
add freq support to sampler
This commit is contained in:
commit
f437d976f8
@ -10,6 +10,7 @@ import {
|
||||
tokenizeNote,
|
||||
toMidi,
|
||||
fromMidi,
|
||||
freqToMidi,
|
||||
_mod,
|
||||
compose,
|
||||
getFrequency,
|
||||
@ -94,6 +95,12 @@ describe('fromMidi', () => {
|
||||
expect(fromMidi(57)).toEqual(220);
|
||||
});
|
||||
});
|
||||
describe('freqToMidi', () => {
|
||||
it('should turn frequency into midi', () => {
|
||||
expect(freqToMidi(440)).toEqual(69);
|
||||
expect(freqToMidi(220)).toEqual(57);
|
||||
});
|
||||
});
|
||||
describe('getFrequency', () => {
|
||||
const happify = (val, context = {}) => pure(val).firstCycle()[0].setContext(context);
|
||||
it('should turn note into frequency', () => {
|
||||
|
||||
@ -31,6 +31,30 @@ export const fromMidi = (n) => {
|
||||
return Math.pow(2, (n - 69) / 12) * 440;
|
||||
};
|
||||
|
||||
export const freqToMidi = (freq) => {
|
||||
return (12 * Math.log(freq / 440)) / Math.LN2 + 69;
|
||||
};
|
||||
|
||||
export const valueToMidi = (value, fallbackValue) => {
|
||||
if (typeof value !== 'object') {
|
||||
throw new Error('valueToMidi: expected object value');
|
||||
}
|
||||
let { freq, note } = value;
|
||||
if (typeof freq === 'number') {
|
||||
return freqToMidi(freq);
|
||||
}
|
||||
if (typeof note === 'string') {
|
||||
return toMidi(note);
|
||||
}
|
||||
if (typeof note === 'number') {
|
||||
return note;
|
||||
}
|
||||
if (!fallbackValue) {
|
||||
throw new Error('valueToMidi: expected freq or note to be set');
|
||||
}
|
||||
return fallbackValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated does not appear to be referenced or invoked anywhere in the codebase
|
||||
*/
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { logger, toMidi } from '@strudel.cycles/core';
|
||||
import { logger, toMidi, valueToMidi } from '@strudel.cycles/core';
|
||||
import { getAudioContext } from './index.mjs';
|
||||
|
||||
const bufferCache = {}; // string: Promise<ArrayBuffer>
|
||||
@ -20,9 +20,12 @@ function humanFileSize(bytes, si) {
|
||||
return bytes.toFixed(1) + ' ' + units[u];
|
||||
}
|
||||
|
||||
export const getSampleBufferSource = async (s, n, note, speed) => {
|
||||
export const getSampleBufferSource = async (s, n, note, speed, freq) => {
|
||||
let transpose = 0;
|
||||
let midi = typeof note === 'string' ? toMidi(note) : note || 36;
|
||||
if (freq !== undefined && note !== undefined) {
|
||||
logger('[sampler] hap has note and freq. ignoring note', 'warning');
|
||||
}
|
||||
let midi = valueToMidi({ freq, note }, 36);
|
||||
transpose = midi - 36; // C3 is middle C
|
||||
|
||||
const ac = getAudioContext();
|
||||
|
||||
@ -288,10 +288,10 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
||||
|
||||
if (soundfont) {
|
||||
// is soundfont
|
||||
bufferSource = await globalThis.getFontBufferSource(soundfont, note || n, ac);
|
||||
bufferSource = await globalThis.getFontBufferSource(soundfont, note || n, ac, freq);
|
||||
} else {
|
||||
// is sample from loaded samples(..)
|
||||
bufferSource = await getSampleBufferSource(s, n, note, speed);
|
||||
bufferSource = await getSampleBufferSource(s, n, note, speed, freq);
|
||||
}
|
||||
// asny stuff above took too long?
|
||||
if (ac.currentTime > t) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Pattern, toMidi } from '@strudel.cycles/core';
|
||||
import { Pattern, toMidi, valueToMidi } from '@strudel.cycles/core';
|
||||
import { samples } from '@strudel.cycles/webaudio';
|
||||
|
||||
export async function prebake({ isMock = false, baseDir = '.' } = {}) {
|
||||
@ -25,9 +25,9 @@ Pattern.prototype.piano = function () {
|
||||
.s('piano')
|
||||
.release(0.1)
|
||||
.fmap((value) => {
|
||||
const midi = typeof value.note === 'string' ? toMidi(value.note) : value.note;
|
||||
const midi = valueToMidi(value);
|
||||
// pan by pitch
|
||||
const pan = panwidth(Math.min(midi / maxPan, 1), 0.5);
|
||||
const pan = panwidth(Math.min(Math.round(midi) / maxPan, 1), 0.5);
|
||||
return { ...value, pan: (value.pan || 1) * pan };
|
||||
});
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user