From 1dd19c08317b1f07b7f2b75861a33f30bdce5ae6 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Wed, 13 Apr 2022 23:25:55 +0200 Subject: [PATCH] add speak output --- packages/core/speak.mjs | 33 +++++++++++++++++++++++++++++++++ repl/src/App.js | 21 ++++++++++++++++----- 2 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 packages/core/speak.mjs diff --git a/packages/core/speak.mjs b/packages/core/speak.mjs new file mode 100644 index 00000000..7acf6d93 --- /dev/null +++ b/packages/core/speak.mjs @@ -0,0 +1,33 @@ +import { Pattern, patternify2 } from './strudel.mjs'; + +const synth = window?.speechSynthesis; +let allVoices = synth?.getVoices(); +// console.log('voices', allVoices); + +function speak(words, lang, voice) { + synth.cancel(); + const utterance = new SpeechSynthesisUtterance(words); + utterance.lang = lang; + allVoices = synth.getVoices(); + const voices = allVoices.filter((v) => v.lang.includes(lang)); + if (typeof voice === 'number') { + utterance.voice = voices[voice % voices.length]; + } else if (typeof voice === 'string') { + utterance.voice = voices.find((voice) => voice.name === voice); + } + // console.log(utterance.voice?.name, utterance.voice?.lang); + speechSynthesis.speak(utterance); +} + +Pattern.prototype._speak = function (lang, voice) { + return this._withEvent((event) => { + const onTrigger = (time, event) => { + speak(event.value, lang, voice); + }; + return event.setContext({ ...event.context, onTrigger }); + }); +}; + +Pattern.prototype.speak = function (lang, voice) { + return patternify2(Pattern.prototype._speak)(reify(lang), reify(voice), this); +}; diff --git a/repl/src/App.js b/repl/src/App.js index 10fdfcd7..1d9d3f61 100644 --- a/repl/src/App.js +++ b/repl/src/App.js @@ -26,17 +26,28 @@ import '@strudel.cycles/tonal/tonal.mjs'; import '@strudel.cycles/xen/xen.mjs'; import '@strudel.cycles/xen/tune.mjs'; import '@strudel.cycles/core/euclid.mjs'; +import '@strudel.cycles/core/speak.mjs'; import '@strudel.cycles/tone/pianoroll.mjs'; import '@strudel.cycles/tone/draw.mjs'; import '@strudel.cycles/osc/osc.mjs'; import controls from '@strudel.cycles/core/controls.mjs'; -extend(Tone, strudel, strudel.Pattern.prototype.bootstrap(), controls, toneHelpers, voicingHelpers, drawHelpers, uiHelpers, { - gist, - euclid, - mini, +extend( Tone, -}); + strudel, + strudel.Pattern.prototype.bootstrap(), + controls, + toneHelpers, + voicingHelpers, + drawHelpers, + uiHelpers, + { + gist, + euclid, + mini, + Tone, + }, +); // eval stuff end const codeParam = window.location.href.split('#')[1];