음정 인식 후 악보 출력 프로그램 만드려는데여
험온이라는 악보로 출력해주는 프로그램이랑
쥐스트링이라는 튜너 프로그램
디코딩해서 봤는데
음정 인식해서 추출하는 부분만 보려고...
근데 마음대로 보게 되어있지않더라고요
암호화라고 해야하나 파일이름이랑 객체들을 a b c d 이런식으로 해놔서 해석이 거의 안된다고 봐야겠더라고요
구글링하다가 pitchdetect라는 파일을 얻을수 있었는데
그 마저도 음성 인식해서 악보로 출력하려해봤는데
innerhtml로 출력만 되더라고요 일단 실행은 잘 되는데여
원하는게
입력된 음을 일정주기마다 하나씩 뽑아서
1초부터 30초까지 30개 음이있었으면 그 30개음을 한눈에 보게 출력하기 랄까요 예를들면
근데 어렵더라고요
제가 자바 스크립트를 잘 몰라서 그런거같은데
그 pitchdect의 html 파일이랑 js 파일 보여드릴게여
그냥 documentwrite 하듯이 입력된음을 한 글자만 이라도 출력가능하게 해주실분 있나여 ㅠㅠ
나머지는 제가 알아서 할게여 출력을 어케해야할지 모르겠어서
아니면
보고 따라하거나 이해할만한 음정 인식 코드 있을까여
===================================html 파일==============================================
<head> <title>Pitch Detector</title> <link href='http://fonts.googleapis.com/css?family=Alike' rel='stylesheet' type='text/css'> <style> body { font: 14pt 'Alike', sans-serif;} #note { font-size: 164px; } .droptarget { background-color: #348781} div.confident { color: black; } div.vague { color: lightgrey; } #note { display: inline-block; height:180px; text-align: left;} #detector { width: 300px; height: 300px; border: 4px solid gray; border-radius: 8px; text-align: center; padding-top: 10px;} #output { width: 300px; height: 42px; } #flat { display: none; } #sharp { display: none; } .flat #flat { display: inline; } .sharp #sharp { display: inline; } </style> </head> <body> <script src="js/pitchdetect.js"></script> <button onclick="this.innerText = togglePlayback()">use demo audio</button> <button onclick="toggleLiveInput()">use live input</button> <button onclick="toggleOscillator()">use oscillator</button> <!--<button onclick="updatePitch(0);">sample</button>--> <div id="detector" class="vague"> <div class="pitch"><span id="pitch">--</span>Hz</div> <div class="note"><span id="note">--</span></div> <canvas id="output" width=300 height=42></canvas> <div id="detune"><span id="detune_amt">--</span><span id="flat">cents ♭</span><span id="sharp">cents ♯</span></div> </div> <!-- just used for debugging <canvas id="waveform" width="512" height="256"></canvas> --> <a href="https://github.com/cwilso/pitchdetect" style="position: absolute; z-index:2; top: 0; right: 0; border: 0;"><img src="img/forkme.png" alt="Fork me on GitHub"></a> <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-35593052-1']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> </body>
===============================js 파일 ========================================================
/*
The MIT License (MIT)
Copyright (c) 2014 Chris Wilson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext = null;
var isPlaying = false;
var sourceNode = null;
var analyser = null;
var theBuffer = null;
var DEBUGCANVAS = null;
var mediaStreamSource = null;
var detectorElem,
canvasElem,
waveCanvas,
pitchElem,
noteElem,
detuneElem,
detuneAmount;
window.onload = function() {
audioContext = new AudioContext();
MAX_SIZE = Math.max(4,Math.floor(audioContext.sampleRate/5000)); // corresponds to a 5kHz signal
var request = new XMLHttpRequest();
request.open("GET", "../sounds/whistling3.ogg", true);
request.responseType = "arraybuffer";
request.onload = function() {
audioContext.decodeAudioData( request.response, function(buffer) {
theBuffer = buffer;
} );
}
request.send();
detectorElem = document.getElementById( "detector" );
canvasElem = document.getElementById( "output" );
DEBUGCANVAS = document.getElementById( "waveform" );
if (DEBUGCANVAS) {
waveCanvas = DEBUGCANVAS.getContext("2d");
waveCanvas.strokeStyle = "black";
waveCanvas.lineWidth = 1;
}
pitchElem = document.getElementById( "pitch" );
noteElem = document.getElementById( "note" );
detuneElem = document.getElementById( "detune" );
detuneAmount = document.getElementById( "detune_amt" );
detectorElem.ondragenter = function () {
this.classList.add("droptarget");
return false; };
detectorElem.ondragleave = function () { this.classList.remove("droptarget"); return false; };
detectorElem.ondrop = function (e) {
this.classList.remove("droptarget");
e.preventDefault();
theBuffer = null;
var reader = new FileReader();
reader.onload = function (event) {
audioContext.decodeAudioData( event.target.result, function(buffer) {
theBuffer = buffer;
}, function(){alert("error loading!");} );
};
reader.onerror = function (event) {
alert("Error: " + reader.error );
};
reader.readAsArrayBuffer(e.dataTransfer.files[0]);
return false;
};
}
function error() {
alert('Stream generation failed.');
}
function getUserMedia(dictionary, callback) {
try {
navigator.getUserMedia =
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
navigator.getUserMedia(dictionary, callback, error);
} catch (e) {
alert('getUserMedia threw exception :' + e);
}
}
function gotStream(stream) {
// Create an AudioNode from the stream.
mediaStreamSource = audioContext.createMediaStreamSource(stream);
// Connect it to the destination.
analyser = audioContext.createAnalyser();
analyser.fftSize = 2048;
mediaStreamSource.connect( analyser );
updatePitch();
}
function toggleOscillator() {
if (isPlaying) {
//stop playing and return
sourceNode.stop( 0 );
sourceNode = null;
analyser = null;
isPlaying = false;
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = window.webkitCancelAnimationFrame;
window.cancelAnimationFrame( rafID );
return "play oscillator";
}
sourceNode = audioContext.createOscillator();
analyser = audioContext.createAnalyser();
analyser.fftSize = 2048;
sourceNode.connect( analyser );
analyser.connect( audioContext.destination );
sourceNode.start(0);
isPlaying = true;
isLiveInput = false;
updatePitch();
return "stop";
}
function toggleLiveInput() {
if (isPlaying) {
//stop playing and return
sourceNode.stop( 0 );
sourceNode = null;
analyser = null;
isPlaying = false;
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = window.webkitCancelAnimationFrame;
window.cancelAnimationFrame( rafID );
}
getUserMedia(
{
"audio": {
"mandatory": {
"googEchoCancellation": "false",
"googAutoGainControl": "false",
"googNoiseSuppression": "false",
"googHighpassFilter": "false"
},
"optional": []
},
}, gotStream);
}
function togglePlayback() {
if (isPlaying) {
//stop playing and return
sourceNode.stop( 0 );
sourceNode = null;
analyser = null;
isPlaying = false;
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = window.webkitCancelAnimationFrame;
window.cancelAnimationFrame( rafID );
return "start";
}
sourceNode = audioContext.createBufferSource();
sourceNode.buffer = theBuffer;
sourceNode.loop = true;
analyser = audioContext.createAnalyser();
analyser.fftSize = 2048;
sourceNode.connect( analyser );
analyser.connect( audioContext.destination );
sourceNode.start( 0 );
isPlaying = true;
isLiveInput = false;
updatePitch();
return "stop";
}
var rafID = null;
var tracks = null;
var buflen = 1024;
var buf = new Float32Array( buflen );
var noteStrings = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
function noteFromPitch( frequency ) {
var noteNum = 12 * (Math.log( frequency / 440 )/Math.log(2) );
return Math.round( noteNum ) + 69;
}
function frequencyFromNoteNumber( note ) {
return 440 * Math.pow(2,(note-69)/12);
}
function centsOffFromPitch( frequency, note ) {
return Math.floor( 1200 * Math.log( frequency / frequencyFromNoteNumber( note ))/Math.log(2) );
}
// this is a float version of the algorithm below - but it's not currently used.
/*
function autoCorrelateFloat( buf, sampleRate ) {
var MIN_SAMPLES = 4; // corresponds to an 11kHz signal
var MAX_SAMPLES = 1000; // corresponds to a 44Hz signal
var SIZE = 1000;
var best_offset = -1;
var best_correlation = 0;
var rms = 0;
if (buf.length < (SIZE + MAX_SAMPLES - MIN_SAMPLES))
return -1; // Not enough data
for (var i=0;i
rms += buf[i]*buf[i];
rms = Math.sqrt(rms/SIZE);
for (var offset = MIN_SAMPLES; offset <= MAX_SAMPLES; offset++) {
var correlation = 0;
for (var i=0; i
correlation += Math.abs(buf[i]-buf[i+offset]);
}
correlation = 1 - (correlation/SIZE);
if (correlation > best_correlation) {
best_correlation = correlation;
best_offset = offset;
}
}
if ((rms>0.1)&&(best_correlation > 0.1)) {
console.log("f = " + sampleRate/best_offset + "Hz (rms: " + rms + " confidence: " + best_correlation + ")");
}
// var best_frequency = sampleRate/best_offset;
}
*/
var MIN_SAMPLES = 0; // will be initialized when AudioContext is created.
var GOOD_ENOUGH_CORRELATION = 0.9; // this is the "bar" for how close a correlation needs to be
function autoCorrelate( buf, sampleRate ) {
var SIZE = buf.length;
var MAX_SAMPLES = Math.floor(SIZE/2);
var best_offset = -1;
var best_correlation = 0;
var rms = 0;
var foundGoodCorrelation = false;
var correlations = new Array(MAX_SAMPLES);
for (var i=0;i
var val = buf[i];
rms += val*val;
}
rms = Math.sqrt(rms/SIZE);
if (rms<0.01) // not enough signal
return -1;
var lastCorrelation=1;
for (var offset = MIN_SAMPLES; offset < MAX_SAMPLES; offset++) {
var correlation = 0;
for (var i=0; i
correlation += Math.abs((buf[i])-(buf[i+offset]));
}
correlation = 1 - (correlation/MAX_SAMPLES);
correlations[offset] = correlation; // store it, for the tweaking we need to do below.
if ((correlation>GOOD_ENOUGH_CORRELATION) && (correlation > lastCorrelation)) {
foundGoodCorrelation = true;
if (correlation > best_correlation) {
best_correlation = correlation;
best_offset = offset;
}
} else if (foundGoodCorrelation) {
// short-circuit - we found a good correlation, then a bad one, so we'd just be seeing copies from here.
// Now we need to tweak the offset - by interpolating between the values to the left and right of the
// best offset, and shifting it a bit. This is complex, and HACKY in this code (happy to take PRs!) -
// we need to do a curve fit on correlations[] around best_offset in order to better determine precise
// (anti-aliased) offset.
// we know best_offset >=1,
// since foundGoodCorrelation cannot go to true until the second pass (offset=1), and
// we can't drop into this clause until the following pass (else if).
var shift = (correlations[best_offset+1] - correlations[best_offset-1])/correlations[best_offset];
return sampleRate/(best_offset+(8*shift));
}
lastCorrelation = correlation;
}
if (best_correlation > 0.01) {
// console.log("f = " + sampleRate/best_offset + "Hz (rms: " + rms + " confidence: " + best_correlation + ")")
return sampleRate/best_offset;
}
return -1;
// var best_frequency = sampleRate/best_offset;
}
function updatePitch( time ) {
var cycles = new Array;
analyser.getFloatTimeDomainData( buf );
var ac = autoCorrelate( buf, audioContext.sampleRate );
// TODO: Paint confidence meter on canvasElem here.
if (DEBUGCANVAS) { // This draws the current waveform, useful for debugging
waveCanvas.clearRect(0,0,512,256);
waveCanvas.strokeStyle = "red";
waveCanvas.beginPath();
waveCanvas.moveTo(0,0);
waveCanvas.lineTo(0,256);
waveCanvas.moveTo(128,0);
waveCanvas.lineTo(128,256);
waveCanvas.moveTo(256,0);
waveCanvas.lineTo(256,256);
waveCanvas.moveTo(384,0);
waveCanvas.lineTo(384,256);
waveCanvas.moveTo(512,0);
waveCanvas.lineTo(512,256);
waveCanvas.stroke();
waveCanvas.strokeStyle = "black";
waveCanvas.beginPath();
waveCanvas.moveTo(0,buf[0]);
for (var i=1;i<512;i++) {
waveCanvas.lineTo(i,128+(buf[i]*128));
}
waveCanvas.stroke();
}
if (ac == -1) {
detectorElem.className = "vague";
pitchElem.innerText = "--";
noteElem.innerText = "-";
detuneElem.className = "";
detuneAmount.innerText = "--";
} else {
detectorElem.className = "confident";
pitch = ac;
pitchElem.innerText = Math.round( pitch ) ;
var note = noteFromPitch( pitch );
noteElem.innerHTML = noteStrings[note%12];
var detune = centsOffFromPitch( pitch, note );
if (detune == 0 ) {
detuneElem.className = "";
detuneAmount.innerHTML = "--";
} else {
if (detune < 0)
detuneElem.className = "flat";
else
detuneElem.className = "sharp";
detuneAmount.innerHTML = Math.abs( detune );
}
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = window.webkitRequestAnimationFrame;
rafID = window.requestAnimationFrame( updatePitch );
}
첨부 | 파일 크기 |
---|---|
![]() | 4.05 KB |
댓글 달기