From d77725cf1d33a401f6cfc4cb3006b22c7c5fc02c Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Thu, 6 Apr 2023 12:34:34 +0200 Subject: [PATCH] add events to audio slide --- iclc2023/slides/src/EventEditor.jsx | 46 +++++++++++++++++++ iclc2023/slides/src/EventsDemo.jsx | 45 ++++++++++++++++++ iclc2023/slides/src/MiniComparison.jsx | 2 +- iclc2023/slides/src/Slides.jsx | 2 +- iclc2023/slides/src/slides/events-audio.mdx | 7 +++ .../slides/src/slides/patterns-events.mdx | 2 +- 6 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 iclc2023/slides/src/EventEditor.jsx create mode 100644 iclc2023/slides/src/EventsDemo.jsx create mode 100644 iclc2023/slides/src/slides/events-audio.mdx diff --git a/iclc2023/slides/src/EventEditor.jsx b/iclc2023/slides/src/EventEditor.jsx new file mode 100644 index 000000000..45ad97114 --- /dev/null +++ b/iclc2023/slides/src/EventEditor.jsx @@ -0,0 +1,46 @@ +import { useState, useCallback } from 'react'; +import { atomone } from '@uiw/codemirror-themes-all'; +import { CodeMirror, flash, useKeydown } from '@strudel.cycles/react'; +import { initAudioOnFirstClick, webaudioOutput } from '@strudel.cycles/webaudio'; +import { TimeSpan } from '@strudel.cycles/core'; + +const initAudio = initAudioOnFirstClick(); + +function EventEditor({ code: initialCode }) { + const [code, setCode] = useState(initialCode); + const [view, setView] = useState(); + useKeydown( + useCallback( + async (e) => { + if (view?.hasFocus) { + if (e.ctrlKey || e.altKey) { + if (e.code === 'Enter') { + /* if (getAudioContext().state !== 'running') { + alert('please click play to initialize the audio. you can use shortcuts after that!'); + return; + } */ + e.preventDefault(); + flash(view); + let json = JSON.parse(code); + if (!Array.isArray(json)) { + json = [json]; + } + await initAudio; + json.forEach((value) => { + const hap = new Hap(new TimeSpan(0, 1), new TimeSpan(0, 1), value); + webaudioOutput(hap, 0.1, 1, 1); + }); + } else if (e.key === '.') { + stop(); + e.preventDefault(); + } + } + } + }, + [code, view], + ), + ); + return setView(v)} fontSize={32} />; +} + +export default EventEditor; diff --git a/iclc2023/slides/src/EventsDemo.jsx b/iclc2023/slides/src/EventsDemo.jsx new file mode 100644 index 000000000..1bdb4e322 --- /dev/null +++ b/iclc2023/slides/src/EventsDemo.jsx @@ -0,0 +1,45 @@ +import EventEditor from './EventEditor.jsx'; +import { useState } from 'react'; + +const snippets = [ + [`{ "s": "cp" }`, 'Samples'], + [`{ "s": "sawtooth", "note": "e3" }`, 'Oscillators'], + [ + `[ + { "s": "gm_epiano2", "note": "c4" }, + { "s": "gm_epiano2", "note": "eb4" }, + { "s": "gm_epiano2", "note": "g4" } +]`, + 'Soundfonts', + ], + [ + `{ + "s": "toys", + "cutoff": 2000, + "delay": 0.5, + "crush": 4 +}`, + 'Effects', + ], +]; + +function EventsDemo() { + const [step, setStep] = useState(1); + + return ( +
+ {snippets.slice(0, step).map(([code, label], i) => { + const isActive = i === step - 1; + return ( +
+

{label}

+ +
+ ); + })} + {step < snippets.length && } +
+ ); +} + +export default EventsDemo; diff --git a/iclc2023/slides/src/MiniComparison.jsx b/iclc2023/slides/src/MiniComparison.jsx index 7cfaee79e..c2c41994b 100644 --- a/iclc2023/slides/src/MiniComparison.jsx +++ b/iclc2023/slides/src/MiniComparison.jsx @@ -14,7 +14,7 @@ function MiniComparison() { const [step, setStep] = useState(1); return ( <> -

Mini Notation vs Regular JS

+

From Mini Notation to JavaScript

{snippets.slice(0, step).map(([a, b, label], i) => { const isActive = i === step - 1; diff --git a/iclc2023/slides/src/Slides.jsx b/iclc2023/slides/src/Slides.jsx index 1ad4a8bee..e6794eb96 100644 --- a/iclc2023/slides/src/Slides.jsx +++ b/iclc2023/slides/src/Slides.jsx @@ -16,7 +16,7 @@ const loadedMDXFiles = await Promise.all( }), ); -const order = ['01', '02-0', '02-1', '02-2', 'mini-comparison', 'patterns-events', '04']; +const order = ['01', '02-0', '02-1', '02-2', 'mini-comparison', 'patterns-events', 'events-audio', '04']; const slideEntries = order.map((name) => loadedMDXFiles.find(([file]) => file === name)); diff --git a/iclc2023/slides/src/slides/events-audio.mdx b/iclc2023/slides/src/slides/events-audio.mdx new file mode 100644 index 000000000..415051100 --- /dev/null +++ b/iclc2023/slides/src/slides/events-audio.mdx @@ -0,0 +1,7 @@ +import { SlideRepl } from '../SlideRepl.jsx'; +import Highlight from '../Highlight.jsx'; +import EventsDemo from '../EventsDemo.jsx'; + +# From Values to Sound + + diff --git a/iclc2023/slides/src/slides/patterns-events.mdx b/iclc2023/slides/src/slides/patterns-events.mdx index 834cc1132..d0b96a86b 100644 --- a/iclc2023/slides/src/slides/patterns-events.mdx +++ b/iclc2023/slides/src/slides/patterns-events.mdx @@ -5,7 +5,7 @@ import Highlight from '../Highlight.jsx'; -query = get events within time arc: +query = get events within time arc. event = time + value