Emulate PC speaker beep sounds

This commit is contained in:
Ernest Wong 2017-11-15 15:10:23 +13:00 committed by Fabian
parent 818a6c211f
commit eb736ab406
6 changed files with 86 additions and 4 deletions

View file

@ -79,7 +79,7 @@ CORE_FILES=const.js config.js io.js main.js lib.js fpu.js ide.js pci.js floppy.j
elf.js
LIB_FILES=9p.js filesystem.js jor1k.js marshall.js utf8.js
BROWSER_FILES=screen.js \
keyboard.js mouse.js serial.js \
keyboard.js mouse.js speaker.js serial.js \
network.js lib.js starter.js worker_bus.js dummy_screen.js
CORE_FILES:=$(addprefix src/,$(CORE_FILES))

View file

@ -10,7 +10,7 @@
"memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js acpi.js apic.js ioapic.js hpet.js " +
"ne2k.js state.js virtio.js bus.js elf.js";
var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js serial.js lib.js network.js starter.js worker_bus.js";
var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js speaker.js serial.js lib.js network.js starter.js worker_bus.js";
//var LIB_FILES = "esprima.js walk.js";
var LIB_FILES = "";

67
src/browser/speaker.js Executable file
View file

@ -0,0 +1,67 @@
"use strict";
/**
* @constructor
* @param {BusConnector} bus
* @suppress {deprecated}
*/
function SpeakerAdapter(bus)
{
if (typeof window === "undefined")
{
return;
}
/** @const @type {BusConnector} */
this.bus = bus;
this.audio_context = new (window.AudioContext || window.webkitAudioContext)();
this.beep_gain = this.audio_context.createGain();
this.beep_gain.gain.value = 0;
this.beep_gain.connect(this.audio_context.destination);
this.beep_oscillator = this.audio_context.createOscillator();
this.beep_oscillator.type = 'square';
this.beep_oscillator.frequency.value = 440;
this.beep_oscillator.connect(this.beep_gain);
this.beep_oscillator.start();
this.beep_playing = false;
this.beep_enable = false;
this.beep_frequency = 440;
this.pit_enabled = false;
bus.register("pcspeaker-enable", function(yesplease)
{
this.beep_enable = yesplease;
this.beep_update();
}, this);
bus.register("pcspeaker-update", function(pit)
{
this.pit_enabled = pit.counter_mode[2] == 3;
this.beep_frequency = OSCILLATOR_FREQ * 1000 / pit.counter_reload[2];
this.beep_update();
}, this);
}
SpeakerAdapter.prototype.beep_update = function()
{
var current_time = this.audio_context.currentTime;
if(this.pit_enabled && this.beep_enable)
{
this.beep_oscillator.frequency.setValueAtTime(this.beep_frequency, current_time);
if(!this.beep_playing)
{
this.beep_gain.gain.setValueAtTime(1, current_time);
this.beep_playing = true;
}
}
else if(this.beep_playing)
{
this.beep_gain.gain.setValueAtTime(0, current_time);
this.beep_playing = false;
}
}

View file

@ -151,6 +151,11 @@ function V86Starter(options)
this.serial_adapter = new SerialAdapter(options["serial_container"], adapter_bus);
}
if(!options["disable_speaker"])
{
this.speaker_adapter = new SpeakerAdapter(adapter_bus);
}
// ugly, but required for closure compiler compilation
function put_on_settings(name, buffer)
{

View file

@ -736,7 +736,7 @@ CPU.prototype.init = function(settings, device_bus)
this.devices.hdb = new IDEDevice(this, settings.hdb, false, ide_device_count++, device_bus);
}
this.devices.pit = new PIT(this);
this.devices.pit = new PIT(this, device_bus);
if(settings.enable_ne2k)
{

View file

@ -11,11 +11,13 @@ var OSCILLATOR_FREQ = 1193.1816666; // 1.193182 MHz
*
* Programmable Interval Timer
*/
function PIT(cpu)
function PIT(cpu, bus)
{
/** @const @type {CPU} */
this.cpu = cpu;
this.bus = bus;
this.counter_start_time = new Float64Array(3);
this.counter_start_value = new Uint16Array(3);
@ -42,6 +44,10 @@ function PIT(cpu)
return ref_toggle << 4 | counter2_out << 5;
});
cpu.io.register_write(0x61, this, function(data)
{
this.bus.send("pcspeaker-enable", data & 1);
});
cpu.io.register_read(0x40, this, function() { return this.counter_read(0); });
cpu.io.register_read(0x41, this, function() { return this.counter_read(1); });
@ -228,6 +234,8 @@ PIT.prototype.counter_write = function(i, value)
{
this.counter_next_low[i] ^= 1;
}
this.bus.send("pcspeaker-update", this);
};
PIT.prototype.port43_write = function(reg_byte)
@ -303,4 +311,6 @@ PIT.prototype.port43_write = function(reg_byte)
this.counter_mode[i] = mode;
this.counter_read_mode[i] = read_mode;
this.bus.send("pcspeaker-update", this);
};