Skip to content

Commit

Permalink
Add new sound options and make breaking changes to config
Browse files Browse the repository at this point in the history
Breaking changes:
* Option `sound` is renamed to `instrument`
* Option `beepTick` is renamed to `tickNotes`
* Option `beepTock` is renamed to `tockNotes`

New:
* Added new instruments: `AMSynth`, `DuoSynth`, `FMSynth`, `MembraneSynth`, `MetalSynth`, `MonoSynth`, `PluckSynth`
* Updated README with additional examples
  • Loading branch information
curtgrimes committed Dec 24, 2021
1 parent 774acf0 commit 5c44742
Show file tree
Hide file tree
Showing 17 changed files with 270 additions and 65 deletions.
165 changes: 134 additions & 31 deletions README.md

Large diffs are not rendered by default.

Binary file modified images/demo-1.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/demo-2.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/demo-3.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/demo-4.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/demo-5.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/demo-6.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/demo-7.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/demo-8.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/demo-theme-atom-dark.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/demo-theme-minimal-light.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/demo-theme-obsidian-dark.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 13 additions & 12 deletions src/components/Metronome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@ import MetronomeToggle from "./MetronomeToggle.vue";
import { ref, watch, toRefs, onBeforeUnmount } from "vue";
import MetronomeIcon from "../components/MetronomeIcon.vue";
import StyleLine from "../components/StyleLine.vue";
import {
tick as playTick,
tickUpbeat as playTickUpbeat,
tock as playTock,
beep as playBeep,
} from "../sounds";
import { playTick, playTickUpbeat, playTock, playSynth } from "../sounds";
import { useTick } from "../hooks/useTick";
import { useParentMarkdownWrapperVisibilityWatcher } from "../hooks/useParentMarkdownWrapperVisibilityWatcher";
import { useCSSAnimationSynchronizer } from "../hooks/useCSSAnimationSynchronizer";
Expand All @@ -23,9 +18,9 @@ const props = defineProps<{
size: MetronomeCodeBlockParameters["size"];
style: MetronomeCodeBlockParameters["style"];
autoStart: MetronomeCodeBlockParameters["autoStart"];
sound: MetronomeCodeBlockParameters["sound"];
beepTick: MetronomeCodeBlockParameters["beepTick"];
beepTock: MetronomeCodeBlockParameters["beepTock"];
instrument: MetronomeCodeBlockParameters["instrument"];
tickNotes: MetronomeCodeBlockParameters["tickNotes"];
tockNotes: MetronomeCodeBlockParameters["tockNotes"];
}>();
const metronome = ref<HTMLElement>(null);
Expand All @@ -47,17 +42,23 @@ const haltAnimationStyle = useCSSAnimationSynchronizer({
onTick(
() =>
!muted.value &&
(props.sound === "beep" ? playBeep(props.beepTick) : playTick())
(props.instrument === "click"
? playTick()
: playSynth(props.tickNotes, props.instrument))
);
onTickAlternate(
() =>
!muted.value &&
(props.sound === "beep" ? playBeep(props.beepTick) : playTickUpbeat())
(props.instrument === "click"
? playTickUpbeat()
: playSynth(props.tockNotes, props.instrument))
);
onTock(
() =>
!muted.value &&
(props.sound === "beep" ? playBeep(props.beepTock) : playTock())
(props.instrument === "click"
? playTock()
: playSynth(props.tockNotes, props.instrument))
);
const emit = defineEmits(["didCreateInterval"]);
Expand Down
19 changes: 12 additions & 7 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import Metronome from "./components/Metronome.vue";
import { App, createApp } from "vue";
import { Meter } from "./models/Meter";
import { MetronomeSize, isMetronomeSize } from "./models/MetronomeSize";
import { MetronomeSound, isMetronomeSound } from "./models/MetronomeSound";
import {
MetronomeInstrument,
isMetronomeInstrument,
} from "./models/MetronomeInstrument";
import { MetronomeStyle, isMetronomeStyle } from "./models/MetronomeStyle";
import { Frequency } from "tone/build/esm/core/type/Units";
import { MetronomeBPM } from "./models/MetronomeBPM";
Expand All @@ -15,9 +18,9 @@ export interface MetronomeCodeBlockParameters {
size: MetronomeSize;
style: MetronomeStyle;
autoStart: boolean;
sound: MetronomeSound;
beepTick: Frequency[];
beepTock: Frequency[];
instrument: MetronomeInstrument;
tickNotes: Frequency[];
tockNotes: Frequency[];
}

export default class MetronomePlugin extends Plugin {
Expand Down Expand Up @@ -82,11 +85,13 @@ export default class MetronomePlugin extends Plugin {
size: isMetronomeSize(values.size) ? values.size : "small",
style: isMetronomeStyle(values.style) ? values.style : "pulse",
autoStart: values.autostart ? values.autoStart === "yes" : null,
sound: isMetronomeSound(values.sound) ? values.sound : "click",
beepTick: parseMaybeCommaSeparatedToArray(values.beeptick) || [
instrument: isMetronomeInstrument(values.instrument)
? values.instrument
: "click",
tickNotes: parseMaybeCommaSeparatedToArray(values.ticknotes) || [
"C6",
],
beepTock: parseMaybeCommaSeparatedToArray(values.beeptock) || [
tockNotes: parseMaybeCommaSeparatedToArray(values.tocknotes) || [
"C5",
],
};
Expand Down
41 changes: 41 additions & 0 deletions src/models/MetronomeInstrument.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export type MetronomeInstrument =
| "click"
| "beep"
| "AMSynth"
| "DuoSynth"
| "FMSynth"
| "MembraneSynth"
| "MetalSynth"
| "MonoSynth"
| "NoiseSynth"
| "PluckSynth"
| "Synth";

export const defaultMetronomeInstrument = "beep";

export function isMetronomeInstrument(inputInstrument: string): boolean {
return [
"click",
"beep",
"AMSynth",
"DuoSynth",
"FMSynth",
"MembraneSynth",
"MetalSynth",
"MonoSynth",
"PluckSynth",
].includes(inputInstrument);
}

export const normalizeInstrumentNameForToneJS = (
instrument: MetronomeInstrument
) => {
switch (instrument) {
case "click":
return "NoiseSynth";
case "beep":
return "Synth";
default:
return instrument;
}
};
7 changes: 0 additions & 7 deletions src/models/MetronomeSound.ts

This file was deleted.

78 changes: 70 additions & 8 deletions src/sounds.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,56 @@
import * as Tone from "tone/build/esm";
import { PolySynth } from "tone/build/esm";
import { Frequency } from "tone/build/esm/core/type/Units";
import {
Instrument,
InstrumentOptions,
} from "tone/build/esm/instrument/Instrument";
import {
MetronomeInstrument,
normalizeInstrumentNameForToneJS,
} from "./models/MetronomeInstrument";

const beepSynth = new Tone.PolySynth().toDestination();
const synthCache: {
[key: string]: Tone.PolySynth | Instrument<InstrumentOptions>;
} = {};
const getSynth = (instrument: MetronomeInstrument) => {
if (!synthCache[instrument]) {
let synth;
switch (instrument) {
case "AMSynth":
synth = new Tone.PolySynth(Tone.AMSynth);
break;
case "DuoSynth":
synth = new Tone.PolySynth(Tone.DuoSynth);
break;
case "FMSynth":
synth = new Tone.PolySynth(Tone.FMSynth);
break;
case "MembraneSynth":
synth = new Tone.PolySynth(Tone.MembraneSynth);
break;
case "MetalSynth":
synth = new Tone.PolySynth(Tone.MetalSynth);
break;
case "MonoSynth":
synth = new Tone.PolySynth(Tone.MonoSynth);
break;
case "NoiseSynth":
synth = new Tone.NoiseSynth();
break;
case "PluckSynth":
synth = new Tone.PluckSynth();
break;
case "Synth":
default:
synth = new Tone.PolySynth(Tone.Synth);
break;
}
synthCache[instrument] = synth.toDestination();
}

return synthCache[instrument];
};

const whiteNoise = new Tone.NoiseSynth({
noise: { type: "white" },
Expand All @@ -15,15 +64,28 @@ const pinkNoise = new Tone.NoiseSynth({
noise: { type: "pink" },
}).toDestination();

export const tick = () => whiteNoise.triggerAttackRelease("8n");
export const tock = () => brownNoise.triggerAttackRelease("8n");
export const tickUpbeat = () => pinkNoise.triggerAttackRelease("8n");
export const beep = (notes: Frequency[] = ["C4"]) => {
export const playTick = () => whiteNoise.triggerAttackRelease("8n");
export const playTock = () => brownNoise.triggerAttackRelease("8n");
export const playTickUpbeat = () => pinkNoise.triggerAttackRelease("8n");
export const playSynth = (
notes: Frequency[] = ["C4"],
instrument: MetronomeInstrument = "click"
) => {
const synth = getSynth(normalizeInstrumentNameForToneJS(instrument));

try {
beepSynth.triggerAttackRelease(notes, "16n");
if (synth instanceof PolySynth) {
synth.triggerAttackRelease(notes, "16n");
} else if (synth instanceof Instrument) {
// Mono synth
synth.triggerAttackRelease(notes[0], "16n");
}
} catch (e) {
// Probably invalid note value. Play no note instead.
console.error(e);
beepSynth.releaseAll();
if (synth instanceof PolySynth) {
synth.releaseAll();
} else if (synth instanceof Instrument) {
synth.triggerRelease();
}
}
};

0 comments on commit 5c44742

Please sign in to comment.