まえがき 私は楽譜の深い知識のふりをしません。 しかし、これは読者が楽譜を理解するのを妨げてはならず、作曲家が音符で録音した音階と少なくとも同じようなことをするべきではありません。 多くの用語と概念は意図的に簡略化されています。 テキストの文法的、構文的、およびその他のエラーの表示は、プライベートメッセージで歓迎されます。
せっかちな人は、すぐに結果を見ることができます(月光ソナタの7つの測定)。 Ubuntu 14.04上の最新のChromeおよびFirefoxで動作します。 ほとんどの場合、モバイルデバイスでは機能しません。
ブラウザで楽譜を再生する方法は? 最初に頭に浮かぶのは、基本的な機能を実装するソリューションを見つけることです。 githubを検索すると、 midi.jsが生成されます。 解決策は便利です。 MITライセンス。 例が動作します。 どうぞ!
$ git clone https://github.com/mudcube/MIDI.js.git
ローカル環境でコピーを取得しました。 サンプルディレクトリで、Basic.htmlを参照してください。 そこにBetchoven.htmlとしてコピーし、内容を変更します。 私たちに興味のある行は次のとおりです。
var delay = 0; // play one note every quarter second var note = 50; // the MIDI note var velocity = 127; // how hard the note hits // play the note MIDI.setVolume(0, 127); MIDI.noteOn(0, note, velocity, delay); MIDI.noteOff(0, note, delay + 0.75);
比較的シンプルで遅いものを書く必要があります。 たとえば、ベートーヴェンの月光ソナタの最初の部分(ウィキが示唆するように、ピアノソナタ第14番ハ短調Op。27、第2番)。 メモを見つけます。
そのようなことがありましょう:

この記譜法を理解するために最低限必要なものに署名します。
理論への小さな余談
ピアノの楽譜。 最初の写真はピアノのレイアウトを示しています。

オクターブレイアウトは完全に正しいわけではありません。左側の最初の2つのノートは、簡略表記ではオクターブ0です。 最初の音符To(Cとしてマーク)から、オクターブ1が始まります。
このレイアウトでピアノのキーを押すと、対応するサウンドが再生されます。
kontroktavnyh Laから-La sharp(別名B flat)-C
5オクターブまで。 音符全体(Do、Re、..)が白いキー、ハーフトーン(シャープとフラット)は黒です。
外国の文献では、別の簡略化された表記法がよく使用されます。これは最終的に使用されます。
ノートはラテン文字C(Do)、D(Pe)、E(Mi)、F(Fa)、G(Salt)、A(A)、B(Cu)で示されます。 オクターブには0から8までの番号が付けられています。したがって、ピアノにはノート記号が表示されます。
A0-A0♯(B0♭)-B0-C1から
C8へ。 上の図のように、黒いキーは表示されない場合があります。 黒には中間音(ミッドトーン)があります-シャープでフラットな音です。
このレイアウトに表示されている各ノートとそれらの間の各半音には、MIDIに対応するノート番号(21から108)があります。 比率は後で見られます。
ピアノの上には、2つの譜表があります(5行に2回)。 アッパー-バイオリン、高いオクターブを示し、ローワー-低音、低いを示します。 行の先頭にある波線は、それぞれ高音と低音の鍵です。 高音部記号の最初の行は、最初の(4)オクターブのMi(E)音符と、最初の低音の行(ソルト(G)音が大きい(2))を示していることに注意してください。
調性
記譜法のキーに続いて、4つのシャープが表示されます。 これが調性の鍵です。 この場合、Cシャープマイナーと呼ばれます。
この調性で正しく演奏するには、シャープが描かれた線の音の代わりに、これらの音の鋭い音(右側の次のキー)を演奏する必要があります。 ノートC、D、F、Gにシャープな部分が描かれています。調性の構成の原理については説明しません。今ではそれほど重要ではなく、ネットワーク上に多くの情報があります。 グーグルにしたい人。
したがって、ノートC1、D1、.. G7が表示された場合、それらを最も近い右のC1♯、D1♯、...G7♯に精神的に変更し、その後、MIDI番号付けで対応する番号を探します。
変更の兆候(♯、♮、♭)
これらの記号が行の先頭ではなく「ランダムな」場所にある場合は、一時的に、現在の小節の最後まで(小節が縦線で区切られている)、音符を次のように変更します。
-キーによって設定されたこのオクターブ内のこの音符の変更はキャンセルされます。 たとえば、音符C3♮および小節の最後(最も近い垂直バー)に続くすべてのC3はC3として再生されます。
-♯は音を半音上げます。 A3♯と、小節の終わりまでのすべての後続のA3は、A3♯として再生されます。
-noteは音を半音下げます。 D3♭および後続のすべてのD3は、C3♯(別名D3♭)として再生されます。
思慮深い読者は、「一時的でシャープで平坦な」場合には意味がないことにすでに気付いています。 例えば、音符C、D、F、Gのある月光ソナタのキーでは、シャープを入れたり入れなかったりできます。 これはどれも変わりません。 はい、そのような場合には二重の鋭利物がありますが、それらはこの記事の範囲外です。
期間
音符の音符は、中空または塗りつぶされた円(頭)、垂直の棒(落ち着いた)、旗を持つことができます。 これにより、ノートの相対的な長さが決まります。 私たちの場合、1つの音符全体が1拍、半音、というように続きます。 わかりやすくするために写真を用意しています。

