Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Making Music with the Web Audio API, JSConf Col...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Steve Kinney
November 16, 2023
140
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Making Music with the Web Audio API, JSConf Colombia 2023
Steve Kinney
November 16, 2023
More Decks by Steve Kinney
See All by Steve Kinney
Enterprise UI, v2
stevekinney
0
230
React_Performance__2022.pdf
stevekinney
0
44
React Performance v2
stevekinney
0
69
Introduction to Testing
stevekinney
0
190
Web Security, Frontend Masters
stevekinney
0
4.3k
React and TypeScript, Turing School
stevekinney
0
390
Redux Workshop, 2021-05-05
stevekinney
2
2.2k
TypeScript and React Utility Types
stevekinney
1
230
A Gentle Introduction to GraphQL Resolvers
stevekinney
1
190
Featured
See All Featured
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
840
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
500
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
320
Optimizing for Happiness
mojombo
378
71k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
The untapped power of vector embeddings
frankvandijk
2
1.9k
Music & Morning Musume
bryan
47
7.4k
Agile that works and the tools we love
rasmusluckow
331
22k
Skip the Path - Find Your Career Trail
mkilby
1
230
Amusing Abliteration
ianozsvald
1
300
Transcript
Steve Kinney — JSConf Colombia 2023 Making Music with the
Web Audio API.
Hi, I’m Steve. I work at Temporal.
https:// synthesizzler.vercel.app Also, you can scan this code at any
time.
Someone snuck a synthesizer into your web browser.
None
None
None
None
const context = new AudioContext();
None
const oscillator = context.createOscillator();
None
oscillator.connect(context.destination);
oscillator.connect(context.destination); const context = new AudioContext(); const oscillator = context.createOscillator();
None
None
oscillator.connect(context.destination); const context = new AudioContext(); const oscillator = context.createOscillator();
oscillator.connect(volume); const context = new AudioContext(); const oscillator = context.createOscillator();
const volume = context.createGain(); volume.connect(context.destination);
const oscillator = context.createOscillator(); oscillator.type = 'sine'; oscillator.frequency.value = 440;
oscillator.connect(context.destination); oscillator.start();
oscillator.start(); oscillator.stop(); oscillator.start(); This won’t work.
oscillator.stop(); oscillator.disconnect(); oscillator = null;
None
Let’s take a look at this in action.
None
A3 220 Hz A4 440 Hz A5 880 Hz
A3 220 Hz A4 440 Hz B4 C5 C#5 D5
D#5 E5 F5 F#5 G5 G#5
https://synthesizzler.vercel.app/ notes
const A4 = 440; const A4_NOTE_NUMBER = 69; const TWELFTH_ROOT_OF_TWO
= Math.pow(2, 1 / 12); export function getFrequency() { const noteNumber = noteToNumber(note); return A4 * Math.pow(TWELFTH_ROOT_OF_TWO, noteNumber - A4_NOTE_NUMBER); }
Note Frequency (hz) A 440.00 A̅ 476.67 B 513.33 C
550.00 C̅ 586.67 D 623.33 D̅ 660.00 E 696.67 F 733.33 F̅ 770.00 G 806.67 G̅ 843.33 A 880.00
Note Frequency (hz) Frequency (hz) A 440.00 A̅ 476.67 B
513.33 C 550.00 550.00 C̅ 586.67 595.83 D 623.33 641.67 D̅ 660.00 687.50 E 696.67 733.33 F 733.33 779.17 F̅ 770.00 825.00 G 806.67 870.83 G̅ 843.33 916.67 A 880.00 962.50 A̅ 1008.33 B 1054.17 C 1100.00
None
const oscillator = context.createOscillator(); const gain = context.createGain(); oscillator.connect(gain); gain.connect(context.destination);
oscillator.type = waveType; oscillator.frequency.value = frequency; gain.gain.setValueAtTime(0, startTime); gain.gain.linearRampToValueAtTime(1, startTime + duration / 100); gain.gain.exponentialRampToValueAtTime(0.0001, startTime + duration); oscillator.start(startTime); oscillator.stop(startTime + duration + 0.05);
const startTime = context.currentTime; const duration = 1; gain.gain.setValueAtTime(0, startTime);
gain.gain.linearRampToValueAtTime(1, startTime + duration / 100); gain.gain.exponentialRampToValueAtTime(0.0001, startTime + duration); oscillator.start(startTime); oscillator.stop(startTime + duration + 0.05);
None
None
const startOscillator = ( context, note, ): OscillatorAndGain = {
const oscillator = context.createOscillator(); const gain = context.createGain(); oscillator.frequency.value = getFrequency(note); gain.gain.value = 0.01; oscillator.connect(gain); gain.connect(context.destination); gain.gain.linearRampToValueAtTime(1, context.currentTime + 0.1); oscillator.start(); return { oscillator, gain }; };
Emits a keyDown event
https://synthesizzler.vercel.app/ keys
⏰ Keeping time.
None
get secondsPerBeat() { return 60 / this.beatsPerMinute; }
public start() { if (this.on) return; this.on = true; this.currentBeat
= 0; this.tick(); } public stop() { this.on = false; this.nextScheduledBeat = null; if (this.interval) clearTimeout(this.interval); }
public tick = () = { if (!this.on) return; if
(!this.nextScheduledBeat) { this.nextScheduledBeat = this.context.currentTime; } this.incrementBeat(); this.onTick(this.currentBeat, this.nextScheduledBeat); this.interval = setTimeout(this.tick, this.secondsPerBeat * 1000); this.nextScheduledBeat += this.secondsPerBeat; };
https://synthesizzler.vercel.app/ metronome
https://synthesizzler.vercel.app/ step-sequencer
Someone snuck a synthesizer into your web browser.
Someone snuck a web browser into your synthesizer.
+
https://synthesizzler.vercel.app/ theremin
None
None
Music is pretty awesome.
The web is pretty awesome.
Music and the web are even more awesome when their
together.
Thank you! @stevekinney https://temporal.io