Skip to content

Commit dcac1af

Browse files
committed
revealjs: slide-tone plugin
1 parent 8d01e83 commit dcac1af

File tree

4 files changed

+99
-1
lines changed

4 files changed

+99
-1
lines changed

src/format/reveal/format-reveal-plugin.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import { kIncludeInHeader } from "../../config/constants.ts";
1111

1212
import {
1313
Format,
14+
FormatDependency,
1415
FormatExtras,
16+
kDependencies,
1517
kTemplatePatches,
1618
Metadata,
1719
} from "../../config/types.ts";
@@ -24,6 +26,8 @@ import { revealMultiplexPlugin } from "./format-reveal-multiplex.ts";
2426

2527
const kRevealjsPlugins = "revealjs-plugins";
2628

29+
const kRevealSlideTone = "slide-tone";
30+
2731
interface RevealPluginBundle {
2832
plugin: string;
2933
config?: Metadata;
@@ -52,14 +56,24 @@ export function revealPluginExtras(format: Format, revealDir: string) {
5256
const scripts: RevealPluginScript[] = [];
5357
const stylesheets: string[] = [];
5458
const config: Metadata = {};
59+
const dependencies: FormatDependency[] = [];
5560

56-
// built-in plugins + user plugins
61+
// built-in plugins
5762
const pluginBundles: Array<RevealPluginBundle | string> = [
5863
{
5964
plugin: formatResourcePath("revealjs", join("plugins", "line-highlight")),
6065
},
6166
{ plugin: formatResourcePath("revealjs", join("plugins", "a11y")) },
6267
];
68+
69+
// tone plugin (optional)
70+
const tonePlugin = revealTonePlugin(format);
71+
if (tonePlugin) {
72+
dependencies.push(toneDependency());
73+
pluginBundles.push(tonePlugin);
74+
}
75+
76+
// multiplex plugin (optional)
6377
const multiplexPlugin = revealMultiplexPlugin(format);
6478
if (multiplexPlugin) {
6579
pluginBundles.push(multiplexPlugin);
@@ -127,6 +141,7 @@ export function revealPluginExtras(format: Format, revealDir: string) {
127141
const extras: FormatExtras = {
128142
[kIncludeInHeader]: [],
129143
html: {
144+
[kDependencies]: dependencies,
130145
[kTemplatePatches]: [],
131146
},
132147
};
@@ -190,6 +205,25 @@ export function injectRevealConfig(
190205
return template;
191206
}
192207

208+
function revealTonePlugin(format: Format) {
209+
if (format.metadata[kRevealSlideTone]) {
210+
return { plugin: formatResourcePath("revealjs", join("plugins", "tone")) };
211+
} else {
212+
return undefined;
213+
}
214+
}
215+
216+
function toneDependency() {
217+
const dependency: FormatDependency = {
218+
name: "tone",
219+
scripts: [{
220+
name: "tone.js",
221+
path: formatResourcePath("revealjs", join("tone", "tone.js")),
222+
}],
223+
};
224+
return dependency;
225+
}
226+
193227
function pluginFromBundle(bundle: RevealPluginBundle): RevealPlugin {
194228
// confirm it's a directory
195229
if (!existsSync(bundle.plugin) || !Deno.statSync(bundle.plugin).isDirectory) {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
window.QuartoTone = function () {
2+
return {
3+
id: "quarto-tone",
4+
init: function (deck) {
5+
function slideToneScale(i) {
6+
// https://www.intmath.com/trigonometric-graphs/music.php
7+
const note = 15 - (deck.getTotalSlides() - i);
8+
return 440 * 2 ** (note / 12);
9+
}
10+
11+
/*
12+
* Sliding tones between C3 and C5 with equal steps between tones
13+
* but not aligned to musical scale
14+
*/
15+
function slideToneBounded(i, lower = 261.63, upper = 1046.5) {
16+
const step = (upper - lower) / deck.getTotalSlides();
17+
return lower + step * i;
18+
}
19+
20+
/*
21+
* Choose slide tone scale automatically based on number of slides.
22+
* If there are <= 32 slides, use musical scale.
23+
*/
24+
function slideToneAuto(toneIdx) {
25+
return deck.getTotalSlides() > 32
26+
? slideToneBounded(toneIdx)
27+
: slideToneScale(toneIdx);
28+
}
29+
30+
const synth = new Tone.Synth({
31+
oscillator: {
32+
type: "sine",
33+
},
34+
envelope: {
35+
attack: 0.001,
36+
decay: 0.2,
37+
sustain: 0.2,
38+
release: 1,
39+
},
40+
}).toMaster();
41+
42+
const playTone = () => {
43+
synth.triggerAttackRelease(
44+
slideToneAuto(deck.getSlidePastCount()),
45+
"8n"
46+
);
47+
};
48+
deck.on("slidechanged", playTone);
49+
deck.on("fragmentshown", playTone);
50+
deck.on("fragmenthidden", playTone);
51+
},
52+
};
53+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# adapted from https://github.com/gadenbuie/xaringanExtra/blob/master/docs/slide-tone/libs/slide-tone/slide-tone.js
2+
name: QuartoTone
3+
script: plugin.js

src/resources/formats/revealjs/tone/tone.js

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)