diff --git a/index.html b/index.html index 7ebfe41..98451ac 100644 --- a/index.html +++ b/index.html @@ -7,193 +7,7 @@ - - - + @@ -215,7 +29,7 @@

5mdt
Noise Generator

Made with pure HTML+CSS+JS

Authors (alphabetically):

- @akamenskiy (JS)

-

- @asyavee (JS)

+

- @asyavee (JS, CSS)

- @kawaiier (CSS)

- @nett00n (Maintainer)

- Belka (Logo)

@@ -225,5 +39,5 @@

5mdt
Noise Generator

- + diff --git a/scripts.js b/scripts.js new file mode 100644 index 0000000..c2ae664 --- /dev/null +++ b/scripts.js @@ -0,0 +1,89 @@ +const types = { + pink: "pink", + brown: "brown", + white: "white", +} +const timerInput = document.getElementById("timer"); +const useTimer = (callback, ms) => { + let intervalId; + + function intervalWrapper(...args) { + intervalId = setInterval(() => callback(...args), ms); + } + + function clearIntervalWrapper() { + clearInterval(intervalId); + } + + return [intervalWrapper, clearIntervalWrapper]; +} + +function updateTimerInput(value) { + const hours = Math.floor(value / 3600); + const minutes = Math.floor((value % 3600) / 60); + const seconds = value % 60; + timerInput.value = `${ padZero(hours) }:${ padZero(minutes) }:${ padZero( + seconds) }`; +} + +async function handleStartNoise(type) { + const durationInSeconds = getUserDuration(); + if (audioContext) { + await handleStopNoise(); + } + + if (durationInSeconds) { + await generateNoise(type); + startNoiseTimer(); + } else { + await generateNoise(type); + } +} + +async function handleStopNoise() { + await audioContext.close(); + audioContext = null; + stopNoiseTimer(); +} + +const noiseTimer = () => { + let duration = getUserDuration(); + duration--; + if (duration <= 0) { + handleStopNoise(); + } + updateTimerInput(duration); +} + +const [startNoiseTimer, stopNoiseTimer] = useTimer(noiseTimer, 1000) + +const getUserDuration = () => { + const duration = getDurationInSeconds(timerInput.value); + return duration +} + +let audioContext; +const generateNoise = async (type) => { + audioContext = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: 96000 }); + await audioContext.audioWorklet.addModule("RandomNoiseProcessor.js"); + const randomNoiseNode = new AudioWorkletNode( + audioContext, + "RandomNoiseProcessor", + { + processorOptions: { + type, + } + } + ); + randomNoiseNode.connect(audioContext.destination); +} + +function getDurationInSeconds(timeValue) { + const [hours, minutes, seconds] = timeValue.split(":").map(Number); + const duration = (hours * 60 * 60) + (minutes * 60) + (seconds || 0) + return duration +} + +function padZero(number) { + return number < 10 ? `0${number}` : number; +} diff --git a/style.css b/style.css new file mode 100644 index 0000000..dafab83 --- /dev/null +++ b/style.css @@ -0,0 +1,103 @@ +body { + font-family: sans-serif; + text-align: center; + transition: background-color 0.3s, color 0.3s; + /* Add transition for smooth theme change */ +} + +.container { + max-width: 620px; + margin: 0 auto; +} + +/* Light mode */ +@media (prefers-color-scheme: light) { + body { + background-color: white; + color: black; + } +} + +/* Dark mode */ +@media (prefers-color-scheme: dark) { + body { + background-color: black; + color: white; + } +} + +h1 { + margin-top: 20px; + font-size: 2.2em; + font-weight: 800; +} + +main { + display: flex; + flex-direction: column; + align-items: center; + padding: 16px 20%; +} + +button { + margin: 10px; + padding: 10px 20px; + font-size: 1.5em; + width: 100%; + border: none; + background-color: #3498db; + color: black; + cursor: pointer; + border-radius: 4px; + border-bottom: 1px solid rgba(15, 17, 17, 0.25); + font-family: sans-serif; +} + +a { + color: #3498db; + text-decoration: none; +} + +button:hover { + background-color: #2980b9; +} + +#brown { + background-color: #c1b3a8; +} + +#pink { + background-color: #FFD1DC; +} + +#white { + background-color: #F3F8FF; +} + +#stop { + background-color: #FFA8A8; + margin-top: 48px; +} + +footer { + color: grey; +} + +#timer { + margin-bottom: 15px; + font-size: 1.2em; + padding: 12px; + width: 100%; + box-sizing: border-box; +} + +#timer.active { + background-color: #FFA8A8; + color: white; +} + +@media only screen and (max-width: 600px) { + button { + /* font-size: 14px; */ + } +} \ No newline at end of file