Start porting DBOPL to Javascript
This commit is contained in:
parent
6952e7faf7
commit
c395d44728
1 changed files with 177 additions and 0 deletions
177
js/dbopl.js
Normal file
177
js/dbopl.js
Normal file
|
@ -0,0 +1,177 @@
|
|||
var DBOPL = new function() { // DBOPL namespace
|
||||
|
||||
// dbopl.h
|
||||
|
||||
this.WAVE_HANDLER = 10;
|
||||
this.WAVE_TABLELOG = 11;
|
||||
this.WAVE_TABLEMUL = 12;
|
||||
this.DBOPL_WAVE = this.WAVE_TABLEMUL;
|
||||
|
||||
this.SynthMode = {
|
||||
sm2AM:0,
|
||||
sm2FM:1,
|
||||
sm3AM:2,
|
||||
sm3FM:3,
|
||||
sm4Start:4,
|
||||
sm3FMFM:5,
|
||||
sm3AMFM:6,
|
||||
sm3FMAM:7,
|
||||
sm3AMAM:8,
|
||||
sm6Start:9,
|
||||
sm2Percussion:10,
|
||||
sm3Percussion:11,
|
||||
};
|
||||
|
||||
this.SHIFT_KSLBASE = 16;
|
||||
this.SHIFT_KEYCODE = 24;
|
||||
|
||||
this.Operator = function() {
|
||||
// public:
|
||||
|
||||
// enum
|
||||
this.MASK_KSR = 0x10;
|
||||
this.MASK_SUSTAIN = 0x20;
|
||||
this.MASK_VIBRATO = 0x40;
|
||||
this.MASK_TREMOLO = 0x80;
|
||||
this.State = { // typedef enum
|
||||
OFF:0,
|
||||
RELEASE:1,
|
||||
SUSTAIN:2,
|
||||
DECAY:3,
|
||||
ATTACK:4,
|
||||
};
|
||||
this.volHandler=0;
|
||||
this.waveBase=0;
|
||||
this.waveMask=0;
|
||||
this.waveStart=0;
|
||||
|
||||
this.waveIndex=0; //WAVE_BITS shifted counter of the frequency index
|
||||
this.waveAdd=0; //The base frequency without vibrato
|
||||
this.waveCurrent=0; //waveAdd + vibratao
|
||||
|
||||
this.chanData=0; //Frequency/octave and derived data coming from whatever channel controls this
|
||||
this.freqMul=0; //Scale channel frequency with this, TODO maybe remove?
|
||||
this.vibrato=0; //Scaled up vibrato strength
|
||||
this.sustainLevel=0; //When stopping at sustain level stop here
|
||||
this.totalLevel=0; //totalLevel is added to every generated volume
|
||||
this.currentLevel=0; //totalLevel + tremolo
|
||||
this.volume=0; //The currently active volume
|
||||
|
||||
this.attackAdd=0; //Timers for the different states of the envelope
|
||||
this.decayAdd=0;
|
||||
this.releaseAdd=0;
|
||||
this.rateIndex=0; //Current position of the evenlope
|
||||
|
||||
this.rateZero=0; //Bits for the different states of the envelope having no changes
|
||||
this.keyOn=0; //Bitmask of different values that can generate keyon
|
||||
//Registers, also used to check for changes
|
||||
this.reg20=0;
|
||||
this.reg40=0;
|
||||
this.reg60=0;
|
||||
this.reg80=0;
|
||||
this.regE0=0;
|
||||
//Active part of the envelope we're in
|
||||
this.state=0;
|
||||
//0xff when tremolo is enabled
|
||||
this.tremoloMask=0;
|
||||
//Strength of the vibrato
|
||||
this.vibStrength=0;
|
||||
//Keep track of the calculated KSR so we can check for changes
|
||||
this.ksr=0;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// dbopl.cpp (private stuff)
|
||||
var ZeroArray = function(size) {
|
||||
// http://stackoverflow.com/questions/1295584/most-efficient-way-to-create-a-zero-filled-javascript-array
|
||||
return Array.apply(null, new Array(size)).map(Number.prototype.valueOf,0);
|
||||
};
|
||||
|
||||
var PI = 3.14159265358979323846;
|
||||
var OPLRATE = 14318180.0 / 288.0;
|
||||
var TREMOLO_TABLE = 52;
|
||||
var WAVE_BITS = 10;
|
||||
var WAVE_SH = 32 - WAVE_BITS;
|
||||
var WAVE_MASK = (1 << WAVE_SH) - 1;
|
||||
var LFO_SH = WAVE_SH - 10;
|
||||
var LFO_MAX = 256 << LFO_SH;
|
||||
var ENV_BITS = 9;
|
||||
var ENV_MIN = 0;
|
||||
var ENV_EXTRA = ENV_BITS - 9;
|
||||
var ENV_MAX = 511 << ENV_EXTRA;
|
||||
var ENV_LIMIT = (12 * 256) >> (3 - ENV_EXTRA);
|
||||
var ENV_SILENT = function(_X_) { return _X_ >= ENV_LIMIT; }
|
||||
var RATE_SH = 24;
|
||||
var RATE_MASK = (1 << RATE_SH ) - 1;
|
||||
var MUL_SH = 16;
|
||||
|
||||
var KslCreateTable = [
|
||||
64, 32, 24, 19,
|
||||
16, 12, 11, 10,
|
||||
8, 6, 5, 4,
|
||||
3, 2, 1, 0,
|
||||
];
|
||||
var M = function(_X_) {return _X_ * 2};
|
||||
var FreqCreateTable = [
|
||||
M(0.5), M(1), M(2), M(3), M(4), M(5), M(6), M(7),
|
||||
M(8), M(9), M(10), M(10), M(12), M(12), M(15), M(15),
|
||||
];
|
||||
|
||||
var AttackSamplesTable = [
|
||||
69, 55, 46, 40,
|
||||
35, 29, 23, 20,
|
||||
19, 15, 11, 10,
|
||||
9
|
||||
];
|
||||
var EnvelopeIncreaseTable = [
|
||||
4, 5, 6, 7,
|
||||
8, 10, 12, 14,
|
||||
16, 20, 24, 28,
|
||||
32,
|
||||
];
|
||||
|
||||
var WaveTable = ZeroArray(8 * 512);
|
||||
|
||||
var WaveBaseTable = [
|
||||
0x000, 0x200, 0x200, 0x800,
|
||||
0xa00, 0xc00, 0x100, 0x400,
|
||||
];
|
||||
|
||||
var WaveMaskTable = [
|
||||
1023, 1023, 511, 511,
|
||||
1023, 1023, 512, 1023,
|
||||
];
|
||||
|
||||
var WaveStartTable = [
|
||||
512, 0, 0, 0,
|
||||
0, 512, 512, 256,
|
||||
];
|
||||
|
||||
var MulTable = ZeroArray(384);
|
||||
var KslTable = ZeroArray(8 * 16);
|
||||
var TremoloTable = ZeroArray(TREMOLO_TABLE);
|
||||
var ChanOffsetTable = ZeroArray(32);
|
||||
var OpOffsetTable = ZeroArray(64);
|
||||
var VibratoTable = [
|
||||
1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00,
|
||||
1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80
|
||||
];
|
||||
|
||||
// Note: the original used reference parameters to return index and shift..
|
||||
function EnvelopeSelect(val) {
|
||||
var shift, index;
|
||||
if ( val < 13 * 4 ) { //Rate 0 - 12
|
||||
shift = 12 - ( val >> 2 );
|
||||
index = val & 3;
|
||||
} else if ( val < 15 * 4 ) { //rate 13 - 14
|
||||
shift = 0;
|
||||
index = val - 12 * 4;
|
||||
} else { //rate 15 and up
|
||||
shift = 0;
|
||||
index = 12;
|
||||
}
|
||||
return [index, shift];
|
||||
}
|
||||
|
||||
}; // end of DBOPL namespace
|
Loading…
Reference in a new issue