Compare commits

...

2 Commits

Author SHA1 Message Date
Felix Roos 0d7438b939 Merge branch 'main' into amplitude-modulation 2023-09-17 17:29:56 +02:00
Felix Roos 52de58ef1f begin am feature 2023-08-23 21:55:11 +02:00
5 changed files with 40 additions and 2 deletions
+2
View File
@@ -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..
+13
View File
@@ -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,
+6 -1
View File
@@ -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(
+1 -1
View File
@@ -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;
+18
View File
@@ -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;
};