UNPKG

crossbrowdy

Version:

A Multimedia JavaScript framework to create real cross-platform and hybrid game engines, games, emulators, multimedia libraries and apps.

442 lines (384 loc) 10.1 kB
<!DOCTYPE html> <head> <meta charset="utf-8"> <meta http-eqv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>jsfx</title> <script> window.onerror = function(msg, url, linenumber) { alert('Error message: '+msg+'\nURL: '+url+'\nLine Number: '+linenumber); return true; } </script> <script src="jsfx.js"></script> </head> <body> <div id="jsfx"> <h1 class="title">jsfx</h1> <div class="description">See <a href="https://github.com/loov/jsfx">github.com/loov/jsfx</a> for more information.</div> <div></div> <div id="control" class="panel"> <div class="panel-title">Control</div> <input type="checkbox" id="use-audiocontext" title="Use AudioContext." onclick="ChangePlayMode()"> <button onclick="PlayCurrent()">Play</button> <button onclick="AddToLibrary()">Add</button> <a class="button" id="download" href="#" onmousedown="UpdateDownloadLink()" download="sound.wav">Download</a> <div id="last-time" title="Time it took to generate."></div> <div class="clear"></div> </div> <div id="presets" class="panel"> <div class="panel-title">Presets</div> </div> <div class="clear"></div> <div id="panels"> </div> <div class="clear"></div> <div class="panel wide"> <div class="panel-title">Library</div> <input type="text" readonly id="library-content" title="Paramset for the current Library."> <div id="library"></div> </div> </div> </body> <script> "use strict"; var Library = {}; var CurrentParams = {}; function PlayCurrent(){ Play(CurrentParams); } var PlayAudio = function(params){ var start = (new Date())|0; jsfx.Sound(params).play(); var stop = (new Date())|0; var time = (stop - start) + "ms" console.log("Generated in", time); document.getElementById("last-time").innerText = time; }; var Play = PlayAudio; var PlayContext; if(typeof AudioContext !== "undefined"){ var Live = jsfx.Live(); PlayContext = function(params){ Live._play(params); }; } else { document.getElementById("use-audiocontext").hidden = true; } function ChangePlayMode(){ if(document.getElementById("use-audiocontext").checked){ Play = PlayContext; } else { Play = PlayAudio; } } function AddToLibrary(){ var name = prompt("Please enter name for the sound:"); if((name == null) || (name == "")){ return; } var params = JSON.parse(JSON.stringify(CurrentParams)); jsfx._RemoveEmptyParams(params); Library[name] = params; UpdateHash(); UpdateCurrentView(); } function SelectPreset(preset){ CurrentParams = preset(); UpdateCurrentView(); PlayCurrent(); } var LastHash = ""; function UpdateHash(){ var json = JSON.stringify(Library); document.getElementById("library-content").value = json; LastHash = "#" + btoa(json); window.location.hash = LastHash; } function LoadFromHash(){ var json = window.location.hash.substr(1); try{ json = atob(json) document.getElementById("library-content").value = json; Library = JSON.parse(json); }catch(e){ console.log(e); } } if(window.location.hash != ""){ LoadFromHash(); } window.onhashchange = function(ev){ if(window.location.hash != LastHash){ LoadFromHash(); UpdateCurrentView(); } }; function UpdateDownloadLink(){ var sound = jsfx.Sound(CurrentParams); var el = document.getElementById("download"); el.href = sound.src; } function UpdateCurrentView(){ // create a copy of params var params = JSON.parse(JSON.stringify(CurrentParams)); jsfx.InitDefaultParams(params, jsfx.DefaultModules); list(params, function(moduleName, params){ list(params, function(paramName, paramValue){ var element = document.getElementById(moduleName + "$" + paramName);; if(element){ element.value = paramValue; } var element = document.getElementById(moduleName + "_" + paramName + "_" + paramValue); if(element){ element.checked = true; } }); }); var library = document.getElementById("library"); library.innerHTML = ""; var els = list(Library, function(name, params){ var load = E("button", "item-load", "#"); load.title = "Load"; load.onclick = function(){ CurrentParams = JSON.parse(JSON.stringify(params)); UpdateCurrentView(); }; var del = E("button", "item-delete", "X"); del.title = "Delete"; del.onclick = function(){ delete Library[name]; UpdateHash(); UpdateCurrentView(); } var el = E("div", "library-item", [ load, E("span", "item-name", name), del ]); el.title = "play"; el.onclick = function(){ Play(params); }; library.appendChild(el); }); } document.getElementById("library-content").click = function(ev){ ev.currentTarget.select(); } function ModifyValue(moduleName, paramName, newValue){ // console.log("CHANGE", moduleName, paramName, newValue); if(CurrentParams[moduleName] == null){ CurrentParams[moduleName] = {}; } CurrentParams[moduleName][paramName] = newValue; PlayCurrent(); } function CreateParam(name, def, module){ var sel; if(def.C){ sel = E("form", "", list(def.C, function(value){ var input = E("input", "", []); input.type = "radio"; input.id = module.name + "_" + name + "_" + value; input.name = module.name + "_" + name; input.value = value; input.onchange = function(ev){ ModifyValue(module.name, name, input.value); }; var label = E("label", "", value); label.htmlFor = input.id; return E("span", "radio-option", [input, label]); })); } else { sel = E("input", "", []); sel.type = "range"; sel.min = def.L; sel.max = def.H; sel.value = def.D; sel.step = 0.01; sel.onchange = function(ev){ ModifyValue(module.name, name, parseFloat(sel.value)); }; if(def.H - def.L > 10){ sel.step = 1; } } sel.id = module.name + "$" + name; return E("tr", "", [ E("td", "", name), E("td", "", [sel]) ]); } function CreatePanel(module){ return E("div", "panel", [ E("div", "panel-title", module.name), E("table", "", list(module.params, CreateParam, module)) ]); } function Add(module){ document.getElementById("panels").appendChild(CreatePanel(module)); } Add(jsfx.Module.Generator); Add(jsfx.Module.Frequency); Add(jsfx.Module.Volume); Add(jsfx.Module.Vibrato); Add(jsfx.Module.Filter); Add(jsfx.Module.Phaser); document.getElementById("panels").appendChild(E("div", "clear", [])); list(jsfx.Preset, function(name, preset){ var button = E("button", "", name); button.onclick = function(){ SelectPreset(preset); }; document.getElementById("presets").appendChild(button); }); document.getElementById("presets").appendChild(E("div", "clear", [])); function E(tag, className, content){ var el = document.createElement(tag); if(className !== ''){ el.className = className; } if(typeof content == 'object'){ for(var i = 0; i < content.length; i += 1){ el.appendChild(content[i]); } } else if (typeof content == 'string'){ el.innerHTML = content; } return el; } function list(obj, fn, X){ var r = []; for(var name in obj){ if(obj.hasOwnProperty(name)){ r.push(fn(name, obj[name], X)); } } return r; } UpdateCurrentView(); </script> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body, html { font-family: RobotoDraft,Roboto,Helvetica Neue,Helvetica,Arial,sans-serif; font-weight: 300; line-height: 1.2; color: #333333; } .clear { clear: both; } #jsfx { margin: 16px auto; max-width: 650px; } #jsfx .title { font-size: 2em; color: #444; clear: both; } #jsfx .description { margin-bottom: 8px; } #jsfx .panel { float: left; clear: left; position: relative; margin: 8px; padding: 4px; width: 300px; background: #FFF; box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); } #jsfx .panel:nth-child(2n) { float: right; clear: right; } #jsfx .panel.wide { float: none; clear: none; width: 100%; } @media(max-width: 650px){ #jsfx { width: 100%; margin: 0; } #jsfx .panel { float: none !important; clear: none !important; margin: 8px 0; width: 100%; } } #jsfx .panel .panel-title { padding: 4px; font-size: 12px; color: #666; } #jsfx .panel button, #jsfx .panel .button { float: left; } #jsfx button, #jsfx .button { font-family: RobotoDraft,Roboto,Helvetica Neue,Helvetica,Arial,sans-serif; font-weight: 300; font-size: 14px; margin: 2px; border: 1px solid #AAA; background: #FFF; cursor: pointer; padding: 4px 8px; text-decoration: none; color: inherit; } #jsfx button:hover, #jsfx .button:hover { border: 1px solid #7DC6FF; box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); } #jsfx .panel table { font-size: 0.8em; width: 100%; } #jsfx #use-audiocontext { float: left; } #jsfx .panel table input[type="range"] { width: 100%; } #jsfx .panel table tr td:first-child { width: 80px; } #jsfx .panel .radio-option { display: inline-block; margin-left: 2px; line-height: 10px; border: 1px solid #eee; margin: 2px 4px; padding: 2px 4px; width: 40%; } #jsfx .panel .radio-option input { height: 10px; } #jsfx #last-time { position: absolute; bottom: 4px; right: 8px; } #jsfx #library-content { position: absolute; top: 4px; right: 4px; } #jsfx #library .library-item { position: relative; cursor: pointer; line-height: 24px; } #jsfx #library .library-item:hover { background: #eee; } #jsfx #library .library-item .item-name { margin-left: 8px; vertical-align: middle; font-size: 14px; } #jsfx #library .library-item button { padding: 0px 4px; width: 32px; text-align: center; } #jsfx #library .library-item .item-delete { display: block; position: absolute; right: 1px; bottom: 1px; top: 1px; border: 1px solid #F88; } </style>