別のニュアンスはポイントです。 音符の直後のポイントは、この音符が指定された1つ半の音を鳴らすことを意味します。 たとえば、1/8のポイントは、ビートの1/8 + 1/16 = 3/16全体で鳴ります。 アダジオを1分あたりのビートに変換しなかったので、すぐに予約します。たとえそうしても、この60-80をどうするかはあまり明確ではありません。 したがって、測定の期間は耳で選択されます。
得られた知識を使用して、次の図に従って音符を計算し、MIDIに変換します。
C2-> 37(キーのためにハーフトーンが高くなります-Cシャープマイナー)
C3-> 49
G3-> 56など。
やや不器用ですが、最初の対策の実装は機能しています:
window.onload = function () { MIDI.loadPlugin({ soundfontUrl: "./soundfont/", instrument: "acoustic_grand_piano", onprogress: function(state, progress) { console.log(state, progress); }, onsuccess: function() { play(); } }); }; function play() { var delay = 0; // play one note every quarter second var velocity = 127; // how hard the note hits var gap = 0.6; var duration = 0.4; MIDI.setVolume(0, 80); // delay += gap; MIDI.noteOn(0, 49, velocity, delay); MIDI.noteOff(0, 49, delay + 4 * gap); MIDI.noteOn(0, 37, velocity, delay); MIDI.noteOff(0, 37, delay + 4 * gap); MIDI.noteOn(0, 56, velocity, delay); MIDI.noteOff(0, 56, delay + duration); delay += gap; MIDI.noteOn(0, 61, velocity, delay); MIDI.noteOff(0, 61, delay + duration); delay += gap; MIDI.noteOn(0, 64, velocity, delay); MIDI.noteOff(0, 64, delay + duration); delay += gap; MIDI.noteOn(0, 56, velocity, delay); MIDI.noteOff(0, 56, delay + duration); delay += gap; MIDI.noteOn(0, 61, velocity, delay); MIDI.noteOff(0, 61, delay + duration); delay += gap; MIDI.noteOn(0, 64, velocity, delay); MIDI.noteOff(0, 64, delay + duration); delay += gap; MIDI.noteOn(0, 56, velocity, delay); MIDI.noteOff(0, 56, delay + duration); delay += gap; MIDI.noteOn(0, 61, velocity, delay); MIDI.noteOff(0, 61, delay + duration); delay += gap; MIDI.noteOn(0, 64, velocity, delay); MIDI.noteOff(0, 64, delay + duration); delay += gap; MIDI.noteOn(0, 56, velocity, delay); MIDI.noteOff(0, 56, delay + duration); delay += gap; MIDI.noteOn(0, 61, velocity, delay); MIDI.noteOff(0, 61, delay + duration); delay += gap; MIDI.noteOn(0, 64, velocity, delay); MIDI.noteOff(0, 64, delay + duration); }
これはほんの始まりに過ぎませんが、訓練されていない人は、調性や一時的な変化を数えるのにもう飽きているかもしれません。 そして、コードシートは長いです。 そして、これは最初のビートです。 もちろん、OOPに焦点を合わせた目は、リファクタリングのターゲットをすぐに見つけます。 同時に、音を計算するタスクをJavaScriptに簡単に転送できます。
調性について説明します。 キーはあいまいな用語です。 しかし、具体的な例では、キーは単にそのキーのノートの必要な変更です。 覚えているように、Cシャープマイナーのキーでは、C1、D1、.. G7のノートが表示され、代わりにC1♯、D1♯、...G7♯が表示されます。 これらの各音符のシフトを示しただけです(+1またはちょうど1)。 4-シャープの数。 フラットは-4として指定されます。 鑑定家は、この狭いケースでは、CシャープマイナーとEメジャーのパラレルキーに違いがないことを理解します。 同じノートで同じシャープ。
記事のコードは散らかってはいけないので、JSDocはなく、JSHintチェックなどもありませんでしたが、ロシア語に翻訳されたコメントがあります。
var keys = { 4 : { C : 1, D : 1, F : 1, G : 1 } };
次に、再生するオブジェクトを作成します。
var player = { // barDuration : 8, // timeline : 0, // velocity : 127, // key : keys[4], // tempAlts : {}, // - , , play : function(noteString, duration, moveTime) { // var noteInt = this.calcNote(noteString); MIDI.noteOn(0, noteInt, this.velocity, this.timeline); // * MIDI.noteOff(0, noteInt, this.velocity, this.timeline + this.barDuration * duration); if (typeof moveTime !== 'undefined' && moveTime === true) { this.move(duration); } }, move : function(duration) { this.timeline += this.barDuration * duration; // , . if (this.timeline % this.barDuration === 0) { this.tempAlts = {};} }, };
それでは、ノートカウントをリリースして、コードをもう少し改善しましょう。
var player = { barDuration : 8, timeline : 0, velocity : 127, key : keys[4], tempAlts : {}, play : function(noteString, duration, moveTime) { var noteInt = this.calcNote(noteString); MIDI.noteOn(0, noteInt, this.velocity, this.timeline); MIDI.noteOff(0, noteInt, this.velocity, this.timeline + this.barDuration * duration); if (typeof moveTime !== 'undefined' && moveTime === true) { this.move(duration); } }, move : function(duration) { this.timeline += this.barDuration * duration; if (this.isEndOfBar()) { this.tempAlts = {};} }, calcNote : function(noteString) { var note = noteString[0]; var noteWithOctave = noteString.substring(0,2); // var altering = this.getAltering(noteString); // , , if (altering) { this.setTempAltering(noteWithOctave, altering); } // - MIDI + if (this.tempAlts[noteWithOctave] !== undefined) { return MIDI.keyToNote[noteWithOctave] + this.tempAlts[noteWithOctave]; } // - MIDI + // return MIDI.keyToNote[noteWithOctave] + (this.key[note] !== undefined ? this.key[note] : 0); }, isEndOfBar : function() { return !!(this.timeline % this.barDuration === 0) }, // false getAltering : function(noteString) { var altering = noteString[2]; return altering !== undefined ? altering : false; }, setTempAltering : function(noteWithOctave, altering) { switch (altering) { // 1 case 'b': this.tempAlts[noteWithOctave] = -1; break; // "%" case '%': this.tempAlts[noteWithOctave] = 0; break; case '#': this.tempAlts[noteWithOctave] = 1; break; } } }
さて、楽譜自体:
player.play('C2', 1); player.play('C1', 1); player.play('G3', 1/12, true); player.play('C4', 1/12, true); player.play('E4', 1/12, true); player.play('G3', 1/12, true); player.play('C4', 1/12, true); player.play('E4', 1/12, true); player.play('G3', 1/12, true); player.play('C4', 1/12, true); player.play('E4', 1/12, true); player.play('G3', 1/12, true); player.play('C4', 1/12, true); player.play('E4', 1/12, true); ...
結果の結果はここで聞くことができ、 ここを参照してください 。 たとえば、私は19のうち7つの措置を講じました。
UPD 隠れコメントに応じてオクターブ、表記法、長さについて修正