adding sound emulation in browser
This commit is contained in:
parent
a751be2e97
commit
d323995196
@ -332,13 +332,69 @@ namespace ks.rt.micro_bit {
|
||||
export function servoSetPulse(pin: Pin, micros:number) {
|
||||
}
|
||||
|
||||
module AudioContextManager {
|
||||
var _context : any; // AudioContext
|
||||
var _vco : any; //OscillatorNode;
|
||||
var _vca: any; // GainNode;
|
||||
|
||||
function context() : any {
|
||||
if (!_context) _context = freshContext();
|
||||
return _context;
|
||||
}
|
||||
|
||||
function freshContext() : any {
|
||||
(<any>window).AudioContext = (<any>window).AudioContext || (<any>window).webkitAudioContext;
|
||||
if ((<any>window).AudioContext) {
|
||||
try {
|
||||
// this call my crash.
|
||||
// SyntaxError: audio resources unavailable for AudioContext construction
|
||||
return new (<any>window).AudioContext();
|
||||
} catch(e) {}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function stop() {
|
||||
if (_vca) _vca.gain.value = 0;
|
||||
}
|
||||
|
||||
export function tone(frequency: number, gain: number) {
|
||||
if (frequency <= 0) return;
|
||||
var ctx = context();
|
||||
if (!ctx) return;
|
||||
|
||||
gain = Math.max(0, Math.min(1, gain));
|
||||
if (!_vco) {
|
||||
try {
|
||||
_vco = ctx.createOscillator();
|
||||
_vca = ctx.createGain();
|
||||
_vco.connect(_vca);
|
||||
_vca.connect(ctx.destination);
|
||||
_vca.gain.value = gain;
|
||||
_vco.start(0);
|
||||
} catch(e) {
|
||||
_vco = undefined;
|
||||
_vca = undefined;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_vco.frequency.value = frequency;
|
||||
_vca.gain.value = gain;
|
||||
}
|
||||
}
|
||||
|
||||
export function enablePitch(pin: Pin) {
|
||||
pin.mode = PinMode.Analog | PinMode.Output;
|
||||
}
|
||||
|
||||
export function pitch(frequency: number, ms: number) {
|
||||
let cb = getResume();
|
||||
setTimeout(() => { cb() }, ms);
|
||||
AudioContextManager.tone(frequency, 1);
|
||||
setTimeout(() => {
|
||||
if (ms > 0) AudioContextManager.stop();
|
||||
cb()
|
||||
}, ms);
|
||||
}
|
||||
|
||||
|
||||
|
64
sim/state.ts
64
sim/state.ts
@ -18,28 +18,28 @@ namespace ks.rt.micro_bit {
|
||||
}
|
||||
|
||||
export class Pin {
|
||||
constructor(public id: number) {}
|
||||
constructor(public id: number) { }
|
||||
touched = false;
|
||||
value = 0;
|
||||
mode = PinMode.Unused;
|
||||
|
||||
isTouched() : boolean {
|
||||
isTouched(): boolean {
|
||||
this.mode = PinMode.Touch;
|
||||
return this.touched;
|
||||
}
|
||||
}
|
||||
|
||||
export class Button {
|
||||
constructor(public id : number) {}
|
||||
constructor(public id: number) { }
|
||||
pressed: boolean;
|
||||
}
|
||||
|
||||
export class EventBus {
|
||||
private queues : Map<EventQueue<number>> = {};
|
||||
private queues: Map<EventQueue<number>> = {};
|
||||
|
||||
constructor(private runtime : Runtime) { }
|
||||
constructor(private runtime: Runtime) { }
|
||||
|
||||
listen(id:number, evid:number, handler: RefAction) {
|
||||
listen(id: number, evid: number, handler: RefAction) {
|
||||
let k = id + ':' + evid;
|
||||
let queue = this.queues[k];
|
||||
if (!queue) queue = this.queues[k] = new EventQueue<number>(this.runtime);
|
||||
@ -54,21 +54,21 @@ namespace ks.rt.micro_bit {
|
||||
}
|
||||
|
||||
export interface PacketBuffer {
|
||||
data:number[];
|
||||
rssi?:number;
|
||||
data: number[];
|
||||
rssi?: number;
|
||||
}
|
||||
|
||||
export class RadioDatagram {
|
||||
datagram: PacketBuffer[] = [];
|
||||
lastReceived: PacketBuffer = {
|
||||
data:[0,0,0,0],
|
||||
data: [0, 0, 0, 0],
|
||||
rssi: -1
|
||||
};
|
||||
|
||||
constructor(private runtime : Runtime) {
|
||||
constructor(private runtime: Runtime) {
|
||||
}
|
||||
|
||||
queue(packet : PacketBuffer) {
|
||||
queue(packet: PacketBuffer) {
|
||||
if (this.datagram.length < 5) {
|
||||
this.datagram.push(packet);
|
||||
let ens = enums();
|
||||
@ -76,17 +76,17 @@ namespace ks.rt.micro_bit {
|
||||
}
|
||||
}
|
||||
|
||||
send(buffer : number[]) {
|
||||
send(buffer: number[]) {
|
||||
Runtime.postMessage(<SimulatorRadioPacketMessage>{
|
||||
type:'radiopacket',
|
||||
type: 'radiopacket',
|
||||
data: buffer.slice(0, 8)
|
||||
})
|
||||
}
|
||||
|
||||
recv() : PacketBuffer {
|
||||
recv(): PacketBuffer {
|
||||
var r = this.datagram.shift();
|
||||
if (!r) r = {
|
||||
data:[0,0,0,0],
|
||||
data: [0, 0, 0, 0],
|
||||
rssi: -1
|
||||
};
|
||||
return this.lastReceived = r;
|
||||
@ -96,9 +96,9 @@ namespace ks.rt.micro_bit {
|
||||
export class RadioBus {
|
||||
// uint8_t radioDefaultGroup = MICROBIT_RADIO_DEFAULT_GROUP;
|
||||
groupId = 0; // todo
|
||||
datagram : RadioDatagram;
|
||||
datagram: RadioDatagram;
|
||||
|
||||
constructor(private runtime : Runtime) {
|
||||
constructor(private runtime: Runtime) {
|
||||
this.datagram = new RadioDatagram(runtime);
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ namespace ks.rt.micro_bit {
|
||||
broadcast(msg: number) {
|
||||
let ens = enums();
|
||||
Runtime.postMessage(<SimulatorEventBusMessage>{
|
||||
type:'eventbus',
|
||||
type: 'eventbus',
|
||||
id: ens.MES_BROADCAST_GENERAL_ID,
|
||||
eventid: msg
|
||||
})
|
||||
@ -123,7 +123,7 @@ namespace ks.rt.micro_bit {
|
||||
}
|
||||
|
||||
export interface SimulatorSerialMessage extends SimulatorMessage {
|
||||
id:string;
|
||||
id: string;
|
||||
data: string;
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ namespace ks.rt.micro_bit {
|
||||
id: string;
|
||||
|
||||
// the bus
|
||||
bus : EventBus;
|
||||
bus: EventBus;
|
||||
radio: RadioBus;
|
||||
|
||||
// display
|
||||
@ -147,10 +147,10 @@ namespace ks.rt.micro_bit {
|
||||
|
||||
// buttons
|
||||
usesButtonAB: boolean = false;
|
||||
buttons : Button[];
|
||||
buttons: Button[];
|
||||
|
||||
// pins
|
||||
pins : Pin[];
|
||||
pins: Pin[];
|
||||
|
||||
// serial
|
||||
serialIn: string[] = [];
|
||||
@ -207,10 +207,10 @@ namespace ks.rt.micro_bit {
|
||||
}
|
||||
|
||||
|
||||
initAsync(msg : SimulatorRunMessage) : Promise<void> {
|
||||
initAsync(msg: SimulatorRunMessage): Promise<void> {
|
||||
let options = (msg.options || {}) as RuntimeOptions;
|
||||
let theme : micro_bit.IBoardTheme;
|
||||
switch(options.theme) {
|
||||
let theme: micro_bit.IBoardTheme;
|
||||
switch (options.theme) {
|
||||
case 'blue': theme = micro_bit.themes[0]; break;
|
||||
case 'yellow': theme = micro_bit.themes[1]; break;
|
||||
case 'green': theme = micro_bit.themes[2]; break;
|
||||
@ -232,7 +232,7 @@ namespace ks.rt.micro_bit {
|
||||
receiveMessage(msg: SimulatorMessage) {
|
||||
if (!runtime || runtime.dead) return;
|
||||
|
||||
switch(msg.type || "") {
|
||||
switch (msg.type || "") {
|
||||
case 'eventbus':
|
||||
let ev = <SimulatorEventBusMessage>msg;
|
||||
this.bus.queue(ev.id, ev.eventid, ev.value);
|
||||
@ -242,7 +242,7 @@ namespace ks.rt.micro_bit {
|
||||
break;
|
||||
case 'radiopacket':
|
||||
let packet = <SimulatorRadioPacketMessage>msg;
|
||||
this.radio.datagram.queue({ data: packet.data || [], rssi: packet.rssi || 0})
|
||||
this.radio.datagram.queue({ data: packet.data || [], rssi: packet.rssi || 0 })
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -253,10 +253,10 @@ namespace ks.rt.micro_bit {
|
||||
}
|
||||
|
||||
serialOutBuffer: string = '';
|
||||
writeSerial(s : string) {
|
||||
for(let i = 0; i < s.length;++i) {
|
||||
writeSerial(s: string) {
|
||||
for (let i = 0; i < s.length; ++i) {
|
||||
let c = s[i];
|
||||
switch(c) {
|
||||
switch (c) {
|
||||
case '\n':
|
||||
Runtime.postMessage(<SimulatorSerialMessage>{
|
||||
type: 'serial',
|
||||
@ -295,8 +295,8 @@ namespace ks.rt.micro_bit {
|
||||
}
|
||||
}
|
||||
}
|
||||
public clear() : void {
|
||||
for(var i = 0;i < this.data.length; ++i)
|
||||
public clear(): void {
|
||||
for (var i = 0; i < this.data.length; ++i)
|
||||
this.data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user