Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Closes #515] Refactor sound resources to address inconsistent behaviors #644

Merged
merged 23 commits into from
Sep 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
46133f7
Add proper simultaneous sound handling to AudioTag and WebAudio provi…
kamranayub Sep 1, 2016
e8e130c
Refactor sounds to be simpler
kamranayub Sep 1, 2016
d2b0b9c
Fix other audio test to not do simultaneous plays
kamranayub Sep 1, 2016
8a676f8
Compile dists and address TSLint
kamranayub Sep 1, 2016
20d21e6
Merge latest PRs and recompile dists
kamranayub Sep 1, 2016
364e30c
Simplify and consolidate Sound resource and sound implementations
kamranayub Sep 2, 2016
ffa05d1
Fix web audio offset calculation to be in seconds
kamranayub Sep 2, 2016
9bab3e5
Fix sandbox
kamranayub Sep 2, 2016
b78a3f5
Compile dists
kamranayub Sep 2, 2016
55efb9c
Fix some potential issues
kamranayub Sep 2, 2016
43ef13d
Add initial sound tests
kamranayub Sep 2, 2016
d4dca5e
Add sound unit test coverage
kamranayub Sep 2, 2016
1f31c28
Add callback tests
kamranayub Sep 2, 2016
c7df9a8
Add callback test with data preloaded
kamranayub Sep 2, 2016
c447e7f
Fix TSlint and add `instanceCount()` method to get number of currentl…
kamranayub Sep 2, 2016
0f11c8d
Compile dists
kamranayub Sep 2, 2016
b48d89f
Ignore audio implementations for coverage
kamranayub Sep 2, 2016
216c4c1
Compile dists
kamranayub Sep 2, 2016
b2c74a1
Merge in master changes and recompile dists
kamranayub Sep 2, 2016
6bc6e2f
Add more debug messages for debugging
kamranayub Sep 2, 2016
10a8a7e
Fix tslint task to include all engine files
kamranayub Sep 2, 2016
4827768
Fix tslint errors
kamranayub Sep 2, 2016
88d509a
Recompile dists
kamranayub Sep 2, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
"name": "Attach to tests",
"type": "node",
"request": "launch",
"preLaunchTask": "compile",
"preLaunchTask": "shell:specs",
"program": "${workspaceRoot}\\node_modules\\jasmine\\bin\\jasmine.js", // ${workspaceRoot}/src/spec/TestsSpec.js",
"args": ["JASMINE_CONFIG_PATH=${workspaceRoot}\\src\\spec\\support\\jasmine.json"],
"cwd": "${workspaceRoot}\\src\\",
"cwd": "${workspaceRoot}",
"outDir": "${workspaceRoot}\\src\\spec\\",
"sourceMaps": true
}
Expand Down
34 changes: 19 additions & 15 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,25 @@
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process

