|
@@ -28,19 +28,50 @@ module BABYLON {
|
|
*/
|
|
*/
|
|
public soundTrackId: number;
|
|
public soundTrackId: number;
|
|
/**
|
|
/**
|
|
|
|
+ * Is this sound currently played.
|
|
|
|
+ */
|
|
|
|
+ public isPlaying: boolean = false;
|
|
|
|
+ /**
|
|
|
|
+ * Is this sound currently paused.
|
|
|
|
+ */
|
|
|
|
+ public isPaused: boolean = false;
|
|
|
|
+ /**
|
|
* Does this sound enables spatial sound.
|
|
* Does this sound enables spatial sound.
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#creating-a-spatial-3d-sound
|
|
*/
|
|
*/
|
|
public spatialSound: boolean = false;
|
|
public spatialSound: boolean = false;
|
|
|
|
+ /**
|
|
|
|
+ * Define the reference distance the sound should be heard perfectly.
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#creating-a-spatial-3d-sound
|
|
|
|
+ */
|
|
public refDistance: number = 1;
|
|
public refDistance: number = 1;
|
|
|
|
+ /**
|
|
|
|
+ * Define the roll off factor of spatial sounds.
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#creating-a-spatial-3d-sound
|
|
|
|
+ */
|
|
public rolloffFactor: number = 1;
|
|
public rolloffFactor: number = 1;
|
|
|
|
+ /**
|
|
|
|
+ * Define the max distance the sound should be heard (intensity just became 0 at this point).
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#creating-a-spatial-3d-sound
|
|
|
|
+ */
|
|
public maxDistance: number = 100;
|
|
public maxDistance: number = 100;
|
|
|
|
+ /**
|
|
|
|
+ * Define the distance attenuation model the sound will follow.
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#creating-a-spatial-3d-sound
|
|
|
|
+ */
|
|
public distanceModel: string = "linear";
|
|
public distanceModel: string = "linear";
|
|
- private _panningModel: string = "equalpower";
|
|
|
|
|
|
+ /**
|
|
|
|
+ * @hidden
|
|
|
|
+ * Back Compat
|
|
|
|
+ **/
|
|
public onended: () => any;
|
|
public onended: () => any;
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Observable event when the current playing sound finishes.
|
|
* Observable event when the current playing sound finishes.
|
|
*/
|
|
*/
|
|
public onEndedObservable = new Observable<Sound>();
|
|
public onEndedObservable = new Observable<Sound>();
|
|
|
|
+
|
|
|
|
+ private _panningModel: string = "equalpower";
|
|
private _playbackRate: number = 1;
|
|
private _playbackRate: number = 1;
|
|
private _streaming: boolean = false;
|
|
private _streaming: boolean = false;
|
|
private _startTime: number = 0;
|
|
private _startTime: number = 0;
|
|
@@ -51,8 +82,6 @@ module BABYLON {
|
|
private _localDirection: Vector3 = new Vector3(1, 0, 0);
|
|
private _localDirection: Vector3 = new Vector3(1, 0, 0);
|
|
private _volume: number = 1;
|
|
private _volume: number = 1;
|
|
private _isReadyToPlay: boolean = false;
|
|
private _isReadyToPlay: boolean = false;
|
|
- public isPlaying: boolean = false;
|
|
|
|
- public isPaused: boolean = false;
|
|
|
|
private _isDirectional: boolean = false;
|
|
private _isDirectional: boolean = false;
|
|
private _readyToPlayCallback: Nullable<() => any>;
|
|
private _readyToPlayCallback: Nullable<() => any>;
|
|
private _audioBuffer: Nullable<AudioBuffer>;
|
|
private _audioBuffer: Nullable<AudioBuffer>;
|
|
@@ -266,6 +295,9 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Release the sound and its associated resources
|
|
|
|
+ */
|
|
public dispose() {
|
|
public dispose() {
|
|
if (Engine.audioEngine.canUseWebAudio) {
|
|
if (Engine.audioEngine.canUseWebAudio) {
|
|
if (this.isPlaying) {
|
|
if (this.isPlaying) {
|
|
@@ -309,6 +341,10 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Gets if the sounds is ready to be played or not.
|
|
|
|
+ * @returns true if ready, otherwise false
|
|
|
|
+ */
|
|
public isReady(): boolean {
|
|
public isReady(): boolean {
|
|
return this._isReadyToPlay;
|
|
return this._isReadyToPlay;
|
|
}
|
|
}
|
|
@@ -325,6 +361,10 @@ module BABYLON {
|
|
}, (err: any) => { Tools.Error("Error while decoding audio data for: " + this.name + " / Error: " + err); });
|
|
}, (err: any) => { Tools.Error("Error while decoding audio data for: " + this.name + " / Error: " + err); });
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Sets the data of the sound from an audiobuffer
|
|
|
|
+ * @param audioBuffer The audioBuffer containing the data
|
|
|
|
+ */
|
|
public setAudioBuffer(audioBuffer: AudioBuffer): void {
|
|
public setAudioBuffer(audioBuffer: AudioBuffer): void {
|
|
if (Engine.audioEngine.canUseWebAudio) {
|
|
if (Engine.audioEngine.canUseWebAudio) {
|
|
this._audioBuffer = audioBuffer;
|
|
this._audioBuffer = audioBuffer;
|
|
@@ -332,7 +372,11 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public updateOptions(options: any) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Updates the current sounds options such as maxdistance, loop...
|
|
|
|
+ * @param options A JSON object containing values named as the object properties
|
|
|
|
+ */
|
|
|
|
+ public updateOptions(options: any): void {
|
|
if (options) {
|
|
if (options) {
|
|
this.loop = options.loop || this.loop;
|
|
this.loop = options.loop || this.loop;
|
|
this.maxDistance = options.maxDistance || this.maxDistance;
|
|
this.maxDistance = options.maxDistance || this.maxDistance;
|
|
@@ -387,11 +431,21 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Switch the panning model to HRTF:
|
|
|
|
+ * Renders a stereo output of higher quality than equalpower — it uses a convolution with measured impulse responses from human subjects.
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#creating-a-spatial-3d-sound
|
|
|
|
+ */
|
|
public switchPanningModelToHRTF() {
|
|
public switchPanningModelToHRTF() {
|
|
this._panningModel = "HRTF";
|
|
this._panningModel = "HRTF";
|
|
this._switchPanningModel();
|
|
this._switchPanningModel();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Switch the panning model to Equal Power:
|
|
|
|
+ * Represents the equal-power panning algorithm, generally regarded as simple and efficient. equalpower is the default value.
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#creating-a-spatial-3d-sound
|
|
|
|
+ */
|
|
public switchPanningModelToEqualPower() {
|
|
public switchPanningModelToEqualPower() {
|
|
this._panningModel = "equalpower";
|
|
this._panningModel = "equalpower";
|
|
this._switchPanningModel();
|
|
this._switchPanningModel();
|
|
@@ -403,7 +457,11 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public connectToSoundTrackAudioNode(soundTrackAudioNode: AudioNode) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Connect this sound to a sound track audio node like gain...
|
|
|
|
+ * @param soundTrackAudioNode the sound track audio node to connect to
|
|
|
|
+ */
|
|
|
|
+ public connectToSoundTrackAudioNode(soundTrackAudioNode: AudioNode): void {
|
|
if (Engine.audioEngine.canUseWebAudio) {
|
|
if (Engine.audioEngine.canUseWebAudio) {
|
|
if (this._isOutputConnected) {
|
|
if (this._isOutputConnected) {
|
|
this._outputAudioNode.disconnect();
|
|
this._outputAudioNode.disconnect();
|
|
@@ -419,7 +477,7 @@ module BABYLON {
|
|
* @param coneOuterAngle Size of the outer cone in degree
|
|
* @param coneOuterAngle Size of the outer cone in degree
|
|
* @param coneOuterGain Volume of the sound outside the outer cone (between 0.0 and 1.0)
|
|
* @param coneOuterGain Volume of the sound outside the outer cone (between 0.0 and 1.0)
|
|
*/
|
|
*/
|
|
- public setDirectionalCone(coneInnerAngle: number, coneOuterAngle: number, coneOuterGain: number) {
|
|
|
|
|
|
+ public setDirectionalCone(coneInnerAngle: number, coneOuterAngle: number, coneOuterGain: number): void {
|
|
if (coneOuterAngle < coneInnerAngle) {
|
|
if (coneOuterAngle < coneInnerAngle) {
|
|
Tools.Error("setDirectionalCone(): outer angle of the cone must be superior or equal to the inner angle.");
|
|
Tools.Error("setDirectionalCone(): outer angle of the cone must be superior or equal to the inner angle.");
|
|
return;
|
|
return;
|
|
@@ -483,7 +541,11 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public setPosition(newPosition: Vector3) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Sets the position of the emitter if spatial sound is enabled
|
|
|
|
+ * @param newPosition Defines the new posisiton
|
|
|
|
+ */
|
|
|
|
+ public setPosition(newPosition: Vector3): void {
|
|
this._position = newPosition;
|
|
this._position = newPosition;
|
|
|
|
|
|
if (Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner && !isNaN(this._position.x) && !isNaN(this._position.y) && !isNaN(this._position.z)) {
|
|
if (Engine.audioEngine.canUseWebAudio && this.spatialSound && this._soundPanner && !isNaN(this._position.x) && !isNaN(this._position.y) && !isNaN(this._position.z)) {
|
|
@@ -491,7 +553,11 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public setLocalDirectionToMesh(newLocalDirection: Vector3) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Sets the local direction of the emitter if spatial sound is enabled
|
|
|
|
+ * @param newLocalDirection Defines the new local direction
|
|
|
|
+ */
|
|
|
|
+ public setLocalDirectionToMesh(newLocalDirection: Vector3): void {
|
|
this._localDirection = newLocalDirection;
|
|
this._localDirection = newLocalDirection;
|
|
|
|
|
|
if (Engine.audioEngine.canUseWebAudio && this._connectedMesh && this.isPlaying) {
|
|
if (Engine.audioEngine.canUseWebAudio && this._connectedMesh && this.isPlaying) {
|
|
@@ -510,6 +576,7 @@ module BABYLON {
|
|
this._soundPanner.setOrientation(direction.x, direction.y, direction.z);
|
|
this._soundPanner.setOrientation(direction.x, direction.y, direction.z);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /** @hidden */
|
|
public updateDistanceFromListener() {
|
|
public updateDistanceFromListener() {
|
|
if (Engine.audioEngine.canUseWebAudio && this._connectedMesh && this.useCustomAttenuation && this._soundGain && this._scene.activeCamera) {
|
|
if (Engine.audioEngine.canUseWebAudio && this._connectedMesh && this.useCustomAttenuation && this._soundGain && this._scene.activeCamera) {
|
|
var distance = this._connectedMesh.getDistanceToCamera(this._scene.activeCamera);
|
|
var distance = this._connectedMesh.getDistanceToCamera(this._scene.activeCamera);
|
|
@@ -517,7 +584,12 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public setAttenuationFunction(callback: (currentVolume: number, currentDistance: number, maxDistance: number, refDistance: number, rolloffFactor: number) => number) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Sets a new custom attenuation function for the sound.
|
|
|
|
+ * @param callback Defines the function used for the attenuation
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#creating-your-own-custom-attenuation-function
|
|
|
|
+ */
|
|
|
|
+ public setAttenuationFunction(callback: (currentVolume: number, currentDistance: number, maxDistance: number, refDistance: number, rolloffFactor: number) => number): void {
|
|
this._customAttenuationFunction = callback;
|
|
this._customAttenuationFunction = callback;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -526,7 +598,7 @@ module BABYLON {
|
|
* @param time (optional) Start the sound after X seconds. Start immediately (0) by default.
|
|
* @param time (optional) Start the sound after X seconds. Start immediately (0) by default.
|
|
* @param offset (optional) Start the sound setting it at a specific time
|
|
* @param offset (optional) Start the sound setting it at a specific time
|
|
*/
|
|
*/
|
|
- public play(time?: number, offset?: number) {
|
|
|
|
|
|
+ public play(time?: number, offset?: number): void {
|
|
if (this._isReadyToPlay && this._scene.audioEnabled && Engine.audioEngine.audioContext) {
|
|
if (this._isReadyToPlay && this._scene.audioEnabled && Engine.audioEngine.audioContext) {
|
|
try {
|
|
try {
|
|
if (this._startOffset < 0) {
|
|
if (this._startOffset < 0) {
|
|
@@ -620,7 +692,7 @@ module BABYLON {
|
|
* Stop the sound
|
|
* Stop the sound
|
|
* @param time (optional) Stop the sound after X seconds. Stop immediately (0) by default.
|
|
* @param time (optional) Stop the sound after X seconds. Stop immediately (0) by default.
|
|
*/
|
|
*/
|
|
- public stop(time?: number) {
|
|
|
|
|
|
+ public stop(time?: number): void {
|
|
if (this.isPlaying) {
|
|
if (this.isPlaying) {
|
|
if (this._streaming) {
|
|
if (this._streaming) {
|
|
if (this._htmlAudioElement) {
|
|
if (this._htmlAudioElement) {
|
|
@@ -645,7 +717,10 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public pause() {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Put the sound in pause
|
|
|
|
+ */
|
|
|
|
+ public pause(): void {
|
|
if (this.isPlaying) {
|
|
if (this.isPlaying) {
|
|
this.isPaused = true;
|
|
this.isPaused = true;
|
|
if (this._streaming) {
|
|
if (this._streaming) {
|
|
@@ -662,7 +737,12 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public setVolume(newVolume: number, time?: number) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Sets a dedicated volume for this sounds
|
|
|
|
+ * @param newVolume Define the new volume of the sound
|
|
|
|
+ * @param time Define in how long the sound should be at this value
|
|
|
|
+ */
|
|
|
|
+ public setVolume(newVolume: number, time?: number): void {
|
|
if (Engine.audioEngine.canUseWebAudio && this._soundGain) {
|
|
if (Engine.audioEngine.canUseWebAudio && this._soundGain) {
|
|
if (time && Engine.audioEngine.audioContext) {
|
|
if (time && Engine.audioEngine.audioContext) {
|
|
this._soundGain.gain.cancelScheduledValues(Engine.audioEngine.audioContext.currentTime);
|
|
this._soundGain.gain.cancelScheduledValues(Engine.audioEngine.audioContext.currentTime);
|
|
@@ -676,7 +756,11 @@ module BABYLON {
|
|
this._volume = newVolume;
|
|
this._volume = newVolume;
|
|
}
|
|
}
|
|
|
|
|
|
- public setPlaybackRate(newPlaybackRate: number) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Set the sound play back rate
|
|
|
|
+ * @param newPlaybackRate Define the playback rate the sound should be played at
|
|
|
|
+ */
|
|
|
|
+ public setPlaybackRate(newPlaybackRate: number): void {
|
|
this._playbackRate = newPlaybackRate;
|
|
this._playbackRate = newPlaybackRate;
|
|
if (this.isPlaying) {
|
|
if (this.isPlaying) {
|
|
if (this._streaming && this._htmlAudioElement) {
|
|
if (this._streaming && this._htmlAudioElement) {
|
|
@@ -687,12 +771,21 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Gets the volume of the sound.
|
|
|
|
+ * @returns the volume of the sound
|
|
|
|
+ */
|
|
public getVolume(): number {
|
|
public getVolume(): number {
|
|
return this._volume;
|
|
return this._volume;
|
|
}
|
|
}
|
|
|
|
|
|
- public attachToMesh(meshToConnectTo: AbstractMesh) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Attach the sound to a dedicated mesh
|
|
|
|
+ * @param meshToConnectTo The mesh to connect the sound with
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#attaching-a-sound-to-a-mesh
|
|
|
|
+ */
|
|
|
|
+ public attachToMesh(meshToConnectTo: AbstractMesh): void {
|
|
if (this._connectedMesh && this._registerFunc) {
|
|
if (this._connectedMesh && this._registerFunc) {
|
|
this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
|
|
this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
|
|
this._registerFunc = null;
|
|
this._registerFunc = null;
|
|
@@ -711,6 +804,10 @@ module BABYLON {
|
|
meshToConnectTo.registerAfterWorldMatrixUpdate(this._registerFunc);
|
|
meshToConnectTo.registerAfterWorldMatrixUpdate(this._registerFunc);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Detach the sound from the previously attached mesh
|
|
|
|
+ * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music#attaching-a-sound-to-a-mesh
|
|
|
|
+ */
|
|
public detachFromMesh() {
|
|
public detachFromMesh() {
|
|
if (this._connectedMesh && this._registerFunc) {
|
|
if (this._connectedMesh && this._registerFunc) {
|
|
this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
|
|
this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
|
|
@@ -738,6 +835,10 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Clone the current sound in the scene.
|
|
|
|
+ * @returns the new sound clone
|
|
|
|
+ */
|
|
public clone(): Nullable<Sound> {
|
|
public clone(): Nullable<Sound> {
|
|
if (!this._streaming) {
|
|
if (!this._streaming) {
|
|
var setBufferAndRun = () => {
|
|
var setBufferAndRun = () => {
|
|
@@ -774,10 +875,18 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public getAudioBuffer() {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Gets the current underlying audio buffer containing the data
|
|
|
|
+ * @returns the audio buffer
|
|
|
|
+ */
|
|
|
|
+ public getAudioBuffer(): Nullable<AudioBuffer> {
|
|
return this._audioBuffer;
|
|
return this._audioBuffer;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Serializes the Sound in a JSON representation
|
|
|
|
+ * @returns the JSON representation of the sound
|
|
|
|
+ */
|
|
public serialize(): any {
|
|
public serialize(): any {
|
|
var serializationObject: any = {
|
|
var serializationObject: any = {
|
|
name: this.name,
|
|
name: this.name,
|
|
@@ -813,6 +922,14 @@ module BABYLON {
|
|
return serializationObject;
|
|
return serializationObject;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Parse a JSON representation of a sound to innstantiate in a given scene
|
|
|
|
+ * @param parsedSound Define the JSON representation of the sound (usually coming from the serialize method)
|
|
|
|
+ * @param scene Define the scene the new parsed sound should be created in
|
|
|
|
+ * @param rootUrl Define the rooturl of the load in case we need to fetch relative dependencies
|
|
|
|
+ * @param sourceSound Define a cound place holder if do not need to instantiate a new one
|
|
|
|
+ * @returns the newly parsed sound
|
|
|
|
+ */
|
|
public static Parse(parsedSound: any, scene: Scene, rootUrl: string, sourceSound?: Sound): Sound {
|
|
public static Parse(parsedSound: any, scene: Scene, rootUrl: string, sourceSound?: Sound): Sound {
|
|
var soundName = parsedSound.name;
|
|
var soundName = parsedSound.name;
|
|
var soundUrl;
|
|
var soundUrl;
|