Metronome JavaScript - function .pause() don't stop the Audio beep - javascript

I trying to do a metronome on Codepen.
But I have one problem because the function .pause() doesn't stop the beep(my sound).
This is the code that I wrote. I read about it but I don't find the problem.
The audio I found on Codepen. I don't think it's the problem. I think the problem is between my computer and my chair.
const beep = new Audio(
"data:audio/flac;base64,ZkxhQwAAACIQABAAAARBAARBAfQBcAAAAZLfwZb9QVlTtnnZLOsaWczxhAAAKCAAAAByZWZlcmVuY2UgbGliRkxBQyAxLjMuMCAyMDEzMDUyNgAAAAD/+HQMAAGRJhgKxHRX63x+6QxXqTpCYAANDJgITNAmIhAB/5BgFt4iAfgBZHY4A9UZAAZ65QManTnQUAKnx8A+ZcwFun6gX1gMVIgAfaXgEml9KIzgfUBYAnhLwJl/Oek+A5rZADhx2ApN3s198CTrfAPyHMGRV3DcKAYAAwBJ7uA8wysUF8HYV6AUyIIKv/ObD0B7BRAOf6QFVnlVIrg0zuwGYTqCTP9rJXAWm4AC1HQDxVMnllwVg94CGPDDq6XrJRgQ2zwHp6wGR5tQFGh9dygZtwIXeHNK+AHAw8BZ34BSgBUY44Ze3IEt2uEhBfQg3BcaTA+MSB/rIUTNIUTWYN9hMdT2M/TYEg+cDC6KGzFJQAzj8TBBUujjHFLnsqB07TAj7JBa4qTwQY15pQ9rKxSdhzrJwxaKA3o/BKIsTkDYtGCwxtDRCIqzegQo2pAr9KD0mKmwtRJeuhMscnKzjNLLCC4CCDoYNaPiZmNPNIsdzTJkF0zHIRyDGDZzCLozKYLfNVZUYt6pWUiy7/Bjf5CyRUJ95iW1TLkIET7MJJU5yxARVwzCNBsIZHCVflJ5ZE+0K30dXKabEjNYdP+TulglDBSFPJNlCtxqLycmj5OeMkURsMFSXgrtnXLllFm5cySbjiZQKoshh0ASOArXdBJuJ9c2syJBjM8II1VJYFtSEVbCw3f80qnABkAClxxw8mPk8NdHt4q9gNy0UpWEuO2UUx3jZSuRqVkcoWnWIWa1ahV3Y3K5KbKMH879vqjUtUZMatwgfZeOMvsQlyisbQ71rIxGX9FhUSYvRHvF3xeunSYfQ4iRItSvuvzR5iO3xDFaEdARSGOC1fGIpY/hll/Z8dBI+J6u22KvVuDK2IiXW9V8Htkhxa94kLDPz25hsMC8qImvymxd70W8D5iDfsU9TYMYt5EIfJnAWr0bS7NbeHbQu6ZsuZyvTuhwMbc9XFv3q4b4amazBWwDvKfuyGSBrwrbr8+kkvhfZKs7C2FwoVooWXOnr/sWmZ5hWFSSpEtq0O6bjQhPR6Eguo8PmOz4SoKeIgpRmJZ1CEWpm1U6F/2UKJhBBJi0KeJ6kgEoPCeWSBmv85AOeDhOk/mJgciON6g0DZHbeVa7jIhYMBSP4ukvNIr36CvTjhkZCkWJk5godIxpiOjqiEnoJQ2K3HjKtYcY2CFWiXpIrqaGEIgef4gs+JXnhRm4GziHB2h/OIRB6BgfhgH4ap2DiTgVwIUN6FjaguFoE0uENThJRYJMOBCwg3zIOyKB00gOl4LXWC79gW14DOaCQAglUoEKCApZgc1YHC2AxzgJBoFcSBWWgICoBp+BEXgO64BeGAXYgMGoCoCAOYgEk4CGWAb5gB54A2SAWGgEfoAHyAINgDuYAkeAAbgBfoAgyAEEgAC4ARGADPgAf4AFyABYgAeIACGAAMgAaYAECABJgAagfd0="
);
const bpm = document.getElementById('bpm-display');
const time = document.getElementById('time');
const timeSlice = document.getElementById('time-slice');
const rangeBpm = document.getElementById('bpm-range');
const btnStartStop = document.getElementById('start-stop');
const btnReset = document.getElementById('reset');
let intervalSound
// function to start and stop the metronome
const startMetronome = (() => {
btnStartStop.innerText==='Start'? btnStartStop.innerText= 'Stop': btnStartStop.innerText='Start';
if(btnStartStop.innerText === 'Stop'){
intervalSound = (60/bpm.value) * 1000;
console.log(intervalSound);
interval(intervalSound);
}
else{
stopBeat();
}
});
const stopBeat = (()=>{
beep.pause();
beep.currentTime = 0;
})
const playBeat = (() =>{
beep.play();
})
const interval = ((interval) => {
setInterval(playBeat, interval)
})
// function to reset all metronome
const resetMetronome = (()=>{
bpm.value = '120';
rangeBpm.value='120';
time.value='4';
timeSlice.value='4';
intervalSound = 0;
stopBeat();
});
btnReset.addEventListener('click', function(){resetMetronome()});
btnStartStop.addEventListener('click', function(){startMetronome()});
bpm.addEventListener('change', function(){
rangeBpm.value=bpm.value;
})
rangeBpm.addEventListener('click', function(){
bpm.value = rangeBpm.value;
})
console.log(bpm.value, time.value, timeSlice.value, rangeBpm.value, btnStartStop.innerText, btnReset.innerText);
Can you help me?