// A task runner that calls grunt
{
"version": "0.1.0",

// The command is grunt. Assumes that grunt-cli has been installed using npm install -g grunt-cli
"command": "grunt",
"isShellCommand": true,
"showOutput": "silent",
"tasks": [
{
"taskName": "compile",
"args": [],
"isBuildCommand": true,
"problemMatcher": "$tsc"
}
]
"version": "0.1.0",
// The command is grunt. Assumes that grunt-cli has been installed using npm install -g grunt-cli
"command": "grunt",
"isShellCommand": true,
"showOutput": "silent",
"tasks": [
{
"taskName": "compile",
"args": [],
"isBuildCommand": true,
"problemMatcher": "$tsc"
},
{
"taskName": "shell:specs",
"args": [],
"isBuildCommand": false,
"problemMatcher": "$tsc"
}
]
}
16 changes: 4 additions & 12 deletions GruntFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ module.exports = function (grunt) {
command: function () {
var files = grunt.file.expand("./src/spec/*.ts");

return '<%= tscCmd %> --target ES5 ' + files.join(' ') + ' --out ./src/spec/TestsSpec.js'
return '<%= tscCmd %> --target ES5 --sourceMap ' + files.join(' ') + ' --out ./src/spec/TestsSpec.js'
},
options: {
stdout: true,
Expand Down Expand Up @@ -186,17 +186,9 @@ module.exports = function (grunt) {
configuration: grunt.file.readJSON('./tslint/tslint.json')
},
src: [
"src/engine/*.ts",
"src/engine/Actions/*.ts",
"src/engine/Collision/*.ts",
"src/engine/Drawing/*.ts",
"src/engine/Input/*.ts",
"src/engine/Interfaces/*.ts",
"src/engine/PostProcessing/*.ts",
"src/engine/Traits/*.ts",
"src/engine/Util/*.ts",
"src/sandbox/web/*.ts",
"src/spec/*.ts",
"src/engine/**/*.ts",
"src/sandbox/web/**/*.ts",
"src/spec/**/*.ts",

// exclusions
"!src/spec/jasmine.d.ts",
Expand Down
Binary file modified dist/Excalibur.0.7.0.nupkg
Binary file not shown.
233 changes: 124 additions & 109 deletions dist/excalibur-0.7.0.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4936,7 +4936,13 @@ declare module ex {
* Begins loading the resource and returns a promise to be resolved on completion
*/
load(): Promise<any>;
/**
* Gets the data that was loaded
*/
getData(): any;
/**
* Sets the data (can be populated from remote request or in-memory data)
*/
setData(data: any): void;
/**
* Processes the downloaded data. Meant to be overridden.
Expand Down Expand Up @@ -5228,6 +5234,97 @@ declare module ex {
}
}
declare module ex {
/**
* Represents an audio control implementation
*/
interface IAudio {
/**
* Set the volume (between 0 and 1)
*/
setVolume(volume: number): any;
/**
* Set whether the audio should loop (repeat forever)
*/
setLoop(loop: boolean): any;
/**
* Whether or not any audio is playing
*/
isPlaying(): boolean;
/**
* Will play the sound or resume if paused
*/
play(): ex.Promise<any>;
/**
* Pause the sound
*/
pause(): any;
/**
* Stop playing the sound and reset
*/
stop(): any;
}
}
declare module ex {
/**
* Represents an audio implementation like [[AudioTag]] or [[WebAudio]]
*/
interface IAudioImplementation {
/**
* XHR response type
*/
responseType: string;
/**
* Processes raw data and transforms into sound data
*/
processData(data: Blob | ArrayBuffer): ex.Promise<string | AudioBuffer>;
/**
* Factory method that returns an instance of a played audio track
*/
createInstance(data: string | AudioBuffer): IAudio;
}
}
declare module ex {
/**
* An audio implementation for HTML5 audio.
*/
class AudioTag implements IAudioImplementation {
responseType: string;
/**
* Transforms raw Blob data into a object URL for use in audio tag
*/
processData(data: Blob): ex.Promise<string>;
/**
* Creates a new instance of an audio tag referencing the provided audio URL
*/
createInstance(url: string): IAudio;
}
/**
* An audio implementation for Web Audio API.
*/
class WebAudio implements IAudioImplementation {
private _logger;
responseType: string;
/**
* Processes raw arraybuffer data and decodes into WebAudio buffer (async).
*/
processData(data: ArrayBuffer): ex.Promise<AudioBuffer>;
/**
* Creates a new WebAudio AudioBufferSourceNode to play a sound instance
*/
createInstance(buffer: AudioBuffer): IAudio;
private static _unlocked;
/**
* Play an empty sound to unlock Safari WebAudio context. Call this function
* right after a user interaction event. Typically used by [[PauseAfterLoader]]
* @source https://paulbakaus.com/tutorials/html5/web-audio-on-ios/
*/
static unlock(): void;
static isUnlocked(): boolean;
}
/**
* Factory method that gets the audio implementation to use
*/
function getAudioImplementation(): IAudioImplementation;
/**
* Sounds
*
Expand All @@ -5252,20 +5349,24 @@ declare module ex {
* });
* ```
*/
class Sound implements ILoadable, ex.Internal.ISound {
class Sound implements ILoadable, IAudio {
private _logger;
private _data;
private _tracks;
private _isLoaded;
private _isPaused;
private _loop;
private _volume;
path: string;
onprogress: (e: any) => void;
oncomplete: () => void;
onerror: (e: any) => void;
onload: (e: any) => void;
private _isLoaded;
private _engine;
private _wasPlayingOnHidden;
/**
* Populated once loading is complete
*/
sound: ex.Internal.FallbackAudio;
sound: IAudioImplementation;
/**
* Whether or not the browser can play this file as HTML5 Audio
*/
Expand All @@ -5275,6 +5376,10 @@ declare module ex {
*/
constructor(...paths: string[]);
wireEngine(engine: Engine): void;
/**
* Returns how many instances of the sound are currently playing
*/
instanceCount(): number;
/**
* Sets the volume of the sound clip
* @param volume A volume value between 0-1.0
Expand All @@ -5292,7 +5397,7 @@ declare module ex {
/**
* Play the sound, returns a promise that resolves when the sound is done playing
*/
play(): ex.Promise<any>;
play(): ex.Promise<boolean>;
/**
* Stop the sound, and do not rewind
*/
Expand All @@ -5308,9 +5413,21 @@ declare module ex {
/**
* Begins loading the sound and returns a promise to be resolved on completion
*/
load(): Promise<ex.Internal.FallbackAudio>;
load(): Promise<IAudioImplementation>;
private _fetchResource(onload);
/**
* Gets the raw sound data (e.g. blob URL or AudioBuffer)
*/
getData(): any;
setData(data: any): void;
/**
* Sets raw sound data and returns a Promise that is resolved when sound data is processed
*
* @param data The XHR data for the sound implementation to process (Blob or ArrayBuffer)
*/
setData(data: any): ex.Promise<any>;
/**
* Set the raw sound data (e.g. blob URL or AudioBuffer)
*/
processData(data: any): any;
}
}
Expand Down Expand Up @@ -5772,108 +5889,6 @@ declare module ex {
play(x: number, y: number): void;
}
}
declare module ex.Internal {
interface ISound {
setVolume(volume: number): any;
setLoop(loop: boolean): any;
isPlaying(): boolean;
play(): ex.Promise<any>;
pause(): any;
stop(): any;
load(): any;
setData(data: any): any;
getData(): any;
processData(data: any): any;
onload: (e: any) => void;
onprogress: (e: any) => void;
onerror: (e: any) => void;
path: string;
}
class FallbackAudio implements ISound {
path: string;
private _soundImpl;
private _log;
constructor(path: string, volume?: number);
setVolume(volume: number): void;
setLoop(loop: boolean): void;
onload: (e: any) => void;
onprogress: (e: any) => void;
onerror: (e: any) => void;
load(): void;
processData(data: any): any;
getData(): any;
setData(data: any): void;
isPlaying(): boolean;
play(): ex.Promise<any>;
pause(): void;
stop(): void;
}
class AudioTag implements ISound {
path: string;
private _audioElements;
private _loadedAudio;
private _isLoaded;
private _index;
private _log;
private _isPlaying;
private _playingTimer;
private _currentOffset;
constructor(path: string, volume?: number);
isPlaying(): boolean;
private _audioLoaded();
setVolume(volume: number): void;
setLoop(loop: boolean): void;
getLoop(): void;
onload: (e: any) => void;
onprogress: (e: any) => void;
onerror: (e: any) => void;
load(): void;
getData(): any;
setData(data: any): void;
processData(data: any): any;
play(): Promise<any>;
pause(): void;
stop(): void;
}
class WebAudio implements ISound {
path: string;
private _context;
private _volume;
private _buffer;
private _sound;
private _isLoaded;
private _loop;
private _isPlaying;
private _isPaused;
private _playingTimer;
private _currentOffset;
private _playPromise;
private _logger;
private _data;
constructor(path: string, volume?: number);
setVolume(volume: number): void;
onload: (e: any) => void;
onprogress: (e: any) => void;
onerror: (e: any) => void;
load(): void;
getData(): any;
setData(data: any): void;
processData(data: any): any;
setLoop(loop: boolean): void;
isPlaying(): boolean;
play(): Promise<any>;
pause(): void;
stop(): void;
private static _unlocked;
/**
* Play an empty sound to unlock Safari WebAudio context. Call this function
* right after a user interaction event. Typically used by [[PauseAfterLoader]]
* @source https://paulbakaus.com/tutorials/html5/web-audio-on-ios/
*/
static unlock(): void;
static isUnlocked(): boolean;
}
}
declare module ex.Util.DrawUtil {
/**
* Draw a line on canvas context
Expand Down
Loading