diff --git a/runtimes/web/src/apu.js b/runtimes/web/src/apu.js index cc318b884..ea2827bd3 100644 --- a/runtimes/web/src/apu.js +++ b/runtimes/web/src/apu.js @@ -20,11 +20,17 @@ const NOISE_LENGTH = 0x8000; // 440.0 / 44100, // ].reverse(); +const twelvth_root_of_2 = Math.pow(2, 1/12); +function midiToFreq(pitch) { + return 440 * Math.pow(twelvth_root_of_2, (pitch / 256) - 69); +} + export class APU { constructor () { const ctx = new (window.AudioContext || window.webkitAudioContext)(); this.ctx = ctx; + this.frequency_mode = 0; this.nodes = new Array(4); this.gains = new Array(4); @@ -58,8 +64,13 @@ export class APU { } tone (frequency, duration, volume, flags) { - const freq1 = frequency & 0xffff; - const freq2 = (frequency >> 16) & 0xffff; + var freq1 = frequency & 0xffff; + var freq2 = (frequency >> 16) & 0xffff; + + if (this.frequency_mode == 1) { + freq1 = midiToFreq(freq1); + freq2 = midiToFreq(freq2); + } const sustain = (duration & 0xff) / 60; const release = ((duration >> 8) & 0xff) / 60; diff --git a/runtimes/web/src/constants.js b/runtimes/web/src/constants.js index 4e814c43a..1af898293 100644 --- a/runtimes/web/src/constants.js +++ b/runtimes/web/src/constants.js @@ -45,6 +45,7 @@ export const MOUSE_MIDDLE = 4; export const SYSTEM_PRESERVE_FRAMEBUFFER = 1; export const SYSTEM_HIDE_GAMEPAD_OVERLAY = 2; +export const SYSTEM_MIDI_FREQUENCY_MODE = 4; // Flags for Runtime.pauseState export const PAUSE_UNFOCUSED = 1; diff --git a/runtimes/web/src/runtime.js b/runtimes/web/src/runtime.js index 96c445622..d378941db 100644 --- a/runtimes/web/src/runtime.js +++ b/runtimes/web/src/runtime.js @@ -324,6 +324,7 @@ export class Runtime { if (!this.getSystemFlag(constants.SYSTEM_PRESERVE_FRAMEBUFFER)) { this.framebuffer.clear(); } + this.api.frequency_mode = this.getSystemFlag(constants.SYSTEM_MIDI_FREQUENCY_MODE) ? 1 : 0; this.safeCall(this.wasm.exports.update);