Last active
April 20, 2016 16:58
-
-
Save zakuroishikuro/6f5ea9e5098308e9c86fa9cc2fda23ba to your computer and use it in GitHub Desktop.
どれみ再生機
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
<style> | |
body { background-color: #CCC; } | |
textarea { width: 500px; height: 300px; } | |
</style> | |
<script> | |
var ctx, gain; | |
window.addEventListener("DOMContentLoaded", ()=>{ | |
ctx = new AudioContext(); | |
gain = ctx.createGain(); | |
gain.connect(ctx.destination); | |
}) | |
String.prototype.count = function(pattern){ | |
var r = new RegExp(pattern, "g"); | |
var m = this.match(r); | |
return m ? m.length : 0; | |
} | |
function parse_frequency(note, pitch){ | |
if (pitch === undefined) pitch = 440; | |
var n; | |
switch (note.trim()[0]) { | |
case "ラ": n = 1 + 12; break; | |
case "シ": n = 3 + 12; break; | |
case "ド": n = 4; break; | |
case "レ": n = 6; break; | |
case "ミ": n = 8; break; | |
case "フ": n = 9; break; | |
case "ソ": n = 11; break; | |
default: return; | |
} | |
n += note.count("#"); | |
n += (note.count("↑") - note.count("↓")) * 12; | |
return pitch * Math.pow(Math.pow(2, 1.0/12), n - 1); | |
} | |
function parse_duration(note, tempo){ | |
if (tempo === undefined) tempo = 120; | |
var dur = 60.0 / tempo; | |
return dur / Math.pow(2, note.count("/")) + dur * note.count("-"); | |
} | |
function play_notes(notes, pitch, type, tempo){ | |
var scanner = /[ドレミフソラシ_]ァ?[^ドレミフソラシ_]*/g; | |
var m = notes.match(scanner); | |
var delay = 0; | |
var oscillators = []; | |
for (var i = 0, len = m.length; i < len; i++){ | |
var note = m[i]; | |
var hz = parse_frequency(note, pitch); | |
var dur = parse_duration(note, tempo); | |
if (!/_/.test(note)){ | |
oscillators.push(create_oscillator(hz, type, delay, dur - 0.01)); | |
}; | |
delay += dur; | |
} | |
return oscillators; | |
} | |
function create_oscillator(freq, type, delay, duration){ | |
var osc = ctx.createOscillator(); | |
osc.connect(gain); | |
osc.frequency.value = freq; | |
osc.type = type || "sine"; | |
osc.start(ctx.currentTime + delay); | |
osc.stop(ctx.currentTime + delay + duration); | |
return osc; | |
} | |
var osc_list = []; | |
function start(){ | |
var notes = document.getElementById("notes").value; | |
notes = notes.replace(/\([^(]*?\)/gm, ""); | |
var pitch = document.getElementById("pitch").value; | |
var type = document.getElementById("type").value; | |
var tempo = document.getElementById("tempo").value; | |
if (osc_list) stop(); | |
osc_list = play_notes(notes, parseInt(pitch), type, tempo); | |
} | |
function stop(){ | |
if (osc_list) osc_list.forEach(osc=>osc.stop()); | |
} | |
</script> | |
<p><button onclick="start()">鳴らす</button><button onclick="stop()">止める</button></p> | |
<textarea id="notes"> | |
シ-レ↑ ラ-- シ-レ↑ ラ-- | |
シ-レ↑ ラ↑-ソ↑ レ↑-ド↑/シ/ ラ-- | |
シ-レ↑ ラ-ソ/ラ/ シ-レ↑ ラ-- | |
シ-レ↑ ラ↑-ソ↑ レ↑↑-- --- | |
レ↑↑-ド↑↑/シ↑/ ド↑↑/シ↑/ソ↑- ド↑↑-シ↑/ラ↑/ シ↑/ラ↑/ミ↑- | |
レ↑↑-ド↑↑/シ↑/ ド↑↑/シ↑/ソ↑ ド↑↑ ソ↑↑-- --- | |
</textarea> | |
<ul> | |
<li>「ドレミファソラシド」のいずれかを書くとその音が鳴る</li> | |
<li>音の高さ変更:「#」で半音上がり、上下の矢印で1オクターブ上下する</li> | |
<li>音の長さ変更:「-」は音符1つ分伸ばし、「/」は半分にする(例えば4分音符が8分音符になる)</li> | |
<li>音を出さない:「_」で音符1つ分休む。丸括弧で囲んだ箇所は無視される | |
<li>それ以外の文字は無視される</li> | |
</ul> | |
<p>音色: | |
<select id="type"> | |
<option value="sine">正弦波(sine) ... 口笛、オルガン</option> | |
<option value="square">矩形波(square) ... クラリネット</option> | |
<option value="sawtooth">ノコギリ波(sawtooth) ... バイオリン、トランペット</option> | |
<option value="triangle">三角波(triangle) ... リコーダー、フルート</option> | |
</select> | |
</p> | |
<p>音符の長さ:1秒に<input id="tempo" type="number" value="120" style="width: 5em">回</p> | |
<p> | |
ピッチ(ラの周波数):<input id="octave" type="range" min=110 max=14080 value="440" list="freq_list" oninput="document.getElementById('pitch').value = this.value"> | |
<input type="number" id="pitch" value="440" style="width: 10em">ヘルツ | |
<datalist id="freq_list"> | |
<option value="110" /> | |
<option value="220" /> | |
<option value="440" /> | |
<option value="880" /> | |
<option value="1760" /> | |
<option value="3520" /> | |
<option value="7040" /> | |
<option value="14080" /> | |
</datalist> | |
</p> | |
<div style="font-size: 0.8em"> | |
<ul> | |
<li>音階は「ラ」の音(周波数:440Hz)に合わせて調律され、1オクターブ上がると2倍になる(880Hz)</li> | |
<li>人間の可聴域は20Hz〜20000Hz程度で、15000Hz以上になると20代後半からは聞こえづらくなる(モスキート音)</li> | |
</ul> | |
<div> | |
<div class="comment" style="display: none"> | |
tempo: 120 | |
シ-レ↑ ラ-- シ-レ↑ ラ-- | |
シ-レ↑ ラ↑-ソ↑ レ↑-ド↑/シ/ ラ-- | |
シ-レ↑ ラ-ソ/ラ/ シ-レ↑ ラ-- | |
シ-レ↑ ラ↑-ソ↑ レ↑↑-- --- | |
レ↑↑-ド↑↑/シ↑/ ド↑↑/シ↑/ソ↑- ド↑↑-シ↑/ラ↑/ シ↑/ラ↑/ミ↑- | |
レ↑↑-ド↑↑/シ↑/ ド↑↑/シ↑/ソ↑ ド↑↑ ソ↑↑-- --- | |
tempo: 120 | |
ソ/ミ/レ- ソ/ミ/レ- | |
ソ/ミ/レミ レ-- | |
シ↓ラ#↓シ↓ ファ#/ソ/ミ- | |
ソソソ ファ#/ミ/レ- | |
ソ/ミ/レ- ソ/ミ/レ- | |
ソ/ミ/レミ レ-- | |
シ↓ラ#↓シ↓ ミ/ファ#/ソ- | |
ソソラソ--/ | |
tempo: 180 | |
レ/ファ/レ↑- レ/ファ/レ↑- | |
ミ↑-/ファ↑/ミ↑/ ファ↑/ミ↑/ド↑/ラ--/ | |
ラレファ/ソ/ラ-- ラレファ/ソ/ミ-- | |
レ/ファ/レ↑- レ/ファ/レ↑- | |
ミ↑-/ファ↑/ミ↑/ ファ↑/ミ↑/ド↑/ラ--/ | |
ラレファ/ソ/ラ- ラレ- --- | |
tempo: 280 | |
ファラシ- ファラシ- | |
ファラシミ↑レ↑- シド↑ | |
シソミ----レ | |
ミソミ----- | |
ファラシ- ファラシ- | |
ファラシミ↑レ↑-シド↑ | |
ミ↑シソ----シ | |
ソレミ----- | |
レミファ-ソラシ- ド↑シミ----- | |
レミファ-ソラシ- ド↑レ↑ミ↑----- | |
レミファ-ソラシ- ド↑シミ----- | |
ファミラソ シラド↑シ | |
レ↑ド↑ミ↑レ↑ファ↑ミ↑ ミ↑/ファ↑/_/ | |
レ↑/ミ↑------- | |
tempo: 120 | |
ソ/レ-/ソ/レ/ミ/ソ- | |
http://www.cosp.jp/community_topic.aspx?id=7735&ti=41219 | |
</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment