Files
interval-calc/index.html
Wiwi Kuan 70cac8f25f Add files via upload
三倍增六度 bug。
2024-11-25 09:58:18 +08:00

171 lines
5.7 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<head>
<title>不囉唆的音程計算器 by NiceChord 好和弦</title>
<script src="tonal.min.js"></script>
<script src="abcjs-basic-min.js"></script>
<style>
input[type="text"] {
font-size: 20px; /* increases font size */
padding: 5px; /* adds space around the text */
width: 400px; /* set a specific width */
}
#chordOutput {
font-size: 20px;
padding: 5px;
}
#footnote {
font-size: 12px;
color: #999;
margin-top: 5px;
margin-bottom: 10px;
}
h3 {
margin-bottom: 5px;
}
a {
color: #2563eb;
text-decoration: none;
}
a:hover {
color: #1d4ed8;
text-decoration: underline;
}
a:visited {
color: #7c3aed;
}
</style>
</head>
<body>
<h3>不囉唆的音程計算器 by <a href="https://nicechord.com">NiceChord 好和弦</a></h3>
<div id="footnote">註:第一個音會被當作低音;所有音程會判別為八度內,同音則自動判為「完全八度」。</div>
<div>
<input type="text" id="inputField" oninput="updateChord(this.value)" placeholder="輸入兩個音名用空白分隔Db G#">
</div>
<div id="chordOutput"></div>
<div id="paper"></div>
<script>
function convertToChineseInterval(result) {
// 定義音程性質對應的中文描述
const intervalQualities = {
'M': '大',
'm': '小',
'A': '增',
'd': '減',
'P': '完全',
'AA': '倍增',
'dd': '倍減',
'AAA': '三倍增',
'ddd': '三倍減',
'AAAA': '四倍增',
'dddd': '四倍減'
};
// 定義數字對應的中文描述
const chineseNumbers = {
'1': '一',
'2': '二',
'3': '三',
'4': '四',
'5': '五',
'6': '六',
'7': '七',
'8': '八',
'9': '九'
};
// 提取第一個字元作為度數
const degree = result[0];
// 提取第二個及以後的字元作為音程性質
const quality = result.slice(1);
// 檢查音程性質是否存在於我們的對照表中
if (intervalQualities.hasOwnProperty(quality)) {
return `${intervalQualities[quality]}${chineseNumbers[degree]}`;
} else {
return "未知的音程性質";
}
}
function updateChord(value) {
// 1. 只保留字母(不分大小寫)、空白和#符號
const valueCleaned = value.replace(/[^a-zA-Z\s#]/g, '')
.replace(/[xX]/g, '##'); // 把 x 和 X 替換成 ##
// 2. 移除開頭和結尾的空白分割成陣列限制每個元素最多3個字元並只取前兩個元素
const firstTwoNotes = valueCleaned
.trim()
.split(/\s+/)
.map(item => {
const firstChar = item.charAt(0).toUpperCase(); // 只把第一個字元轉大寫
const restChars = item.slice(1, 3); // 取得剩餘字元最多2個保持原樣
return firstChar + restChars;
})
.slice(0, 2);
// 把完全一度改成完全八度。
let result = Tonal.Interval.distance(firstTwoNotes[0], firstTwoNotes[1]);
if (result == "1P") {
result = "8P";
}
// Tonal.js 在三倍增六度以上會輸出「-1」硬改回「6」。
if (result.startsWith('-1')) {
result = '6' + result.slice(2);
}
console.log(convertToChineseInterval(result));
let resultWithOctave = [];
resultWithOctave[0] = firstTwoNotes[0] + "4";
resultWithOctave[1] = Tonal.Note.transpose(resultWithOctave[0], result);
console.log(resultWithOctave);
if (result != "") {
document.getElementById('chordOutput').innerHTML = firstTwoNotes[0] + " 和 " + firstTwoNotes[1] + " 的音程是 <b>" + convertToChineseInterval(result) + "</b>";
let abcNoteArray = resultWithOctave.map(item => {
// Replace '#' with '^' and 'b' with '_'
let replaced = item.replace(/#/g, '^').replace(/b/g, '_');
// Check if item contains '5' or '6', if so, convert to lowercase
if (replaced.includes('5') || replaced.includes('6')) {
replaced = replaced.toLowerCase();
}
// Move the first character to the end
let rearranged = replaced.substring(1) + replaced.charAt(0);
// Check if item contains '6', if so, add a "'" at the end
if (rearranged.includes('6')) {
rearranged = rearranged + "'";
}
// Remove all numbers
rearranged = rearranged.replace(/\d/g, '');
return rearranged;
});
const abcSyntax = "[" + abcNoteArray.join('8') + "8]"
ABCJS.renderAbc("paper", `X:1\nK:C\n${abcSyntax}`);
}
}
</script>
</body>
</html>