You need to clear your interval.
let intervalId = -1;
const stopBeat = (()=>{
beep.pause();
beep.currentTime = 0;
clearInterval(intervalId);
})
const interval = ((interval) => {
intervalId = setInterval(playBeat, interval)
})

Related

react decibel meter and use

i need to make a decibel meter
i try to use 2 libary but they wont work and they very old
i found a function that make this but it wont work as expected
first of all the issue is
inside this function i get the
" let decibelNumString = decibelNum.toString().substring(0, 2); "
which is get me the number of the decibel and make it to integear
but
i want to make the minNumber and MaxNumber as state because it should re render after the changes happen
the probme it make a lot of re render becuase every 100ms it change the numbers
i have also the current decibel so it need to be render every 100ms
and it not good for perfomance
// const [minNumber, setMinNumber] = useState(25);
// const [maxNumber, setMaxNumber] = useState(30);
let arr = [];
let volumeCallback = null;
let volumeInterval = null;
(async () => {
// Initialize
try {
const audioStream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true,
},
});
const audioContext = new AudioContext();
const audioSource = audioContext.createMediaStreamSource(audioStream);
const analyser = audioContext.createAnalyser();
analyser.fftSize = 512;
analyser.minDecibels = -127;
analyser.maxDecibels = 0;
analyser.smoothingTimeConstant = 0.4;
audioSource.connect(analyser);
const volumes = new Uint8Array(analyser.frequencyBinCount);
volumeCallback = () => {
analyser.getByteFrequencyData(volumes);
let volumeSum = 0;
for (const volume of volumes) volumeSum += volume;
const averageVolume = volumeSum / volumes.length;
// Value range: 127 = analyser.maxDecibels - analyser.minDecibels;
let decibelNum = (averageVolume * 100) / 127;
let decibelNumString = decibelNum.toString().substring(0, 2);
if (Number(decibelNumString) > maxNumber) {
// (maxNumber = Number(decibelNum))
// setMaxNumber((prev) => {
// return (prev = Number(decibelNumString));
// });
}
if (Number(decibelNumString) < minNumber) {
// setMinNumber((prev) => {
// return (prev = Number(decibelNumString));
// });
}
console.log(decibelNumString);
// console.log(minNumber + "min");
// console.log(maxNumber + "max");
arr.push(Number(decibelNumString));
// console.log(arr)
};
} catch (e) {
console.error("Failed to initialize volume visualizer, simulating instead...", e);
// Simulation
//TODO remove in production!
let lastVolume = 50;
volumeCallback = () => {
const volume = Math.min(Math.max(Math.random() * 100, 0.8 * lastVolume), 1.2 * lastVolume);
lastVolume = volume;
};
}
// Use
// start();
})();
const stop = () => {
clearInterval(volumeInterval);
// volumeInterval = null;
};
const start = () => {
// Updating every 100ms (should be same as CSS transition speed)
if (volumeCallback !== null && volumeInterval === null) volumeInterval = setInterval(volumeCallback, 100);
};

