broken-neees
Version:
A really broken NEEES emulator that introduces glitches and random bugs on purpose!
64 lines (63 loc) • 2.48 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _AudioRegisters = _interopRequireDefault(require("./AudioRegisters"));
var _FrameSequencer = _interopRequireDefault(require("./FrameSequencer"));
var _PulseChannel = _interopRequireDefault(require("./PulseChannel"));
var _TriangleChannel = _interopRequireDefault(require("./TriangleChannel"));
var _NoiseChannel = _interopRequireDefault(require("./NoiseChannel"));
var _DMCChannel = _interopRequireDefault(require("./DMCChannel"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const FREQ_APU_HZ = 894887;
const APU_SAMPLE_RATE = 44100;
const STEPS_PER_SAMPLE = Math.floor(FREQ_APU_HZ / APU_SAMPLE_RATE);
class APU {
constructor(cpu) {
this.cpu = cpu;
this.sampleCounter = 0;
this.sample = 0;
this.registers = new _AudioRegisters.default(this);
this.frameSequencer = new _FrameSequencer.default(this);
this.channels = {
pulses: [new _PulseChannel.default(this, 0, "enablePulse1"), new _PulseChannel.default(this, 1, "enablePulse2")],
triangle: new _TriangleChannel.default(this),
noise: new _NoiseChannel.default(this),
dmc: new _DMCChannel.default(this, this.cpu)
};
}
step(onSample) {
this.channels.pulses[0].step();
this.channels.pulses[1].step();
this.channels.noise.step();
this.channels.dmc.step();
this.sampleCounter++;
this.frameSequencer.step();
if (this.sampleCounter === STEPS_PER_SAMPLE) {
this.sampleCounter = 0;
const pulse1 = this.channels.pulses[0].sample();
const pulse2 = this.channels.pulses[1].sample();
const triangle = this.channels.triangle.sample();
const noise = this.channels.noise.sample();
const dmc = this.channels.dmc.sample();
const pulseOut = 0.00752 * (pulse1 + pulse2);
const tndOut = 0.00851 * triangle + 0.00494 * noise + 0.00335 * dmc;
this.sample = pulseOut + tndOut;
onSample(this.sample, pulse1, pulse2, triangle, noise, dmc);
}
}
onQuarterFrameClock() {
this.channels.pulses[0].quarterFrame();
this.channels.pulses[1].quarterFrame();
this.channels.triangle.quarterFrame();
this.channels.noise.quarterFrame();
}
onHalfFrameClock() {
this.channels.pulses[0].halfFrame();
this.channels.pulses[1].halfFrame();
this.channels.triangle.halfFrame();
this.channels.noise.halfFrame();
}
}
exports.default = APU;