SSブログ

Digisparkで音楽演奏【楽譜編】 [JavaScript]

kewpie3score.jpg
以前につくった notes.h ですが、やっぱり楽譜から入力しづらい。大文字が多いこととアンダーバー('_')が入力しにくさの原因ではないかと考えました。
もうちょっと楽譜から入力しやすいようにしました。
変更点としては、小文字メインで、半音上がるシャープ(♯)がつくのを大文字にするのと、長さを数字ではなく英語での頭文字の小文字としました。
以下、再度楽譜のマイルール。

【マイコンで処理しやすい楽譜・音符情報を作ります。】
  • 音の高さ(音高、ピッチ)は、周波数(Hz)等ではなく、音階とオクターブで表す
  • 音の長さ(音価)は基準の最小音符の何倍かで表す
  • 一音で2byte(16bit)使用する
    • 上位8bitが音の高さ(音高)
      • 0xooの時は休符
      • 上位4ビットがオクターブ
        • 0-9まで
      • 次の4ビットが音階・スケール(ド~シの12音階で0-11)
        • 音名は、英語でCDEFGAB
        • 入力簡便化のため小文字とし、半音上げる際は大文字を使用
          • 'c','C','d','D','e','f','F','g','G','a','A','b'
        • 半音下げるのは、一音下げてから半音あげる対応で   
      • MIDIノート番号でいうとNo.13(C#0)~127(G9)まで網羅
      • C0は休符用に使用, A9, A#9, B9はMIDI番号にもないため除く
      • 音階とオクターブを分けることで12個の基本音階情報からシフト演算を用いて容易に算出できる
    • 下位8ビットが音の長さ(音価)
      • 96分音符を最小単位の1とする
        • 1-255までに各種音符の長さを入れるとすると32分音符(3)から倍全音符(192)まで入れることができる
        • 3連符には対応できるよう通常の音符は3の倍数
      • 音符の長さの表記は、英語訳の頭文字
        • 32分音符 thirty-second note
        • 16分音符 sixteenth note
        • 8分音符 eighth note
        • 4分音符 quarter note
        • 2分音符 half note
        • 全音符 whole note (breve)
        • 倍全音符 double whole note (longa)
        • 4倍全音符 4x whole note (maxima)
      • 入力簡便化のため小文字を使用する
      • 付点音符はさらに'd' (dotted) を付ける
      • 3連符用に三分の一の長さ(one third)には't'を付ける
        • 本来は3連符は3等分する前の音符の半分の長さの音符で書かれる   
      • タイによる音符の結合は、休符(長さ情報のみでできている)を加算することで可能
  • 楽譜としては、音符となるunsigned int(2byte)の情報を配列に羅列する
    • 先頭は、テンポ(♩=1~65535)を入れて、次に0で区切る
    • 1トラック内に和音は置けないため、必要な和音の分だけトラックを使用する
    • 各トラック内の終わりは0とし、つづけて次のトラック情報に入る
    • すべてのトラック情報のあとにさらに0を入れて楽譜データ終了とする

【楽譜定義のヘッダーファイルを作るjavascript】

前回はエクセルでしこしこ作りましたが、今回は修正もしやすいようにjavascriptを使用。
以下を「note2.html」として保存してブラウザで開く。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Musical notes 2</title>
<script>
// *** twelve-tone scale ***
//   capital letter : raise a semitone. (e.g. C means C#)
const twelveTone = ['c','C','d','D','e','f','F','g','G','a','A','b'];

// *** note value (sound length) ***
const noteValue  = [
  { note: 't' , value:   3 },   // thirty-second note
  { note: 's' , value:   6 },   // sixteenth note
  { note: 'e' , value:  12 },   // eighth note
  { note: 'q' , value:  24 },   // quarter note
  { note: 'h' , value:  48 },   // half note
  { note: 'w' , value:  96 },   // whole note (breve)
  { note: 'd' , value: 192 },   // double whole note (longa)

  { note: 'sd', value:   9 },   // dotted sixteenth note
  { note: 'ed', value:  18 },   // dotted eighth note
  { note: 'qd', value:  36 },   // dotted quarter note
  { note: 'hd', value:  72 },   // dotted half note
  { note: 'wd', value: 144 },   // dotted whole note (breve)

  { note: 'tt', value:   1 },   // 1/3 of a 32nd note
  { note: 'st', value:   2 },   // 1/3 of a 16th note
  { note: 'et', value:   4 },   // 1/3 of an eighth note
  { note: 'qt', value:   8 },   // 1/3 of a quarter note
  { note: 'ht', value:  16 },   // 1/3 of a half note
  { note: 'wt', value:  32 },   // 1/3 of a whole note (breve)
  { note: 'dt', value:  64 },   // 1/3 of a double whole note (longa)
  { note: 'mt', value: 128 },   // 1/3 of a 4x whole note (maxima)
 ];

$ = function(id) { return document.getElementById(id); }

function notes() {
    let  octave, scale;
    $('main').value  = $('explanation').value;
    $('main').value += '#define MIN_NOTE  96    // 96th note (reference note)\n';
    $('main').value += '\n// Rests of various lengths (rests are just Length, so it is also for connection by Tie)\n';
    for( let nv of noteValue ) $('main').value += '#define RS' + (nv.note + '   ').slice(0,2)  + "   "  + ('   ' + nv.value).slice(-3) + '\n';
    $('main').value += '\n// combination of pitch and length\n';
    for( octave = 0; octave < 10; octave++ ) {
        for( scale = 0; scale < 12; scale++ ) {
            if( octave == 0 && scale == 0) continue;
            if( octave == 9 && scale >  8) continue;
            for( let nv of noteValue ) {
                $('main').value += '#define ' + twelveTone[scale] + octave +  (nv.note + '  ').slice(0,2)
                                +  '   (0x' + octave + scale.toString(16) + '00 | ' +  ('   ' + nv.value).slice(-3) + ')\n';
            }
        }
    }
    $('main').style.display  = 'block';
    $('dlBtn').style.display = 'inline';
}

function downloadText(fileName) {
  const blob = new Blob([$('main').value], { type: 'text/plain' });
  const aTag = document.createElement('a');
  aTag.href = URL.createObjectURL(blob);
  aTag.target = '_blank';
  aTag.download = fileName;
  aTag.click();
  URL.revokeObjectURL(aTag.href);
}
</script>
</head>
<body>
<h1>Musical notes 2</h1>
<p>Creates musical score and note information that is easy to process with a microcomputer.
<p>
<button onClick="notes()">Create a note definition data</button>
<button onClick="downloadText('note2.h')" style="display:none;" id="dlBtn">Download the header file</button>
<p>
<textarea id="explanation" disabled style="display:none;">
// ****************************************************************
//  notes2.h
// ****************************************************************
//   upper 8 bits   : pitch of a sound (0x00 : rest)
//     upper 4 bits : octaves  [0-9]
//     next  4 bits : 12 tone scale (C,C#,D,D#,E,F,F#,G,G#,A,A#,B)
//                      ['c','C','d','D','e','f','F','g','G','a','A','b']
//   lower 8 bits   : length of the sound 
//                      Let the 96th note be 1
//                      't'  =   3   thirty-second note
//                      's'  =   6   sixteenth note
//                      'e'  =  12   eighth note
//                      'q'  =  24   quarter note
//                      'h'  =  48   half note
//                      'w'  =  96   whole note (breve)
//                      'd'  = 192   double whole note (longa)
//                      'sd' =   9   dotted sixteenth note
//                      'ed' =  18   dotted eighth note
//                      'qd' =  36   dotted quarter note
//                      'hd' =  72   dotted half note
//                      'wd' = 144   dotted whole note (breve)
//                      'tt' =   1   1/3 of a 32nd note
//                      'st' =   2   1/3 of a 16th note
//                      'et' =   4   1/3 of an eighth note
//                      'qt' =   8   1/3 of a quarter note
//                      'ht' =  16   1/3 of a half note
//                      'wt' =  32   1/3 of a whole note (breve)
//                      'dt' =  64   1/3 of a double whole note (longa)
//                      'mt' = 128   1/3 of a 4x whole note (maxima)
// ****************************************************************

</textarea>
<textarea id="main" style="display:none; width:90%; height: calc( 1.2em * 25 );  line-height: 1.2;"></textarea>
</body>
</html>

再生のスケッチは後日。
nice!(0)  コメント(0) 

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。