たま日記

たまに書く

導出方法を考えてみた

32個あるオペレータの出力値を決めるレジスタ(0x60~0x7f)に書き込まれる値V_{TL}は、次の式で求まる.

V_{TL} = 0 + A_{vol} + A_{alg} + A_{ol} + A_{ls} + A_{kvs} + A_{ebs}

このうち、表が巨大になったA_{ls}A_{kvs}A_{ebs}の値を導出するアルゴリズムを考えた。計測値とも一致した。

A_{ls}:Level Scalingによる減衰量
VCEDのLevel Scaling(0~99)とMIDIノート番号(0~127)が与えられた時の減衰量A_{ls}を整数部7bit+小数部1bitで返す手続きを示す。

int attLS(int ls, int note) {
    int table[] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9,11,14,16,19,23,28,33,39,47,57,67,80,95,113,134,160,190,224,255
    };
    int index = 0;
    if (note < 24) {
        index = 0;
    } else if (note <= 108) {
        index = (note-24)/3;
    } else if (note < 121) {
        index = (note-12-24)/3;
    } else {
        index = (note-24-24)/3;
    }
    return (table[index] * (ls*165/64) ) >>8;
}

A_{kvs}:Key Velocity Sensitivityによる減衰量
VCEDのKVS(0~7)とMIDIのvelocity値(0~127)が与えられた時の減衰量A_{kvs}を整数部7bit+小数部1bitで返す手続きを示す。

int attKVS(int kvs, int velocity) {
    int table[] = {
        192,180,174,168,162,158,152,148,144,141,138,134,130,128,125,122,
        119,116,114,112,109,107,105,103,101, 99, 97, 95, 93, 92, 90, 88,
         86, 85, 83, 82, 81, 79, 78, 76, 75, 74, 72, 71, 70, 68, 67, 66,
         65, 64, 63, 62, 60, 59, 58, 57, 56, 55, 54, 53, 52, 50, 49, 48,
         47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32,
         31, 30, 29, 28, 27, 26, 26, 25, 24, 23, 22, 22, 21, 20, 19, 18,
         18, 17, 16, 16, 15, 14, 14, 13, 12, 12, 11, 11, 10,  9,  9,  8,
          7,  7,  6,  6,  5,  5,  4,  4,  3,  3,  2,  2,  1,  1,  0      // [0]~[126]
    };
    return kvs == 0 ? 0 : (( kvs * table[velocity-1] + (7 - kvs)*16)>>3) +1; // +1は四捨五入のため
}

A_{ebs}:ブレスコントロールによる減衰量
VCEDのBCEG Bias(0~99)、EBS(0~7)およびMIDIのCC#2の値(0~127)が与えられた時の減衰量A_{ebs}を整数部7bit+小数部1bitで返す手続きを示す。

int attEBS(int bias, int ebs, int cc2) {
    int table[] = {
        255,255,224,205,192,181,173,166,160,154,149,145,141,137,134,130,
        128,125,122,120,117,115,113,111,109,107,105,103,102,100, 98, 97,
         96, 94, 93, 91, 90, 89, 88, 86, 85, 84, 83, 82, 81, 80, 79, 78,
         77, 76, 75, 74, 73, 72, 71, 70, 70, 69, 68, 67, 66, 66, 65, 64,
         64, 63, 62, 61, 61, 60, 59, 59, 58, 57, 57, 56, 56, 55, 54, 54,
         53, 53, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45,
         45, 44, 44, 43, 43, 42, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38,
         38, 37, 37, 36, 36, 36, 35, 35, 34, 34, 34, 33, 33, 33, 32, 32,
         32, 31, 31, 30, 30, 30, 29, 29, 29, 28, 28, 28, 27, 27, 27, 26,
         26, 26, 25, 25, 25, 24, 24, 24, 24, 23, 23, 23, 22, 22, 22, 21,
         21, 21, 21, 20, 20, 20, 19, 19, 19, 19, 18, 18, 18, 18, 17, 17,
         17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13,
         13, 13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10,  9,  9,
          9,  9,  8,  8,  8,  8,  8,  7,  7,  7,  7,  6,  6,  6,  6,  6,
          5,  5,  5,  5,  5,  4,  4,  4,  4,  4,  3,  3,  3,  3,  3,  2,
          2,  2,  2,  2,  2,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0
    };
    int b3[] = { 0, 37, 73, 110, 146, 183, 219, 255 };
    int index1 = bias * 165 / 64;
    int index2 = index1 - index1 * cc2 / 128;
    int index3 = index2 * b3[ebs] / 256;
    int index = 255 - index3;
    return table[index];
}

ひと月ほどかけてExcelであっちを増やしこっちを減らししながら法則を見つけていった。最後はシンプルな式になるのが面白かった。