From 88ac28a4e9c6b0981095c6ffb7ab3077ea8f0c79 Mon Sep 17 00:00:00 2001 From: David Su Date: Sun, 7 Feb 2016 08:49:31 +0800 Subject: [PATCH 01/28] create MultiSoundPlayer constructor, Conductor boilerplate --- .gitignore | 2 ++ .../Sup.Audio.Conductor.d.ts.txt | 7 ++++++ .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 7 ++++++ .../Sup.Audio.MultiSoundPlayer.d.ts.txt | 7 ++++++ .../Sup.Audio.MultiSoundPlayer.ts.txt | 23 +++++++++++++++++++ plugins/default/sound/typescriptAPI/index.ts | 5 ++++ 6 files changed, 51 insertions(+) create mode 100644 plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt create mode 100644 plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt create mode 100644 plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt create mode 100644 plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt diff --git a/.gitignore b/.gitignore index 62de6e38d..7cd7d9bfc 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ plugins/**/*.css plugins/**/*.js !plugins/**/*Gulpfile.js **/node_modules +.DS_Store +npm-debug.log diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt new file mode 100644 index 000000000..9e68ab55f --- /dev/null +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -0,0 +1,7 @@ +namespace Sup { + namespace Audio { + class Conductor { + + } + } +} \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt new file mode 100644 index 000000000..9e68ab55f --- /dev/null +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -0,0 +1,7 @@ +namespace Sup { + namespace Audio { + class Conductor { + + } + } +} \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt new file mode 100644 index 000000000..8a9d0bfd6 --- /dev/null +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -0,0 +1,7 @@ +declare namespace Sup { + namespace Audio { + class MultiSoundPlayer { + constructor(init: string|Sound, loop: string|Sound, tails: Array|Array, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; }); + } + } +} \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt new file mode 100644 index 000000000..5de2f72ae --- /dev/null +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -0,0 +1,23 @@ +namespace Sup { + export namespace Audio { + export class MultiSoundPlayer { + init: SoundPlayer; + loop: SoundPlayer; + tails: Array; + volume: number; + + constructor(init: string|Sound, loop: string|Sound, tails: Array|Array, volume=1.0, options?: { loop?: boolean; pitch?: number; pan?: number; }) { + this.init = new SoundPlayer(init, volume, options); + this.loop = new SoundPlayer(loop, volume, options); + this.tails = []; + + for (var i = 0; i < tails.length; i++) { + let tail = new SoundPlayer(tails[i], volume, options); + this.tails.push(tail); + } + + this.volume = volume; + } + } + } +} \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/index.ts b/plugins/default/sound/typescriptAPI/index.ts index a3036c054..3511f747f 100644 --- a/plugins/default/sound/typescriptAPI/index.ts +++ b/plugins/default/sound/typescriptAPI/index.ts @@ -16,3 +16,8 @@ SupCore.system.registerPlugin("typescriptAPI", "Sup code: fs.readFileSync(`${__dirname}/Sup.Audio.SoundPlayer.ts.txt`, { encoding: "utf8" }), defs: fs.readFileSync(`${__dirname}/Sup.Audio.SoundPlayer.d.ts.txt`, { encoding: "utf8" }) }); + +SupCore.system.registerPlugin("typescriptAPI", "Sup.Audio.MultiSoundPlayer", { + code: fs.readFileSync(`${__dirname}/Sup.Audio.MultiSoundPlayer.ts.txt`, { encoding: "utf8" }), + defs: fs.readFileSync(`${__dirname}/Sup.Audio.MultiSoundPlayer.d.ts.txt`, { encoding: "utf8" }) +}); From 7ef5169cf3a9346eb8c463e8721fbd45b467dfce Mon Sep 17 00:00:00 2001 From: David Su Date: Sun, 7 Feb 2016 08:51:07 +0800 Subject: [PATCH 02/28] add (commented out) getAudioContext() method to Audio class --- plugins/default/sound/typescriptAPI/Sup.Audio.d.ts.txt | 1 + plugins/default/sound/typescriptAPI/Sup.Audio.ts.txt | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.d.ts.txt index b6fed439c..f53c11b46 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.d.ts.txt @@ -2,5 +2,6 @@ declare namespace Sup { namespace Audio { function getMasterVolume(): number; function setMasterVolume(volume: number): void; + // function getAudioContext(): any; } } diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.ts.txt index 19992c36d..0d97e270b 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.ts.txt @@ -8,5 +8,11 @@ namespace Sup { if (player.gameInstance.audio.getContext() == null) return; player.gameInstance.audio.masterGain.gain.value = volume; } + /* + export function getAudioContext() { + if (player.gameInstance.audio.getContext() == null) return 0; + return player.gameInstance.audio.getContext(); + } + */ } } From f142ecd7feec47fd4ab004f6431f4951681b8ffb Mon Sep 17 00:00:00 2001 From: David Su Date: Sun, 7 Feb 2016 10:47:57 +0800 Subject: [PATCH 03/28] define basic Conductor methods and structure (metro still not working); add play() to MultiSoundPlayer --- .../Sup.Audio.Conductor.d.ts.txt | 10 ++- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 66 ++++++++++++++++++- .../Sup.Audio.MultiSoundPlayer.d.ts.txt | 3 +- .../Sup.Audio.MultiSoundPlayer.ts.txt | 35 ++++++++-- plugins/default/sound/typescriptAPI/index.ts | 5 ++ 5 files changed, 110 insertions(+), 9 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 9e68ab55f..d7a389c1e 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -1,7 +1,15 @@ -namespace Sup { +declare namespace Sup { namespace Audio { class Conductor { + constructor(bpm: number, timesig: number, transitionBeats: Array, players: any); + getPlayer(playerName): MultiSoundPlayer | SoundPlayer; + start(); + stop(); + updateBeatTimes(); + } + namespace Conductor { + function calculateNextBeatTime(currentBeatTime: number, bpm: number): number; } } } \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 9e68ab55f..afc1002af 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -1,7 +1,69 @@ namespace Sup { - namespace Audio { - class Conductor { + export namespace Audio { + export class Conductor { + bpm: number; + timesig: number; + currentBeat: number; + transitionBeats: Array; + players: any; // dictionary of players + ctx: any; // audio context + currentBeatTime: number; + nextBeatTime: number; + lookaheadTime: number; + active: boolean; + constructor(bpm: number, timesig: number, transitionBeats: Array, players: any) { + this.bpm = bpm; + this.timesig = timesig; + this.currentBeat = 0; + this.transitionBeats = transitionBeats; + this.players = players; + + this.ctx = player.gameInstance.audio.getContext(); + this.currentBeatTime = this.ctx.currentTime; + this.updateBeatTimes(); + + this.lookaheadTime = 0; + this.active = false; + } + + getPlayer(playerName): MultiSoundPlayer | SoundPlayer { + return this.players[playerName]; + } + + start() { + this.currentBeatTime = this.ctx.currentTime; + this.active = true; + while(this.active && this.nextBeatTime < this.ctx.currentTime + this.lookaheadTime) { + this.currentBeat = (this.currentBeat + 1) % this.timesig; + this.updateBeatTimes(); + Sup.log(this.currentBeat); + } + } + + stop() { + this.active = false; + } + + updateBeatTimes() { + let nextBeatTime = Sup.Audio.Conductor.calculateNextBeatTime(this.currentBeatTime, this.bpm); + this.currentBeatTime = this.nextBeatTime; + this.nextBeatTime = nextBeatTime; + } + + // calculateNextBeatTime(currentBeatTime: number, bpm: number): number { + // return currentBeatTime + ((60 / bpm) * 1000); + // } + } + + export namespace Conductor { + export function calculateNextBeatTime(currentBeatTime: number, bpm: number): number { + return currentBeatTime + ((60 / bpm) * 1000); + } + + // static bpmToMs(bpm) { + // return (60/bpm)*1000; + // } } } } \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt index 8a9d0bfd6..bc402bebb 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -1,7 +1,8 @@ declare namespace Sup { namespace Audio { class MultiSoundPlayer { - constructor(init: string|Sound, loop: string|Sound, tails: Array|Array, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; }); + constructor(init: string|Sound, loop: string|Sound, tails: Array, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; }); + play(beatNum: number /* 0 */); } } } \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 5de2f72ae..d692b73d8 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -3,20 +3,45 @@ namespace Sup { export class MultiSoundPlayer { init: SoundPlayer; loop: SoundPlayer; - tails: Array; + tails: Array; + soundPlayers: any; volume: number; + playMode: string; // init, loop, tail - constructor(init: string|Sound, loop: string|Sound, tails: Array|Array, volume=1.0, options?: { loop?: boolean; pitch?: number; pan?: number; }) { + constructor(init: string|Sound, loop: string|Sound, tails: Array, volume=1.0, options?: { loop?: boolean; pitch?: number; pan?: number; }) { this.init = new SoundPlayer(init, volume, options); - this.loop = new SoundPlayer(loop, volume, options); + this.loop = new SoundPlayer(loop, volume, {loop: true}); + + // for multiple tails corresponding to multiple beats this.tails = []; for (var i = 0; i < tails.length; i++) { - let tail = new SoundPlayer(tails[i], volume, options); - this.tails.push(tail); + let tailAudio = new SoundPlayer(tails[i].audio, volume, options); + let beat = tails[i].beat; + this.tails.push({ + audio: tailAudio, + beat: beat + }); } this.volume = volume; + + this.soundPlayers = { + init: this.init, + loop: this.loop, + tails: this.tails + }; + + this.playMode = "init"; + } + + play(beatNum=0) { + if (this.playMode != "tail") { + this.soundPlayers[this.playMode].play(); + } + else { + this.soundPlayers["tails"][beatNum].play(); + } } } } diff --git a/plugins/default/sound/typescriptAPI/index.ts b/plugins/default/sound/typescriptAPI/index.ts index 3511f747f..4290b181f 100644 --- a/plugins/default/sound/typescriptAPI/index.ts +++ b/plugins/default/sound/typescriptAPI/index.ts @@ -21,3 +21,8 @@ SupCore.system.registerPlugin("typescriptAPI", "Sup code: fs.readFileSync(`${__dirname}/Sup.Audio.MultiSoundPlayer.ts.txt`, { encoding: "utf8" }), defs: fs.readFileSync(`${__dirname}/Sup.Audio.MultiSoundPlayer.d.ts.txt`, { encoding: "utf8" }) }); + +SupCore.system.registerPlugin("typescriptAPI", "Sup.Audio.Conductor", { + code: fs.readFileSync(`${__dirname}/Sup.Audio.Conductor.ts.txt`, { encoding: "utf8" }), + defs: fs.readFileSync(`${__dirname}/Sup.Audio.Conductor.d.ts.txt`, { encoding: "utf8" }) +}); From 4aa5660c920882f4aef31428ba27c87e71107769 Mon Sep 17 00:00:00 2001 From: David Su Date: Mon, 8 Feb 2016 03:51:44 +0800 Subject: [PATCH 04/28] implement working internal metronome for Conductor; add some documentation --- .../Sup.Audio.Conductor.d.ts.txt | 2 +- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 84 ++++++++++++++----- .../Sup.Audio.MultiSoundPlayer.ts.txt | 13 +++ 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index d7a389c1e..575bed6fa 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -5,7 +5,7 @@ declare namespace Sup { getPlayer(playerName): MultiSoundPlayer | SoundPlayer; start(); stop(); - updateBeatTimes(); + updateNextBeatTime(); } namespace Conductor { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index afc1002af..81e90f14c 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -1,64 +1,102 @@ +/* + * A class that schedules audio events, in the form of MultiSoundPlayers, + * based on beats according to an internal metronome. + * + * The metronome is an interval that uses the Web Audio API's clock for timing. + * + */ + namespace Sup { export namespace Audio { export class Conductor { bpm: number; timesig: number; - currentBeat: number; + beatNum: number; transitionBeats: Array; players: any; // dictionary of players ctx: any; // audio context - currentBeatTime: number; nextBeatTime: number; lookaheadTime: number; active: boolean; + interval: any; // the internal metronome + + /* + Constructs a Conductor. + - bpm -> beats per minute + - timesig -> time signature (how many beats in a cycle) + - transitionBeats -> list of beat numbers at which a transition is possible (based on players' tails) + - players -> a dictionary of MultiSoundPlayers + */ constructor(bpm: number, timesig: number, transitionBeats: Array, players: any) { + // set default params + this.beatNum = 0; + this.lookaheadTime = 0; + this.active = false; + + // set params passed in this.bpm = bpm; this.timesig = timesig; - this.currentBeat = 0; this.transitionBeats = transitionBeats; this.players = players; + // create audio context and setup beat time this.ctx = player.gameInstance.audio.getContext(); - this.currentBeatTime = this.ctx.currentTime; - this.updateBeatTimes(); - - this.lookaheadTime = 0; - this.active = false; + this.nextBeatTime = this.ctx.currentTime; + // this.updateNextBeatTime(); } getPlayer(playerName): MultiSoundPlayer | SoundPlayer { return this.players[playerName]; } + /* + Begin the Conductor's scheduling. + */ start() { - this.currentBeatTime = this.ctx.currentTime; + let conductor = this; + + Sup.log("started"); + // this.nextBeatTime = this.ctx.currentTime; this.active = true; - while(this.active && this.nextBeatTime < this.ctx.currentTime + this.lookaheadTime) { - this.currentBeat = (this.currentBeat + 1) % this.timesig; - this.updateBeatTimes(); - Sup.log(this.currentBeat); - } + + // set the interval that increments beat number + this.interval = Sup.setInterval(10, function() { + if (conductor.nextBeatTime < conductor.ctx.currentTime + conductor.lookaheadTime) { + conductor.updateNextBeatTime(); + Sup.log(conductor.beatNum); + conductor.beatNum = (conductor.beatNum + 1) % conductor.timesig; + } + }); } + /* + Stop the Conductor and reset params for next start(). + */ stop() { this.active = false; + Sup.clearInterval(this.interval); + this.beatNum = 0; + Sup.log("stopped " + this.interval); } - updateBeatTimes() { - let nextBeatTime = Sup.Audio.Conductor.calculateNextBeatTime(this.currentBeatTime, this.bpm); - this.currentBeatTime = this.nextBeatTime; + /* + Update the next beat time based on the latest beat time and BPM. + */ + updateNextBeatTime() { + let nextBeatTime = Sup.Audio.Conductor.calculateNextBeatTime(this.nextBeatTime, this.bpm); + // Sup.log(this.nextBeatTime + " -> " + nextBeatTime); this.nextBeatTime = nextBeatTime; } - - // calculateNextBeatTime(currentBeatTime: number, bpm: number): number { - // return currentBeatTime + ((60 / bpm) * 1000); - // } } export namespace Conductor { - export function calculateNextBeatTime(currentBeatTime: number, bpm: number): number { - return currentBeatTime + ((60 / bpm) * 1000); + + /* + Return the next beat time (in seconds). + */ + export function calculateNextBeatTime(beatTime: number, bpm: number): number { + return beatTime + (60 / bpm); } // static bpmToMs(bpm) { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index d692b73d8..5b0e30b92 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -1,3 +1,10 @@ +/* + * A class, comprised of multiple SoundPlayers, that provides methods for + * smoother and more robust game audio in the form of an "init, loop, tail(s)" + * scheme. + * + */ + namespace Sup { export namespace Audio { export class MultiSoundPlayer { @@ -8,6 +15,9 @@ namespace Sup { volume: number; playMode: string; // init, loop, tail + /* + Constructs a MultiSoundPlayer. + */ constructor(init: string|Sound, loop: string|Sound, tails: Array, volume=1.0, options?: { loop?: boolean; pitch?: number; pan?: number; }) { this.init = new SoundPlayer(init, volume, options); this.loop = new SoundPlayer(loop, volume, {loop: true}); @@ -35,6 +45,9 @@ namespace Sup { this.playMode = "init"; } + /* + Play the appropriate sound (init, loop, or tail). + */ play(beatNum=0) { if (this.playMode != "tail") { this.soundPlayers[this.playMode].play(); From 53f0bef248d6fdf8917f36360e78cb2545bd82b7 Mon Sep 17 00:00:00 2001 From: David Su Date: Tue, 9 Feb 2016 22:27:31 +0800 Subject: [PATCH 05/28] successfully implement init-tail-loop playing; restructure MultiSoundPlayer.tails --- .../Sup.Audio.Conductor.d.ts.txt | 4 ++ .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 63 +++++++++++++++++-- .../Sup.Audio.MultiSoundPlayer.d.ts.txt | 5 +- .../Sup.Audio.MultiSoundPlayer.ts.txt | 45 ++++++++++--- 4 files changed, 101 insertions(+), 16 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 575bed6fa..563de97e9 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -6,6 +6,10 @@ declare namespace Sup { start(); stop(); updateNextBeatTime(); + playAllInitOrLoop(); + playAllTails(beatNum: number); + resetAllPlayers(); + setTransition(transition: boolean); } namespace Conductor { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 81e90f14c..5bcd11faf 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -1,8 +1,7 @@ /* * A class that schedules audio events, in the form of MultiSoundPlayers, - * based on beats according to an internal metronome. - * - * The metronome is an interval that uses the Web Audio API's clock for timing. + * based on beats per phrase according to an internal metronome/interval that + * uses the Web Audio API's clock for timing. * */ @@ -10,9 +9,10 @@ namespace Sup { export namespace Audio { export class Conductor { bpm: number; - timesig: number; + timesig: number; // beats per phrase beatNum: number; transitionBeats: Array; + transition: boolean; players: any; // dictionary of players ctx: any; // audio context nextBeatTime: number; @@ -33,6 +33,7 @@ namespace Sup { this.beatNum = 0; this.lookaheadTime = 0; this.active = false; + this.transition = false; // set params passed in this.bpm = bpm; @@ -60,11 +61,35 @@ namespace Sup { // this.nextBeatTime = this.ctx.currentTime; this.active = true; - // set the interval that increments beat number + // set the interval and handle beats + players this.interval = Sup.setInterval(10, function() { if (conductor.nextBeatTime < conductor.ctx.currentTime + conductor.lookaheadTime) { conductor.updateNextBeatTime(); Sup.log(conductor.beatNum); + + if (conductor.transition) { + let beatIndex = conductor.transitionBeats.indexOf(conductor.beatNum); + if (beatIndex >= 0) { // transition beat + conductor.playAllTails(conductor.beatNum); + // conductor.active = false; + + // either do nothing OR begin next section + // depending on active settings + + Sup.log("playing tails for beat " + conductor.beatNum); + } + else { + Sup.log("sorry, no tails found for beat " + conductor.beatNum); + } + } else { + if (conductor.beatNum == 0) { // downbeat + conductor.playAllInitOrLoop(); + + Sup.log("playing downbeat!"); + } + } + + // increment the beat number conductor.beatNum = (conductor.beatNum + 1) % conductor.timesig; } }); @@ -77,7 +102,9 @@ namespace Sup { this.active = false; Sup.clearInterval(this.interval); this.beatNum = 0; + this.transition = false; Sup.log("stopped " + this.interval); + this.resetAllPlayers(); } /* @@ -88,6 +115,32 @@ namespace Sup { // Sup.log(this.nextBeatTime + " -> " + nextBeatTime); this.nextBeatTime = nextBeatTime; } + + playAllInitOrLoop() { + for (var pk in this.players) { + let player = this.players[pk]; + player.playInitOrLoop(); + } + } + + playAllTails(beatNum: number) { + for (var pk in this.players) { + let player = this.players[pk]; + player.playTail(beatNum); + } + } + + resetAllPlayers() { + for (var pk in this.players) { + let player = this.players[pk]; + player.reset(); + } + } + + setTransition(transition: boolean) { + this.transition = transition; + } + } export namespace Conductor { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt index bc402bebb..2bf89493e 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -1,8 +1,11 @@ declare namespace Sup { namespace Audio { class MultiSoundPlayer { - constructor(init: string|Sound, loop: string|Sound, tails: Array, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; }); + constructor(init: string|Sound, loop: string|Sound, tails: any, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; }); play(beatNum: number /* 0 */); + playInitOrLoop(); + playTail(beatNum: number /*0*/); + reset(); } } } \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 5b0e30b92..08f271eb1 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -10,28 +10,26 @@ namespace Sup { export class MultiSoundPlayer { init: SoundPlayer; loop: SoundPlayer; - tails: Array; + tails: any; soundPlayers: any; volume: number; playMode: string; // init, loop, tail + initPlayed: boolean; /* Constructs a MultiSoundPlayer. */ constructor(init: string|Sound, loop: string|Sound, tails: Array, volume=1.0, options?: { loop?: boolean; pitch?: number; pan?: number; }) { this.init = new SoundPlayer(init, volume, options); + // this.loop = new SoundPlayer(loop, volume, options); this.loop = new SoundPlayer(loop, volume, {loop: true}); // for multiple tails corresponding to multiple beats - this.tails = []; - - for (var i = 0; i < tails.length; i++) { - let tailAudio = new SoundPlayer(tails[i].audio, volume, options); - let beat = tails[i].beat; - this.tails.push({ - audio: tailAudio, - beat: beat - }); + this.tails = {}; + + for (var beatNum in tails) { + let tailAudio = tails[beatNum]; + this.tails[beatNum] = new SoundPlayer(tailAudio, volume, options); } this.volume = volume; @@ -43,6 +41,7 @@ namespace Sup { }; this.playMode = "init"; + this.initPlayed = false; } /* @@ -56,6 +55,32 @@ namespace Sup { this.soundPlayers["tails"][beatNum].play(); } } + + // NOTE that calling play() on SoundPlayer won't do anything if it's + // already playing, so loops should be set to {loop: true} + playInitOrLoop() { + if (this.initPlayed) { + this.soundPlayers.loop.play(); + Sup.log("playing loop"); + } + else { + this.soundPlayers.init.play(); + this.initPlayed = true; + Sup.log("playing init"); + } + } + + playTail(beatNum=0) { + this.soundPlayers.loop.setLoop(false); // stop loop from continuing + this.soundPlayers.tails[beatNum].play(); // play tail sample + Sup.log("playing tail"); + + } + + reset() { + this.playMode = "init"; + this.initPlayed = false; + } } } } \ No newline at end of file From e1db0b7f22f48d3931fa1a7cbcd9189f10d756e7 Mon Sep 17 00:00:00 2001 From: David Su Date: Wed, 10 Feb 2016 21:14:35 +0800 Subject: [PATCH 06/28] add 'active' property for MultiSoundPlayers, allow Conductor to reinitialize params and choose diff transition modes ('toNext' still not working 100%), auto-fill transitionBeats --- .../Sup.Audio.Conductor.d.ts.txt | 9 ++- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 60 +++++++++++--- .../Sup.Audio.MultiSoundPlayer.d.ts.txt | 5 +- .../Sup.Audio.MultiSoundPlayer.ts.txt | 78 +++++++++++++------ 4 files changed, 116 insertions(+), 36 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 563de97e9..915767f48 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -1,15 +1,20 @@ declare namespace Sup { namespace Audio { class Conductor { - constructor(bpm: number, timesig: number, transitionBeats: Array, players: any); - getPlayer(playerName): MultiSoundPlayer | SoundPlayer; + constructor(bpm: number, timesig: number, players: any); + initializeParams(params: any); + getPlayer(playerName: string): MultiSoundPlayer | SoundPlayer; start(); stop(); updateNextBeatTime(); playAllInitOrLoop(); playAllTails(beatNum: number); resetAllPlayers(); + setNextParams(params: {bpm: number, timesig: number, players: any}); + setToNext(toNext: boolean); setTransition(transition: boolean); + activatePlayer(playerName: string); + deactivatePlayer(playerName: string); } namespace Conductor { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 5bcd11faf..37c1d737b 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -19,32 +19,49 @@ namespace Sup { lookaheadTime: number; active: boolean; interval: any; // the internal metronome + + toNext: boolean; + nextParams: any; // bpm, timesig, players /* Constructs a Conductor. - bpm -> beats per minute - timesig -> time signature (how many beats in a cycle) - - transitionBeats -> list of beat numbers at which a transition is possible (based on players' tails) - players -> a dictionary of MultiSoundPlayers */ - constructor(bpm: number, timesig: number, transitionBeats: Array, players: any) { + constructor(bpm: number, timesig: number, players: any) { + // initialize parameters + this.initializeParams({bpm, timesig, players}); + + // create audio context and setup beat time + this.ctx = player.gameInstance.audio.getContext(); + this.nextBeatTime = this.ctx.currentTime; + // this.updateNextBeatTime(); + } + + initializeParams(params: any) { // set default params this.beatNum = 0; this.lookaheadTime = 0; this.active = false; this.transition = false; + this.toNext = false; + this.nextParams = {}; // set params passed in - this.bpm = bpm; - this.timesig = timesig; - this.transitionBeats = transitionBeats; - this.players = players; + this.bpm = params.bpm; + this.timesig = params.timesig; + this.transitionBeats = []; + this.players = params.players; - // create audio context and setup beat time - this.ctx = player.gameInstance.audio.getContext(); - this.nextBeatTime = this.ctx.currentTime; - // this.updateNextBeatTime(); + // get transition beats from players' tails + for (var pk in this.players) { + let player = this.players[pk]; + for (var beat in player.tails) { + this.transitionBeats.push(parseInt(beat)); + } + } } getPlayer(playerName): MultiSoundPlayer | SoundPlayer { @@ -75,6 +92,12 @@ namespace Sup { // either do nothing OR begin next section // depending on active settings + if (conductor.toNext) { + conductor.initializeParams(conductor.nextParams); + } + else { // stop + conductor.stop(); + } Sup.log("playing tails for beat " + conductor.beatNum); } @@ -112,6 +135,7 @@ namespace Sup { */ updateNextBeatTime() { let nextBeatTime = Sup.Audio.Conductor.calculateNextBeatTime(this.nextBeatTime, this.bpm); + Sup.log(this.bpm); // Sup.log(this.nextBeatTime + " -> " + nextBeatTime); this.nextBeatTime = nextBeatTime; } @@ -141,6 +165,22 @@ namespace Sup { this.transition = transition; } + setNextParams(params: {bpm: number, timesig: number, players: any}) { + this.nextParams = params; + } + + setToNext(toNext: boolean) { + this.toNext = toNext; + } + + activatePlayer(playerName: string) { + this.players[playerName].activate(); + } + + deactivatePlayer(playerName: string) { + this.players[playerName].deactivate(); + } + } export namespace Conductor { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt index 2bf89493e..aa8070bab 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -1,11 +1,14 @@ declare namespace Sup { namespace Audio { class MultiSoundPlayer { - constructor(init: string|Sound, loop: string|Sound, tails: any, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; }); + constructor(init: string | Sound, loop: string | Sound, tails: any, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}); play(beatNum: number /* 0 */); playInitOrLoop(); playTail(beatNum: number /*0*/); + setPlayMode(playMode: string); reset(); + activate(); + deactivate(); } } } \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 08f271eb1..905639a5a 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -11,15 +11,16 @@ namespace Sup { init: SoundPlayer; loop: SoundPlayer; tails: any; - soundPlayers: any; + // soundPlayers: any; volume: number; playMode: string; // init, loop, tail initPlayed: boolean; + active: boolean; /* Constructs a MultiSoundPlayer. */ - constructor(init: string|Sound, loop: string|Sound, tails: Array, volume=1.0, options?: { loop?: boolean; pitch?: number; pan?: number; }) { + constructor(init: string | Sound, loop: string | Sound, tails: Array, volume = 1.0, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}) { this.init = new SoundPlayer(init, volume, options); // this.loop = new SoundPlayer(loop, volume, options); this.loop = new SoundPlayer(loop, volume, {loop: true}); @@ -34,53 +35,84 @@ namespace Sup { this.volume = volume; - this.soundPlayers = { - init: this.init, - loop: this.loop, - tails: this.tails - }; + // this.soundPlayers = { + // init: this.init, + // loop: this.loop, + // tails: this.tails + // }; this.playMode = "init"; this.initPlayed = false; + + this.active = true; + if (options) { + if ("active" in options) { + this.active = options.active; + } + } } /* Play the appropriate sound (init, loop, or tail). */ play(beatNum=0) { - if (this.playMode != "tail") { - this.soundPlayers[this.playMode].play(); - } - else { - this.soundPlayers["tails"][beatNum].play(); + if (this.active) { + if (this.playMode == "init") { + this.init.play(); + } + else if (this.playMode == "loop") { + this.loop.play(); + } + else if (this.playMode == "tail") { + this.tails[beatNum].play(); + } + else { + Sup.log(this.playMode + " is not a valid playMode"); + } } } // NOTE that calling play() on SoundPlayer won't do anything if it's // already playing, so loops should be set to {loop: true} playInitOrLoop() { - if (this.initPlayed) { - this.soundPlayers.loop.play(); - Sup.log("playing loop"); - } - else { - this.soundPlayers.init.play(); - this.initPlayed = true; - Sup.log("playing init"); + if (this.active) { + if (this.initPlayed) { + this.loop.play(); + Sup.log("playing loop"); + } + else { + this.init.play(); + this.initPlayed = true; + Sup.log("playing init"); + this.playMode = "loop"; + } } } playTail(beatNum=0) { - this.soundPlayers.loop.setLoop(false); // stop loop from continuing - this.soundPlayers.tails[beatNum].play(); // play tail sample - Sup.log("playing tail"); + if (this.active) { + this.loop.setLoop(false); // stop loop from continuing + this.tails[beatNum].play(); // play tail sample + Sup.log("playing tail"); + } + } + setPlayMode(playMode: string) { + this.playMode = playMode; } reset() { this.playMode = "init"; this.initPlayed = false; } + + activate() { + this.active = true; + } + + deactivate() { + this.active = false; + } } } } \ No newline at end of file From 4dd98f413e925dc1a57117e9fd601307c3f7a244 Mon Sep 17 00:00:00 2001 From: David Su Date: Thu, 11 Feb 2016 01:57:01 +0800 Subject: [PATCH 07/28] get toNext transition working fully --- .../sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt | 2 +- .../sound/typescriptAPI/Sup.Audio.Conductor.ts.txt | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 915767f48..19f9c7de6 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -2,7 +2,7 @@ declare namespace Sup { namespace Audio { class Conductor { constructor(bpm: number, timesig: number, players: any); - initializeParams(params: any); + initializeParams(params: {bpm: number, timesig: number, players: any}); getPlayer(playerName: string): MultiSoundPlayer | SoundPlayer; start(); stop(); diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 37c1d737b..70667918e 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -40,7 +40,7 @@ namespace Sup { // this.updateNextBeatTime(); } - initializeParams(params: any) { + initializeParams(params: {bpm: number, timesig: number, players: any}) { // set default params this.beatNum = 0; this.lookaheadTime = 0; @@ -94,21 +94,24 @@ namespace Sup { // depending on active settings if (conductor.toNext) { conductor.initializeParams(conductor.nextParams); + conductor.resetAllPlayers(); } else { // stop conductor.stop(); } Sup.log("playing tails for beat " + conductor.beatNum); + conductor.beatNum = -1; } else { - Sup.log("sorry, no tails found for beat " + conductor.beatNum); + // Sup.log("sorry, no tails found for beat " + conductor.beatNum); } } else { - if (conductor.beatNum == 0) { // downbeat + if (conductor.beatNum <= 0) { // downbeat (allow -1 for toNexts) conductor.playAllInitOrLoop(); Sup.log("playing downbeat!"); + Sup.log(conductor.players); } } From e5278bd87dc0794a7aa256aacbc310f1ef78a9dc Mon Sep 17 00:00:00 2001 From: David Su Date: Thu, 11 Feb 2016 03:06:44 +0800 Subject: [PATCH 08/28] allow msp to take a string in for single tail --- .../Sup.Audio.MultiSoundPlayer.d.ts.txt | 2 +- .../Sup.Audio.MultiSoundPlayer.ts.txt | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt index aa8070bab..abf84b425 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -1,7 +1,7 @@ declare namespace Sup { namespace Audio { class MultiSoundPlayer { - constructor(init: string | Sound, loop: string | Sound, tails: any, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}); + constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string*/, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}); play(beatNum: number /* 0 */); playInitOrLoop(); playTail(beatNum: number /*0*/); diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 905639a5a..444082159 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -20,17 +20,21 @@ namespace Sup { /* Constructs a MultiSoundPlayer. */ - constructor(init: string | Sound, loop: string | Sound, tails: Array, volume = 1.0, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}) { + constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume = 1.0, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}) { this.init = new SoundPlayer(init, volume, options); // this.loop = new SoundPlayer(loop, volume, options); this.loop = new SoundPlayer(loop, volume, {loop: true}); // for multiple tails corresponding to multiple beats this.tails = {}; - - for (var beatNum in tails) { - let tailAudio = tails[beatNum]; - this.tails[beatNum] = new SoundPlayer(tailAudio, volume, options); + if (typeof tails == "object") { + for (var beatNum in tails) { + let tailAudio = tails[beatNum]; + this.tails[beatNum] = new SoundPlayer(tailAudio, volume, options); + } + } + else if (typeof tails == "string" || typeof tails == "Sound") { // default to beat 0 + this.tails[0] = new SoundPlayer(tails, volume, options); } this.volume = volume; From 75c589973f109beb4279c9968663fcf23caa7de4 Mon Sep 17 00:00:00 2001 From: David Su Date: Thu, 11 Feb 2016 05:23:48 +0800 Subject: [PATCH 09/28] trying to implement smarter tail behavior --- .../typescriptAPI/Sup.Audio.Conductor.d.ts.txt | 2 +- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 9 +++++---- .../Sup.Audio.MultiSoundPlayer.d.ts.txt | 4 ++-- .../Sup.Audio.MultiSoundPlayer.ts.txt | 15 +++++++++++++-- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 19f9c7de6..089033488 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -8,7 +8,7 @@ declare namespace Sup { stop(); updateNextBeatTime(); playAllInitOrLoop(); - playAllTails(beatNum: number); + playAllTails(); resetAllPlayers(); setNextParams(params: {bpm: number, timesig: number, players: any}); setToNext(toNext: boolean); diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 70667918e..0bae3cc86 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -87,7 +87,7 @@ namespace Sup { if (conductor.transition) { let beatIndex = conductor.transitionBeats.indexOf(conductor.beatNum); if (beatIndex >= 0) { // transition beat - conductor.playAllTails(conductor.beatNum); + conductor.playAllTails(); // conductor.active = false; // either do nothing OR begin next section @@ -146,14 +146,14 @@ namespace Sup { playAllInitOrLoop() { for (var pk in this.players) { let player = this.players[pk]; - player.playInitOrLoop(); + player.playInitOrLoop(this.beatNum); } } - playAllTails(beatNum: number) { + playAllTails() { for (var pk in this.players) { let player = this.players[pk]; - player.playTail(beatNum); + player.playTail(this.beatNum); } } @@ -182,6 +182,7 @@ namespace Sup { deactivatePlayer(playerName: string) { this.players[playerName].deactivate(); + this.players[playerName].reset(); } } diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt index abf84b425..08cda301c 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -1,9 +1,9 @@ declare namespace Sup { namespace Audio { class MultiSoundPlayer { - constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string*/, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}); + constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}); play(beatNum: number /* 0 */); - playInitOrLoop(); + playInitOrLoop(beatNum: number); playTail(beatNum: number /*0*/); setPlayMode(playMode: string); reset(); diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 444082159..2bb8082a2 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -15,6 +15,7 @@ namespace Sup { volume: number; playMode: string; // init, loop, tail initPlayed: boolean; + tailPlayed: boolean; active: boolean; /* @@ -47,6 +48,7 @@ namespace Sup { this.playMode = "init"; this.initPlayed = false; + this.tailPlayed = false; this.active = true; if (options) { @@ -65,7 +67,9 @@ namespace Sup { this.init.play(); } else if (this.playMode == "loop") { - this.loop.play(); + if (!this.loop.isPlaying()) { + this.loop.play(); + } } else if (this.playMode == "tail") { this.tails[beatNum].play(); @@ -78,7 +82,7 @@ namespace Sup { // NOTE that calling play() on SoundPlayer won't do anything if it's // already playing, so loops should be set to {loop: true} - playInitOrLoop() { + playInitOrLoop(beatNum=0) { if (this.active) { if (this.initPlayed) { this.loop.play(); @@ -91,12 +95,18 @@ namespace Sup { this.playMode = "loop"; } } + // else { + // if (!this.tailPlayed) { + // this.playTail(beatNum); + // } + // } } playTail(beatNum=0) { if (this.active) { this.loop.setLoop(false); // stop loop from continuing this.tails[beatNum].play(); // play tail sample + this.tailPlayed = true; Sup.log("playing tail"); } } @@ -108,6 +118,7 @@ namespace Sup { reset() { this.playMode = "init"; this.initPlayed = false; + this.tailPlayed = false; } activate() { From 2e71cdbe305d6c7d773c2d042be07f448d2a8d41 Mon Sep 17 00:00:00 2001 From: David Su Date: Thu, 11 Feb 2016 21:52:33 +0800 Subject: [PATCH 10/28] add calculation for s/ms until next downbeat; fix up some conductor methods --- .../Sup.Audio.Conductor.d.ts.txt | 12 ++++- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 18 +++++-- .../Sup.Audio.MultiSoundPlayer.ts.txt | 51 +++++++++++-------- 3 files changed, 54 insertions(+), 27 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 089033488..2144e8978 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -3,18 +3,26 @@ declare namespace Sup { class Conductor { constructor(bpm: number, timesig: number, players: any); initializeParams(params: {bpm: number, timesig: number, players: any}); - getPlayer(playerName: string): MultiSoundPlayer | SoundPlayer; + start(); stop(); - updateNextBeatTime(); + playAllInitOrLoop(); playAllTails(); + + getPlayer(playerName: string): MultiSoundPlayer | SoundPlayer; resetAllPlayers(); + setNextParams(params: {bpm: number, timesig: number, players: any}); setToNext(toNext: boolean); setTransition(transition: boolean); + activatePlayer(playerName: string); deactivatePlayer(playerName: string); + + updateNextBeatTime(); + getSecondsLeftUntilNextDownbeat(): number; + getMillisecondsLeftUntilNextDownbeat(): number; } namespace Conductor { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 0bae3cc86..4eb29f30e 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -93,15 +93,16 @@ namespace Sup { // either do nothing OR begin next section // depending on active settings if (conductor.toNext) { - conductor.initializeParams(conductor.nextParams); - conductor.resetAllPlayers(); + conductor.resetAllPlayers(); // reset current players + conductor.initializeParams(conductor.nextParams); // then load next ones + // conductor.resetAllPlayers(); } else { // stop conductor.stop(); } Sup.log("playing tails for beat " + conductor.beatNum); - conductor.beatNum = -1; + conductor.beatNum = -1; // hacky } else { // Sup.log("sorry, no tails found for beat " + conductor.beatNum); @@ -185,6 +186,17 @@ namespace Sup { this.players[playerName].reset(); } + getSecondsLeftUntilNextDownbeat(): number { + let beatsLeft = this.timesig - (this.beatNum % this.timesig); + let secondsLeft = Conductor.calculateNextBeatTime(0, this.bpm) * beatsLeft; + // return secondsLeft * 1000; + return secondsLeft; + } + + getMillisecondsLeftUntilNextDownbeat(): number { + return this.getSecondsLeftUntilNextDownbeat() * 1000; + } + } export namespace Conductor { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 2bb8082a2..52c23b8b4 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -23,8 +23,8 @@ namespace Sup { */ constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume = 1.0, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}) { this.init = new SoundPlayer(init, volume, options); - // this.loop = new SoundPlayer(loop, volume, options); - this.loop = new SoundPlayer(loop, volume, {loop: true}); + this.loop = new SoundPlayer(loop, volume, options); + // this.loop = new SoundPlayer(loop, volume, {loop: true}); // for multiple tails corresponding to multiple beats this.tails = {}; @@ -62,31 +62,38 @@ namespace Sup { Play the appropriate sound (init, loop, or tail). */ play(beatNum=0) { - if (this.active) { - if (this.playMode == "init") { - this.init.play(); - } - else if (this.playMode == "loop") { - if (!this.loop.isPlaying()) { - this.loop.play(); - } - } - else if (this.playMode == "tail") { - this.tails[beatNum].play(); - } - else { - Sup.log(this.playMode + " is not a valid playMode"); - } - } + Sup.log("please use playInitOrLoop() or playTail()"); + + // if (this.active) { + // if (this.playMode == "init") { + // this.init.play(); + // } + // else if (this.playMode == "loop") { + // if (!this.loop.getLoop() || !this.loop.isPlaying()) { + // this.loop.play(); + // } + // } + // else if (this.playMode == "tail") { + // this.tails[beatNum].play(); + // } + // else { + // Sup.log(this.playMode + " is not a valid playMode"); + // } + // } } - // NOTE that calling play() on SoundPlayer won't do anything if it's - // already playing, so loops should be set to {loop: true} playInitOrLoop(beatNum=0) { if (this.active) { if (this.initPlayed) { - this.loop.play(); - Sup.log("playing loop"); + if (!this.loop.getLoop()) { // {loop: false}; retrigger every time + this.loop.stop(); // calling play() on SoundPlayer won't do anything if it's already playing, so we must stop it first + this.loop.play(); + Sup.log("playing loop"); + } + else if (!this.loop.isPlaying) { // {loop: true}; only play if it's not already playing + this.loop.play(); + Sup.log("playing loop"); + } } else { this.init.play(); From 0f9437bb4dffa9645e3411d67e5a1a471d9c62f0 Mon Sep 17 00:00:00 2001 From: David Su Date: Thu, 11 Feb 2016 22:02:12 +0800 Subject: [PATCH 11/28] set playTail() to stop init+loop as well as check for tails[beatNum] --- .../typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 52c23b8b4..8555bd67d 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -110,8 +110,13 @@ namespace Sup { } playTail(beatNum=0) { - if (this.active) { - this.loop.setLoop(false); // stop loop from continuing + // stop init and loop + this.init.stop(); + this.loop.stop(); + this.loop.setLoop(false); // stop loop from continuing + + // play tail + if (this.active && beatNum in this.tails) { this.tails[beatNum].play(); // play tail sample this.tailPlayed = true; Sup.log("playing tail"); From b2bc8d915de3045a26c73e5d56bd106a694c7e78 Mon Sep 17 00:00:00 2001 From: David Su Date: Fri, 12 Feb 2016 03:43:50 +0800 Subject: [PATCH 12/28] implement fade() and setVolume(), set intervalMs to 1 for better performance, output log options --- .../Sup.Audio.Conductor.d.ts.txt | 5 +- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 35 +++++--- .../Sup.Audio.MultiSoundPlayer.d.ts.txt | 8 +- .../Sup.Audio.MultiSoundPlayer.ts.txt | 89 +++++++++++++++++-- 4 files changed, 117 insertions(+), 20 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 2144e8978..cfc091dcd 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -10,7 +10,7 @@ declare namespace Sup { playAllInitOrLoop(); playAllTails(); - getPlayer(playerName: string): MultiSoundPlayer | SoundPlayer; + getPlayer(playerName: string): MultiSoundPlayer; resetAllPlayers(); setNextParams(params: {bpm: number, timesig: number, players: any}); @@ -23,6 +23,9 @@ declare namespace Sup { updateNextBeatTime(); getSecondsLeftUntilNextDownbeat(): number; getMillisecondsLeftUntilNextDownbeat(): number; + + setLogOutput(logOutput: boolean); + log(message?: any); } namespace Conductor { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 4eb29f30e..13e0e64f4 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -19,6 +19,7 @@ namespace Sup { lookaheadTime: number; active: boolean; interval: any; // the internal metronome + logOutput: boolean; toNext: boolean; nextParams: any; // bpm, timesig, players @@ -48,6 +49,7 @@ namespace Sup { this.transition = false; this.toNext = false; this.nextParams = {}; + this.logOutput = false; // set params passed in this.bpm = params.bpm; @@ -64,7 +66,7 @@ namespace Sup { } } - getPlayer(playerName): MultiSoundPlayer | SoundPlayer { + getPlayer(playerName): MultiSoundPlayer { return this.players[playerName]; } @@ -73,16 +75,17 @@ namespace Sup { */ start() { let conductor = this; + let intervalMs = 1; - Sup.log("started"); + this.log("started"); // this.nextBeatTime = this.ctx.currentTime; this.active = true; // set the interval and handle beats + players - this.interval = Sup.setInterval(10, function() { + this.interval = Sup.setInterval(intervalMs, function() { if (conductor.nextBeatTime < conductor.ctx.currentTime + conductor.lookaheadTime) { conductor.updateNextBeatTime(); - Sup.log(conductor.beatNum); + conductor.log(conductor.beatNum); if (conductor.transition) { let beatIndex = conductor.transitionBeats.indexOf(conductor.beatNum); @@ -101,18 +104,18 @@ namespace Sup { conductor.stop(); } - Sup.log("playing tails for beat " + conductor.beatNum); + conductor.log("playing tails for beat " + conductor.beatNum); conductor.beatNum = -1; // hacky } else { - // Sup.log("sorry, no tails found for beat " + conductor.beatNum); + // conductor.log("sorry, no tails found for beat " + conductor.beatNum); } } else { if (conductor.beatNum <= 0) { // downbeat (allow -1 for toNexts) conductor.playAllInitOrLoop(); - Sup.log("playing downbeat!"); - Sup.log(conductor.players); + conductor.log("playing downbeat!"); + conductor.log(conductor.players); } } @@ -130,7 +133,7 @@ namespace Sup { Sup.clearInterval(this.interval); this.beatNum = 0; this.transition = false; - Sup.log("stopped " + this.interval); + this.log("stopped " + this.interval); this.resetAllPlayers(); } @@ -139,8 +142,8 @@ namespace Sup { */ updateNextBeatTime() { let nextBeatTime = Sup.Audio.Conductor.calculateNextBeatTime(this.nextBeatTime, this.bpm); - Sup.log(this.bpm); - // Sup.log(this.nextBeatTime + " -> " + nextBeatTime); + this.log(this.bpm); + // this.log(this.nextBeatTime + " -> " + nextBeatTime); this.nextBeatTime = nextBeatTime; } @@ -197,6 +200,16 @@ namespace Sup { return this.getSecondsLeftUntilNextDownbeat() * 1000; } + setLogOutput(logOutput: boolean) { + this.logOutput = logOutput; + } + + log(message?: any) { + if (this.logOutput) { + Sup.log("Sup.Audio.Conductor: " + message); + } + } + } export namespace Conductor { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt index 08cda301c..10c6d08ae 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -1,7 +1,7 @@ declare namespace Sup { namespace Audio { class MultiSoundPlayer { - constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}); + constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean; logOutput?: boolean;}); play(beatNum: number /* 0 */); playInitOrLoop(beatNum: number); playTail(beatNum: number /*0*/); @@ -9,6 +9,12 @@ declare namespace Sup { reset(); activate(); deactivate(); + getVolume(): number; + setVolume(volume: number); + fade(targetVolume: number, fadeLength: number /* in ms */); + + setLogOutput(logOutput: boolean); + log(message?: any); } } } \ No newline at end of file diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 8555bd67d..62d404266 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -17,11 +17,12 @@ namespace Sup { initPlayed: boolean; tailPlayed: boolean; active: boolean; + logOutput: boolean; /* Constructs a MultiSoundPlayer. */ - constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume = 1.0, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean;}) { + constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume = 1.0, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean; logOutput?: boolean;}) { this.init = new SoundPlayer(init, volume, options); this.loop = new SoundPlayer(loop, volume, options); // this.loop = new SoundPlayer(loop, volume, {loop: true}); @@ -50,19 +51,27 @@ namespace Sup { this.initPlayed = false; this.tailPlayed = false; + // properties adjustable by optional params this.active = true; + this.logOutput = false; + if (options) { if ("active" in options) { this.active = options.active; } + + if ("logOutput" in options) { + this.logOutput = options.logOutput; + } } + } /* Play the appropriate sound (init, loop, or tail). */ play(beatNum=0) { - Sup.log("please use playInitOrLoop() or playTail()"); + this.log("please use playInitOrLoop() or playTail()"); // if (this.active) { // if (this.playMode == "init") { @@ -77,7 +86,7 @@ namespace Sup { // this.tails[beatNum].play(); // } // else { - // Sup.log(this.playMode + " is not a valid playMode"); + // this.log(this.playMode + " is not a valid playMode"); // } // } } @@ -88,17 +97,17 @@ namespace Sup { if (!this.loop.getLoop()) { // {loop: false}; retrigger every time this.loop.stop(); // calling play() on SoundPlayer won't do anything if it's already playing, so we must stop it first this.loop.play(); - Sup.log("playing loop"); + this.log("playing loop"); } else if (!this.loop.isPlaying) { // {loop: true}; only play if it's not already playing this.loop.play(); - Sup.log("playing loop"); + this.log("playing loop"); } } else { this.init.play(); this.initPlayed = true; - Sup.log("playing init"); + this.log("playing init"); this.playMode = "loop"; } } @@ -119,7 +128,7 @@ namespace Sup { if (this.active && beatNum in this.tails) { this.tails[beatNum].play(); // play tail sample this.tailPlayed = true; - Sup.log("playing tail"); + this.log("playing tail"); } } @@ -140,6 +149,72 @@ namespace Sup { deactivate() { this.active = false; } + + getVolume(): number { + return this.volume; + } + + setVolume(volume: number) { + this.init.setVolume(volume); + this.loop.setVolume(volume); + + for (var beatNum in this.tails) { + this.tails[beatNum].setVolume(volume); + } + + this.volume = volume; + } + + setLogOutput(logOutput: boolean) { + this.logOutput = logOutput; + } + + log(message?: any) { + if (this.logOutput) { + Sup.log("Sup.Audio.MultiSoundPlayer: " + message); + } + } + + fade(targetVolume: number, fadeLength: number /* in ms */) { + let intervalMs = 1; + + // let volDiff = Math.abs(this.volume - targetVolume); + let volDiff = this.volume - targetVolume; + if (volDiff < 0) { + volDiff *= -1; + } + + let step = intervalMs * volDiff / fadeLength; + + let direction = "up"; + if (targetVolume < this.volume) { + direction = "down"; + } + + let msp = this; + let timer = Sup.setInterval(intervalMs, function() { + if (direction == "up") { + if (msp.volume >= targetVolume) { + clearInterval(timer); + msp.log("fade " + timer + " done"); + } + else { + msp.setVolume(msp.volume); + msp.volume += step; + } + } + else if (direction == "down") { + if (msp.volume <= targetVolume) { + clearInterval(timer); + msp.log("fade " + timer + " done"); + } + else { + msp.setVolume(msp.volume); + msp.volume -= step; + } + } + }); + } } } } \ No newline at end of file From 5e11cff8dda800c131b6184a920df37d7e4b0dcb Mon Sep 17 00:00:00 2001 From: David Su Date: Fri, 12 Feb 2016 04:04:07 +0800 Subject: [PATCH 13/28] allow next downbeat calculation to take a custom (usually next) bpm --- .../typescriptAPI/Sup.Audio.Conductor.d.ts.txt | 4 ++-- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index cfc091dcd..87ba256bb 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -21,8 +21,8 @@ declare namespace Sup { deactivatePlayer(playerName: string); updateNextBeatTime(); - getSecondsLeftUntilNextDownbeat(): number; - getMillisecondsLeftUntilNextDownbeat(): number; + getSecondsLeftUntilNextDownbeat(bpmIn?: number): number; + getMillisecondsLeftUntilNextDownbeat(bpm?: number): number; setLogOutput(logOutput: boolean); log(message?: any); diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 13e0e64f4..1affdd0ac 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -189,15 +189,22 @@ namespace Sup { this.players[playerName].reset(); } - getSecondsLeftUntilNextDownbeat(): number { + getSecondsLeftUntilNextDownbeat(bpmIn?: number): number { + let bpm = this.bpm; + if (bpmIn) { + bpm = bpmIn; + this.log("bpmIn is " + bpmIn); + } + this.log("bpm is " + bpm); let beatsLeft = this.timesig - (this.beatNum % this.timesig); - let secondsLeft = Conductor.calculateNextBeatTime(0, this.bpm) * beatsLeft; + let secondsLeft = Conductor.calculateNextBeatTime(0, bpm) * beatsLeft; // return secondsLeft * 1000; return secondsLeft; } - getMillisecondsLeftUntilNextDownbeat(): number { - return this.getSecondsLeftUntilNextDownbeat() * 1000; + getMillisecondsLeftUntilNextDownbeat(bpm?: number): number { + this.log("ms: bpm is " + bpm); + return this.getSecondsLeftUntilNextDownbeat(bpm) * 1000; } setLogOutput(logOutput: boolean) { From a7e5d3d1e02888375222946271f1dec4b62f880a Mon Sep 17 00:00:00 2001 From: David Su Date: Fri, 12 Feb 2016 05:03:18 +0800 Subject: [PATCH 14/28] implement getMillisecondsLeftUntilNextTransitionBeat() --- .../Sup.Audio.Conductor.d.ts.txt | 1 + .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 26 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 87ba256bb..35a707b1f 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -23,6 +23,7 @@ declare namespace Sup { updateNextBeatTime(); getSecondsLeftUntilNextDownbeat(bpmIn?: number): number; getMillisecondsLeftUntilNextDownbeat(bpm?: number): number; + getMillisecondsLeftUntilNextTransitionBeat(): number; setLogOutput(logOutput: boolean); log(message?: any); diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 1affdd0ac..72f7890eb 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -142,7 +142,7 @@ namespace Sup { */ updateNextBeatTime() { let nextBeatTime = Sup.Audio.Conductor.calculateNextBeatTime(this.nextBeatTime, this.bpm); - this.log(this.bpm); + // this.log(this.bpm); // this.log(this.nextBeatTime + " -> " + nextBeatTime); this.nextBeatTime = nextBeatTime; } @@ -193,18 +193,30 @@ namespace Sup { let bpm = this.bpm; if (bpmIn) { bpm = bpmIn; - this.log("bpmIn is " + bpmIn); } - this.log("bpm is " + bpm); - let beatsLeft = this.timesig - (this.beatNum % this.timesig); + // this.log("bpm is " + bpm); + let beatsLeft = this.timesig - this.beatNum; let secondsLeft = Conductor.calculateNextBeatTime(0, bpm) * beatsLeft; // return secondsLeft * 1000; return secondsLeft; } - getMillisecondsLeftUntilNextDownbeat(bpm?: number): number { - this.log("ms: bpm is " + bpm); - return this.getSecondsLeftUntilNextDownbeat(bpm) * 1000; + getMillisecondsLeftUntilNextDownbeat(bpmIn?: number): number { + return this.getSecondsLeftUntilNextDownbeat(bpmIn) * 1000; + } + + getMillisecondsLeftUntilNextTransitionBeat(): number { + if (this.transitionBeats.length < 1) { + this.log("no transition beats!"); + return -1; + } + let nextTransitionBeat = this.transitionBeats.slice().sort()[0]; + let beatsLeft = nextTransitionBeat - this.beatNum; + if (beatsLeft < 0) { + beatsLeft *= -1; + } + let secondsLeft = Conductor.calculateNextBeatTime(0, this.bpm) * beatsLeft + return secondsLeft * 1000; } setLogOutput(logOutput: boolean) { From eedd28e8d09111230077d9460a2a94198b3f5bb6 Mon Sep 17 00:00:00 2001 From: David Su Date: Sat, 13 Feb 2016 15:47:59 +0800 Subject: [PATCH 15/28] add api documentation --- .../Sup.Audio.Conductor.d.ts.txt | 46 ++++++++++++++++- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 2 +- .../Sup.Audio.MultiSoundPlayer.d.ts.txt | 50 ++++++++++++++++++- .../Sup.Audio.MultiSoundPlayer.ts.txt | 11 ++++ 4 files changed, 105 insertions(+), 4 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 35a707b1f..cdb5f6d4c 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -1,35 +1,79 @@ +/* + * A music conductor that schedules audio events, in the form of MultiSoundPlayers, + * based on beats per phrase according to an internal metronome/interval that + * uses the Web Audio API's clock for timing. + * + */ + declare namespace Sup { namespace Audio { class Conductor { + + // Construct a Conductor. + // + // - bpm -> beats per minute + // - timesig -> time signature (how many beats in a cycle, i.e. num of beats * num of measures) + // - players -> an object with player names as keys and MultiSoundPlayers as values, + // e.g. {"violin": MultiSoundPlayer, "piano": MultiSoundPlayer} constructor(bpm: number, timesig: number, players: any); + + // Initialize Conductor's members via a params object initializeParams(params: {bpm: number, timesig: number, players: any}); + // Start the Conductor's interval and player scheduling start(); + + // Stop the Conductor and reset params for next start() stop(); + // Have all players play init sample if !initPlayed, otherwise loop sample playAllInitOrLoop(); + + // Have all players play tail samples for Conductor's current beatNum playAllTails(); + // Return a player getPlayer(playerName: string): MultiSoundPlayer; + + // Call reset() on all players resetAllPlayers(); + // Set the params that Conductor will be reinitialized with for next section setNextParams(params: {bpm: number, timesig: number, players: any}); - setToNext(toNext: boolean); + + // Set whether Conductor should transition upon next available beat setTransition(transition: boolean); + // Set whether Conductor should go to next section at the next available transition + // (if false, Conductor will call stop() upon transitioning) + setToNext(toNext: boolean); + + // Activate or deactivate a player activatePlayer(playerName: string); deactivatePlayer(playerName: string); + // Update the next beat's time based on the latest beat time and BPM updateNextBeatTime(); + + // Return time, in seconds, until the next downbeat + // ("downbeat" refers to when beatNum==0) getSecondsLeftUntilNextDownbeat(bpmIn?: number): number; + + // Return time, in milliseconds, until the next downbeat getMillisecondsLeftUntilNextDownbeat(bpm?: number): number; + + // Return time, in milliseconds, until the next available transition beat getMillisecondsLeftUntilNextTransitionBeat(): number; + // Set console logging on/off setLogOutput(logOutput: boolean); + + // Log to console if logOutput is true log(message?: any); } namespace Conductor { + // Return the next beat time (in seconds) function calculateNextBeatTime(currentBeatTime: number, bpm: number): number; } } diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 72f7890eb..6d56527ed 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -1,5 +1,5 @@ /* - * A class that schedules audio events, in the form of MultiSoundPlayers, + * A music conductor that schedules audio events, in the form of MultiSoundPlayers, * based on beats per phrase according to an internal metronome/interval that * uses the Web Audio API's clock for timing. * diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt index 10c6d08ae..0e7d4846b 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -1,19 +1,65 @@ +/* + * A music player, comprised of multiple SoundPlayers, that provides methods for + * smoother and more robust game audio in the form of an "init, loop, tail(s)" + * scheme, allowing for looped sections of varying repetitions to begin and end + * seamlessly. + * + */ + declare namespace Sup { namespace Audio { class MultiSoundPlayer { - constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean; logOutput?: boolean;}); - play(beatNum: number /* 0 */); + + // Construct a MultiSoundPlayer. + // + // init -> sample for the first time the MultiSoundPlayer is played + // loop -> sample for all subsequent repeats + // tails -> sample(s) to play when looping is done + // + // If tails is a string, then the single tail sample will be played for any + // transition, regardless of beat number. + // + // If tails is an object, it should have beat numbers as keys and + // sample paths as values, such as {0: "path/to/tail0.mp3", 6: "path/to/tail6.mp3"} + // In that case, a tail corresponding to a beat number will only be played when + // transitioning on that exact beat. + constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean; logOutput?: boolean;}); + + // Play init, loop, or tail depending on playMode + // play(beatNum: number /* 0 */); + + // Play init or loop sample (depending on whether init has already been played) playInitOrLoop(beatNum: number); + + // Play tail sample for a given beat number playTail(beatNum: number /*0*/); + + // Set the play mode to "init", "loop", or "tail" setPlayMode(playMode: string); + + // Reset the player and the values of its members reset(); + + // Activate a player so that it will play when called on activate(); + + // Deactivate a player so that it doesn't play deactivate(); + + // Get the volume of the player getVolume(): number; + + // Set the volume of the player setVolume(volume: number); + + // Increment the player's volume up or down, over a given amount of time, + // until it reaches the target volume fade(targetVolume: number, fadeLength: number /* in ms */); + // Set console logging on/off setLogOutput(logOutput: boolean); + + // Log to console if logOutput is true log(message?: any); } } diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 62d404266..4efb9a768 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -130,6 +130,17 @@ namespace Sup { this.tailPlayed = true; this.log("playing tail"); } + else { + let keys = []; + for (var key in this.tails) { + keys.push(key); + } + if (keys.length == 1 && 0 in this.tails) { + this.tails[0].play();// play default tail sample + this.tailPlayed = true; + this.log("playing default tail"); + } + } } setPlayMode(playMode: string) { From f210ab87c3d251a05c9d6194bd2e5472d1ba4773 Mon Sep 17 00:00:00 2001 From: David Su Date: Sat, 13 Feb 2016 16:39:22 +0800 Subject: [PATCH 16/28] add getBeatNum(); further doc --- .../typescriptAPI/Sup.Audio.Conductor.d.ts.txt | 16 +++++----------- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 4 ++++ .../Sup.Audio.MultiSoundPlayer.d.ts.txt | 18 ++++-------------- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index cdb5f6d4c..c62425424 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -12,7 +12,8 @@ declare namespace Sup { // Construct a Conductor. // // - bpm -> beats per minute - // - timesig -> time signature (how many beats in a cycle, i.e. num of beats * num of measures) + // - timesig -> time signature (how many beats in a cycle, + // i.e. num of beats * num of measures) // - players -> an object with player names as keys and MultiSoundPlayers as values, // e.g. {"violin": MultiSoundPlayer, "piano": MultiSoundPlayer} constructor(bpm: number, timesig: number, players: any); @@ -22,28 +23,23 @@ declare namespace Sup { // Start the Conductor's interval and player scheduling start(); - // Stop the Conductor and reset params for next start() stop(); // Have all players play init sample if !initPlayed, otherwise loop sample playAllInitOrLoop(); - // Have all players play tail samples for Conductor's current beatNum playAllTails(); // Return a player getPlayer(playerName: string): MultiSoundPlayer; - // Call reset() on all players resetAllPlayers(); // Set the params that Conductor will be reinitialized with for next section setNextParams(params: {bpm: number, timesig: number, players: any}); - - // Set whether Conductor should transition upon next available beat + // Set whether Conductor should transition upon next available beat setTransition(transition: boolean); - // Set whether Conductor should go to next section at the next available transition // (if false, Conductor will call stop() upon transitioning) setToNext(toNext: boolean); @@ -52,22 +48,20 @@ declare namespace Sup { activatePlayer(playerName: string); deactivatePlayer(playerName: string); + // Get the current beat number + getBeatNum(): number; // Update the next beat's time based on the latest beat time and BPM updateNextBeatTime(); - // Return time, in seconds, until the next downbeat // ("downbeat" refers to when beatNum==0) getSecondsLeftUntilNextDownbeat(bpmIn?: number): number; - // Return time, in milliseconds, until the next downbeat getMillisecondsLeftUntilNextDownbeat(bpm?: number): number; - // Return time, in milliseconds, until the next available transition beat getMillisecondsLeftUntilNextTransitionBeat(): number; // Set console logging on/off setLogOutput(logOutput: boolean); - // Log to console if logOutput is true log(message?: any); } diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 6d56527ed..e20a94f70 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -189,6 +189,10 @@ namespace Sup { this.players[playerName].reset(); } + getBeatNum(): number { + return this.beatNum; + } + getSecondsLeftUntilNextDownbeat(bpmIn?: number): number { let bpm = this.bpm; if (bpmIn) { diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt index 0e7d4846b..03581d169 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -23,33 +23,24 @@ declare namespace Sup { // sample paths as values, such as {0: "path/to/tail0.mp3", 6: "path/to/tail6.mp3"} // In that case, a tail corresponding to a beat number will only be played when // transitioning on that exact beat. - constructor(init: string | Sound, loop: string | Sound, tails: any /* object or string */, volume: number /* 1.0 */, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean; logOutput?: boolean;}); - - // Play init, loop, or tail depending on playMode - // play(beatNum: number /* 0 */); + constructor(init: string | Sound, loop: string | Sound, tails: any /*object or string*/, volume: number /*1.0*/, options?: { loop?: boolean; pitch?: number; pan?: number; active?: boolean; logOutput?: boolean;}); // Play init or loop sample (depending on whether init has already been played) playInitOrLoop(beatNum: number); - // Play tail sample for a given beat number playTail(beatNum: number /*0*/); - // Set the play mode to "init", "loop", or "tail" setPlayMode(playMode: string); - // Reset the player and the values of its members - reset(); - // Activate a player so that it will play when called on activate(); - // Deactivate a player so that it doesn't play deactivate(); + // Reset the player and the values of its members + reset(); - // Get the volume of the player + // Get or set the volume of the player getVolume(): number; - - // Set the volume of the player setVolume(volume: number); // Increment the player's volume up or down, over a given amount of time, @@ -58,7 +49,6 @@ declare namespace Sup { // Set console logging on/off setLogOutput(logOutput: boolean); - // Log to console if logOutput is true log(message?: any); } From 5629ef1825cd8fa382d57f8018eb93b6124fca75 Mon Sep 17 00:00:00 2001 From: David Su Date: Sat, 13 Feb 2016 22:53:26 +0100 Subject: [PATCH 17/28] add Conductor.scheduleEvent(); fix up some loop setting during de/activation and resetting for MultiSoundPlayer --- .../Sup.Audio.Conductor.d.ts.txt | 6 +++++ .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 22 +++++++++++++++++-- .../Sup.Audio.MultiSoundPlayer.ts.txt | 13 +++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index c62425424..5ef6621f2 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -60,6 +60,12 @@ declare namespace Sup { // Return time, in milliseconds, until the next available transition beat getMillisecondsLeftUntilNextTransitionBeat(): number; + // Return the Conductor's AudioContext + getContext(): any; + + // Schedule an event to occur a certain number of milliseconds in the future + scheduleEvent(msFromNow: number, event: any); + // Set console logging on/off setLogOutput(logOutput: boolean); // Log to console if logOutput is true diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index e20a94f70..7e36e6bbf 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -19,6 +19,7 @@ namespace Sup { lookaheadTime: number; active: boolean; interval: any; // the internal metronome + intervalMs: number; logOutput: boolean; toNext: boolean; @@ -50,6 +51,7 @@ namespace Sup { this.toNext = false; this.nextParams = {}; this.logOutput = false; + this.intervalMs = 1; // set params passed in this.bpm = params.bpm; @@ -75,14 +77,13 @@ namespace Sup { */ start() { let conductor = this; - let intervalMs = 1; this.log("started"); // this.nextBeatTime = this.ctx.currentTime; this.active = true; // set the interval and handle beats + players - this.interval = Sup.setInterval(intervalMs, function() { + this.interval = Sup.setInterval(this.intervalMs, function() { if (conductor.nextBeatTime < conductor.ctx.currentTime + conductor.lookaheadTime) { conductor.updateNextBeatTime(); conductor.log(conductor.beatNum); @@ -189,6 +190,10 @@ namespace Sup { this.players[playerName].reset(); } + getContext(): any { + return this.ctx; + } + getBeatNum(): number { return this.beatNum; } @@ -223,6 +228,19 @@ namespace Sup { return secondsLeft * 1000; } + scheduleEvent(msFromNow: number, event: any) { + let ctx = this.ctx; + let eventTime = this.ctx.currentTime + (msFromNow / 1000); + let eventInterval = Sup.setInterval(this.intervalMs, function() { + Sup.log(eventTime + ", " + ctx.currentTime); + if (eventTime < ctx.currentTime) { + event(); + Sup.clearInterval(eventInterval); + } + }); + Sup.log("scheduling"); + } + setLogOutput(logOutput: boolean) { this.logOutput = logOutput; } diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 4efb9a768..299027842 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -11,6 +11,7 @@ namespace Sup { init: SoundPlayer; loop: SoundPlayer; tails: any; + originalLoopSetting: boolean; // soundPlayers: any; volume: number; playMode: string; // init, loop, tail @@ -26,6 +27,10 @@ namespace Sup { this.init = new SoundPlayer(init, volume, options); this.loop = new SoundPlayer(loop, volume, options); // this.loop = new SoundPlayer(loop, volume, {loop: true}); + this.originalLoopSetting = false; + if ("loop" in options) { + this.originalLoopSetting = options.loop; + } // for multiple tails corresponding to multiple beats this.tails = {}; @@ -111,6 +116,11 @@ namespace Sup { this.playMode = "loop"; } } + else { + // this.init.stop(); + // this.loop.stop(); + } + // else { // if (!this.tailPlayed) { // this.playTail(beatNum); @@ -151,14 +161,17 @@ namespace Sup { this.playMode = "init"; this.initPlayed = false; this.tailPlayed = false; + this.loop.setLoop(this.originalLoopSetting); } activate() { this.active = true; + this.loop.setLoop(this.originalLoopSetting); } deactivate() { this.active = false; + this.loop.setLoop(false); } getVolume(): number { From 148101eb1363944eab3633f9dfcefa26c50b9134 Mon Sep 17 00:00:00 2001 From: David Su Date: Mon, 15 Feb 2016 23:20:39 +0100 Subject: [PATCH 18/28] fix transitionBeat sorting; add getBpm() --- .../Sup.Audio.Conductor.d.ts.txt | 2 ++ .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 27 ++++++++++++++++-- .../Sup.Audio.MultiSoundPlayer.ts.txt | 28 ++++++++++--------- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 5ef6621f2..7c05b6111 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -60,6 +60,8 @@ declare namespace Sup { // Return time, in milliseconds, until the next available transition beat getMillisecondsLeftUntilNextTransitionBeat(): number; + // Return the Conductor's BPM + getBpm(): number; // Return the Conductor's AudioContext getContext(): any; diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 7e36e6bbf..040f49d7a 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -159,6 +159,9 @@ namespace Sup { for (var pk in this.players) { let player = this.players[pk]; player.playTail(this.beatNum); + + // player.init.stop(); + // player.loop.stop(); } } @@ -198,6 +201,10 @@ namespace Sup { return this.beatNum; } + getBpm(): number { + return this.bpm; + } + getSecondsLeftUntilNextDownbeat(bpmIn?: number): number { let bpm = this.bpm; if (bpmIn) { @@ -219,12 +226,28 @@ namespace Sup { this.log("no transition beats!"); return -1; } - let nextTransitionBeat = this.transitionBeats.slice().sort()[0]; + + let numericComparison = function(a, b) { + return a - b; + }; + let tbSorted = this.transitionBeats.slice().sort(numericComparison); + tbSorted.push(tbSorted[0] + this.timesig); // add first transition beat of next cycle + // let nextTransitionBeat = tbSorted[tbSorted.length-1]; + tbSorted.reverse(); + + let nextTransitionBeat = tbSorted[0]; + for (var i = 0; i < tbSorted.length; i++) { + if (tbSorted[i] > this.beatNum) { + nextTransitionBeat = tbSorted[i]; + } + } + this.log("current beat: " + this.beatNum + ", nextTransitionBeat: " + nextTransitionBeat); + let beatsLeft = nextTransitionBeat - this.beatNum; if (beatsLeft < 0) { beatsLeft *= -1; } - let secondsLeft = Conductor.calculateNextBeatTime(0, this.bpm) * beatsLeft + let secondsLeft = Conductor.calculateNextBeatTime(0, this.bpm) * beatsLeft; return secondsLeft * 1000; } diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 299027842..0f3e5c40d 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -135,20 +135,22 @@ namespace Sup { this.loop.setLoop(false); // stop loop from continuing // play tail - if (this.active && beatNum in this.tails) { - this.tails[beatNum].play(); // play tail sample - this.tailPlayed = true; - this.log("playing tail"); - } - else { - let keys = []; - for (var key in this.tails) { - keys.push(key); - } - if (keys.length == 1 && 0 in this.tails) { - this.tails[0].play();// play default tail sample + if (this.active) { + if (beatNum in this.tails) { + this.tails[beatNum].play(); // play tail sample this.tailPlayed = true; - this.log("playing default tail"); + this.log("playing tail"); + } + else { + let keys = []; + for (var key in this.tails) { + keys.push(key); + } + if (keys.length == 1 && 0 in this.tails) { + this.tails[0].play();// play default tail sample + this.tailPlayed = true; + this.log("playing default tail"); + } } } } From 1e40bea9b9f7e9558cceab4f62836e035850b2cb Mon Sep 17 00:00:00 2001 From: David Su Date: Tue, 16 Feb 2016 00:15:04 +0100 Subject: [PATCH 19/28] add isTransitioning() and comment out event schedule timing --- .../sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt | 2 ++ .../default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 7c05b6111..4d737b722 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -43,6 +43,8 @@ declare namespace Sup { // Set whether Conductor should go to next section at the next available transition // (if false, Conductor will call stop() upon transitioning) setToNext(toNext: boolean); + // Get whether Conductor is transitioning + isTransitioning(): boolean; // Activate or deactivate a player activatePlayer(playerName: string); diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 040f49d7a..b4505d8e5 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -184,6 +184,10 @@ namespace Sup { this.toNext = toNext; } + isTransitioning(): boolean { + return this.transition; + } + activatePlayer(playerName: string) { this.players[playerName].activate(); } @@ -255,7 +259,7 @@ namespace Sup { let ctx = this.ctx; let eventTime = this.ctx.currentTime + (msFromNow / 1000); let eventInterval = Sup.setInterval(this.intervalMs, function() { - Sup.log(eventTime + ", " + ctx.currentTime); + // Sup.log(eventTime + ", " + ctx.currentTime); if (eventTime < ctx.currentTime) { event(); Sup.clearInterval(eventInterval); From 8a20e519fba6b9fae1e46c25c672fcf7139c059a Mon Sep 17 00:00:00 2001 From: David Su Date: Tue, 16 Feb 2016 02:06:28 +0100 Subject: [PATCH 20/28] explain init-loop-tail more --- .../sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt index 0f3e5c40d..acb12a942 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.ts.txt @@ -1,7 +1,11 @@ /* * A class, comprised of multiple SoundPlayers, that provides methods for * smoother and more robust game audio in the form of an "init, loop, tail(s)" - * scheme. + * scheme similar to that of other game audio engines. + * + * In other words, the first time a MultiSoundPlayer is played, it should play + * the "init" sample; subsequent plays will play the "loop" sample, and the final + * time it should play the "tail" sample for the corresponding beat number. * */ From 8a851040ca81c9e158f106ac080255b87bb9d89f Mon Sep 17 00:00:00 2001 From: David Su Date: Tue, 16 Feb 2016 10:57:32 +0100 Subject: [PATCH 21/28] and to the .d.ts file --- .../sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt index 03581d169..76eb36aca 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.MultiSoundPlayer.d.ts.txt @@ -4,6 +4,10 @@ * scheme, allowing for looped sections of varying repetitions to begin and end * seamlessly. * + * The first time a MultiSoundPlayer is played, it should play + * the "init" sample; subsequent plays will play the "loop" sample, and the final + * time it should play the "tail" sample for the corresponding beat number. + * */ declare namespace Sup { From 89fe73eeec05d103c28b21636d5e7812725eb0fe Mon Sep 17 00:00:00 2001 From: David Su Date: Thu, 10 Nov 2016 16:16:02 +0100 Subject: [PATCH 22/28] add methods for conductor to activate multiple players from an array of names --- .../Sup.Audio.Conductor.d.ts.txt | 4 +++ .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 28 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 4d737b722..99f0f0b33 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -49,6 +49,10 @@ declare namespace Sup { // Activate or deactivate a player activatePlayer(playerName: string); deactivatePlayer(playerName: string); + + // Activate or deactivate multiple players + activatePlayers(playerNames: Array); + deactivatePlayers(playerNames: Array); // Get the current beat number getBeatNum(): number; diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index b4505d8e5..49da7b2e4 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -189,12 +189,34 @@ namespace Sup { } activatePlayer(playerName: string) { - this.players[playerName].activate(); + if (this.players[playerName]) { + this.players[playerName].activate(); + } + else { + this.log("no player named " + playerName + " found!"); + } } deactivatePlayer(playerName: string) { - this.players[playerName].deactivate(); - this.players[playerName].reset(); + if (this.players[playerName]) { + this.players[playerName].deactivate(); + this.players[playerName].reset(); + } + else { + this.log("no player named " + playerName + " found!"); + } + } + + activatePlayers(playerNames: Array) { + for (var playerName of playerNames) { + this.activatePlayer(playerName); + } + } + + deactivatePlayers(playerNames: Array) { + for (var playerName of playerNames) { + this.deactivatePlayer(playerName); + } } getContext(): any { From 221af8e3b007fcf0bf72dfeaf9eab82134244565 Mon Sep 17 00:00:00 2001 From: David Su Date: Thu, 10 Nov 2016 17:44:37 +0100 Subject: [PATCH 23/28] add conductor methods to safely fade one, some, or all players --- .../Sup.Audio.Conductor.d.ts.txt | 7 +++++- .../typescriptAPI/Sup.Audio.Conductor.ts.txt | 25 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 99f0f0b33..883fbc210 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -53,7 +53,12 @@ declare namespace Sup { // Activate or deactivate multiple players activatePlayers(playerNames: Array); deactivatePlayers(playerNames: Array); - + + // Fade a single player, multiple players, or all players + fadePlayer(playerName: string, targetVolume: number, fadeLength: number /* in ms */); + fadePlayers(playerNames: Array, targetVolume: number, fadeLength: number); + fadeAllPlayers(targetVolume: number, fadeLength: number); + // Get the current beat number getBeatNum(): number; // Update the next beat's time based on the latest beat time and BPM diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index 49da7b2e4..f63e94398 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -193,7 +193,7 @@ namespace Sup { this.players[playerName].activate(); } else { - this.log("no player named " + playerName + " found!"); + this.log("activatePlayer: no player named " + playerName + " found!"); } } @@ -203,7 +203,7 @@ namespace Sup { this.players[playerName].reset(); } else { - this.log("no player named " + playerName + " found!"); + this.log("deactivatePlayer: no player named " + playerName + " found!"); } } @@ -219,6 +219,27 @@ namespace Sup { } } + fadePlayer(playerName: string, targetVolume: number, fadeLength: number /* in ms */) { + if (this.players[playerName]) { + this.players[playerName].fade(targetVolume, fadeLength); + } + else { + this.log("fadePlayer: no player named " + playerName + " found!"); + } + } + + fadePlayers(playerNames: Array, targetVolume: number, fadeLength: number) { + for (var playerName of playerNames) { + this.fadePlayer(playerName, targetVolume, fadeLength); + } + } + + fadeAllPlayers(targetVolume: number, fadeLength: number) { + for (var pk in this.players) { + this.fadePlayer(pk, targetVolume, fadeLength); + } + } + getContext(): any { return this.ctx; } From a8e273079691045e0acb9eff7178771f277919bd Mon Sep 17 00:00:00 2001 From: David Su Date: Thu, 10 Nov 2016 17:46:29 +0100 Subject: [PATCH 24/28] add conductor methods to activate/deactivate all players --- .../sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt | 4 ++++ .../sound/typescriptAPI/Sup.Audio.Conductor.ts.txt | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt index 883fbc210..5c6e914cb 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.d.ts.txt @@ -54,6 +54,10 @@ declare namespace Sup { activatePlayers(playerNames: Array); deactivatePlayers(playerNames: Array); + // Activate or deactivate all players + activateAllPlayers(); + deactivateAllPlayers(); + // Fade a single player, multiple players, or all players fadePlayer(playerName: string, targetVolume: number, fadeLength: number /* in ms */); fadePlayers(playerNames: Array, targetVolume: number, fadeLength: number); diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt index f63e94398..966c1e1ca 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.Conductor.ts.txt @@ -219,6 +219,18 @@ namespace Sup { } } + activateAllPlayers() { + for (var pk in this.players) { + this.activatePlayer(pk); + } + } + + deactivateAllPlayers() { + for (var pk in this.players) { + this.deactivatePlayer(pk); + } + } + fadePlayer(playerName: string, targetVolume: number, fadeLength: number /* in ms */) { if (this.players[playerName]) { this.players[playerName].fade(targetVolume, fadeLength); From 30ac5d9c626c30a863a0a94fe1ce112de28e5717 Mon Sep 17 00:00:00 2001 From: David Su Date: Sat, 11 Feb 2017 17:22:35 -0800 Subject: [PATCH 25/28] update plugins/common subproject commit --- plugins/common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/common b/plugins/common index b3df3bfd4..919f700ce 160000 --- a/plugins/common +++ b/plugins/common @@ -1 +1 @@ -Subproject commit b3df3bfd40dfa7602b092a68b60be6b8823efc62 +Subproject commit 919f700ced7db2d26a5ddbfe547fe43c1003d740 From 015b39bf11cb92a07bf9226668abbe101ec20f83 Mon Sep 17 00:00:00 2001 From: David Su Date: Sat, 11 Feb 2017 17:34:28 -0800 Subject: [PATCH 26/28] revert Sup.Audio.ts.txt to original; (get rid of trailing whitespace) --- .../sound/typescriptAPI/Sup.Audio.ts.txt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/default/sound/typescriptAPI/Sup.Audio.ts.txt b/plugins/default/sound/typescriptAPI/Sup.Audio.ts.txt index 19992c36d..a9c496f13 100644 --- a/plugins/default/sound/typescriptAPI/Sup.Audio.ts.txt +++ b/plugins/default/sound/typescriptAPI/Sup.Audio.ts.txt @@ -1,12 +1,12 @@ -namespace Sup { - export namespace Audio { - export function getMasterVolume(volume) { - if (player.gameInstance.audio.getContext() == null) return 0; - return player.gameInstance.audio.masterGain.gain.value; - } - export function setMasterVolume(volume) { - if (player.gameInstance.audio.getContext() == null) return; - player.gameInstance.audio.masterGain.gain.value = volume; - } - } -} +namespace Sup { + export namespace Audio { + export function getMasterVolume(volume) { + if (player.gameInstance.audio.getContext() == null) return 0; + return player.gameInstance.audio.masterGain.gain.value; + } + export function setMasterVolume(volume) { + if (player.gameInstance.audio.getContext() == null) return; + player.gameInstance.audio.masterGain.gain.value = volume; + } + } +} From be5916164bcea8b3ca2d6faf0bc10158dc1823df Mon Sep 17 00:00:00 2001 From: David Su Date: Sat, 11 Feb 2017 17:37:17 -0800 Subject: [PATCH 27/28] Revert "update plugins/common subproject commit" This reverts commit 30ac5d9c626c30a863a0a94fe1ce112de28e5717. --- plugins/common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/common b/plugins/common index 919f700ce..b3df3bfd4 160000 --- a/plugins/common +++ b/plugins/common @@ -1 +1 @@ -Subproject commit 919f700ced7db2d26a5ddbfe547fe43c1003d740 +Subproject commit b3df3bfd40dfa7602b092a68b60be6b8823efc62 From db50ec4650a50701d95819e970d8a0390bcda51d Mon Sep 17 00:00:00 2001 From: David Su Date: Sat, 11 Feb 2017 17:44:10 -0800 Subject: [PATCH 28/28] fix plugins/common commit hash number to match master branch --- plugins/common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/common b/plugins/common index b3df3bfd4..19888790f 160000 --- a/plugins/common +++ b/plugins/common @@ -1 +1 @@ -Subproject commit b3df3bfd40dfa7602b092a68b60be6b8823efc62 +Subproject commit 19888790ffefebef1c4d1b52cbd331ac0a866189