Skip to content

Commit bf74998

Browse files
authored
Merge pull request #47 from cmpadden/playground-add-metronome
[playground] add link to simple-tempo
2 parents 0e8cdb3 + cb0b00d commit bf74998

File tree

3 files changed

+10
-102
lines changed

3 files changed

+10
-102
lines changed

components/section/Playground.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ export default {
6060
return {
6161
title: "Experiments",
6262
links: [
63+
{
64+
title: "Metronome",
65+
description:
66+
"A simple metronome for tracking tempo.",
67+
link: "/playground/metronome",
68+
img: "/images/previews/metronome.png",
69+
},
6370
{
6471
title: "Sequence Plotter",
6572
description:

pages/playground/metronome.vue

Lines changed: 3 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,9 @@
11
<script setup>
2-
definePageMeta({ layout: "empty" });
3-
4-
const params = reactive({
5-
frequency: 440,
6-
frequency_min: 20,
7-
frequency_max: 1000,
8-
frequency_steps: 20,
9-
bpm: 90,
10-
});
11-
12-
let audio_context;
13-
let oscillator;
14-
let gain_node;
15-
let metronome_interval_id;
16-
17-
const bpm_to_ms = (bpm) => {
18-
if (bpm <= 0) {
19-
return 0;
20-
}
21-
return (60 / bpm) * 1000;
22-
};
23-
24-
const start = () => {
25-
clearInterval(metronome_interval_id);
26-
metronome_interval_id = setInterval(() => {
27-
oscillator.frequency.value = params.frequency;
28-
29-
// fade-in and fade-out to prevent undesired click
30-
gain_node.gain.setValueAtTime(0, audio_context.currentTime);
31-
gain_node.gain.linearRampToValueAtTime(1, audio_context.currentTime + 0.05);
32-
gain_node.gain.linearRampToValueAtTime(0, audio_context.currentTime + 0.1);
33-
}, bpm_to_ms(params.bpm));
34-
};
35-
36-
const adjust_bpm = (value) => {
37-
params.bpm += value;
38-
start(); // re-start interval w/ new bpm value
39-
};
40-
41-
onMounted(() => {
42-
audio_context = new (window.AudioContext || window.webkitAudioContext)();
43-
oscillator = audio_context.createOscillator();
44-
gain_node = audio_context.createGain();
45-
gain_node.gain.value = 0;
46-
gain_node.connect(audio_context.destination);
47-
oscillator.connect(gain_node);
48-
oscillator.type = "sine";
49-
oscillator.frequency.value = params.frequency;
50-
oscillator.start();
51-
52-
start();
53-
});
2+
definePageMeta({ layout: "light" });
543
</script>
554

565
<template>
57-
<main class="flex h-screen justify-center bg-white">
58-
<div class="space-y-2 p-2">
59-
<div class="flex justify-center border-2 border-gray-400 p-2">
60-
<div class="flex space-x-2">
61-
<div class="flex items-center">
62-
<button
63-
class="button rounded-full bg-gradient-to-r from-red-500 to-blue-500 px-2 text-white"
64-
@click="adjust_bpm(-10)"
65-
>
66-
-
67-
</button>
68-
</div>
69-
<div class="text-[72px] font-bold">
70-
{{ params.bpm.toString().padStart(3, "&ensp;")
71-
}}<span class="text-[16px]">bpm</span>
72-
</div>
73-
74-
<div class="flex items-center">
75-
<button
76-
class="button rounded-full bg-gradient-to-r from-red-500 to-blue-500 px-2 text-white"
77-
@click="adjust_bpm(10)"
78-
>
79-
+
80-
</button>
81-
</div>
82-
</div>
83-
</div>
84-
85-
<!-- Frequency -->
86-
<div class="border-2 border-gray-400 p-2">
87-
<div class="flex">
88-
<div class="flex-1 font-bold">
89-
Frequency
90-
<span class="bg-yellow-200 px-2"> {{ params.frequency }} </span>
91-
</div>
92-
</div>
93-
<div class="flex space-x-2">
94-
<div>{{ params.frequency_min }}Hz</div>
95-
<input
96-
type="range"
97-
v-model="params.frequency"
98-
:min="params.frequency_min"
99-
:max="params.frequency_max"
100-
:step="params.frequency_steps"
101-
class="accent-red-500"
102-
/>
103-
<div>{{ params.frequency_max }}Hz</div>
104-
</div>
105-
</div>
106-
</div>
6+
<main class="flex h-[768px] justify-center border-2 border-gray-500">
7+
<iframe src="https://simple-tempo.com" width="100%" height="100%"></iframe>
1078
</main>
1089
</template>

public/images/previews/metronome.png

117 KB
Loading

0 commit comments

Comments
 (0)