2
0
Fork 0

Start porting DBOPL to Javascript

This commit is contained in:
bruce 2013-10-20 00:28:53 +08:00
parent 6952e7faf7
commit c395d44728

177
js/dbopl.js Normal file
View 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