|
|
|
@ -1,21 +1,20 @@
|
|
|
|
document.querySelector('#analyze-pitch button').addEventListener('click', startListening);
|
|
|
|
document.querySelector('#analyze-pitch button').addEventListener('click', startListening);
|
|
|
|
|
|
|
|
|
|
|
|
const calculateCent = (frequency) => {
|
|
|
|
|
|
|
|
return frequency * 2 ** (1/1200) - frequency
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getCentDifference = (startingFrequency, newFrequency) => {
|
|
|
|
|
|
|
|
const frequencyDifference = newFrequency - startingFrequency
|
|
|
|
|
|
|
|
const cent = calculateCent(startingFrequency)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return frequencyDifference/cent
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const generateCentsString = (centDifference) => {
|
|
|
|
const generateCentsString = (centDifference) => {
|
|
|
|
const flatSharpChar = (centDifference > 0) ? '♯' : '♭'
|
|
|
|
const flatSharpChar = (centDifference > 0) ? '♯' : '♭'
|
|
|
|
return flatSharpChar + Math.abs(parseInt(centDifference)).toString().padStart(2, '0')
|
|
|
|
return flatSharpChar + Math.abs(parseInt(centDifference)).toString().padStart(2, '0')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const centsArray = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getMedianCents = (cents) => {
|
|
|
|
|
|
|
|
centsArray.push(cents)
|
|
|
|
|
|
|
|
if(centsArray.length > 50){
|
|
|
|
|
|
|
|
centsArray.shift()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return centsArray[Math.floor(centsArray.length/2)]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function startListening() {
|
|
|
|
function startListening() {
|
|
|
|
navigator.mediaDevices.getUserMedia({ audio: true, video: false })
|
|
|
|
navigator.mediaDevices.getUserMedia({ audio: true, video: false })
|
|
|
|
.then(stream => {
|
|
|
|
.then(stream => {
|
|
|
|
@ -36,8 +35,13 @@ function startListening() {
|
|
|
|
analyser.getFloatTimeDomainData(buffer);
|
|
|
|
analyser.getFloatTimeDomainData(buffer);
|
|
|
|
const pitch = autoCorrelate(buffer, audioContext.sampleRate);
|
|
|
|
const pitch = autoCorrelate(buffer, audioContext.sampleRate);
|
|
|
|
if(pitch != -1){
|
|
|
|
if(pitch != -1){
|
|
|
|
document.querySelector('#analyze-pitch dd:nth-of-type(1)').textContent = pitch.toFixed(2)
|
|
|
|
const heardTone = teoria.note.fromFrequency(pitch)
|
|
|
|
document.querySelector('#analyze-pitch dd:nth-of-type(2)').innerHTML = generateCentsString(getCentDifference(newTone, pitch))
|
|
|
|
const generatedTone = teoria.note.fromFrequency(newTone)
|
|
|
|
|
|
|
|
if(heardTone.note.toString() === generatedTone.note.toString()){
|
|
|
|
|
|
|
|
const medianCents = Math.floor(getMedianCents(heardTone.cents-generatedTone.cents))
|
|
|
|
|
|
|
|
document.querySelector('#analyze-pitch input[type="range"]').value = medianCents
|
|
|
|
|
|
|
|
document.querySelector('#analyze-pitch label').innerText = medianCents
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|