UNPKG

vgm-conv

Version:
152 lines (151 loc) 5.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.YM2612ToYM2413Converter = void 0; const opn_to_ym2413_converter_1 = require("./opn-to-ym2413-converter"); const vgm_parser_1 = require("vgm-parser"); const ym2413_dac_table_1 = require("./ym2413-dac-table"); class YM2612ToYM2413Converter extends opn_to_ym2413_converter_1.OPNToYM2413Converter { rootPcmChannel = 6; _dacEmulation = "fmpcm"; constructor(from, to, opts) { super(from, { chip: "ym2413", index: from.index, clock: 1 / 2, relativeClock: true }, opts); this._dacEmulation = this.opts.dacEmulation || this.opts.voiceTable?.opn2opll?.dacEmulation || this._dacEmulation; } getInitialCommands() { if (this._dacEmulation === "test") { // select FM 9-ch mode this._y(14, 0); this._y(15, 4); // Set saw wave to user-defined voice. this._y(1, 0x2c); this._y(0, 0x2c); this._y(2, 0x28); this._y(3, 0x07); this._y(4, 0xf0); this._y(5, 0xf0); this._y(6, 0x0f); this._y(7, 0x0f); this._y(48 + this.rootPcmChannel, 0, false); this._y(49 + this.rootPcmChannel, 0, false); this._y(50 + this.rootPcmChannel, 0, false); this._y(32 + this.rootPcmChannel, 0x1e, false); this._y(33 + this.rootPcmChannel, 0x1e, false); this._y(34 + this.rootPcmChannel, 0x1e, false); return this._buf.commit(); } else if (this._dacEmulation === "fmpcm") { // select FM 9-ch mode this._y(14, 0); // make sure all channels key-off this._y(37, 0, false); this._y(38, 0, false); this._y(39, 0, false); this._y(40, 0, false); // select violin tone whose modulator AR is 15. this._y(53, (1 << 4) | 15, false); this._y(54, (1 << 4) | 15, false); this._y(55, (1 << 4) | 15, false); this._y(56, (1 << 4) | 15, false); // set f-number fnum=1 is the most accurate but need longer wait time. const fnum = 32; this._y(21, fnum, false); this._y(22, fnum, false); this._y(23, fnum, false); this._y(24, fnum, false); // start phase generator this._y(37, 16, false); this._y(38, 16, false); this._y(39, 16, false); this._y(40, 16, false); const goalClock = this.to.relativeClock ? (this.from.clock * this.to.clock) : (this.to.clock || 3579545); // wait until 1/4 cycle of phase generator const freq = (fnum * goalClock) / 72 / (1 << 19); const cycleInSeconds = 1.0 / freq; const nnnn = Math.round(44100 * (cycleInSeconds / 4)); this._buf.push(new vgm_parser_1.VGMWaitWordCommand({ count: nnnn }), false); // stop phase generator this._y(21, 0, false); this._y(22, 0, false); this._y(23, 0, false); this._y(24, 0, false); return this._buf.commit(); } else { return super.getInitialCommands(); } } _pcmData = new Uint8Array(); _pcmIndex = 0; convert2A(cmd) { const v = this._pcmData[this._pcmIndex]; this._pcmIndex++; if (this.opts.decimation <= 1 || this._div % this.opts.decimation == 0) { if (this._dacEmulation === "test") { const vv = 47 + Math.round((208 * v) / 255); this._y(16 + this.rootPcmChannel, vv, false); this._y(17 + this.rootPcmChannel, vv, false); this._y(18 + this.rootPcmChannel, vv, false); } else if (this._dacEmulation === "fmpcm") { const idx = Math.min(768, v * 4) & 0x3f8; const vs = ym2413_dac_table_1.YM2413DACTable[idx]; for (let i = 0; i < 3; i++) { this._y(56 - i, (8 << 4) | vs[2 - i], false); } } } if (1 <= cmd.count) { this._buf.push(new vgm_parser_1.VGMWaitNibbleCommand({ count: cmd.count })); } this._div++; return this._buf.commit(); } convertSeekPCM(cmd) { this._pcmIndex = cmd.offset; return []; } convertDataBlock(cmd) { if (cmd.chip === "ym2612") { this._pcmData = cmd.blockData; return []; } return [cmd]; } convertCommand(cmd) { const convertFM = this.from.subModule == null || this.from.subModule === "fm"; const convertDAC = this.from.subModule == null || this.from.subModule === "dac"; if (cmd instanceof vgm_parser_1.VGMWriteDataCommand && cmd.chip === "ym2612" && cmd.index === this.from.index) { if (convertFM) { if (this.from.subModule == "fm" && cmd.addr == 0x2b) { return [cmd]; } if (this._dacEmulation != "test") { return this.convertFM(cmd); } return []; } } else if (cmd instanceof vgm_parser_1.VGMDataBlockCommand && cmd.chip === "ym2612") { if (convertDAC) { return this.convertDataBlock(cmd); } } else if (cmd instanceof vgm_parser_1.VGMWrite2ACommand) { if (convertDAC) { return this.convert2A(cmd); } } else if (cmd instanceof vgm_parser_1.VGMSeekPCMCommand) { if (convertDAC) { return this.convertSeekPCM(cmd); } } else { return super.convertCommand(cmd); } return [cmd]; } } exports.YM2612ToYM2413Converter = YM2612ToYM2413Converter;