Files

409 lines
14 KiB
JavaScript

class TraxPlayer {
ticker;
playing;
position;
samples;
author;
name;
tracks;
volume;
playerElement;
time;
timeInSeconds;
traxLengthInSeconds;
constructor(songUrl, sampleUrl) {
this.volume = 0.5;
this.samples = new Array();
this.ready = false;
this.position = 0;
this.playing = false;
this.songUrl = songUrl;
this.sampleUrl = sampleUrl;
this.traxLengthInSeconds = 0;
this.timeInSeconds = 0;
this.name = "";
this.author = "";
this.playerElement = document.getElementById("trax-player");
var tracks = [];
for (var i = 0; i < 4; i++) {
tracks.push({
player: new Audio(),
timeLeft: 0,
blocks: 0,
sample: 0,
playlist: []
});
}
this.tracks = tracks;
var _self = this;
_self.SetVolume(this.volume * 100);
var volume = _self.playerElement.getElementsByClassName("volume");
if (volume.length > 0) {
var slider = volume[0];
slider.oninput = function() {
_self.SetVolume(this.value);
}
}
}
SetVolume(volume) {
var volumeIndicator = this.playerElement.getElementsByClassName("volume-indicator-filled");
if (volumeIndicator.length > 0) {
volumeIndicator[0].style.width = ((62 / 100) * volume) + "px";
}
this.volume = volume / 100;
for (var i = 0; i < this.tracks.length; i++) {
this.tracks[i].player.volume = this.volume;
}
this.samples.forEach(sample => {
sample.audioObj.volume = this.volume;
});
}
GetSampleUrl(sampleId) {
return this.sampleUrl + "sound_machine_sample_" + sampleId + ".mp3";
}
GetTrack(sample) {
var track = [];
sample.split(";").forEach(sample => {
var samplePiece = sample.split(",")[0];
var blocks = sample.split(",")[1];
track.push({ blocks: blocks, piece: samplePiece })
});
return track;
}
GetSampleLength(duration) {
var result = duration * 1000;
if (result < 2100) {
return 1;
}
if (result < 4100) {
return 2;
}
if (result < 6100) {
return 3;
}
//if (result < 8100) {
// return 4;
//}
return 4;
//console.log(result);
//throw new Error("Sample is too long:");
}
GetDuration(sample) {
var _self = this;
return new Promise(function(resolve) {
var audio = new Audio();
audio.addEventListener('loadedmetadata', function() {
audio.volume = _self.volume;
resolve({
sampleLength: _self.GetSampleLength(audio.duration),
sample: sample,
audioObj: audio,
src: audio.src
});
});
audio.src = _self.GetSampleUrl(sample.piece);
});
}
GetUniqueSamples(tracks) {
var flags = [];
var output = [];
for (var t = 0; t < tracks.length; t++) {
for (var i = 0; i < tracks[t].length; i++) {
if (flags[tracks[t][i].piece])
continue;
flags[tracks[t][i].piece] = true;
output.push(tracks[t][i]);
}
}
return output;
}
async FetchSong() {
// I will have to work with this later
/*fetch(this.songUrl)
.then(response => response.json())
.then(data => console.log(data));*/
//var song = "status=0&name=Too lost in the lido&author=Patrick&track1=317,4;408,7;0,1;410,16;413,4;406,4;410,8;412,4&track2=0,2;321,2;443,22;91,2;317,8;443,8;412,2;0,2&track3=0,3;320,2;0,7;414,4;445,4;412,2;323,2;412,4;96,2;412,2;414,4;445,7;448,1;317,4&track4=0,3;324,2;0,6;448,1;0,6;96,2;322,4;96,2;99,2;322,4;412,2;0,2;322,2;96,2;322,2;0,1;324,2;0,3";
//var song = "status=0&name=Too lost in the lido&author=Patrick&track1=317,4;408,7;0,1;410,16;413,4;406,4;410,8;412,4:2:0,2;321,2;443,22;91,2;317,8;443,8;412,2;0,2:3:0,3;320,2;0,7;414,4;445,4;412,2;323,2;412,4;96,2;412,2;414,4;445,7;448,1;317,4:4:0,3;324,2;0,6;448,1;0,6;96,2;322,4;96,2;99,2;322,4;412,2;0,2;322,2;96,2;322,2;0,1;324,2;0,3&track2=0,2;321,2;443,22;91,2;317,8;443,8;412,2;0,2:3:0,3;320,2;0,7;414,4;445,4;412,2;323,2;412,4;96,2;412,2;414,4;445,7;448,1;317,4:4:0,3;324,2;0,6;448,1;0,6;96,2;322,4;96,2;99,2;322,4;412,2;0,2;322,2;96,2;322,2;0,1;324,2;0,3&track3=0,3;320,2;0,7;414,4;445,4;412,2;323,2;412,4;96,2;412,2;414,4;445,7;448,1;317,4:4:0,3;324,2;0,6;448,1;0,6;96,2;322,4;96,2;99,2;322,4;412,2;0,2;322,2;96,2;322,2;0,1;324,2;0,3&track4=0,3;324,2;0,6;448,1;0,6;96,2;322,4;96,2;99,2;322,4;412,2;0,2;322,2;96,2;322,2;0,1;324,2;0,3";
//var song = "status=0&name=test&author=Patrick&track1=4,4;9,2:2:0,5;311,&track2=0,5;311,1:3:0,4;308,1;0,1:4:0,2;307,1;0,3&track3=0,4;308,1;0,1:4:0,2;307,1;0,3&track4=0,2;307,1;0,3";
//var song = "status=0&name=test&author=Patrick&track1=4,12:2:0,5;311,1;0,6:3:0,4;308,1;0,7:4:0,2;307,1;0,9&track2=0,5;311,1;0,6:3:0,4;308,1;0,7:4:0,2;307,1;0,9&track3=0,4;308,1;0,7:4:0,2;307,1;0,9&track4=0,2;307,1;0,9";
var song = await this.fetchUrl(this.songUrl);
var urlSearchParams = new URLSearchParams("?" + song);
var track1 = urlSearchParams.get("track1");
var track2 = urlSearchParams.get("track2");
var track3 = urlSearchParams.get("track3");
var track4 = urlSearchParams.get("track4");
this.title = urlSearchParams.get("name");
this.author = urlSearchParams.get("author");
return new Promise((resolve, reject) => {
resolve([this.GetTrack(track1), this.GetTrack(track2), this.GetTrack(track3), this.GetTrack(track4)]);
});
}
fetchUrl(url) {
let myHeaders = new Headers();
let options = {
method: 'GET',
headers: myHeaders,
mode: 'cors'
};
return fetch(url, options).then(response => response.text());
};
OnReady() {
this.ready = true;
this.RemoveLoading();
this.SetTitleAndAuthor();
}
RemoveLoading() {
var loading = this.playerElement.getElementsByClassName("loading");
if (loading.length > 0) {
loading[0].remove();
}
}
SetTitleAndAuthor() {
var title = this.playerElement.getElementsByClassName("title");
var author = this.playerElement.getElementsByClassName("author");
if (title.length > 0) {
title[0].innerHTML = this.title;
}
if (author.length > 0) {
author[0].innerHTML = this.author;
}
}
async Preload() { // Load all samples in song
console.log(`SongUrl: ${
this.songUrl
}, sampleUrl: ${
this.sampleUrl
}`);
var _self = this;
try {
var tracks = await this.FetchSong();
console.log("Song loaded, loading samples");
console.log("TRACKS");
console.log(tracks);
var uniqueSamples = _self.GetUniqueSamples(tracks).map(function(sample) {
return _self.GetDuration(sample);
});
Promise.all(uniqueSamples).then(function(richSamples) {
for (var i = 0; i < richSamples.length; i++) {
_self.samples[richSamples[i].sample.piece] = richSamples[i];
}
console.log("All samples loaded")
for (var i = 0; i < tracks.length; i++) {
// BUILD Actual Tracks
var actualTrack = [];
for (var t = 0; t < tracks[i].length; t++) {
var repeat = tracks[i][t].blocks / _self.samples[tracks[i][t].piece].sampleLength;
for (var x = 0; x < repeat; x++) {
actualTrack.push(tracks[i][t].piece);
for (var l = 0; l < _self.samples[tracks[i][t].piece].sampleLength - 1; l++) {
actualTrack.push("0");
}
}
}
_self.tracks[i].playlist = actualTrack;
}
_self.CalculatePlaytime();
_self.OnReady();
});
} catch (err) {
console.log("Failed during preload", err);
}
/*this.FetchSong().then(function(tracks) {
console.log("Song loaded, loading samples");
console.log("TRACKS");
console.log(tracks);
var uniqueSamples = _self.GetUniqueSamples(tracks).map(function(sample) {
return _self.GetDuration(sample);
});
Promise.all(uniqueSamples).then(function(richSamples) {
for (var i = 0; i < richSamples.length; i++) {
_self.samples[richSamples[i].sample.piece] = richSamples[i];
}
console.log("All samples loaded")
for (var i = 0; i < tracks.length; i++) {
// BUILD Actual Tracks
var actualTrack = [];
for (var t = 0; t < tracks[i].length; t++) {
var repeat = tracks[i][t].blocks / _self.samples[tracks[i][t].piece].sampleLength;
for (var x = 0; x < repeat; x++) {
actualTrack.push(tracks[i][t].piece);
for (var l = 0; l < _self.samples[tracks[i][t].piece].sampleLength - 1; l++) {
actualTrack.push("0");
}
}
}
_self.tracks[i].playlist = actualTrack;
}
_self.CalculatePlaytime();
_self.OnReady();
});
}).catch(function(err) {
console.log("Failed during preload");
});*/
}
CalculatePlaytime() {
var longestTrack = this.tracks[0].playlist;
for (var t = 0; t < this.tracks.length; t++) {
console.log(this.tracks[t].playlist.length)
if (this.tracks[t].playlist.length > longestTrack.length) {
longestTrack = this.tracks[t].playlist;
}
}
var traxLengthInSeconds = longestTrack.length * 2;
this.traxLengthInSeconds = traxLengthInSeconds;
this.SetPlayTime();
}
SetPlayTime() {
var str = this.SecondsToString(this.traxLengthInSeconds);
var time = this.playerElement.getElementsByClassName("time");
if (time.length > 0) {
var totalTimeElement = document.createElement('span');
totalTimeElement.innerHTML = "(" + str + ")";
totalTimeElement.classList.add("length");
time[0].innerHTML = this.SecondsToString(this.timeInSeconds);
time[0].appendChild(totalTimeElement);
}
console.log(str);
}
SecondsToString(seconds) {
var d = Number(seconds);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
var str = "0" + m + ":";
if (s < 10) {
str += "0";
}
str += "" + s;
return str;
}
Tick() {
if (this.playing) {
for (var i = 0; i < this.tracks.length; i++) {
this.PlayNextBeat(i);
}
this.position = this.position + 1;
}
}
Time() {
this.timeInSeconds = this.timeInSeconds + 1;
if (this.timeInSeconds > this.traxLengthInSeconds) {
this.ResetPlayer();
} else {
this.SetPlayTime();
}
}
PlayNextBeat(track) {
if (this.samples[this.tracks[track].playlist[this.position]]) {
this.tracks[track].player = this.samples[this.tracks[track].playlist[this.position]].audioObj;
this.tracks[track].timeLeft = this.samples[this.tracks[track].playlist[this.position]].sampleLength;
this.tracks[track].blocks = this.tracks[track].playlist[this.position].blocks;
this.tracks[track].sample = this.tracks[track].playlist[this.position];
if (this.tracks[track].sample != 0) {
console.log("TRACK " + track + " PLAYING: " + this.tracks[track].playlist[this.position])
this.tracks[track].player.currentTime = 0;
this.tracks[track].player.volume = this.volume;
this.tracks[track].player.play();
}
}
}
Play() {
this.playing = !this.playing;
var playBtn = this.playerElement.getElementsByClassName("play-btn");
var musicActivity = this.playerElement.getElementsByClassName("music-activity");
if (this.playing) {
if (playBtn.length > 0) {
playBtn[0].classList.add("playing");
}
if (musicActivity.length > 0) {
musicActivity[0].classList.add("playing");
}
this.position = 0;
this.Tick();
this.ticker = setInterval(function() {
this.Tick()
}.bind(this), 2000);
this.time = setInterval(function() {
this.Time()
}.bind(this), 1000);
} else {
this.ResetPlayer();
}
}
ResetPlayer() {
var musicActivity = this.playerElement.getElementsByClassName("music-activity");
var playBtn = this.playerElement.getElementsByClassName("play-btn");
clearInterval(this.ticker);
clearInterval(this.time);
this.timeInSeconds = 0;
this.SetPlayTime();
for (var i = 0; i < this.tracks.length; i++) {
this.tracks[i].player.pause();
}
this.samples.forEach(sample => {
sample.audioObj.pause();
});
if (playBtn.length > 0) {
playBtn[0].classList.remove("playing");
}
if (musicActivity.length > 0) {
musicActivity[0].classList.remove("playing");
}
}
}