mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-14 06:43:47 -04:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d7438b939 | |||
| 52de58ef1f |
@@ -139,6 +139,8 @@ const generic_params = [
|
||||
*
|
||||
*/
|
||||
[['fmi', 'fmh'], 'fm'],
|
||||
['amh'],
|
||||
['ami'],
|
||||
// fm envelope
|
||||
/**
|
||||
* Ramp type of fm envelope. Exp might be a bit broken..
|
||||
|
||||
@@ -78,6 +78,19 @@ export const getParamADSR = (param, attack, decay, sustain, release, min, max, b
|
||||
param.linearRampToValueAtTime(min, end + Math.max(release, 0.1));
|
||||
};
|
||||
|
||||
export const getAM = (freq, harmonicityRatio, amount, wave = 'sine') => {
|
||||
const carrfreq = freq;
|
||||
const modfreq = carrfreq * harmonicityRatio;
|
||||
const { node: modulator, stop } = mod(modfreq, amount, wave);
|
||||
const g = gainNode(1);
|
||||
modulator.connect(g.gain);
|
||||
return g; /*
|
||||
const c = 1 / 1 ** amount;
|
||||
console.log('c', c);
|
||||
const compensate = gainNode(1/amount);
|
||||
g.connect(compensate);
|
||||
return compensate; */
|
||||
};
|
||||
export function createFilter(
|
||||
context,
|
||||
type,
|
||||
|
||||
@@ -7,7 +7,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
||||
import './feedbackdelay.mjs';
|
||||
import './reverb.mjs';
|
||||
import './vowel.mjs';
|
||||
import { clamp } from './util.mjs';
|
||||
import { clamp, getFrequency } from './util.mjs';
|
||||
import workletsUrl from './worklets.mjs?url';
|
||||
import { createFilter, gainNode } from './helpers.mjs';
|
||||
import { map } from 'nanostores';
|
||||
@@ -217,6 +217,8 @@ export const superdough = async (value, deadline, hapDuration) => {
|
||||
room,
|
||||
size = 2,
|
||||
velocity = 1,
|
||||
amh, // amplitude modulation harmonicity
|
||||
ami = 4, // amplitude modulation index
|
||||
analyze, // analyser wet
|
||||
fft = 8, // fftSize 0 - 10
|
||||
} = value;
|
||||
@@ -257,6 +259,9 @@ export const superdough = async (value, deadline, hapDuration) => {
|
||||
// gain stage
|
||||
chain.push(gainNode(gain));
|
||||
|
||||
amh !== undefined && chain.push(getAM(getFrequency(value), amh, ami));
|
||||
|
||||
// filters
|
||||
if (cutoff !== undefined) {
|
||||
let lp = () =>
|
||||
createFilter(
|
||||
|
||||
@@ -2,7 +2,7 @@ import { midiToFreq, noteToMidi } from './util.mjs';
|
||||
import { registerSound, getAudioContext } from './superdough.mjs';
|
||||
import { gainNode, getEnvelope, getExpEnvelope } from './helpers.mjs';
|
||||
|
||||
const mod = (freq, range = 1, type = 'sine') => {
|
||||
export const mod = (freq, range = 1, type = 'sine') => {
|
||||
const ctx = getAudioContext();
|
||||
const osc = ctx.createOscillator();
|
||||
osc.type = type;
|
||||
|
||||
@@ -51,3 +51,21 @@ export const valueToMidi = (value, fallbackValue) => {
|
||||
}
|
||||
return fallbackValue;
|
||||
};
|
||||
|
||||
export const getFrequency = (value) => {
|
||||
// if value is number => interpret as midi number as long as its not marked as frequency
|
||||
if (typeof value === 'object') {
|
||||
if (value.freq) {
|
||||
return value.freq;
|
||||
}
|
||||
return getFreq(value.note || value.n || value.value || 36);
|
||||
}
|
||||
if (typeof value === 'number' && context.type !== 'frequency') {
|
||||
value = midiToFreq(hap.value);
|
||||
} else if (typeof value === 'string' && isNote(value)) {
|
||||
value = midiToFreq(noteToMidi(hap.value));
|
||||
} else if (typeof value !== 'number') {
|
||||
throw new Error('not a note or frequency: ' + value);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user