Nuke trailing whitespace (#35)

master
Anna-Maria Meriniemi 7 years ago committed by Will
parent 287e95121f
commit a225a103b1
  1. 2
      gulpfile.js
  2. 4
      index.html
  3. 50
      src/js/HuesCanvas.js
  4. 84
      src/js/HuesCore.js
  5. 206
      src/js/HuesEditor.js
  6. 14
      src/js/HuesInfo.js
  7. 30
      src/js/HuesSettings.js
  8. 72
      src/js/HuesUI.js
  9. 28
      src/js/HuesWindow.js
  10. 36
      src/js/ResourceManager.js
  11. 4
      src/js/ResourcePack.js
  12. 68
      src/js/SoundManager.js

@ -96,7 +96,7 @@ gulp.task('release', ['default', 'lint'], function() {
'favicon.ico'], {
base: '.'
}).pipe(gulp.dest('release'));
gulp.src(['lib/workers/**/*','lib/zip*'], {base: 'lib'})
.pipe(uglify())
.pipe(gulp.dest("release/lib"));

@ -12,8 +12,8 @@
window.addEventListener("load", function() {
var defaults = {
workersPath : "lib/workers/",
respacks : ["./respacks/Defaults_v5.0.zip",
"./respacks/CharPackagev0.03.zip",
respacks : ["./respacks/Defaults_v5.0.zip",
"./respacks/CharPackagev0.03.zip",
"./respacks/HuesMixA.zip"
],
firstSong : "Nhato - Miss You",

@ -58,14 +58,14 @@ class HuesCanvas {
this.blurDistance = 0;
this.xBlur = false;
this.yBlur = false;
this.sliceDistance = 0;
this.sliceStart = 0;
this.slices = {
x : this.makeSliceObj(25),
y : this.makeSliceObj(15)
};
// trippy mode
this.trippyStart = [0, 0]; // x, y
this.trippyRadii = [0, 0]; // x, y
@ -80,7 +80,7 @@ class HuesCanvas {
this.lastBlackout = 0;
this.currentBlackout = -1;
this.lastFrameBlack = false;
this.invert = false;
this.colourFade = false;
@ -94,21 +94,21 @@ class HuesCanvas {
this.setBlurAmount("medium");
this.setBlurQuality("high");
this.setBlurDecay("fast");
this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext("2d");
this.canvas.width = 1280;
this.canvas.height = 720;
this.canvas.className = "hues-canvas";
root.appendChild(this.canvas);
this.offCanvas = document.createElement('canvas');
this.offContext = this.offCanvas.getContext('2d');
window.addEventListener('resize', this.resize.bind(this));
this.resize();
}
makeSliceObj(avgSegments) {
return {
count : 0,
@ -130,7 +130,7 @@ class HuesCanvas {
this.setBlurQuality(this.core.settings.blurQuality);
this.trippyOn = this.core.settings.trippyMode == "on";
}
resetEffects() {
this.colourFadeStart = 0;
this.colourFade = false;
@ -211,13 +211,13 @@ class HuesCanvas {
} else {
offset = width/2 - drawWidth/2;
}
if(this.sliceStart) {
bitmap = this.drawSlice(bitmap, drawWidth, drawHeight, width, height);
drawWidth = width;
drawHeight = height;
}
if(this.xBlur || this.yBlur) {
this.drawBlur(bitmap, offset, drawWidth, drawHeight);
}else {
@ -225,7 +225,7 @@ class HuesCanvas {
this.context.drawImage(bitmap, offset, 0, drawWidth, drawHeight);
}
}
if(this.trippyStart[0] || this.trippyStart[1]) {
this.drawTrippy(width, height);
} else {
@ -287,10 +287,10 @@ class HuesCanvas {
bitmapXOffset += segmentBitmapWidth;
drawXOffset += segmentDrawWidth;
}
return this.offCanvas;
}
drawBlur(bitmap, offset, drawWidth, drawHeight) {
this.context.globalAlpha = this.blurAlpha;
if(this.xBlur) {
@ -326,12 +326,12 @@ class HuesCanvas {
let normalC = this.intToHex(this.colour);
this.offContext.fillStyle = baseInvert ? invertC : normalC;
this.offContext.fillRect(0,0,width,height);
// sort high to low
this.trippyRadii.sort(function(a,b) {
return b - a;
});
let invert = !baseInvert;
for(let i = 0; i < 2; i++) {
if(this.trippyRadii[i] === 0) {
@ -390,7 +390,7 @@ class HuesCanvas {
// flash offsets blur gen by a frame
let delta = this.audio.currentTime - this.blurStart + (1/30);
this.blurDistance = this.blurAmount * Math.exp(-this.blurDecay * delta);
// Update UI
let dist = this.blurDistance / this.blurAmount;
if(this.xBlur)
@ -436,7 +436,7 @@ class HuesCanvas {
}
}
}
if(this.blurStart && this.blurDistance < 1) {
this.core.blurUpdated(0, 0);
this.blurDistance = 0;
@ -544,7 +544,7 @@ class HuesCanvas {
this.blackoutTimeout = this.audio.currentTime + beatTime / 1.7;
this.currentBlackout++;
}
doInstantBlackout() {
this.doBlackout();
// sufficiently negative
@ -613,15 +613,15 @@ class HuesCanvas {
this.doYBlur();
this.trippyOn = saveTrippy;
}
doSlice(beatLength, beatCount, sliceX, sliceY) {
let transitionTime = Math.min(0.06, beatLength);
this.sliceStart = this.audio.currentTime;
this.sliceRampUp = this.sliceStart + transitionTime;
this.sliceRampDown = this.sliceStart + (beatLength * beatCount) - transitionTime;
this.sliceTransitionTime = transitionTime;
if (sliceX)
this.generateSliceSegments('x');
else
@ -633,7 +633,7 @@ class HuesCanvas {
this.needsRedraw = true;
}
generateSliceSegments(direction) {
let even = 1.0 / this.slices[direction].avgSegments;
let spread = even / 2;
@ -643,16 +643,16 @@ class HuesCanvas {
let rando = even + Math.random() * spread * 2 - spread;
this.slices[direction].segments[i] = rando;
total += rando;
this.slices[direction].distances[i] =
Math.random() * this.blurAmount - this.blurAmount / 2;
if(total > 1.0) {
this.slices[direction].segments[i] -= total - 1.0;
break;
}
}
this.slices[direction].count = i + 1;
}

@ -30,34 +30,34 @@ class HuesCore {
* When everything has completely loaded and we're ready to go
*/
loaded : [],
/* callback time(seconds)
*
* When the song time is updated - negative for buildup
* Returns a floating point number denoting seconds
*/
time : [],
/* callback blurUpdate(xPercent, yPercent)
*
* The current blur amounts, in percent of full blur
*/
blurupdate : [],
/* callback newsong(song)
*
* Called on song change, whether user triggered or autosong.
* Song object is passed.
*/
newsong : [],
/* callback newimage(image)
*
* Called on image change, whether user triggered or FULL AUTO mode.
* Image object is passed.
*/
newimage : [],
/* callback newcolour(colour, isFade)
*
* Called on colour change.
@ -65,14 +65,14 @@ class HuesCore {
* isFade: if the colour is fading from the previous value
*/
newcolour : [],
/* callback newmode(mode)
*
* Called on mode change.
* Mode is passed as a boolean.
*/
newmode : [],
/* callback beat(beatString, beatIndex)
*
* Called on every new beat.
@ -80,27 +80,27 @@ class HuesCore {
* beatIndex is the beat index. Negative during buildups
*/
beat : [],
/* callback invert(isInverted)
*
* Called whenever the invert state changes.
* Invert state is passed as a boolean.
*/
invert : [],
/* callback frame()
*
* Called on each new frame, at the end of all other frame processing
*/
frame : [],
/* callback songstarted(song)
*
* Called when the song actually begins to play, not just when the
* new song processing begins. Song object passed.
*/
songstarted : [],
/* callback settingsupdated()
*
* Called when settings are updated and should be re-read from the settings object
@ -113,30 +113,30 @@ class HuesCore {
this.versionStr = (this.version/10).toFixed(1);
this.versionHex = this.version.toString(16);
this.beatIndex = 0;
// How long a beat lasts for in each section
this.buildLength = -1;
this.loopLength = -1;
this.currentSong = null;
this.currentImage = null;
this.songIndex = -1;
this.imageIndex = -1;
this.lastSongArray = [];
this.lastImageArray = [];
this.colourIndex = 0x3f;
this.colours = HuesCore.oldColours;
this.invert = false;
this.loopCount = 0;
this.doBuildup = true;
this.userInterface = null;
this.uiArray = [];
this.settings = new HuesSettings(defaults);
zip.workerScriptsPath = this.settings.workersPath;
// What's our root element?
this.root = null;
if(!this.settings.root) {
@ -157,7 +157,7 @@ class HuesCore {
}
// Yes, we do indeed have Javascript
this.root.innerHTML = "";
this.makePreloader(this.root);
window.onerror = (msg, url, line, col, error) => {
@ -165,16 +165,16 @@ class HuesCore {
// Get more info in console
return false;
};
this.window = new HuesWindow(this.root, this.settings);
console.log("0x40 Hues v" + this.versionStr + " - start your engines!");
this.resourceManager = new Resources(this, this.window);
this.editor = new HuesEditor(this, this.window);
this.settings.initUI(this.window);
populateHuesInfo(this.versionStr, this.window, this.settings);
this.window.selectTab(this.settings.firstWindow, true);
let ui = document.createElement("div");
@ -182,16 +182,16 @@ class HuesCore {
this.root.appendChild(ui);
this.uiArray.push(new RetroUI(ui), new WeedUI(ui), new ModernUI(ui),
new XmasUI(ui), new HalloweenUI(ui), new MinimalUI(ui));
this.autoSong = this.settings.autoSong;
this.visualiser = document.createElement("canvas");
this.visualiser.className = "hues-visualiser";
this.visualiser.height = "64";
this.vCtx = this.visualiser.getContext("2d");
this.soundManager = new SoundManager(this);
this.soundManager.init().then(() => {
if(!this.soundManager.locked && this.settings.skipPreloader == "on") {
return null;
@ -202,7 +202,7 @@ class HuesCore {
if(sizes === null) {
return;
}
let size = sizes.reduce( (prev, curr) => {
return typeof curr === 'number' ? prev + curr : null;
}, 0);
@ -211,11 +211,11 @@ class HuesCore {
} else {
size = '<abbr title="Content-Length header not present for respack URLs">???</abbr>';
}
let warning = size + "MB of music/images.<br />" +
"Flashing lights.<br />" +
"<b>Tap or click to start</b>";
if(!this.soundManager.locked) {
warning += "<br /><span>Skip this screen from Options</span>";
}
@ -231,7 +231,7 @@ class HuesCore {
this.settingsUpdated();
this.setColour(this.colourIndex);
this.animationLoop();
if(this.settings.load) {
return this.resourceManager.addAll(this.settings.respacks, progress => {
this.preloader.style.backgroundPosition = (100 - progress*100) + "% 0%";
@ -316,19 +316,19 @@ class HuesCore {
this.preloader = document.createElement("div");
this.preloader.className = "hues-preloader";
root.appendChild(this.preloader);
if(this.settings.preloadTitle) {
this.preloadTitle = document.createElement("div");
this.preloadTitle.className = "hues-preloader__title";
this.preloadTitle.textContent = this.settings.preloadTitle;
this.preloader.appendChild(this.preloadTitle);
}
this.preloadMsg = document.createElement("div");
this.preloadMsg.className = "hues-preloader__text";
this.preloadMsg.textContent = "Initialising...";
this.preloader.appendChild(this.preloadMsg);
this.preloadSubMsg = document.createElement("div");
this.preloadSubMsg.className = "hues-preloader__subtext";
this.preloader.appendChild(this.preloadSubMsg);
@ -342,14 +342,14 @@ class HuesCore {
if(this.settings.visualiser != "on") {
return;
}
let logArrays = this.soundManager.getVisualiserData();
if(!logArrays) {
return;
}
this.vCtx.clearRect(0, 0, this.vCtx.canvas.width, this.vCtx.canvas.height);
let gradient=this.vCtx.createLinearGradient(0,64,0,0);
if(this.invert) {
gradient.addColorStop(1,"rgba(20,20,20,0.6)");
@ -359,7 +359,7 @@ class HuesCore {
gradient.addColorStop(0,"rgba(20,20,20,0.6)");
}
this.vCtx.fillStyle = gradient;
let barWidth = 2;
let barHeight;
let x = 0;
@ -373,7 +373,7 @@ class HuesCore {
index = i;
}
barHeight = vals[index]/4;
this.vCtx.fillRect(x,this.vCtx.canvas.height-barHeight,barWidth,barHeight);
x += barWidth;
@ -410,7 +410,7 @@ class HuesCore {
this.setInvert(false);
return;
}
// We should sync up to how many inverts there are
let build = this.currentSong.buildupRhythm;
let rhythm = this.currentSong.rhythm;
@ -820,8 +820,8 @@ class HuesCore {
}
}
}
charsToNextBeat() {
// case: fade in build, not in rhythm. Must max out fade timer.
let maxSearch = this.currentSong.rhythm.length;
@ -836,7 +836,7 @@ class HuesCore {
}
return nextBeat;
}
timeToNextBeat() {
return (this.charsToNextBeat() * this.getBeatLength()) / this.soundManager.playbackRate;
}
@ -1290,7 +1290,7 @@ HuesCore.weedColours =
{'c': 0xB62084, 'n': "Harold's Crayon"},
{'c': 0x694489, 'n': 'Purple Rain'},
{'c': 0xFFD700, 'n': 'Gold'}];
window.HuesCore = HuesCore;
})(window, document);

@ -18,7 +18,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
(function(window, document) {
"use strict";
@ -32,15 +32,15 @@ class HuesEditor {
this.loopEdit = null;
this.editArea = null;
this.wrapAt = 32;
this.hilightWidth = 0;
this.hilightHeight = 0;
this.undoBuffer = [];
this.redoBuffer = [];
// Will be an array if many actions are performed in one undo
this.batchUndoArray = null;
// For rendering the waveform
this.buildWave = null;
this.loopWave = null;
@ -48,12 +48,12 @@ class HuesEditor {
this.loopWaveBuff = null;
this.waveContext = null;
this.waveCanvas = null;
// for storing respacks created with "new"
this.respack = null;
// when we're actually following the playing song
this.linked = false;
this.core = core;
if(core.settings.enableWindow) {
this.initUI();
@ -82,29 +82,29 @@ class HuesEditor {
help.addEventListener("click", () => {
window.open("https://github.com/mon/0x40-web/tree/master/docs/Editor.md", '_blank');
});
this.statusMsg = document.createElement("span");
this.statusMsg.className = "editor__status-msg";
titleButtons.appendChild(this.statusMsg);
this.topBar = document.createElement("div");
this.topBar.className = "editor__top-bar";
this.root.appendChild(this.topBar);
this.uiCreateInfo();
this.uiCreateImport();
this.root.appendChild(document.createElement("hr"));
this.uiCreateEditArea();
this.uiCreateControls();
this.uiCreateVisualiser();
document.addEventListener("keydown", e => {
e = e || window.event;
if(e.defaultPrevented) {
return true;
}
let key = e.keyCode || e.which;
if (e.ctrlKey) {
if(key == 90) { // Z
this.undo();
@ -118,7 +118,7 @@ class HuesEditor {
}
return true;
});
window.addEventListener('resize', this.resize.bind(this));
// Fix Chrome rendering - redraw on tab load
// tabselected passes the name of the selected tab, we force noHilightCalc to false
@ -140,15 +140,15 @@ class HuesEditor {
let loopHeight = maxHeight - buildHeight + lHeadHeight;
this.loopEdit.style.height = loopHeight + "px";
this.loopEdit._box.style.height = (loopHeight - lHeadHeight) + "px";
// For window resizing down situation
if(this.editArea.offsetHeight != boxHeight) {
this.resize();
}
// Resize the time lock
this.timeLock.style.height = (buildHeight + handleHeight) + "px";
// Save to fix Chrome rendering and to enable right click to seek
// We only resize on a window resize event, not when dragging the handle
if(!noHilightCalc) {
@ -169,7 +169,7 @@ class HuesEditor {
this.hilightWidth = hilight.clientWidth / 100;
this.hilightHeight = hilight.clientHeight / 100;
this.loopEdit.removeChild(hilight);
this.waveCanvas.width = this.waveCanvas.clientWidth;
}
}
@ -249,14 +249,14 @@ class HuesEditor {
this.copyBtn.classList.add("hues-button--disabled");
this.buildEdit._removeBtn.classList.add("hues-button--disabled");
this.loopEdit._removeBtn.classList.add("hues-button--disabled");
if(!this.song) {
return;
}
this.saveBtn.classList.remove("hues-button--disabled");
this.copyBtn.classList.remove("hues-button--disabled");
if(this.song.independentBuild) {
this.timeLock._locker.innerHTML = "&#xe904;";
this.timeLock.classList.add("edit-area__timelock--unlocked");
@ -272,15 +272,15 @@ class HuesEditor {
this.seekStart.classList.remove("hues-button--disabled");
this.buildEdit._removeBtn.classList.remove("hues-button--disabled");
}
if(!this.linked) {
return;
}
let loopLen = this.core.soundManager.loopLength;
let buildLen = this.core.soundManager.buildLength;
let beatLen = (loopLen / this.song.rhythm.length) * 1000;
this.loopLen.textContent = loopLen.toFixed(2);
this.buildLen.textContent = buildLen.toFixed(2);
this.beatLen.textContent = beatLen.toFixed(2);
@ -292,14 +292,14 @@ class HuesEditor {
}
// If first load, this makes fresh, gets the core synced up
this.newSong(this.song);
// Have we just added a build to a song with a rhythm, or vice versa?
// If so, link their lengths
let newlyLinked = !this.song[editor._sound] && !!this.song[this.getOther(editor)._sound];
// Disable load button TODO
let file = editor._fileInput.files[0];
// load audio
this.blobToArrayBuffer(file)
.then(buffer => {
@ -348,7 +348,7 @@ class HuesEditor {
if(!this.song) {
return;
}
this.song[editor._sound] = null;
this.song[editor._rhythm] = "";
this.setIndependentBuild(true);
@ -407,30 +407,30 @@ class HuesEditor {
// Clear instructions
this.buildEdit._hilight.className = "beat-hilight invisible";
this.loopEdit._hilight.className = "beat-hilight invisible";
// Clear helpful glows
this.newSongBtn.classList.remove("hues-button--glow");
this.fromSongBtn.classList.remove("hues-button--glow");
// Enable title edits
this.title.disabled = false;
this.source.disabled = false;
this.clearUndoRedo();
this.song = song;
this.reflow(this.buildEdit, song.buildupRhythm);
this.reflow(this.loopEdit, song.rhythm);
this.title.value = song.title;
this.source.value = song.source;
// Force independent build if only 1 source is present
this.updateIndependentBuild();
// Unlock beatmap lengths
this.setLocked(this.buildEdit, 0);
this.setLocked(this.loopEdit, 0);
this.linked = true;
this.updateInfo();
this.updateWaveform();
@ -438,7 +438,7 @@ class HuesEditor {
updateIndependentBuild() {
// Force independent build if only 1 source is present
// Effectively buildup XOR loop - does only 1 exist?
let hasBuild = !!this.song.buildup;
let hasLoop = !!this.song.sound;
@ -485,7 +485,7 @@ class HuesEditor {
return;
}
this.redoBuffer = [];
let undoObj = {songVar: name,
editor: editor,
text: oldText,
@ -554,7 +554,7 @@ class HuesEditor {
updateUndoUI() {
this.undoBtn.className = "hues-button hues-button--disabled";
this.redoBtn.className = "hues-button hues-button--disabled";
if(this.undoBuffer.length > 0) {
this.undoBtn.classList.remove("hues-button--disabled");
}
@ -632,9 +632,9 @@ class HuesEditor {
input.value = subtitle;
container.appendChild(input);
div.appendChild(container);
parent.appendChild(div);
return input;
}
@ -667,7 +667,7 @@ class HuesEditor {
let info = document.createElement("div");
this.topBar.appendChild(info);
info.className = "editor__info";
let songUpdate = function(name) {
if(!this.song ) {
return;
@ -678,7 +678,7 @@ class HuesEditor {
}
this.core.callEventListeners("newsong", this.song);
};
this.title = this.createTextInput("Title:", "Song name", info);
this.title.oninput = songUpdate.bind(this, "title");
this.title.disabled = true;
@ -691,7 +691,7 @@ class HuesEditor {
let imports = document.createElement("div");
this.topBar.appendChild(imports);
imports.className = "editor__imports";
let songEdits = document.createElement("div");
imports.appendChild(songEdits);
let newSongBtn = this.createButton("New song", songEdits, false, "hues-button--glow");
@ -706,11 +706,11 @@ class HuesEditor {
}
});
this.fromSongBtn = fromSong;
let songInfos = document.createElement("div");
songInfos.className = "settings-individual editor__song-stats";
imports.appendChild(songInfos);
this.loopLen = this.uiCreateSongStat("Loop length (s):", "0.00", songInfos);
this.buildLen = this.uiCreateSongStat("Build length (s):", "0.00", songInfos);
this.beatLen = this.uiCreateSongStat("Beat length (ms):", "0.00", songInfos);
@ -734,7 +734,7 @@ class HuesEditor {
this.editArea = editArea;
editArea.className = "edit-area";
this.root.appendChild(editArea);
// Lock build/loop lengths
this.timeLock = document.createElement("div");
editArea.appendChild(this.timeLock);
@ -749,7 +749,7 @@ class HuesEditor {
this.setIndependentBuild(!this.song.independentBuild);
});
this.timeLock._locker = locker;
this.buildEdit = this.uiCreateSingleEditor("Buildup", "buildup", "buildupRhythm", editArea);
this.seekStart = this.buildEdit._seek;
// FIRST |<<
@ -757,7 +757,7 @@ class HuesEditor {
this.seekStart.addEventListener("click", () => {
this.core.soundManager.seek(-this.core.soundManager.buildLength);
});
// drag handle
let handleContainer = document.createElement("div");
handleContainer.className = "resize-handle";
@ -767,22 +767,22 @@ class HuesEditor {
handle.innerHTML = "&#xe908;"; // DRAG HANDLE
handleContainer.appendChild(handle);
this.resizeHandle = handleContainer;
handleContainer.addEventListener("mousedown", (e) => {
e.preventDefault();
let editTop = this.editArea.getBoundingClientRect().top;
let handleSize = this.resizeHandle.clientHeight;
let resizer = (e) => {
this.buildEditSize = Math.floor(e.clientY - editTop + handleSize/2);
this.resize(true);
};
let mouseup = function(e) {
document.removeEventListener("mousemove", resizer);
document.removeEventListener("mouseup", mouseup);
};
document.addEventListener("mousemove", resizer);
document.addEventListener("mouseup", mouseup);
});
@ -794,11 +794,11 @@ class HuesEditor {
this.seekLoop.addEventListener("click", () => {
this.core.soundManager.seek(0);
});
this.buildEdit._hilight.textContent = "[none]";
this.loopEdit._hilight.innerHTML =
'<br />' +
'Click [LOAD RHYTHM] to load a loop! LAME encoded MP3s work best.<br />' +
this.loopEdit._hilight.innerHTML =
'<br />' +
'Click [LOAD RHYTHM] to load a loop! LAME encoded MP3s work best.<br />' +
'(LAME is important for seamless MP3 loops)<br />' +
'<br />' +
'[DOUBLE] doubles the selected map length by padding it with "."s.<br />' +
@ -817,19 +817,19 @@ class HuesEditor {
uiCreateSingleEditor(title, soundName, rhythmName, parent) {
let container = document.createElement("div");
parent.appendChild(container);
let header = document.createElement("div");
header.className = "edit-area__header";
container.appendChild(header);
let nameLabel = document.createElement("span");
header.appendChild(nameLabel);
nameLabel.innerHTML = title;
let seek = this.createButton("", header, true, "hues-icon");
header.appendChild(seek);
container._seek = seek;
let beatCount = document.createElement("span");
header.appendChild(beatCount);
beatCount.className = "edit-area__beat-count";
@ -843,16 +843,16 @@ class HuesEditor {
this.setLocked(container, textLen);
}
});
let rightHeader = document.createElement("span");
rightHeader.className = "edit-area__header__right";
header.appendChild(rightHeader);
container._halveBtn = this.createButton("Halve", rightHeader, true);
container._halveBtn.addEventListener("click", this.halveBeats.bind(this, container));
container._doubleBtn = this.createButton("Double", rightHeader, true);
container._doubleBtn.addEventListener("click", this.doubleBeats.bind(this, container));
let fileInput = document.createElement("input");
fileInput.type ="file";
fileInput.accept=".mp3, .wav, .ogg";
@ -860,10 +860,10 @@ class HuesEditor {
fileInput.onchange = this.loadAudio.bind(this, container);
let load = this.createButton("Load " + title.replace(/&nbsp;/g,""), rightHeader);
load.addEventListener("click", () => {fileInput.click();});
container._removeBtn = this.createButton("Remove", rightHeader, true);
container._removeBtn.addEventListener("click", this.removeAudio.bind(this, container));
let editBox = document.createElement("div");
editBox.className = "edit-area__box";
let beatmap = document.createElement("div");
@ -872,27 +872,27 @@ class HuesEditor {
beatmap.spellcheck = false;
beatmap.oninput = this.textUpdated.bind(this, container);
beatmap.oncontextmenu = this.rightClick.bind(this, container);
let beatHilight = document.createElement("div");
beatHilight.className = "beat-hilight";
editBox.appendChild(beatHilight);
editBox.appendChild(beatmap);
container.appendChild(editBox);
container._header = header;
container._beatCount = beatCount;
container._box = editBox;
container._beatmap = beatmap;
container._hilight = beatHilight;
container._fileInput = fileInput;
container._sound = soundName;
container._rhythm = rhythmName;
// Are we in insert mode? Default = no
container._locked = 0;
return container;
}
@ -900,7 +900,7 @@ class HuesEditor {
let controls = document.createElement("div");
controls.className = "edit__controls";
this.root.appendChild(controls);
let changeRate = function(change) {
let rate = this.core.soundManager.playbackRate;
rate += change;
@ -909,30 +909,30 @@ class HuesEditor {
let newRate = this.core.soundManager.playbackRate;
playRateLab.textContent = newRate.toFixed(2) + "x";
};
let speedControl = document.createElement("div");
controls.appendChild(speedControl);
// BACKWARD
let speedDown = this.createButton("&#xe909;", speedControl, false, "hues-icon");
speedDown.addEventListener("click", changeRate.bind(this, -0.25));
// FORWARD
let speedUp = this.createButton("&#xe90a;", speedControl, false, "hues-icon");
speedUp.addEventListener("click", changeRate.bind(this, 0.25));
let playRateLab = document.createElement("span");
playRateLab.className = "settings-individual";
playRateLab.textContent = "1.00x";
speedControl.appendChild(playRateLab);
let wrapControl = document.createElement("div");
controls.appendChild(wrapControl);
let wrapLab = document.createElement("span");
wrapLab.className = "settings-individual";
wrapLab.textContent = "New line at beat ";
wrapControl.appendChild(wrapLab);
let wrapAt = document.createElement("input");
wrapAt.className = "settings-input";
wrapAt.value = this.wrapAt;
@ -946,7 +946,7 @@ class HuesEditor {
this.wrapAt = parseInt(wrapAt.value);
this.reflow(this.buildEdit, this.song.buildupRhythm);
this.reflow(this.loopEdit, this.song.rhythm);
};
wrapControl.appendChild(wrapAt);
}
@ -958,7 +958,7 @@ class HuesEditor {
this.root.appendChild(wave);
this.waveCanvas = wave;
this.waveContext = wave.getContext("2d");
this.core.addEventListener("frame", this.drawWave.bind(this));
}
@ -968,7 +968,7 @@ class HuesEditor {
}
// If the right click is also a focus event, caret doesn't move, so we have to use coords
let coords = this.getTextCoords(event);
if(coords.x > this.wrapAt)
return true;
@ -976,7 +976,7 @@ class HuesEditor {
let totalLen = this.getText(editor).length;
if(caret > totalLen)
return true;
// in case of focus event
this.setCaret(editor._beatmap, caret);
let percent = caret / totalLen;
@ -988,7 +988,7 @@ class HuesEditor {
seekTime = -bLen + bLen * percent;
}
this.core.soundManager.seek(seekTime);
event.preventDefault();
return false;
}
@ -1007,7 +1007,7 @@ class HuesEditor {
x = Math.floor((event.clientX - x) / this.hilightWidth);
y = Math.floor((event.clientY - y) / this.hilightHeight);
return {x: x, y: y};
}
@ -1094,7 +1094,7 @@ class HuesEditor {
this.reflow(editor, this.song[editor._rhythm]);
this.setCaret(editor._beatmap, caret);
this.updateHalveDoubleButtons(editor);
this.core.updateBeatLength();
// We may have to go backwards in time
this.core.recalcBeatIndex();
@ -1174,10 +1174,10 @@ class HuesEditor {
// The individual wave section
let wave = document.createElement("canvas");
let waveContext = wave.getContext("2d");
wave.height = WAVE_HEIGHT_PIXELS;
wave.width = Math.floor(WAVE_PIXELS_PER_SECOND * length);
let samplesPerPixel = Math.floor(buffer.sampleRate / WAVE_PIXELS_PER_SECOND);
let waveData = [];
for(let i = 0; i < buffer.numberOfChannels; i++) {
@ -1211,7 +1211,7 @@ class HuesEditor {
waveContext.moveTo(pixel, maxPix);
waveContext.lineTo(pixel, minPix);
waveContext.stroke();
// Draw the average too, gives a better feel for the wave
avgHi /= j * channels;
avgLo /= j * channels;
@ -1223,26 +1223,26 @@ class HuesEditor {
waveContext.moveTo(pixel, maxAvg);
waveContext.lineTo(pixel, minAvg);
waveContext.stroke();
pixel+=1;
}
return wave;
}
drawWave() {
if((!this.buildWave && !this.loopWave) || !this.linked)
return;
let width = this.waveCanvas.width;
let now = this.core.soundManager.currentTime;
let timespan = width / WAVE_PIXELS_PER_SECOND / 2;
let minTime = now - timespan;
let maxTime = now + timespan;
let bLen = this.core.soundManager.buildLength;
let loopLen = this.core.soundManager.loopLength;
let drawTime, drawOffset;
if(bLen) {
drawTime = Math.max(minTime, -bLen);
@ -1251,9 +1251,9 @@ class HuesEditor {
}
// drawOffset is "pixels from the left"
drawOffset = Math.floor((drawTime - minTime) * WAVE_PIXELS_PER_SECOND);
this.waveContext.clearRect(0, 0, width, WAVE_HEIGHT_PIXELS);
if(this.buildWave && bLen && minTime < 0) {
// Bit of legwork to convert negative to positive
let waveOffset = Math.floor((1 - drawTime / -bLen) * (this.buildWave.width-1));
@ -1265,21 +1265,21 @@ class HuesEditor {
// If there's more to draw after the build, it'll be from the start of the wave
drawTime = 0;
}
let loopPoints = [];
if(this.loopWave && loopLen && maxTime > 0) {
while(drawOffset < width) {
if(drawTime === 0) {
loopPoints.push(drawOffset);
}
let waveOffset = Math.floor((drawTime / loopLen) * (this.loopWave.width-1));
drawOffset = this.drawOneWave(this.loopWave, waveOffset, drawOffset, width);
// If we're drawing more than 1 loop it's starting at 0
drawTime = 0;
}
}
// trackbar
this.drawWaveBar("red", width/2);
// Signify loop point with a green bar, drawing over the wave
@ -1350,7 +1350,7 @@ class HuesEditor {
let result = "<songs>\n";
result += xml;
result += "</songs>\n";
// http://stackoverflow.com/a/18197341
let element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
@ -1362,19 +1362,19 @@ class HuesEditor {
element.click();
document.body.removeChild(element);
window.onbeforeunload = null;
}
// http://stackoverflow.com/a/30810322
copyXML() {
let text = this.generateXML();
// Clicking when disabled
if(!text) {
return;
}
let textArea = document.createElement("textarea");
textArea.className = "copybox";
@ -1383,7 +1383,7 @@ class HuesEditor {
document.body.appendChild(textArea);
textArea.select();
let success;
try {
@ -1391,7 +1391,7 @@ class HuesEditor {
} catch (err) {
success = false;
}
document.body.removeChild(textArea);
if(success) {
this.alert("Beatmap XML copied to clipboard!");
@ -1400,7 +1400,7 @@ class HuesEditor {
}
}
}
window.HuesEditor = HuesEditor;
})(window, document);

@ -21,7 +21,7 @@
*/
(function(window, document) {
"use strict";
"use strict";
/* HuesInfo.js populates the INFO tab in the Hues Window.
*/
@ -74,10 +74,10 @@ function populateHuesInfo(version, huesWin, settings) {
return;
}
let verString = (parseInt(version)/10).toFixed(1);
let info = document.createElement("div");
info.className = "hues-ref";
let huesName = settings.huesName.replace("%VERSION%", version);
let about = document.createElement("div");
about.className = "hues-about";
@ -86,10 +86,10 @@ function populateHuesInfo(version, huesWin, settings) {
'<h2>Web-ified by <a target="_blank" href="https://github.com/mon">mon</a></h2>' +
'<h3>With help from <a target="_blank" href="https://github.com/kepstin/0x40hues-html5">Kepstin</a></h3>';
info.appendChild(about);
addReference(info, "Beat glossary", beatGlossary);
addReference(info, "Keyboard shortcuts", shortcuts);
huesWin.addTab("INFO", info);
}
@ -97,11 +97,11 @@ let addReference = function(root, titleText, list) {
let ref = document.createElement("div");
ref.className = "hues-ref__info";
root.appendChild(ref);
let title = document.createElement("h3");
title.textContent = titleText;
ref.appendChild(title);
let listElem = document.createElement("ul");
list.forEach(function(elem) {
let item = document.createElement("li");

@ -153,11 +153,11 @@ const settingsOptions = {
},
autoSong : {
name : "AutoSong",
options : ["off", "loop", "time",
options : ["off", "loop", "time",
{type:"varText", text:function() {
// only display if autosong is on
return this.autoSong == "off" ? "" : "after";
}},
}},
{type:"input", variable:"autoSongDelay", inputType:"int",
visiblity:function() {
return this.autoSong != "off";
@ -215,22 +215,22 @@ class HuesSettings {
*/
updated : []
};
let settingsVersion = "1";
if(localStorage.settingsVersion != settingsVersion) {
localStorage.clear();
localStorage.settingsVersion = settingsVersion;
}
this.hasUI = false;
this.settingCheckboxes = {};
this.textCallbacks = [];
this.visCallbacks = [];
this.ephemerals = {};
for(let attr in defaultSettings) {
if(!defaultSettings.hasOwnProperty(attr)) {
continue;
@ -238,7 +238,7 @@ class HuesSettings {
Object.defineProperty(this, attr, {
set: this.makeSetter(attr), get: this.makeGetter(attr)
});
if(defaults[attr] !== undefined) {
if(defaults.overwriteLocal) {
this[attr] = defaults[attr];
@ -247,9 +247,9 @@ class HuesSettings {
}
}
}
let querySettings = this.getQuerySettings();
for(let attr in defaultSettings) {
// query string overrides, finally
if(querySettings[attr] !== undefined && attr != 'respacks') {
@ -259,7 +259,7 @@ class HuesSettings {
this.respacks = this.respacks.concat(querySettings.respacks);
}
getQuerySettings() {
let results = {};
results.respacks = [];
@ -288,7 +288,7 @@ class HuesSettings {
initUI(huesWin) {
let root = document.createElement("div");
root.className = "hues-options";
// Don't make in every loop
let intValidator = function(self, variable) {
this.value = this.value.replace(/\D/g,'');
@ -316,7 +316,7 @@ class HuesSettings {
setContainer.className = "settings-individual";
let buttonContainer = document.createElement("div");
buttonContainer.className = "settings-buttons";
for(let j = 0; j < setting.options.length; j++) {
let option = setting.options[j];
if(typeof option === "string") {
@ -421,7 +421,7 @@ class HuesSettings {
return true;
};
}
isEphemeral(setting) {
return settingsOptions[setting] === undefined;
}

@ -28,7 +28,7 @@
underneath so it can be entirely hidden.
*/
class HuesUI {
constructor(parent, name) {
if(!parent) {
return;
@ -60,7 +60,7 @@ class HuesUI {
this.settingsToggle = null;
this.hideToggle = null;
// To deregister on UI hide we need to keep track of these
// Each callback is { name : "callbackname", func : function }
// Add using this.addCoreCallback
@ -362,10 +362,10 @@ class RetroUI extends HuesUI {
this.listContainer.className = "hues-r-listcontainer";
this.root.appendChild(this.listContainer);
this.visualiserContainer.className = "hues-r-visualisercontainer";
this.root.appendChild(this.visualiserContainer);
this.addCoreCallback("beat", this.beat.bind(this));
this.addCoreCallback("newmode", this.newMode.bind(this));
}
@ -429,7 +429,7 @@ class MinimalUI extends RetroUI {
initUI() {
super.initUI();
this.root.removeChild(this.controls);
this.root.removeChild(this.subControls);
this.container.removeChild(this.beatBar);
@ -471,7 +471,7 @@ class WeedUI extends RetroUI {
this.imageModeManual.textContent = "ONE";
this.imageModeAuto.textContent = "MANY";
this.visualiserContainer.className += " hues-w-visualisercontainer";
}
@ -489,7 +489,7 @@ class WeedUI extends RetroUI {
this.beatLeft.textContent = rest;
this.beatRight.textContent = rest;
this.beatCount.textContent = "B=" + this.intToHex(index, 4);
if(["x", "o", "X", "O"].indexOf(beats[0]) != -1) {
@ -520,7 +520,7 @@ class WeedUI extends RetroUI {
class ModernUI extends HuesUI {
constructor(parent, name) {
super(parent, name ? name : "ModernUI");
this.textSize_normal = 0;
this.textSize_small = 0;
this.songLink_size = 0;
@ -655,7 +655,7 @@ class ModernUI extends HuesUI {
this.leftInfo = leftInfo;
controls.appendChild(leftInfo);
controls.appendChild(rightInfo);
this.visualiserContainer.className = "hues-m-visualisercontainer";
controls.appendChild(this.visualiserContainer);
@ -688,7 +688,7 @@ class ModernUI extends HuesUI {
this.listContainer.className = "hues-m-listcontainer";
this.root.appendChild(this.listContainer);
this.addCoreCallback("beat", this.beat.bind(this));
this.addCoreCallback("newmode", this.newMode.bind(this));
}
@ -762,9 +762,9 @@ class ModernUI extends HuesUI {
// We override this just after so don't bother to restore it
el.className = className;
let size = el.offsetWidth / 100;
el.innerHTML = oldContent;
return size;
}
@ -824,10 +824,10 @@ class XmasUI extends ModernUI {
constructor(parent, name) {
super(parent, name ? name : "XmasUI");
this.initSnow();
// This will cache our inverted lights images
this.invert(true);
this.controls.removeChild(this.leftBox);
this.controls.removeChild(this.rightBox);
this.controls.removeChild(this.rightInfo);
@ -885,15 +885,15 @@ class XmasUI extends ModernUI {
bottomHelper.appendChild(bottom);
wires.appendChild(bottomHelper);
this.root.appendChild(wires);
this.visualiserContainer.className = "hues-x-visualisercontainer";
this.controls.removeChild(this.visualiserContainer);
this.beatBar.appendChild(this.visualiserContainer);
}
invert(invert) {
super.invert(invert);
if(invert) {
this.snowContext.fillStyle = "rgba(0, 0, 0, 0.8)";
} else {
@ -963,11 +963,11 @@ class XmasUI extends ModernUI {
if(this.currentBeat != ".") {
this.lights.forEach(function(light, i, a) {
switch(this.currentBeat) {
case ":":
case ":":
this.lightOn(light);
this.lightRecolour(light);
break;
case "+":
case "+":
this.lightFadeOut(light);
break;
default:
@ -984,7 +984,7 @@ class XmasUI extends ModernUI {
this.snowCanvas.height = 720;
this.snowCanvas.style.display = "none";
this.snowCanvas.className = "hues-canvas hues-x-snow";
this.root.appendChild(this.snowCanvas);
this.snowing = false;
@ -992,7 +992,7 @@ class XmasUI extends ModernUI {
this.snowAngle = 0;
this.lastSnow = 0;
this.snowflakes = [];
this.addCoreCallback("frame", this.drawSnow.bind(this));
}
@ -1070,7 +1070,7 @@ class XmasUI extends ModernUI {
resize() {
super.resize();
let ratio = window.innerWidth / window.innerHeight;
// cleared on resize
let savedFill = this.snowContext.fillStyle;
@ -1092,13 +1092,13 @@ class HalloweenUI extends ModernUI {
initUI() {
super.initUI();
this.controls.className += " hues-h-controls";
this.beatBar.className += " hues-h-beatbar";
this.leftBox.className += " hues-h-leftbox";
this.rightBox.className += " hues-h-rightbox";
this.volBar.className += " hues-h-vol-bar";
this.beatLeft.className += " hues-h-text";
this.beatRight.className += " hues-h-text";
this.beatCenter.className += " hues-h-text";
@ -1113,47 +1113,47 @@ class HalloweenUI extends ModernUI {
this.imageList.className += " hues-h-text";
this.imageName.className += " hues-h-text";
this.hueName.className += " hues-h-text";
this.settingsToggle.className += " hues-h-text";
this.hideToggle.className += " hues-h-text";
this.infoToggle.className += " hues-h-text";
this.volLabel.className += " hues-h-text";
this.timer.className = "hues-h-textfade";
this.beatCount.className = "hues-h-textfade";
this.xBlur.className = "hues-h-textfade";
this.yBlur.className = "hues-h-textfade";
let leftBoxTomb = document.createElement("div");
leftBoxTomb.className = "hues-h-tombstone";
this.leftBox.appendChild(leftBoxTomb);
let songTomb = document.createElement("div");
songTomb.className = "hues-h-tombstone";
this.songBlock.insertBefore(songTomb,this.songBlock.firstChild);
let imageTomb = document.createElement("div");
imageTomb.className = "hues-h-tombstone";
this.imageBlock.insertBefore(imageTomb,this.imageBlock.firstChild);
let topLeft = document.createElement("div");
topLeft.className = "hues-h-topleft";
let topRight = document.createElement("div");
topRight.className = "hues-h-topright";
let bottomRight = document.createElement("div");
bottomRight.className = "hues-h-bottomright";
this.root.appendChild(topLeft);
this.root.appendChild(topRight);
this.root.appendChild(bottomRight);
let leftHand = document.createElement("div");
leftHand.className = "hues-h-left-hand";
this.beatBar.appendChild(leftHand);
let rightHand = document.createElement("div");
rightHand.className = "hues-h-right-hand";
this.beatBar.appendChild(rightHand);
this.vignette = document.createElement("div");
this.vignette.className = "hues-h-vignette";
this.root.appendChild(this.vignette);
@ -1161,7 +1161,7 @@ class HalloweenUI extends ModernUI {
beat(beats, index) {
super.beat(beats, index);
if (this.currentBeat != ".") {
let eyes = this.beatCenter.ownerDocument.createElement("div");
eyes.className = "hues-m-beatcenter hues-h-eyes";
@ -1171,13 +1171,13 @@ class HalloweenUI extends ModernUI {
connectCore(core) {
super.connectCore(core);
this.core.preloader.classList.add("hues-h-text");
}
disconnect() {
this.core.preloader.classList.remove("hues-h-text");
super.disconnect();
}
}

@ -20,7 +20,7 @@
*/
(function(window, document) {
"use strict";
"use strict";
class HuesWindow {
constructor(root, settings) {
@ -37,38 +37,38 @@ class HuesWindow {
*/
tabselected : []
};
this.hasUI = settings.enableWindow;
if(!this.hasUI)
return;
this.window = document.createElement("div");
this.window.className = "hues-win-helper";
root.appendChild(this.window);
let actualWindow = document.createElement("div");
actualWindow.className = "hues-win";
this.window.appendChild(actualWindow);
let closeButton = document.createElement("div");
closeButton.className = "hues-win__closebtn";
closeButton.onclick = this.hide.bind(this);
actualWindow.appendChild(closeButton);
this.tabContainer = document.createElement("div");
this.tabContainer.className = "hues-win__tabs";
actualWindow.appendChild(this.tabContainer);
this.contentContainer = document.createElement("div");
this.contentContainer.className = "hues-win__content";
actualWindow.appendChild(this.contentContainer);
this.contents = [];
this.tabs = [];
this.tabNames = [];
if(settings.showWindow) {
this.show();
} else {
@ -79,7 +79,7 @@ class HuesWindow {
addTab(tabName, tabContent) {
if(!this.hasUI)
return;
let label = document.createElement("div");
label.textContent = tabName;
label.className = "tab-label";
@ -87,7 +87,7 @@ class HuesWindow {
this.tabContainer.appendChild(label);
this.tabs.push(label);
this.tabNames.push(tabName);
let content = document.createElement("div");
content.className = "tab-content";
content.appendChild(tabContent);
@ -117,7 +117,7 @@ class HuesWindow {
hide() {
if(!this.hasUI)
return;
this.window.classList.add("hidden");
this.callEventListeners("windowshown", false);
}
@ -125,7 +125,7 @@ class HuesWindow {
show() {
if(!this.hasUI)
return;
this.window.classList.remove("hidden");
this.callEventListeners("windowshown", true);
}

@ -92,7 +92,7 @@ class Resources {
Returns an Promise.all which will resolve to an array of sizes */
getSizes(urls) {
let promises = [];
urls.forEach(url => {
let p = new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
@ -117,7 +117,7 @@ class Resources {
});
promises.push(p);
});
return Promise.all(promises);
}
@ -128,14 +128,14 @@ class Resources {
this.progressCallback = progressCallback;
this.progressState = Array.apply(null, Array(urls.length)).map(Number.prototype.valueOf,0);
}
let respackPromises = [];
let progressFunc = function(index, progress, pack) {
this.progressState[index] = progress;
this.updateProgress(pack);
};
for(let i = 0; i < urls.length; i++) {
let r = new Respack();
respackPromises.push(r.loadFromURL(urls[i], progressFunc.bind(this, i)));
@ -266,7 +266,7 @@ class Resources {
loadLocal() {
console.log("Loading local zip(s)");
let files = this.fileInput.files;
let p = Promise.resolve();
for(let i = 0; i < files.length; i++) {
@ -310,7 +310,7 @@ class Resources {
initUI() {
this.root = document.createElement("div");
this.root.className = "respacks";
let packsContainer = document.createElement("div");
packsContainer.className = "respacks__manager";
@ -415,10 +415,10 @@ class Resources {
let packDesc = document.createElement("div");
packDesc.className = "respack-description";
packDesc.textContent = "<no description>";
let tabContainer = document.createElement("div");
tabContainer.className = "respack-tab-container";
let songCount = document.createElement("div");
songCount.textContent = "Songs:";
songCount.className = "respack-tab respack-tab--checked";
@ -431,24 +431,24 @@ class Resources {
songList.className = "resource-list respack-tab__content respack-tab__content--checked";
let imageList = document.createElement("div");
imageList.className = "resource-list respack-tab__content";
songCount.onclick = () => {
songCount.classList.add("respack-tab--checked");
imageCount.classList.remove("respack-tab--checked");
songList.classList.add("respack-tab__content--checked");
imageList.classList.remove("respack-tab__content--checked");
this.currentTab = TAB_SONGS;
};
imageCount.onclick = () => {
imageCount.classList.add("respack-tab--checked");
songCount.classList.remove("respack-tab--checked");
imageList.classList.add("respack-tab__content--checked");
songList.classList.remove("respack-tab__content--checked");
this.currentTab = TAB_IMAGES;
};
@ -509,13 +509,13 @@ class Resources {
indivView.appendChild(packName);
indivView.appendChild(packInfo);
indivView.appendChild(packDesc);
tabContainer.appendChild(songCount);
tabContainer.appendChild(imageCount);
indivView.appendChild(tabContainer);
indivView.appendChild(songList);
indivView.appendChild(imageList);
indivView.appendChild(packButtons);
indivView.appendChild(totalCounts);
@ -530,7 +530,7 @@ class Resources {
this.listView.appendChild(this.enabledSongList);
this.listView.appendChild(this.enabledImageList);
this.hasUI = true;
}

@ -287,7 +287,7 @@ class Respack {
console.log("WARNING: Image", name, "already exists! Conflict with", file.name, "and", existing.name);
return;
}
return this.loadImage(file, img);
}
@ -420,7 +420,7 @@ class Respack {
newSongs.push(song);
debug(" [I] " + song.name, ": '" + song.title + "' added to songs");
} else {
debug(" WARNING!", "songs.xml: <song> element",
debug(" WARNING!", "songs.xml: <song> element",
+ el.attributes[0].value + "- no song found");
}
}

@ -32,12 +32,12 @@ class SoundManager {
*/
seek : []
};
this.core = core;
this.playing = false;
this.playbackRate = 1;
this.song = null;
this.initPromise = null;
this.lockedPromise = null;
this.locked = true;
@ -57,7 +57,7 @@ class SoundManager {
this.gainNode = null;
this.mute = false;
this.lastVol = 1;
// Visualiser
this.vReady = false;
this.vBars = 0;
@ -71,7 +71,7 @@ class SoundManager {
this.logBins = 0;
this.maxBinLin = 0;
}
callEventListeners(ev) {
let args = Array.prototype.slice.call(arguments, 1);
this.eventListeners[ev].forEach(function(callback) {
@ -109,7 +109,7 @@ class SoundManager {
// These don't always exist
AudioContext.prototype.suspend = AudioContext.prototype.suspend || (() => {return Promise.resolve();});
AudioContext.prototype.resume = AudioContext.prototype.resume || (() => {return Promise.resolve();});
this.context = new window.AudioContext();
this.gainNode = this.context.createGain();
this.gainNode.connect(this.context.destination);
@ -130,7 +130,7 @@ class SoundManager {
});
});
}).then(() => {
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
// See if our audio decoder is working
let audioWorker;
try {
@ -175,7 +175,7 @@ class SoundManager {
// play the file
source.start(0);
window.removeEventListener('touchend', unlocker);
window.removeEventListener('click', unlocker);
this.core.clearMessage();
@ -198,7 +198,7 @@ class SoundManager {
if(!song || (!song.sound)) { // null song
return p;
}
// if there's a fadeout happening from AutoSong, kill it
this.gainNode.gain.cancelScheduledValues(0);
// Reset original volume
@ -214,7 +214,7 @@ class SoundManager {
if(song != this.song) {
return Promise.reject("Song changed between load and play - this message can be ignored");
}
this.buildup = buffers.buildup;
this.buildLength = this.buildup ? this.buildup.duration : 0;
this.loop = buffers.loop;
@ -228,7 +228,7 @@ class SoundManager {
} else {
this.seek(0, true);
}
return this.context.resume();
}).then(() => {
this.playing = true;
@ -244,7 +244,7 @@ class SoundManager {
this.buildSource = null;
if(!dontDeleteBuffers)
this.buildup = null;
}
}
// arg required for mobile webkit
this.loopSource.stop(0);
// TODO needed?
@ -261,7 +261,7 @@ class SoundManager {
setRate(rate) {
// Double speed is more than enough. Famous last words?
rate = Math.max(Math.min(rate, 2), 0.25);
let time = this.clampedTime;
this.playbackRate = rate;
this.seek(time);
@ -271,19 +271,19 @@ class SoundManager {
if(!this.song) {
return;
}
this.callEventListeners("seek");
//console.log("Seeking to " + time);
// Clamp the blighter
time = Math.min(Math.max(time, -this.buildLength), this.loopLength);
this.stop(true);
if(!this.loop) {
return;
}
this.loopSource = this.context.createBufferSource();
this.loopSource.buffer = this.loop;
this.loopSource.playbackRate.value = this.playbackRate;
@ -291,7 +291,7 @@ class SoundManager {
this.loopSource.loopStart = 0;
this.loopSource.loopEnd = this.loopLength;
this.loopSource.connect(this.gainNode);
if(time < 0 && this.buildup) {
this.buildSource = this.context.createBufferSource();
this.buildSource.buffer = this.buildup;
@ -302,7 +302,7 @@ class SoundManager {
} else {
this.loopSource.start(0, time);
}
this.startTime = this.context.currentTime - (time / this.playbackRate);
if(!noPlayingUpdate) {
this.playing = true;
@ -321,7 +321,7 @@ class SoundManager {
get clampedTime() {
let time = this.currentTime;
if(time > 0) {
time %= this.loopLength;
}
@ -336,9 +336,9 @@ class SoundManager {
NOTE: If anything but playSong calls loadSong, this idea is broken. */
return Promise.reject("Song changed between load and play - this message can be ignored");
}
let buffers = {loop: null, buildup: null};
let promises = [this.loadBuffer(song, "sound").then(buffer => {
buffers.loop = buffer;
})];
@ -359,7 +359,7 @@ class SoundManager {
loadBuffer(song, soundName) {
let buffer = song[soundName];
// Is this an ogg file?
let view = new Uint8Array(buffer);
// Signature for ogg file: OggS
@ -380,15 +380,15 @@ class SoundManager {
} else { // Use our JS decoder
return new Promise((resolve, reject) => {
let audioWorker = this.createWorker();
audioWorker.addEventListener('error', () => {
reject(Error("Audio Worker failed to convert track"));
}, false);
audioWorker.addEventListener('message', e => {
let decoded = e.data;
audioWorker.terminate();
// restore transferred buffer
song[soundName] = decoded.arrayBuffer;
if(decoded.error) {
@ -399,7 +399,7 @@ class SoundManager {
let audio = this.audioBufFromRaw(decoded.rawAudio);
resolve(audio);
}, false);
// transfer the buffer to save time
audioWorker.postMessage({buffer: buffer, ogg: this.oggSupport}, [buffer]);
});
@ -448,11 +448,11 @@ class SoundManager {
this.analyserArrays = [];
this.logArrays = [];
this.binCutoffs = [];
this.linBins = 0;
this.logBins = 0;
this.maxBinLin = 0;
this.attachVisualiser();
}
@ -472,7 +472,7 @@ class SoundManager {
}
// Split display up into each channel
this.vBars = Math.floor(this.vTotalBars/channels);
for(let i = 0; i < channels; i++) {
let analyser = this.context.createAnalyser();
// big fft buffers are new-ish
@ -487,7 +487,7 @@ class SoundManager {
analyser.maxDecibels = -25;
this.analyserArrays.push(new Uint8Array(analyser.frequencyBinCount));
analyser.getByteTimeDomainData(this.analyserArrays[i]);
this.splitter.connect(analyser, i);
this.splitter.connect(analyser, i);
this.analysers.push(analyser);
this.logArrays.push(new Uint8Array(this.vBars));
}
@ -528,7 +528,7 @@ class SoundManager {
let data = this.analyserArrays[a];
let result = this.logArrays[a];
this.analysers[a].getByteFrequencyData(data);
for(let i = 0; i < this.linBins; i++) {
let scaled = Math.round(i * this.maxBinLin / this.linBins);
result[i] = data[scaled];
@ -536,7 +536,7 @@ class SoundManager {
result[this.linBins] = data[this.binCutoffs[0]];
for(let i = this.linBins+1; i < this.vBars; i++) {
let cutoff = i - this.linBins;
result[i] = this.sumArray(data, this.binCutoffs[cutoff-1],
result[i] = this.sumArray(data, this.binCutoffs[cutoff-1],
this.binCutoffs[cutoff]);
}
}
@ -589,7 +589,7 @@ class SoundManager {
}
}
let miniOggRaw =
let miniOggRaw =
"T2dnUwACAAAAAAAAAADFYgAAAAAAAMLKRdwBHgF2b3JiaXMAAAAAAUSsAAAA" +
"AAAAgLsAAAAAAAC4AU9nZ1MAAAAAAAAAAAAAxWIAAAEAAACcKCV2Dzv/////" +
"////////////MgN2b3JiaXMrAAAAWGlwaC5PcmcgbGliVm9yYmlzIEkgMjAx" +

Loading…
Cancel
Save