mirror of
https://github.com/house-of-vanity/hexound.ru.git
synced 2025-07-06 22:34:08 +00:00
Initial
This commit is contained in:
218
js/chiptune2.js
Executable file
218
js/chiptune2.js
Executable file
@ -0,0 +1,218 @@
|
||||
// audio context
|
||||
ChiptuneAudioContext = AudioContext || webkitAudioContext;
|
||||
|
||||
// config
|
||||
function ChiptuneJsConfig(repeatCount, context) {
|
||||
this.repeatCount = repeatCount;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// player
|
||||
function ChiptuneJsPlayer(config) {
|
||||
this.config = config;
|
||||
this.context = config.context || new ChiptuneAudioContext;
|
||||
this.currentPlayingNode = null;
|
||||
this.handlers = [];
|
||||
}
|
||||
|
||||
// event handlers section
|
||||
ChiptuneJsPlayer.prototype.fireEvent = function (eventName, response) {
|
||||
var handlers = this.handlers;
|
||||
if (handlers.length) {
|
||||
handlers.forEach(function (handler) {
|
||||
if (handler.eventName === eventName) {
|
||||
handler.handler(response);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.addHandler = function (eventName, handler) {
|
||||
this.handlers.push({eventName: eventName, handler: handler});
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.onEnded = function (handler) {
|
||||
this.addHandler('onEnded', handler);
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.onError = function (handler) {
|
||||
this.addHandler('onError', handler);
|
||||
}
|
||||
|
||||
// metadata
|
||||
ChiptuneJsPlayer.prototype.duration = function() {
|
||||
return Module._openmpt_module_get_duration_seconds(this.currentPlayingNode.modulePtr);
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.metadata = function() {
|
||||
var data = {};
|
||||
var keys = Module.Pointer_stringify(Module._openmpt_module_get_metadata_keys(this.currentPlayingNode.modulePtr)).split(';');
|
||||
var keyNameBuffer = 0;
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
keyNameBuffer = Module._malloc(keys[i].length + 1);
|
||||
Module.writeStringToMemory(keys[i], keyNameBuffer);
|
||||
data[keys[i]] = Module.Pointer_stringify(Module._openmpt_module_get_metadata(player.currentPlayingNode.modulePtr, keyNameBuffer));
|
||||
Module._free(keyNameBuffer);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.seek = function(position) {
|
||||
Module._openmpt_module_set_position_seconds(this.currentPlayingNode.modulePtr, position);
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.getPosition = function() {
|
||||
return Module._openmpt_module_get_position_seconds(this.currentPlayingNode.modulePtr);
|
||||
}
|
||||
// playing, etc
|
||||
ChiptuneJsPlayer.prototype.load = function(input, callback) {
|
||||
var player = this;
|
||||
if (input instanceof File) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
return callback(reader.result); // no error
|
||||
}.bind(this);
|
||||
reader.readAsArrayBuffer(input);
|
||||
} else {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', input, true);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onload = function(e) {
|
||||
if (xhr.status === 200) {
|
||||
return callback(xhr.response); // no error
|
||||
} else {
|
||||
player.fireEvent('onError', {type: 'onxhr'});
|
||||
}
|
||||
}.bind(this);
|
||||
xhr.onerror = function() {
|
||||
player.fireEvent('onError', {type: 'onxhr'});
|
||||
};
|
||||
xhr.onabort = function() {
|
||||
player.fireEvent('onError', {type: 'onxhr'});
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.play = function(buffer) {
|
||||
this.stop();
|
||||
var processNode = this.createLibopenmptNode(buffer, this.config);
|
||||
if (processNode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set config options on module
|
||||
Module._openmpt_module_set_repeat_count(processNode.modulePtr, this.config.repeatCount);
|
||||
|
||||
this.currentPlayingNode = processNode;
|
||||
processNode.connect(this.context.destination);
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.stop = function() {
|
||||
if (this.currentPlayingNode != null) {
|
||||
this.currentPlayingNode.disconnect();
|
||||
this.currentPlayingNode.cleanup();
|
||||
this.currentPlayingNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.togglePause = function() {
|
||||
if (this.currentPlayingNode != null) {
|
||||
this.currentPlayingNode.togglePause();
|
||||
}
|
||||
}
|
||||
|
||||
ChiptuneJsPlayer.prototype.createLibopenmptNode = function(buffer, config) {
|
||||
// TODO error checking in this whole function
|
||||
|
||||
var maxFramesPerChunk = 4096;
|
||||
var processNode = this.context.createScriptProcessor(0, 0, 2);
|
||||
processNode.config = config;
|
||||
processNode.player = this;
|
||||
var byteArray = new Int8Array(buffer);
|
||||
var ptrToFile = Module._malloc(byteArray.byteLength);
|
||||
Module.HEAPU8.set(byteArray, ptrToFile);
|
||||
processNode.modulePtr = Module._openmpt_module_create_from_memory(ptrToFile, byteArray.byteLength, 0, 0, 0);
|
||||
processNode.paused = false;
|
||||
processNode.leftBufferPtr = Module._malloc(4 * maxFramesPerChunk);
|
||||
processNode.rightBufferPtr = Module._malloc(4 * maxFramesPerChunk);
|
||||
processNode.cleanup = function() {
|
||||
if (this.modulePtr != 0) {
|
||||
Module._openmpt_module_destroy(this.modulePtr);
|
||||
this.modulePtr = 0;
|
||||
}
|
||||
if (this.leftBufferPtr != 0) {
|
||||
Module._free(this.leftBufferPtr);
|
||||
this.leftBufferPtr = 0;
|
||||
}
|
||||
if (this.rightBufferPtr != 0) {
|
||||
Module._free(this.rightBufferPtr);
|
||||
this.rightBufferPtr = 0;
|
||||
}
|
||||
}
|
||||
processNode.stop = function() {
|
||||
this.disconnect();
|
||||
this.cleanup();
|
||||
}
|
||||
processNode.pause = function() {
|
||||
this.paused = true;
|
||||
}
|
||||
processNode.unpause = function() {
|
||||
this.paused = false;
|
||||
}
|
||||
processNode.togglePause = function() {
|
||||
this.paused = !this.paused;
|
||||
}
|
||||
processNode.onaudioprocess = function(e) {
|
||||
var outputL = e.outputBuffer.getChannelData(0);
|
||||
var outputR = e.outputBuffer.getChannelData(1);
|
||||
var framesToRender = outputL.length;
|
||||
if (this.ModulePtr == 0) {
|
||||
for (var i = 0; i < framesToRender; ++i) {
|
||||
outputL[i] = 0;
|
||||
outputR[i] = 0;
|
||||
}
|
||||
this.disconnect();
|
||||
this.cleanup();
|
||||
return;
|
||||
}
|
||||
if (this.paused) {
|
||||
for (var i = 0; i < framesToRender; ++i) {
|
||||
outputL[i] = 0;
|
||||
outputR[i] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
var framesRendered = 0;
|
||||
var ended = false;
|
||||
var error = false;
|
||||
while (framesToRender > 0) {
|
||||
var framesPerChunk = Math.min(framesToRender, maxFramesPerChunk);
|
||||
var actualFramesPerChunk = Module._openmpt_module_read_float_stereo(this.modulePtr, this.context.sampleRate, framesPerChunk, this.leftBufferPtr, this.rightBufferPtr);
|
||||
if (actualFramesPerChunk == 0) {
|
||||
ended = true;
|
||||
// modulePtr will be 0 on openmpt: error: openmpt_module_read_float_stereo: ERROR: module * not valid or other openmpt error
|
||||
error = !this.modulePtr;
|
||||
}
|
||||
var rawAudioLeft = Module.HEAPF32.subarray(this.leftBufferPtr / 4, this.leftBufferPtr / 4 + actualFramesPerChunk);
|
||||
var rawAudioRight = Module.HEAPF32.subarray(this.rightBufferPtr / 4, this.rightBufferPtr / 4 + actualFramesPerChunk);
|
||||
for (var i = 0; i < actualFramesPerChunk; ++i) {
|
||||
outputL[framesRendered + i] = rawAudioLeft[i];
|
||||
outputR[framesRendered + i] = rawAudioRight[i];
|
||||
}
|
||||
for (var i = actualFramesPerChunk; i < framesPerChunk; ++i) {
|
||||
outputL[framesRendered + i] = 0;
|
||||
outputR[framesRendered + i] = 0;
|
||||
}
|
||||
framesToRender -= framesPerChunk;
|
||||
framesRendered += framesPerChunk;
|
||||
}
|
||||
if (ended) {
|
||||
this.disconnect();
|
||||
this.cleanup();
|
||||
error ? processNode.player.fireEvent('onError', {type: 'openmpt'}) : processNode.player.fireEvent('onEnded');
|
||||
}
|
||||
}
|
||||
return processNode;
|
||||
}
|
||||
|
35
js/libopenmpt.js
Normal file
35
js/libopenmpt.js
Normal file
File diff suppressed because one or more lines are too long
251
js/logic.js
Executable file
251
js/logic.js
Executable file
@ -0,0 +1,251 @@
|
||||
var player;
|
||||
var interval;
|
||||
var playlist = [];
|
||||
var fileaccess = document.querySelector('*');
|
||||
var current_mod;
|
||||
var mode = "direct_order";
|
||||
var VERSION = 0.07
|
||||
|
||||
|
||||
function init() {
|
||||
if (player == undefined) {
|
||||
player = new ChiptuneJsPlayer(new ChiptuneJsConfig(0));
|
||||
setInterval(progress, 200);
|
||||
}
|
||||
else {
|
||||
player.stop();
|
||||
playPauseButton();
|
||||
}
|
||||
}
|
||||
|
||||
function getRandomInt(max) {
|
||||
min = 0;
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
}
|
||||
|
||||
function start_play(id, action) {
|
||||
document.getElementById("mod_"+current_mod).style.color = "#4c4cbd";
|
||||
if (action == "user") {
|
||||
var result = $.grep(playlist, function(e){ return e.id == id; });
|
||||
console.log(result[0].name);
|
||||
console.log("Currently playing: "+current_mod)
|
||||
document.getElementById("mod_"+current_mod).style.color = "#4c4cbd";
|
||||
id = result[0].id;
|
||||
name = result[0].name;
|
||||
console.log('PLaying ' + name + ". Initiated by User.");
|
||||
loadURL('/mods/' + name);
|
||||
document.getElementById('filename').innerHTML = name
|
||||
window.location.hash = '#' + (id);
|
||||
document.getElementById("mod_" + id).style.color = "#b30059";
|
||||
current_mod = id;
|
||||
} else {
|
||||
if (check_mode() == "shuffle") {
|
||||
|
||||
var next = getRandomInt(playlist.length);
|
||||
console.log('PLaying ' + playlist[next].name + ". Initiated by System. Shuffle");
|
||||
loadURL('/mods/' + playlist[next].name);
|
||||
document.getElementById('filename').innerHTML = playlist[next].name
|
||||
window.location.hash = '#' + playlist[next].id
|
||||
document.getElementById("mod_" + playlist[next].id).style.color = "#b30059";
|
||||
current_mod = next;
|
||||
} else if (check_mode() == "direct_order") {
|
||||
|
||||
var next = playlist.findIndex(x => x.id == current_mod) + 1;
|
||||
id = playlist[next].id;
|
||||
name = playlist[next].name;
|
||||
console.log('PLaying ' + name + ". Initiated by System. Direct order.");
|
||||
loadURL('/mods/' + name);
|
||||
document.getElementById('filename').innerHTML = name
|
||||
window.location.hash = '#' + id
|
||||
document.getElementById("mod_" + id).style.color = "#b30059";
|
||||
current_mod = id;
|
||||
} else if (check_mode() == "loop") {
|
||||
|
||||
var next = playlist.findIndex(x => x.id == current_mod);
|
||||
id = playlist[next].id;
|
||||
name = playlist[next].name;
|
||||
console.log('PLaying ' + name + ". Initiated by System. Loop.");
|
||||
loadURL('/mods/' + name);
|
||||
document.getElementById('filename').innerHTML = name
|
||||
window.location.hash = '#' + id
|
||||
document.getElementById("mod_" + id).style.color = "#b30059";
|
||||
current_mod = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setMetadata(filename) {
|
||||
var metadata = player.metadata();
|
||||
|
||||
if (metadata['title'] != '') {
|
||||
document.getElementById('title').innerHTML = metadata['title'];
|
||||
}
|
||||
else {
|
||||
document.getElementById('title').innerHTML = filename;
|
||||
}
|
||||
|
||||
if (metadata['artist'] != '') {
|
||||
document.getElementById('artist').innerHTML = '<br />' + metadata['artist'];
|
||||
}
|
||||
else {
|
||||
document.getElementById('artist').innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
function toInt(n) {
|
||||
return Math.round(Number(n));
|
||||
};
|
||||
|
||||
function progress() {
|
||||
document.getElementById('rangeinput').value = player.getPosition();
|
||||
$("#output").html(toInt(player.getPosition()));
|
||||
if (toInt(player.getPosition()) == toInt(player.duration()))
|
||||
start_play(0, "system")
|
||||
}
|
||||
|
||||
function loadURL(path) {
|
||||
clearInterval(interval);
|
||||
init();
|
||||
player.load(path, function (buffer) {
|
||||
player.play(buffer);
|
||||
setMetadata(path);
|
||||
$("#rangeinput").attr('max', player.duration());
|
||||
$("#rangeinput").attr('value', 0);
|
||||
$("#duration").html(toInt(player.duration()));
|
||||
pausePauseButton();
|
||||
});
|
||||
}
|
||||
|
||||
function pauseButton() {
|
||||
player.togglePause();
|
||||
switchPauseButton();
|
||||
}
|
||||
|
||||
function switchPauseButton() {
|
||||
var button = document.getElementById('pause')
|
||||
if (button) {
|
||||
button.id = "play_tmp";
|
||||
}
|
||||
button = document.getElementById('play')
|
||||
if (button) {
|
||||
button.id = "pause";
|
||||
}
|
||||
button = document.getElementById('play_tmp')
|
||||
if (button) {
|
||||
button.id = "play";
|
||||
}
|
||||
}
|
||||
|
||||
function playPauseButton() {
|
||||
var button = document.getElementById('pause');
|
||||
if (button) {
|
||||
button.id = "play";
|
||||
}
|
||||
}
|
||||
|
||||
function pausePauseButton() {
|
||||
var button = document.getElementById('play')
|
||||
if (button) {
|
||||
button.id = "pause";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fileaccess.ondrop = function (e) {
|
||||
e.preventDefault();
|
||||
var file = e.dataTransfer.files[0];
|
||||
var fd = new FormData();
|
||||
fd.append("files", file);
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'handle_file_upload.php', true);
|
||||
xhr.upload.onprogress = function (e) {
|
||||
if (e.lengthComputable) {
|
||||
var percentComplete = (e.loaded / e.total) * 100;
|
||||
console.log(percentComplete + '% uploaded');
|
||||
}
|
||||
};
|
||||
xhr.onload = function () {
|
||||
if (this.status == 200) {
|
||||
var resp = JSON.parse(this.response);
|
||||
console.log('Server got:', resp);
|
||||
};
|
||||
};
|
||||
xhr.send(fd);
|
||||
init();
|
||||
|
||||
player.load(file, function (buffer) {
|
||||
player.play(buffer);
|
||||
setMetadata(file.name);
|
||||
pausePauseButton();
|
||||
});
|
||||
get_files();
|
||||
}
|
||||
|
||||
fileaccess.ondragenter = function (e) { e.preventDefault(); }
|
||||
fileaccess.ondragover = function (e) { e.preventDefault(); };
|
||||
|
||||
function get_files() {
|
||||
$.getJSON('library.php', function (data) {
|
||||
$('#list').append('<ul style="list-style-type: none;margin: 0;padding: 0;">')
|
||||
$.each(data, function (key, val) {
|
||||
//if(val.time == undefined){val.time = 1493299893}
|
||||
var tmp = {
|
||||
'name' : val.filename,
|
||||
'id' : val.id
|
||||
//'uploaded': val.time
|
||||
};
|
||||
$('#list').append('<li style="list-style-type: none;" class="thumb selectable arrow light" ><span class="song name" onclick="start_play('+val.id+',\'user\')"><a href="mods/' + val.filename + '"><img style="height:1em;" src="/img/save1.png"></a> <span id="mod_' + val.id + '" class="name_song">' + val.filename + '</span></span></li>');
|
||||
console.log(key, val.id);
|
||||
tmp
|
||||
playlist.push(tmp);
|
||||
});
|
||||
console.log('Summary:', playlist.length, 'tracks.')
|
||||
current_mod = playlist.length - 1;
|
||||
$('#list').append('</ul>')
|
||||
|
||||
var mod_number = parseInt(window.location.hash.substr(1));
|
||||
if (window.location.hash.substr(1) != "") {
|
||||
start_play(mod_number,"user")
|
||||
console.log("Playing from url mod # " + window.location.hash.substr(1));
|
||||
}
|
||||
});
|
||||
|
||||
$(window).on('hashchange', function() {
|
||||
var mod_number = parseInt(window.location.hash.substr(1));
|
||||
if (window.location.hash.substr(1) != "") {
|
||||
start_play(mod_number,"user")
|
||||
console.log("Playing from url mod # " + window.location.hash.substr(1));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
get_files();
|
||||
window.onload = function up() {
|
||||
var input = document.getElementById('input');
|
||||
document.getElementById('version').innerHTML =VERSION;
|
||||
input.onkeyup = function () {
|
||||
var filter = input.value.toUpperCase();
|
||||
var lis = document.getElementsByTagName('li');
|
||||
for (var i = 0; i < lis.length; i++) {
|
||||
var name = lis[i].getElementsByClassName('name_song')[0].innerHTML;
|
||||
//if (name.toUpperCase().indexOf(filter) == 0)
|
||||
if (name.toUpperCase().includes(filter) == true) {
|
||||
lis[i].style.display = 'list-item'
|
||||
}
|
||||
else
|
||||
lis[i].style.display = 'none';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function check_mode()
|
||||
{
|
||||
var inp = document.getElementsByName('playmode');
|
||||
for (var i = 0; i < inp.length; i++) {
|
||||
if (inp[i].type == "radio" && inp[i].checked) {
|
||||
return inp[i].value;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user