Skip to content

Commit

Permalink
added simple sound output
Browse files Browse the repository at this point in the history
  • Loading branch information
y0014984 committed Jan 15, 2025
1 parent 79c0429 commit 1e0a2e0
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 1 deletion.
Binary file modified src/assets/games/snake.prg
Binary file not shown.
8 changes: 8 additions & 0 deletions src/logic/Computer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Processor from './Processor';
import Graphics from './Graphics';
import Sound from './Sound';
import Memory from './Memory';
import { Storage, File, Directory, Program } from './Storage';
import biosUrl from '../assets/roms/bios.prg?url';
Expand Down Expand Up @@ -32,6 +33,7 @@ export class Computer {
status: Status = Status.OFF;
cpu: Processor;
gfx: Graphics;
snd: Sound;
mem: Memory;
stor: Storage;
domUpdateInstructionsInterval: number = 2_500; // adjust this for fps
Expand All @@ -55,6 +57,10 @@ export class Computer {
if (!this.gfx) return;
this.gfx.checkMemWrite(index);
},
index => {
if (!this.snd) return;
this.snd.checkMemWrite(index);
},
index => {
if (!this.stor) return;
this.stor.checkMemWrite(index);
Expand All @@ -63,6 +69,8 @@ export class Computer {

this.gfx = new Graphics(monitorWidth, monitorHeight, this.mem);

this.snd = new Sound(this.mem);

this.cpu = new Processor(this.mem);

this.stor = new Storage(this.mem);
Expand Down
14 changes: 13 additions & 1 deletion src/logic/Memory.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
export default class Memory {
int: number[];
private onChangeGfx: (index: number) => void;
private onChangeSnd: (index: number) => void;
private onChangeStor: (index: number) => void;

constructor(size: number = 65536, callbackGfx: (index: number) => void, callbackStor: (index: number) => void) {
constructor(
size: number = 65536,
callbackGfx: (index: number) => void,
callbackSnd: (index: number) => void,
callbackStor: (index: number) => void
) {
this.onChangeGfx = callbackGfx;
this.onChangeSnd = callbackSnd;
this.onChangeStor = callbackStor;

this.int = [];
Expand All @@ -26,6 +33,7 @@ export default class Memory {
this.int[index] = value;

this.onChangeGfx(index);
this.onChangeSnd(index);
this.onChangeStor(index);
}

Expand All @@ -38,6 +46,7 @@ export default class Memory {
this.int[index] = isNaN(value) ? 0 : value;

this.onChangeGfx(index);
this.onChangeSnd(index);
this.onChangeStor(index);
}

Expand All @@ -57,6 +66,7 @@ export default class Memory {
}

this.onChangeGfx(index);
this.onChangeSnd(index);
this.onChangeStor(index);
}

Expand All @@ -65,6 +75,7 @@ export default class Memory {
if (this.int[index] > 255) this.int[index] = this.int[index] % 256;

this.onChangeGfx(index);
this.onChangeSnd(index);
this.onChangeStor(index);
}

Expand All @@ -73,6 +84,7 @@ export default class Memory {
if (this.int[index] < 0) this.int[index] = 256 + this.int[index]; // this.int is negative

this.onChangeGfx(index);
this.onChangeSnd(index);
this.onChangeStor(index);
}

Expand Down
82 changes: 82 additions & 0 deletions src/logic/Sound.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import Memory from './Memory';

const registerWaveformDuration = 0x0224;
const registerStartStopFrequency = 0x0225; // Word

export default class Sound {
private mem: Memory;
private duration: number = 0;
private frequency: number = 0;
private waveform: OscillatorType = 'sine';

constructor(mem: Memory) {
this.mem = mem;

this.init();
}

init() {
this.updateWaveformDuration();

this.updateStartStopFrequency(0);
}

start() {
const ctx = new AudioContext();
const osc = ctx.createOscillator();
osc.type = this.waveform;
osc.frequency.value = this.frequency;
osc.connect(ctx.destination);
osc.start();

const classSound = this;
// Beep for 500 milliseconds
setTimeout(function () {
osc.stop();
classSound.mem.setInt(registerStartStopFrequency + 1, classSound.mem.int[registerStartStopFrequency + 1] & 0b01111111);
}, this.duration); // Duration in ms
}

checkMemWrite(index: number) {
if (index === registerWaveformDuration) this.updateWaveformDuration();
if (index === registerStartStopFrequency || index === registerStartStopFrequency + 1) this.updateStartStopFrequency(index);
}

updateWaveformDuration() {
// registerWaveformDuration
// [2 Bits Waveform | 6 Bits Duration *10 in ms]
let waveform: OscillatorType;
switch ((this.mem.int[registerWaveformDuration] & 0b11000000) >> 6) {
case 0:
waveform = 'sine';
break;
case 1:
waveform = 'square';
break;
case 2:
waveform = 'sawtooth';
break;
case 3:
waveform = 'triangle';
break;

default:
waveform = 'sine';
break;
}

this.waveform = waveform;

this.duration = (this.mem.int[registerWaveformDuration] & 0b00111111) * 10;
}

updateStartStopFrequency(index: number) {

Check failure on line 73 in src/logic/Sound.ts

View workflow job for this annotation

GitHub Actions / deploy

'index' is declared but its value is never read.
// registerStartStopFrequency
// [1 Bit Start/Stop | 7 Bits Frequency]
this.frequency = ((this.mem.int[registerStartStopFrequency + 1] & 0b01111111) << 8) | this.mem.int[registerStartStopFrequency];

if ((this.mem.int[registerStartStopFrequency + 1] & 0b10000000) >> 7 === 1) {
this.start();
}
}
}

0 comments on commit 1e0a2e0

Please sign in to comment.