@@ -2,13 +2,39 @@ import { midiToFreq, noteToMidi } from './util.mjs';
22import { registerSound } from './superdough.mjs' ;
33import { getOscillator , gainNode , getEnvelope } from './helpers.mjs' ;
44
5+ const mod = ( freq , range = 1 , type = 'sine' ) => {
6+ const ctx = getAudioContext ( ) ;
7+ const osc = ctx . createOscillator ( ) ;
8+ osc . type = type ;
9+ osc . frequency . value = freq ;
10+ osc . start ( ) ;
11+ const g = new GainNode ( ctx , { gain : range } ) ;
12+ osc . connect ( g ) ; // -range, range
13+ return { node : g , stop : ( t ) => osc . stop ( t ) } ;
14+ } ;
15+
16+ const fm = ( osc , harmonicityRatio , modulationIndex , wave = 'sine' ) => {
17+ const carrfreq = osc . frequency . value ;
18+ const modfreq = carrfreq * harmonicityRatio ;
19+ const modgain = modfreq * modulationIndex ;
20+ const { node : modulator , stop } = mod ( modfreq , modgain , wave ) ;
21+ return { node : modulator , stop } ;
22+ } ;
23+
524export function registerSynthSounds ( ) {
625 [ 'sine' , 'square' , 'triangle' , 'sawtooth' ] . forEach ( ( wave ) => {
726 registerSound (
827 wave ,
928 ( t , value , onended ) => {
1029 // destructure adsr here, because the default should be different for synths and samples
11- const { attack = 0.001 , decay = 0.05 , sustain = 0.6 , release = 0.01 } = value ;
30+ const {
31+ attack = 0.001 ,
32+ decay = 0.05 ,
33+ sustain = 0.6 ,
34+ release = 0.01 ,
35+ fmh : fmHarmonicity = 1 ,
36+ fmi : fmModulationIndex ,
37+ } = value ;
1238 let { n, note, freq } = value ;
1339 // with synths, n and note are the same thing
1440 n = note || n || 36 ;
@@ -22,6 +48,13 @@ export function registerSynthSounds() {
2248 // maybe pull out the above frequency resolution?? (there is also getFrequency but it has no default)
2349 // make oscillator
2450 const { node : o , stop } = getOscillator ( { t, s : wave , freq } ) ;
51+
52+ let stopFm ;
53+ if ( fmModulationIndex ) {
54+ const { node : modulator , stop } = fm ( o , fmHarmonicity , fmModulationIndex ) ;
55+ modulator . connect ( o . frequency ) ;
56+ stopFm = stop ;
57+ }
2558 const g = gainNode ( 0.3 ) ;
2659 // envelope
2760 const { node : envelope , stop : releaseEnvelope } = getEnvelope ( attack , decay , sustain , release , 1 , t ) ;
@@ -34,7 +67,9 @@ export function registerSynthSounds() {
3467 node : o . connect ( g ) . connect ( envelope ) ,
3568 stop : ( releaseTime ) => {
3669 releaseEnvelope ( releaseTime ) ;
37- stop ( releaseTime + release ) ;
70+ let end = releaseTime + release ;
71+ stop ( end ) ;
72+ stopFm ?. ( end ) ;
3873 } ,
3974 } ;
4075 } ,
0 commit comments