Rolling numbers in js

I created rolling numbers
On the site I'm building in React.
How do I make it start working that it gets to the working place that it is?
It's starting to work for me that the page comes up
const RollingNumbers = () => {
useEffect(() => {
let valueDisplays = document.querySelectorAll(".amount");
let interval = 4000;
valueDisplays.forEach((valueDisplay) => {
let startValue = 0;
let endValue = parseInt(valueDisplay.getAttribute("data-val"));
let duration = Math.floor(interval / endValue);
let counter = setInterval(function () {
startValue += 1;
valueDisplay.textContent = startValue;
if (startValue === endValue) {
clearInterval(counter);
}
}, duration);
});
enter image description here
Thank you

Getting the current value of a counter used in setInterval javaScript

Suppose I define the following function
export const startMoving = () => {
let counter = 0;
var intervalId = setInterval(() => {
// Do something…
counter++;
}, 1000);
return intervalId;
};
Although 'counter' is defined with let in the function, it works, but my question is: How do I get the value of 'counter' after a while?
Rafael
Return not only the interval ID, but also a function that returns the current value of counter.
const startMoving = () => {
let counter = 0;
var intervalId = setInterval(() => {
// Do something…
counter++;
}, 1000);
return [intervalId, () => counter];
};
const [intervalId, getCounter] = startMoving();
document.body.addEventListener('click', () => document.body.textContent = getCounter());
click here

Javascript pause/resume toggle button

I am working on a little challenge with school. We have learned CSS, HTML, and Javascript. I am trying to create a timer that is always running in the background. Then I need a button that pauses said timer and changes into a resume button that will resume the timer. This is what I have come up with.
document.addEventListener("DOMContentLoaded", () => {
const counterElement = document.getElementById('counter')
let counterValue = 0
const pauseButton = document.getElementById('pause')
const resumeButton = document.getElementById('resume')
const submitButton = document.getElementById(`submit`)
const minusButton = document.getElementById(`minus`)
const plusButton = document.getElementById('plus')
const heartButton = document.getElementById('heart')
intervalId = setInterval(myCallback, 1000);
function myCallback() {
counterValue += 1;
counterElement.innerHTML = counterValue;
}
function resume() {
setInterval(myCallback, 1000);
pauseButton.style.display = '';
resumeButton.style.display = 'none';
}
function pause() {
clearInterval(intervalId);
pauseButton.style.display = 'none';
resumeButton.style.display = '';
}
pauseButton.addEventListener("click", (e) => {
pause()
})
resumeButton.addEventListener("click", (e) => {
resume()
})
It does not function properly. Only the first few clicks work.
function resume() {
intervalId = setInterval(myCallback, 1000);
pauseButton.style.display = '';
resumeButton.style.display = 'none';
}
Try this. The root issue is that you're not assigning your setInterval reference back to your intervalId variable. So when you call clearInterval(intervalId) later, your code is saying, "That's already been cleared..." and not doing anything.
In short, your current resume() function creates a NEW setInterval - it doesn't update the old one. And since there was no reference to the new setInterval, there was no way for your pause function to be able to find it and clear it.
When you call setTimeout in the resume function, you have to reassign the intervalId variable to store the new interval ID. If you don't do that, your pause function will keep cancelling the first interval, which is a no-op.
So do this instead:
document.addEventListener("DOMContentLoaded", () => {
const counterElement = document.getElementById('counter')
let counterValue = 0
const pauseButton = document.getElementById('pause')
const resumeButton = document.getElementById('resume')
//const submitButton = document.getElementById(`submit`)
//const minusButton = document.getElementById(`minus`)
//const plusButton = document.getElementById('plus')
//const heartButton = document.getElementById('heart')
//It's a good idea to declare your variables. Since you want to reassign it, you probably want `let`.
let intervalId = setInterval(myCallback, 1000);
function myCallback() {
counterValue += 1;
counterElement.innerHTML = counterValue;
}
function resume() {
//Assign the new interval ID to `intervalId`
intervalId = setInterval(myCallback, 1000);
pauseButton.style.display = '';
resumeButton.style.display = 'none';
}
function pause() {
clearInterval(intervalId);
pauseButton.style.display = 'none';
resumeButton.style.display = '';
}
pauseButton.addEventListener("click", (e) => {
pause()
})
resumeButton.addEventListener("click", (e) => {
resume()
})
})
<button id="pause" >Pause</button>
<button id="resume" style="display:none;" >Resume</button>
<div id="counter" >0</div>
When you create a new Interval in your resume() function, you need to store its return value again in your intervalId variable for the next time you call pause().

How to assign clearInterval function to the button which would stop the function started by another button?

As I understood from MDN, I am supposed to make variable and assign setInterval function to it, so that I could use that variable and call clearInterval for it, but for some reason, my code is now working. It is properly fetching data with buttonStart, but will not stop fetching data with buttonStop.
Thank you for your time.
const buttonStart = document.querySelector('#start')
const buttonStop = document.querySelector('#stop')
const list = document.querySelector('#list')
class Price {
constructor(time, price) {
this.time = time
this.price = price
}
}
const fetchBitcoin = async () => {
try {
const res = await fetch('https://api.cryptonator.com/api/ticker/btc-usd');
const data = await res.json();
const newPrice = new Price(data.timestamp, data.ticker.price)
return newPrice
} catch (e) {
console.log("Something went wrong in downloading price", e)
}
}
const addNewPrice = async () => {
const newLI = document.createElement('LI')
const newElement = await fetchBitcoin()
const newTime = convertTime(newElement.time)
newLI.append(newTime, ' ', newElement.price.slice(0, 8))
list.append(newLI)
}
function convertTime(time) {
let unix_timestamp = time
var date = new Date(unix_timestamp * 1000);
var hours = date.getHours();
var minutes = "0" + date.getMinutes();
var seconds = "0" + date.getSeconds();
var formattedTime = hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
return formattedTime
}
let interval = buttonStart.addEventListener('click', () => {
setInterval(addNewPrice, 2000)
})
buttonStop.addEventListener('click', () => clearInterval(interval));
You need to create interval variable and assign the return value of the setInterval method rather than addEventListener because addEventListener does not return anything,
let interval;
buttonStart.addEventListener('click', () => {
interval = setInterval(addNewPrice, 2000)
})
You need to adjust the example below to your use case but this is what you need in general:
var timerEl = document.querySelector('.js-timer');
var startBtn = document.querySelector('.js-start');
var stopBtn = document.querySelector('.js-stop');
var intervalId;
var timer = 0;
startBtn.addEventListener('click', function() {
stopTimer();
console.log('start timer');
intervalId = setInterval(execTimer, 100);
});
stopBtn.addEventListener('click', stopTimer);
function stopTimer() {
timer = 0;
console.log('stop timer');
clearInterval(intervalId);
renderTimer();
}
function execTimer() {
timer++;
renderTimer();
console.log('timer score', timer);
}
function renderTimer() {
timerEl.textContent = timer;
}
<span class="js-timer"></span><br />
<button class="js-start">Start</button>
<button class="js-stop">Stop</button>

Categories

Resources