1 module pxtone.pulse.frequency; 2 3 enum _OCTAVE_NUM = 16; // octave num. 4 enum _KEY_PER_OCTAVE = 12; // key per octave 5 enum _FREQUENCY_PER_KEY = 0x10; // sample per key 6 7 enum _BASIC_FREQUENCY_INDEX = ((_OCTAVE_NUM / 2) * _KEY_PER_OCTAVE * _FREQUENCY_PER_KEY); 8 enum _TABLE_SIZE = (_OCTAVE_NUM * _KEY_PER_OCTAVE * _FREQUENCY_PER_KEY); 9 10 struct pxtnPulse_Frequency { 11 static immutable float[] _freq_table = genTables(); 12 13 float Get(int key) const nothrow @safe { 14 int i; 15 16 i = (key + 0x6000) * _FREQUENCY_PER_KEY / 0x100; 17 if (i < 0) { 18 i = 0; 19 } else if (i >= _TABLE_SIZE) { 20 i = _TABLE_SIZE - 1; 21 } 22 return _freq_table[i]; 23 } 24 25 float Get2(int key) nothrow @safe { 26 int i = key >> 4; 27 if (i < 0) { 28 i = 0; 29 } else if (i >= _TABLE_SIZE) { 30 i = _TABLE_SIZE - 1; 31 } 32 return _freq_table[i]; 33 } 34 35 const(float)[] GetDirect(int* p_size) nothrow @safe { 36 *p_size = _TABLE_SIZE; 37 return _freq_table; 38 } 39 } 40 41 private double _GetDivideOctaveRate(int divi) nothrow @safe { 42 double parameter = 1.0; 43 double work; 44 double result; 45 double add; 46 int i, j, k; 47 48 // double is 17keta. 49 for (i = 0; i < 17; i++) { 50 // make add. 51 add = 1; 52 for (j = 0; j < i; j++) { 53 add = add * 0.1; 54 } 55 56 // check 0 .. 9 57 for (j = 0; j < 10; j++) { 58 work = parameter + add * j; 59 60 // divide 61 result = 1.0; 62 for (k = 0; k < divi; k++) { 63 result *= work; 64 if (result >= 2.0) { 65 break; 66 } 67 } 68 69 // under '2' 70 if (k != divi) { 71 break; 72 } 73 } 74 // before '2' 75 parameter += add * (j - 1); 76 } 77 78 return parameter; 79 } 80 private float[] genTables() @safe { 81 float[] _freq_table; 82 static immutable double[_OCTAVE_NUM] oct_table = [0.00390625, //0 -8 83 0.0078125, //1 -7 84 0.015625, //2 -6 85 0.03125, //3 -5 86 0.0625, //4 -4 87 0.125, //5 -3 88 0.25, //6 -2 89 0.5, //7 -1 90 1, //8 91 2, //9 1 92 4, //a 2 93 8, //b 3 94 16, //c 4 95 32, //d 5 96 64, //e 6 97 128, //f 7 98 ]; 99 100 int key; 101 int f; 102 double oct_x24; 103 double work; 104 105 _freq_table = new float[_TABLE_SIZE]; 106 //if (!(_freq_table)) { 107 // goto End; 108 //} 109 110 oct_x24 = _GetDivideOctaveRate(_KEY_PER_OCTAVE * _FREQUENCY_PER_KEY); 111 112 for (f = 0; f < _OCTAVE_NUM * (_KEY_PER_OCTAVE * _FREQUENCY_PER_KEY); f++) { 113 work = oct_table[f / (_KEY_PER_OCTAVE * _FREQUENCY_PER_KEY)]; 114 for (key = 0; key < f % (_KEY_PER_OCTAVE * _FREQUENCY_PER_KEY); key++) { 115 work *= oct_x24; 116 } 117 _freq_table[f] = cast(float) work; 118 } 119 return _freq_table; 120 }