Last active
November 17, 2019 06:15
-
-
Save ayaysir/bffed1164c42300adf238afff2e48d93 to your computer and use it in GitHub Desktop.
스케일 보여주는 프로그램 (http://yoonbumtae.com/music/scale/)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="ko"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Musical Scales</title> | |
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> | |
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script> | |
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> | |
<link href="./res/abcjs-audio.css" media="all" rel="stylesheet" type="text/css" /> | |
<script src="./res/abcjs_basic_5.9.1-min.js" type="text/javascript"></script> | |
<style> | |
</style> | |
</head> | |
<body class="container"> | |
<?php | |
include "init-db.php"; | |
// if($mysqli){echo "MySQL 접속 성공";} | |
// else{echo "MySQL 접속 실패";} | |
$sql = 'SELECT * FROM music_scale order by priority desc, name'; | |
$res = $mysqli -> query($sql); | |
?> | |
<header> | |
<h2>Musical Scales</h2> | |
</header> | |
<nav> | |
</nav> | |
<section> | |
<table id="freq-table" class="table table-hover"> | |
<thead> | |
<tr class="table-info"> | |
<th>Name</th> | |
<th>Alias</th> | |
<th>Priority</th> | |
</tr> | |
</thead> | |
<tbody id="freq-tbody"> | |
<?php while($row = mysqli_fetch_array($res)) { ?> | |
<tr class="each-scale" data-description="<?=$row['description']?>" data-pattern="<?=$row['pattern']?>" data-priority="<?=$row['priority']?>"> | |
<td class="scale-title"> | |
<?php | |
$flt0 = str_replace("Double-Flat ", "𝄫", $row['name']); | |
$flt1 = str_replace("Flat ", "♭" , $flt0); | |
$flt2 = str_replace("Sharp ", "♯", $flt1); | |
echo str_replace("Nat. ", "♮", $flt2); | |
?> | |
</td> | |
<td class="scale-alias"> | |
<?=$row['alias']?> | |
</td> | |
<td class="area-priority"> | |
<span class="badge badge-warning"> | |
<?php | |
for($i = 1; $i <= $row['priority']; $i++ ){ | |
echo "★"; | |
} | |
?> | |
</span> | |
</td> | |
</tr> | |
<?php }?> | |
</tbody> | |
</table> | |
</section> | |
<article> | |
<div class="modal fade"> | |
<div class="modal-dialog modal-xl" role="document"> | |
<div class="modal-content"> | |
<div class="modal-header"> | |
<h5 class="modal-title">Modal title</h5> | |
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> | |
<span aria-hidden="true">×</span> | |
</button> | |
</div> | |
<div class="modal-body"> | |
<table> | |
<tbody> | |
<tr> | |
<th>Name</th> | |
<td id="mod-cont-name"></td> | |
</tr> | |
<tr> | |
<th>Alias</th> | |
<td id="mod-cont-alias"></td> | |
</tr> | |
<tr> | |
<th>Pattern</th> | |
<td id="mod-cont-pattern"></td> | |
</tr> | |
<tr> | |
<th>Priority</th> | |
<td><span id="mod-cont-prior" class="badge badge-warning"></span></td> | |
</tr> | |
<tr> | |
<th colspan="2">Description</th> | |
</tr> | |
<tr> | |
<td id="mod-cont-desc" colspan="2"></td> | |
</tr> | |
</tbody> | |
</table> | |
<hr> | |
<div> | |
<label>Transpose</label> | |
<select id=transpose> | |
<option value="0">C</option> | |
<option value="1">C♯(D♭)</option> | |
<option value="2">D</option> | |
<option value="3">E♭(D♯)</option> | |
<option value="4">E</option> | |
<option value="5">F</option> | |
<option value="6">F♯(G♭)</option> | |
<option value="7">G</option> | |
<option value="8">A♭(G♯)</option> | |
<option value="9">A</option> | |
<option value="10">B♭(A♯)</option> | |
<option value="11">B</option> | |
</select> | |
</div> | |
<div> | |
<label>Display Enharmonic Notes</label> | |
<select id="change-enharmonic"> | |
<option value="common">Standard</option> | |
<option value="sharp">Sharp(♯) only</option> | |
<option value="flat">Flat(♭) only</option> | |
</select> | |
</div> | |
<hr> | |
<div id="notation"></div> | |
<div id="audio"></div> | |
</div> | |
<div class="modal-footer"> | |
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</article> | |
<footer> | |
Copyright by <a href="http://yoonbumtae.com" target="_blank">BGSMM</a> | |
</footer> | |
<script> | |
const NAME_COMMON = ["", "C", "C+", "D", "E-", "E", "F", "F+", "G", "A-", "A", "B-", "B"]; | |
const NAME_FLAT = ["", "C", "D-", "D", "E-", "E", "F", "G-", "G", "A-", "A", "B-", "B"]; | |
const NAME_SHARP = ["", "C", "C+", "D", "D+", "E", "F", "F+", "G", "G+", "A", "A+", "B"]; | |
let glb_currentName = NAME_COMMON | |
function getScale(param) { | |
const pattern = param.pattern | |
const transpose = param.transpose | |
const patternArr = pattern.split('') | |
let sum = 1; | |
const output = { | |
scaleByName: [], | |
scaleBySemitone: [] | |
} | |
const input_ = (semitone) => { | |
if (semitone > 12) { | |
output.scaleByName.push(glb_currentName[semitone - 12]) | |
} else { | |
output.scaleByName.push(glb_currentName[semitone]) | |
} | |
output.scaleBySemitone.push(semitone) | |
} | |
input_(parseInt(transpose) + sum) | |
for (let o of patternArr) { | |
sum += parseInt(o) | |
const dispNum = parseInt(transpose) + sum | |
input_(dispNum) | |
} | |
//console.log(output) | |
return output | |
} | |
// C2 ^C2 _E2 =E2 ^F2 G2 A2 _B2 c2| | |
// ^: sharp | |
// =: natural | |
// _: flat | |
function translateToAbcjs(scaleBySemitone) { | |
//console.log(scaleBySemitone) | |
const outArr = [] | |
const changedNotes = [] | |
for (let each of scaleBySemitone) { | |
//onsole.log(each) | |
const nameIndex = each > 12 ? each - 12 : each | |
const octave = each > 12 ? 1 : 0 | |
//console.log("octave", octave) | |
const note = (_ => { | |
if (octave == 0) { | |
return glb_currentName[nameIndex].substr(0, 1) | |
} else if (octave == 1) { | |
return glb_currentName[nameIndex].substr(0, 1).toLowerCase() | |
} | |
})() | |
const postfix = glb_currentName[nameIndex].substr(glb_currentName[nameIndex].length - 1, 1) | |
//console.log(note, postfix) | |
if (note.toUpperCase() != postfix) { | |
const prefix = postfix == "+" ? "^" : "_" | |
changedNotes.push(note) | |
outArr.push(prefix + note + "2") | |
} else { | |
if (changedNotes.indexOf(note) != -1) { | |
outArr.push("=" + note + "2") | |
} else { | |
outArr.push(note + "2") | |
} | |
} | |
} | |
//console.log(outArr) | |
return outArr.join(" ") | |
} | |
function displayScore(scaleObj, title, key) { | |
const scaleStr = `Scale by Name: ${scaleObj.scaleByName}\nScale by Semitone: ${scaleObj.scaleBySemitone}` | |
console.log(scaleStr) | |
const translatedScale = translateToAbcjs(scaleObj.scaleBySemitone) | |
key = key || "C" | |
var cooleys = ` | |
X: 1 | |
T: | |
I: speed 50 | |
M: | |
L: 1/8 | |
R: ${key.trim()} ${title.trim()} | |
K: C | |
${translatedScale}|`; | |
//alert(cooleys) | |
var visualObj = ABCJS.renderAbc('notation', cooleys, { | |
responsive: "resize", | |
staffwidth: 500, | |
paddingright: 5, | |
paddingleft: 5, | |
})[0]; | |
var synthControl = new ABCJS.synth.SynthController(); | |
synthControl.load("#audio", null, { | |
displayRestart: true, | |
displayPlay: true, | |
displayProgress: true | |
}); | |
synthControl.setTune(visualObj, false); | |
} | |
$(".each-scale").on("click", e => { | |
const eachScale = $(e.target).closest(".each-scale") | |
const title = eachScale.find(".scale-title").text() | |
const pattern = eachScale.data("pattern") + "" | |
const alias = eachScale.data("alias") | |
const desc = eachScale.data("description") | |
const prior = eachScale.data("priority") | |
const priorStar = (_ => { | |
let str = "" | |
for (let i = 1; i <= parseInt(prior); i++) { | |
str += "★" | |
} | |
return str | |
})(); | |
console.log(pattern) | |
const scaleObj = getScale({ | |
pattern, | |
transpose: $("#transpose").val() | |
}) | |
displayScore(scaleObj, title, $("#transpose option:selected").text()) | |
$(".modal-title").text(title) | |
$("#mod-cont-name").text(title) | |
$("#mod-cont-alias").text(alias) | |
$("#mod-cont-prior").text(priorStar) | |
$("#mod-cont-desc").text(desc) | |
$("#mod-cont-pattern").text(pattern) | |
$(".modal").modal("show") | |
}) | |
$("#transpose").on("change", e => { | |
const scaleObj = getScale({ | |
pattern: $("#mod-cont-pattern").text(), | |
transpose: $(e.target).val() | |
}) | |
displayScore(scaleObj, $("#mod-cont-name").text(), $("#transpose option:selected").text()) | |
}) | |
$("#change-enharmonic").on("change", e => { | |
const value = $(e.target).val() | |
switch (value) { | |
case "common": | |
glb_currentName = NAME_COMMON; | |
break; | |
case "sharp": | |
glb_currentName = NAME_SHARP; | |
break; | |
case "flat": | |
glb_currentName = NAME_FLAT; | |
break; | |
} | |
const scaleObj = getScale({ | |
pattern: $("#mod-cont-pattern").text(), | |
transpose: $("#transpose").val() | |
}) | |
displayScore(scaleObj, $("#mod-cont-name").text(), $("#transpose option:selected").text()) | |
}) | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment