149 lines
4.5 KiB
JavaScript
149 lines
4.5 KiB
JavaScript
|
// an audio source
|
||
|
// This is the actual sound
|
||
|
import { SourceType } from './source-type';
|
||
|
export default class AudioSource {
|
||
|
constructor(graph, scene, context, buffer = null, type = SourceType.WorldSource) {
|
||
|
this.position = {
|
||
|
x: 0,
|
||
|
y: 0,
|
||
|
z: 0
|
||
|
};
|
||
|
this.buffer = buffer;
|
||
|
this.context = context;
|
||
|
this.scene = scene;
|
||
|
this.graph = graph;
|
||
|
this.type = type;
|
||
|
this.playbackRate = 1;
|
||
|
this.volume = 1;
|
||
|
this.init();
|
||
|
}
|
||
|
init() {
|
||
|
this.gain = this.context.createGain();
|
||
|
// bind methods so we can add and removve them from event listeners
|
||
|
this.stop = this.stop.bind(this);
|
||
|
}
|
||
|
getBuffer() {
|
||
|
return this.buffer;
|
||
|
}
|
||
|
setBuffer(data) {
|
||
|
this.buffer = data;
|
||
|
if (this.playOnLoad) {
|
||
|
this.play();
|
||
|
this.playOnLoad = false;
|
||
|
}
|
||
|
}
|
||
|
play(when = 0, offset = 0, duration = this.buffer ? this.buffer.duration : 0) {
|
||
|
if (this.playing && this.node) {
|
||
|
this.stop();
|
||
|
}
|
||
|
if (!this.buffer) {
|
||
|
this.playOnLoad = true;
|
||
|
return;
|
||
|
}
|
||
|
if (!this.node) {
|
||
|
this.node = this.context.createBufferSource();
|
||
|
this.node.buffer = this.buffer;
|
||
|
this.createConnections();
|
||
|
}
|
||
|
if (this.node) {
|
||
|
this.node.playbackRate.value = this.playbackRate;
|
||
|
this.node.start(when, offset, duration);
|
||
|
this.node.loop = this.looping;
|
||
|
this.playing = true;
|
||
|
if (this.sceneNode) {
|
||
|
this.sceneNode.setPosition(this.position.x, this.position.y, this.position.z);
|
||
|
}
|
||
|
this.node.addEventListener('ended', this.stop);
|
||
|
}
|
||
|
}
|
||
|
setPosition(x, y, z) {
|
||
|
this.position = {
|
||
|
x,
|
||
|
y,
|
||
|
z
|
||
|
};
|
||
|
if (this.sceneNode)
|
||
|
this.sceneNode.setPosition(x, y, z);
|
||
|
}
|
||
|
setPlaybackRate(rate) {
|
||
|
this.playbackRate = rate;
|
||
|
if (this.node)
|
||
|
this.node.playbackRate.value = rate;
|
||
|
}
|
||
|
getPlaybackRate() {
|
||
|
return this.playbackRate;
|
||
|
}
|
||
|
setVolume(volume) {
|
||
|
this.volume = volume;
|
||
|
if (this.gain)
|
||
|
this.gain.gain.value = volume;
|
||
|
}
|
||
|
getVolume() {
|
||
|
return this.volume;
|
||
|
}
|
||
|
createConnections() {
|
||
|
switch (this.type) {
|
||
|
case SourceType.WorldSource:
|
||
|
if (!this.sceneNode) {
|
||
|
this.sceneNode = this.scene.createSource();
|
||
|
}
|
||
|
this.node.connect(this.gain);
|
||
|
this.gain.connect(this.sceneNode);
|
||
|
break;
|
||
|
case SourceType.UISource:
|
||
|
this.node.connect(this.gain);
|
||
|
this.graph.connectToUI(this.gain);
|
||
|
break;
|
||
|
default:
|
||
|
this.node.connect(this.gain);
|
||
|
this.graph.connectToMaster(this.gain);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
stop() {
|
||
|
this.playing = false;
|
||
|
if (this.node) {
|
||
|
this.node.removeEventListener('ended', this.stop);
|
||
|
this.node.stop();
|
||
|
this.node.disconnect();
|
||
|
this.node = null;
|
||
|
this.playing = false;
|
||
|
if (this.sceneNode) {
|
||
|
this.sceneNode.disconnect();
|
||
|
this.sceneNode = null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
destroy() {
|
||
|
this.stop();
|
||
|
// set all refs to null to encourage gc
|
||
|
this.node = null;
|
||
|
this.sceneNode = null;
|
||
|
this.buffer = null;
|
||
|
this.context = null;
|
||
|
this.graph = null;
|
||
|
this.scene = null;
|
||
|
}
|
||
|
loop(value) {
|
||
|
this.looping = value;
|
||
|
if (this.node) {
|
||
|
this.node.loop = value;
|
||
|
}
|
||
|
}
|
||
|
fadeOut(time) {
|
||
|
this.gain.gain.setValueAtTime(this.getVolume(), this.context.getContext().currentTime);
|
||
|
if (!this.node) {
|
||
|
return;
|
||
|
}
|
||
|
this.gain.gain.exponentialRampToValueAtTime(0.0001, this.context.getContext().currentTime + time);
|
||
|
setTimeout(() => this.stop(), time * 1000);
|
||
|
}
|
||
|
fadeIn(time) {
|
||
|
this.gain.gain.setValueAtTime(0.0001, this.context.getContext().currentTime);
|
||
|
if (!this.node) {
|
||
|
this.play();
|
||
|
}
|
||
|
this.gain.gain.exponentialRampToValueAtTime(this.volume, this.context.getContext().currentTime + time);
|
||
|
}
|
||
|
}
|