Robustify AudioContext code (thanks for the surprise, Chrome!)
This commit is contained in:
parent
e8b7298919
commit
568c4e031e
6 changed files with 1628 additions and 1597 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -3,20 +3,22 @@ PCjs Sources
|
||||||
|
|
||||||
Structure
|
Structure
|
||||||
---
|
---
|
||||||
All the code for PCjs is contained in the following JavaScript files, which roughly divide the
|
These JavaScript files divide PCjs functionality into major PC components. Most of the files are device
|
||||||
functionality into major PC components, aka "devices". However, not every file implements a device,
|
components, implementing a specific device (or set of devices, in the case of [chipset.js](chipset.js)).
|
||||||
and "component" is an overloaded term, since *[Component](/docs/pcjs/component/)* is also the name of
|
|
||||||
the shared base class used for most PCjs devices (see [component.js](../../shared/lib/component.js)).
|
|
||||||
So it's best to refer to these files generically as "modules", and more specifically as "device modules"
|
|
||||||
whenever they implement a specific device (or set of devices, in the case of [*ChipSet*](/docs/pcjs/chipset/)).
|
|
||||||
|
|
||||||
Examples of non-device modules include UI modules like [panel.js](panel.js) and [debugger.js](debugger.js),
|
Be aware that *component* is an overloaded term, since **Component** is also the name of the
|
||||||
and sub-modules like [x86opxx.js](x86opxx.js) and [x86func.js](x86func.js) that separate the CPU functionality
|
shared base class in [component.js](../../shared/lib/component.js) used by most machine components.
|
||||||
of [x86.js](x86.js) into more manageable pieces.
|
A few low-level components (eg, the **Memory** and **State** components, the Card class of the **Video**
|
||||||
|
component, the Color and Rectangle classes of the **Panel** component, etc) do not extend **Component**,
|
||||||
|
so don't assume that every PCjs object has access to [component.js](../../shared/lib/component.js) methods.
|
||||||
|
|
||||||
These modules should always be loaded or compiled in the order listed by the *pcJSFiles* property in
|
Examples of non-device components include UI components like [panel.js](panel.js) and [debugger.js](debugger.js),
|
||||||
[package.json](../../../package.json), which includes all the necessary *shared* modules as well.
|
and sub-components like [x86opxx.js](x86opxx.js) and [x86func.js](x86func.js) that separate the CPU
|
||||||
At the time of this writing, the order is:
|
functionality of [x86.js](x86.js) into more manageable pieces.
|
||||||
|
|
||||||
|
These components should always be loaded or compiled in the order listed by the *pcJSFiles* property in
|
||||||
|
[package.json](../../../package.json), which includes all the necessary *shared* components as well.
|
||||||
|
At the time of this writing, the recommended order is:
|
||||||
|
|
||||||
* [shared/defines.js](../../shared/lib/defines.js)
|
* [shared/defines.js](../../shared/lib/defines.js)
|
||||||
* [shared/diskapi.js](../../shared/lib/diskapi.js)
|
* [shared/diskapi.js](../../shared/lib/diskapi.js)
|
||||||
|
|
@ -38,6 +40,8 @@ At the time of this writing, the order is:
|
||||||
* [pcjs/x86seg.js](x86seg.js)
|
* [pcjs/x86seg.js](x86seg.js)
|
||||||
* [pcjs/x86cpu.js](x86cpu.js)
|
* [pcjs/x86cpu.js](x86cpu.js)
|
||||||
* [pcjs/x86func.js](x86func.js)
|
* [pcjs/x86func.js](x86func.js)
|
||||||
|
* [pcjs/x86opxx.js](x86opxx.js)
|
||||||
|
* [pcjs/x86op0f.js](x86op0f.js)
|
||||||
* [pcjs/x86modb.js](x86modb.js)
|
* [pcjs/x86modb.js](x86modb.js)
|
||||||
* [pcjs/x86modw.js](x86modw.js)
|
* [pcjs/x86modw.js](x86modw.js)
|
||||||
* [pcjs/x86modb16.js](x86modb16.js)
|
* [pcjs/x86modb16.js](x86modb16.js)
|
||||||
|
|
@ -45,8 +49,6 @@ At the time of this writing, the order is:
|
||||||
* [pcjs/x86modb32.js](x86modb32.js)
|
* [pcjs/x86modb32.js](x86modb32.js)
|
||||||
* [pcjs/x86modw32.js](x86modw32.js)
|
* [pcjs/x86modw32.js](x86modw32.js)
|
||||||
* [pcjs/x86modsib.js](x86modsib.js)
|
* [pcjs/x86modsib.js](x86modsib.js)
|
||||||
* [pcjs/x86opxx.js](x86opxx.js)
|
|
||||||
* [pcjs/x86op0f.js](x86op0f.js)
|
|
||||||
* [pcjs/chipset.js](chipset.js)
|
* [pcjs/chipset.js](chipset.js)
|
||||||
* [pcjs/rom.js](rom.js)
|
* [pcjs/rom.js](rom.js)
|
||||||
* [pcjs/ram.js](ram.js)
|
* [pcjs/ram.js](ram.js)
|
||||||
|
|
@ -62,16 +64,16 @@ At the time of this writing, the order is:
|
||||||
* [pcjs/computer.js](computer.js)
|
* [pcjs/computer.js](computer.js)
|
||||||
* [shared/embed.js](../../shared/lib/embed.js)
|
* [shared/embed.js](../../shared/lib/embed.js)
|
||||||
|
|
||||||
Some of the modules *can* be reordered or even omitted (eg, [debugger.js](debugger.js) or
|
Some of the components *can* be reordered or even omitted (eg, [debugger.js](debugger.js) or
|
||||||
[embed.js](../../shared/lib/embed.js)), but you should observe the following:
|
[embed.js](../../shared/lib/embed.js)), but you should observe the following:
|
||||||
|
|
||||||
* [component.js](../../shared/lib/component.js) must be listed before any module that extends [*Component*](/docs/pcjs/component/)
|
* [component.js](../../shared/lib/component.js) must be listed before any component that extends **Component**
|
||||||
* [panel.js](panel.js) should be loaded early to initialize the Control Panel (if any) as soon as possible
|
* [panel.js](panel.js) should be loaded early to initialize the Control Panel (if any) as soon as possible
|
||||||
* [computer.js](computer.js) should be the last device module, as it supervises and notifies all the other device modules
|
* [computer.js](computer.js) should be the last device component, as it supervises and notifies all the other device components
|
||||||
|
|
||||||
To minimize ordering requirements, the init() handlers and constructors of all modules should avoid
|
To minimize ordering requirements, the init() handlers and constructors of all components should avoid
|
||||||
referencing other modules. Device modules should define an initBus() notification handler, which the
|
referencing other components. Device components should define an initBus() notification handler, which the
|
||||||
[*Computer*](/docs/pcjs/computer/) will call after it has created/initialized the *Bus* object.
|
*Computer* component will call after it has created/initialized the *Bus* component.
|
||||||
|
|
||||||
Features
|
Features
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -233,10 +233,14 @@ function ChipSet(parmsChipSet)
|
||||||
*/
|
*/
|
||||||
this.fSpeaker = false;
|
this.fSpeaker = false;
|
||||||
if (parmsChipSet['sound']) {
|
if (parmsChipSet['sound']) {
|
||||||
if (window && 'webkitAudioContext' in window) {
|
this.classAudio = this.contextAudio = null;
|
||||||
this.contextAudio = new window['webkitAudioContext']();
|
if (window) {
|
||||||
|
this.classAudio = window['AudioContext'] || window['webkitAudioContext'];
|
||||||
|
}
|
||||||
|
if (this.classAudio) {
|
||||||
|
this.contextAudio = new this.classAudio();
|
||||||
} else {
|
} else {
|
||||||
if (DEBUG) this.log("webkitAudioContext not available");
|
if (DEBUG) this.log("AudioContext not available");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4771,6 +4775,7 @@ ChipSet.prototype.parseSwitches = function(s, def)
|
||||||
ChipSet.prototype.setSpeaker = function(fOn)
|
ChipSet.prototype.setSpeaker = function(fOn)
|
||||||
{
|
{
|
||||||
if (this.contextAudio) {
|
if (this.contextAudio) {
|
||||||
|
try {
|
||||||
if (fOn !== undefined) {
|
if (fOn !== undefined) {
|
||||||
this.fSpeaker = fOn;
|
this.fSpeaker = fOn;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -4789,20 +4794,38 @@ ChipSet.prototype.setSpeaker = function(fOn)
|
||||||
if (this.messageEnabled(Messages.SPEAKER)) this.printMessage("speaker set to " + freq + "hz", true);
|
if (this.messageEnabled(Messages.SPEAKER)) this.printMessage("speaker set to " + freq + "hz", true);
|
||||||
} else {
|
} else {
|
||||||
this.sourceAudio = this.contextAudio['createOscillator']();
|
this.sourceAudio = this.contextAudio['createOscillator']();
|
||||||
this.sourceAudio['type'] = "square"; // any of: "sine", "square", "sawtooth", "triangle", "custom"
|
if (this.sourceAudio) {
|
||||||
|
if (typeof this.sourceAudio['type'] == "number") {
|
||||||
|
this.sourceAudio['type'] = 1; // deprecated: 0: "sine", 1: "square", 2: "sawtooth", 3: "triangle"
|
||||||
|
} else {
|
||||||
|
this.sourceAudio['type'] = "square";
|
||||||
|
}
|
||||||
this.sourceAudio['connect'](this.contextAudio['destination']);
|
this.sourceAudio['connect'](this.contextAudio['destination']);
|
||||||
this.sourceAudio['frequency']['value'] = freq;
|
this.sourceAudio['frequency']['value'] = freq;
|
||||||
if (this.messageEnabled(Messages.SPEAKER)) this.printMessage("speaker on at " + freq + "hz", true);
|
if ('start' in this.sourceAudio) {
|
||||||
this.sourceAudio['start'](0);
|
this.sourceAudio['start'](0);
|
||||||
|
} else {
|
||||||
|
this.sourceAudio['noteOn'](0); // deprecated: this.sourceAudio['noteOn'](0)
|
||||||
|
}
|
||||||
|
if (this.messageEnabled(Messages.SPEAKER)) this.printMessage("speaker on at " + freq + "hz", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.sourceAudio) {
|
if (this.sourceAudio) {
|
||||||
|
if ('stop' in this.sourceAudio) {
|
||||||
this.sourceAudio['stop'](0);
|
this.sourceAudio['stop'](0);
|
||||||
|
} else {
|
||||||
|
this.sourceAudio['noteOff'](0); // deprecated: this.sourceAudio['noteOff'](0)
|
||||||
|
}
|
||||||
this.sourceAudio['disconnect'](); // QUESTION: is this automatic following a stop(), since this particular source cannot be started again?
|
this.sourceAudio['disconnect'](); // QUESTION: is this automatic following a stop(), since this particular source cannot be started again?
|
||||||
delete this.sourceAudio; // QUESTION: ditto?
|
delete this.sourceAudio; // QUESTION: ditto?
|
||||||
if (this.messageEnabled(Messages.SPEAKER)) this.printMessage("speaker off at " + freq + "hz", true);
|
if (this.messageEnabled(Messages.SPEAKER)) this.printMessage("speaker off at " + freq + "hz", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
this.notice("AudioContext exception: " + e.message);
|
||||||
|
this.contextAudio = null;
|
||||||
|
}
|
||||||
} else if (fOn) {
|
} else if (fOn) {
|
||||||
this.printMessage("BEEP", Messages.SPEAKER);
|
this.printMessage("BEEP", Messages.SPEAKER);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue