From 83d0644fd9ce4d0eb8e76db22838e1ff1b5e555c Mon Sep 17 00:00:00 2001 From: charlieroberts Date: Fri, 25 Feb 2022 21:08:56 -0800 Subject: [PATCH] higher latencyHint --- repl/src/App.tsx | 3 +- repl/src/tone.ts | 7 ++-- repl/src/tunes.ts | 82 ++++++++++++++++++++++---------------------- repl/src/useCycle.ts | 14 ++++---- 4 files changed, 54 insertions(+), 52 deletions(-) diff --git a/repl/src/App.tsx b/repl/src/App.tsx index fd8d029d..05cd9a5d 100644 --- a/repl/src/App.tsx +++ b/repl/src/App.tsx @@ -18,7 +18,8 @@ try { console.warn('failed to decode', err); } -const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.Destination); +Tone.setContext( new Tone.Context({ latencyHint : .5, lookAhead:1 })) +const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.getDestination()); defaultSynth.set({ oscillator: { type: 'triangle' }, envelope: { diff --git a/repl/src/tone.ts b/repl/src/tone.ts index 7636f173..763db837 100644 --- a/repl/src/tone.ts +++ b/repl/src/tone.ts @@ -16,6 +16,7 @@ import { NoiseSynth, PluckSynth, Sampler, + getDestination } from 'tone'; // what about @@ -62,7 +63,7 @@ export const lowpass = (v) => new Filter(v, 'lowpass'); export const highpass = (v) => new Filter(v, 'highpass'); export const adsr = (a, d = 0.1, s = 0.4, r = 0.01) => ({ envelope: { attack: a, decay: d, sustain: s, release: r } }); export const osc = (type) => ({ oscillator: { type } }); -export const out = Destination; +export const out = () => getDestination(); /* @@ -78,7 +79,7 @@ const chainable = function (instr) { instr.chain = (...args) => { chained = chained.concat(args); instr.disconnect(); // disconnect from destination / previous chain - return _chain(...chained, Destination); + return _chain(...chained, getDestination()); }; // shortcuts: chaining multiple won't work forn now.. like filter(1000).gain(0.5). use chain + native Tone calls instead instr.filter = (freq = 1000, type: BiquadFilterType = 'lowpass') => @@ -178,7 +179,7 @@ Pattern.prototype.chain = function (...effectGetters: any) { const chain = (value.chain || []).concat(effectGetters); const getChain = () => { const effects = chain.map((getEffect: any) => getEffect()); - return value.getInstrument().chain(...effects, Destination); + return value.getInstrument().chain(...effects, getDestination()); }; const onTrigger = getTrigger(getChain, value.value); return { ...value, getChain, onTrigger, chain }; diff --git a/repl/src/tunes.ts b/repl/src/tunes.ts index ff394ed4..2b0e51a3 100644 --- a/repl/src/tunes.ts +++ b/repl/src/tunes.ts @@ -273,22 +273,22 @@ export const zeldasRescue = `stack( new Gain(0.3), new Chorus(2, 2.5, 0.5).start(), new Freeverb(), - Destination) + getDestination()) )`; export const technoDrums = `stack( "c1*2".tone(new Tone.MembraneSynth().toDestination()), "~ x".tone(new Tone.NoiseSynth().toDestination()), - "[~ c4]*2".tone(new Tone.MetalSynth().set({envelope:{decay:0.06,sustain:0}}).chain(new Gain(0.5),Destination)) + "[~ c4]*2".tone(new Tone.MetalSynth().set({envelope:{decay:0.06,sustain:0}}).chain(new Gain(0.5),getDestination())) )`; export const loungerave = `() => { - const delay = new FeedbackDelay(1/8, .2).chain(vol(0.5), out); - const kick = new MembraneSynth().chain(vol(.8), out); - const snare = new NoiseSynth().chain(vol(.8), out); - const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out); - const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out); - const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out); + const delay = new FeedbackDelay(1/8, .2).chain(vol(0.5), out()); + const kick = new MembraneSynth().chain(vol(.8), out()); + const snare = new NoiseSynth().chain(vol(.8), out()); + const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out()); + const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out()); + const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out()); const drums = stack( "c1*2".tone(kick).mask("/8"), @@ -311,12 +311,12 @@ export const loungerave = `() => { export const caverave = `() => { - const delay = new FeedbackDelay(1/8, .4).chain(vol(0.5), out); - const kick = new MembraneSynth().chain(vol(.8), out); - const snare = new NoiseSynth().chain(vol(.8), out); - const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out); - const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out); - const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out); + const delay = new FeedbackDelay(1/8, .4).chain(vol(0.5), out()); + const kick = new MembraneSynth().chain(vol(.8), out()); + const snare = new NoiseSynth().chain(vol(.8), out()); + const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out()); + const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out()); + const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out()); const drums = stack( "c1*2".tone(kick).mask("/8"), @@ -345,16 +345,16 @@ export const caverave = `() => { export const callcenterhero = `()=>{ const bpm = 90; - const lead = polysynth().set({...osc('sine4'),...adsr(.004)}).chain(vol(0.15),out) - const bass = fmsynth({...osc('sawtooth6'),...adsr(0.05,.6,0.8,0.1)}).chain(vol(0.6), out); + const lead = polysynth().set({...osc('sine4'),...adsr(.004)}).chain(vol(0.15),out()) + const bass = fmsynth({...osc('sawtooth6'),...adsr(0.05,.6,0.8,0.1)}).chain(vol(0.6), out()); const s = scale(slowcat('F3 minor', 'Ab3 major', 'Bb3 dorian', 'C4 phrygian dominant').slow(4)); return stack( "0 2".struct(" [x ~]").apply(s).scaleTranspose(stack(0,2)).tone(lead), "<6 7 9 7>".struct("[~ [x ~]*2]*2").apply(s).scaleTranspose("[0,2] [2,4]".fast(2).every(4,rev)).tone(lead), "-14".struct("[~ x@0.8]*2".early(0.01)).apply(s).tone(bass), - "c2*2".tone(membrane().chain(vol(0.6), out)), - "~ c2".tone(noise().chain(vol(0.2), out)), - "c4*4".tone(metal(adsr(0,.05,0)).chain(vol(0.03), out)) + "c2*2".tone(membrane().chain(vol(0.6), out())), + "~ c2".tone(noise().chain(vol(0.2), out())), + "c4*4".tone(metal(adsr(0,.05,0)).chain(vol(0.03), out())) ) .slow(120 / bpm) } @@ -364,22 +364,22 @@ export const primalEnemy = `()=>{ const f = fast("<1 <2 [4 8]>>"); return stack( "c3,g3,c4".struct("[x ~]*2").apply(f).transpose("<0 <3 [5 [7 [9 [11 13]]]]>>"), - "c2 [c2 ~]*2".tone(synth(osc('sawtooth8')).chain(vol(0.8),out)), - "c1*2".tone(membrane().chain(vol(0.8),out)) + "c2 [c2 ~]*2".tone(synth(osc('sawtooth8')).chain(vol(0.8),out())), + "c1*2".tone(membrane().chain(vol(0.8),out())) ).slow(1) }`; export const drums = `stack( - "c1*2".tone(membrane().chain(vol(0.8),out)), - "~ c3".tone(noise().chain(vol(0.8),out)), - "c3*4".transpose("[-24 0]*2").tone(metal(adsr(0,.015)).chain(vol(0.8),out)) + "c1*2".tone(membrane().chain(vol(0.8),out())), + "~ c3".tone(noise().chain(vol(0.8),out())), + "c3*4".transpose("[-24 0]*2").tone(metal(adsr(0,.015)).chain(vol(0.8),out())) ) `; export const xylophoneCalling = `()=>{ const t = x=> x.scaleTranspose("<0 2 4 3>/4").transpose(-2) const s = x => x.scale(slowcat('C3 minor pentatonic','G3 minor pentatonic').slow(4)) - const delay = new FeedbackDelay(1/8, .6).chain(vol(0.1), out); + const delay = new FeedbackDelay(1/8, .6).chain(vol(0.1), out()); const chorus = new Chorus(1,2.5,0.5).start(); return stack( // melody @@ -389,28 +389,28 @@ export const xylophoneCalling = `()=>{ .apply(t).tone(polysynth().set({ ...osc('triangle4'), ...adsr(0,.08,0) - }).chain(vol(0.2).connect(delay),chorus,out)).mask("<~@3 x>/16".early(1/8)), + }).chain(vol(0.2).connect(delay),chorus,out())).mask("<~@3 x>/16".early(1/8)), // pad "[1,3]/4".scale('G3 minor pentatonic').apply(t).tone(polysynth().set({ ...osc('square2'), ...adsr(0.1,.4,0.8) - }).chain(vol(0.2),chorus,out)).mask("<~ x>/32"), + }).chain(vol(0.2),chorus,out())).mask("<~ x>/32"), // xylophone "c3,g3,c4".struct("").fast("<1 <2!3 [4 8]>>").apply(s).scaleTranspose("<0 <1 [2 [3 <4 5>]]>>").apply(t).tone(polysynth().set({ ...osc('sawtooth4'), ...adsr(0,.1,0) - }).chain(vol(0.4).connect(delay),out)).mask("/16".early(1/8)), + }).chain(vol(0.4).connect(delay),out())).mask("/16".early(1/8)), // bass "c2 [c2 ~]*2".scale('C hirajoshi').apply(t).tone(synth({ ...osc('sawtooth6'), ...adsr(0,.03,.4,.1) - }).chain(vol(0.4),out)), + }).chain(vol(0.4),out())), // kick - "*2".tone(membrane().chain(vol(0.8),out)), + "*2".tone(membrane().chain(vol(0.8),out())), // snare - "~ ".tone(noise().chain(vol(0.8),out)), + "~ ".tone(noise().chain(vol(0.8),out())), // hihat - "c3*4".transpose("[-24 0]*2").tone(metal(adsr(0,.02)).chain(vol(0.5).connect(delay),out)) + "c3*4".transpose("[-24 0]*2").tone(metal(adsr(0,.02)).chain(vol(0.5).connect(delay),out())) ).slow(1) }`; @@ -424,18 +424,18 @@ export const sowhatelse = `()=> { kick: .9, hihat: .35, }[key]||0); - const delay = new FeedbackDelay(1/6, .3).chain(vol(.7), out); - const delay2 = new FeedbackDelay(1/6, .2).chain(vol(.15), out); + const delay = new FeedbackDelay(1/6, .3).chain(vol(.7), out()); + const delay2 = new FeedbackDelay(1/6, .2).chain(vol(.15), out()); const chorus = new Chorus(1,2.5,0.5).start(); // instruments const instr = (instrument) => ({ - organ: polysynth().set({...osc('sawtooth4'), ...adsr(.01,.2,0)}).chain(mix('chords').connect(delay),out), - lead: polysynth().set({...osc('triangle4'),...adsr(0.01,.05,0)}).chain(mix('lead').connect(delay2), out), - bass: polysynth().set({...osc('sawtooth8'),...adsr(.02,.05,.3,.2)}).chain(mix('bass'),lowpass(3000), out), - pad: polysynth().set({...osc('square2'),...adsr(0.1,.4,0.8)}).chain(vol(0.15),chorus,out), - hihat: metal(adsr(0, .02, 0)).chain(mix('hihat'), out), - snare: noise(adsr(0, .15, 0.01)).chain(mix('snare'), lowpass(5000), out), - kick: membrane().chain(mix('kick'), out) + organ: polysynth().set({...osc('sawtooth4'), ...adsr(.01,.2,0)}).chain(mix('chords').connect(delay),out()), + lead: polysynth().set({...osc('triangle4'),...adsr(0.01,.05,0)}).chain(mix('lead').connect(delay2), out()), + bass: polysynth().set({...osc('sawtooth8'),...adsr(.02,.05,.3,.2)}).chain(mix('bass'),lowpass(3000), out()), + pad: polysynth().set({...osc('square2'),...adsr(0.1,.4,0.8)}).chain(vol(0.15),chorus,out()), + hihat: metal(adsr(0, .02, 0)).chain(mix('hihat'), out()), + snare: noise(adsr(0, .15, 0.01)).chain(mix('snare'), lowpass(5000), out()), + kick: membrane().chain(mix('kick'), out()) }[instrument]); // harmony const t = transpose("<0 0 1 0>/8"); diff --git a/repl/src/useCycle.ts b/repl/src/useCycle.ts index bce7a8da..45391abe 100644 --- a/repl/src/useCycle.ts +++ b/repl/src/useCycle.ts @@ -16,7 +16,7 @@ function useCycle(props: UseCycleProps) { const { onEvent, onQuery, onSchedule, ready = true } = props; const [started, setStarted] = useState(false); const cycleDuration = 1; - const activeCycle = () => Math.floor(Tone.Transport.seconds / cycleDuration); + const activeCycle = () => Math.floor(Tone.getTransport().seconds / cycleDuration); // pull events with onQuery + count up to next cycle const query = (cycle = activeCycle()) => { @@ -27,13 +27,13 @@ function useCycle(props: UseCycleProps) { // console.log('schedule', cycle); // query next cycle in the middle of the current const cancelFrom = timespan.begin.valueOf(); - Tone.Transport.cancel(cancelFrom); + Tone.getTransport().cancel(cancelFrom); // const queryNextTime = (cycle + 1) * cycleDuration - 0.1; const queryNextTime = (cycle + 1) * cycleDuration - 0.5; // if queryNextTime would be before current time, execute directly (+0.1 for safety that it won't miss) - const t = Math.max(Tone.Transport.seconds, queryNextTime) + 0.1; - Tone.Transport.schedule(() => { + const t = Math.max(Tone.getTransport().seconds, queryNextTime) + 0.1; + Tone.getTransport().schedule(() => { query(cycle + 1); }, t); @@ -41,7 +41,7 @@ function useCycle(props: UseCycleProps) { events ?.filter((event) => event.part.begin.valueOf() === event.whole.begin.valueOf()) .forEach((event) => { - Tone.Transport.schedule((time) => { + Tone.getTransport().schedule((time) => { const toneEvent = { time: event.part.begin.valueOf(), duration: event.whole.end.sub(event.whole.begin).valueOf(), @@ -59,12 +59,12 @@ function useCycle(props: UseCycleProps) { const start = async () => { setStarted(true); await Tone.start(); - Tone.Transport.start('+0.1'); + Tone.getTransport().start('+0.1'); }; const stop = () => { console.log('stop'); setStarted(false); - Tone.Transport.pause(); + Tone.getTransport().pause(); }; const toggle = () => (started ? stop() : start()); return { start, stop, setStarted, onEvent, started, toggle, query, activeCycle };