Creating a custom echo node with web-audio - javascript

I'm playing with the webkit Audio API and I'm trying to create an Echo effect, to accomplish that I've connected a DelayNode with a GainNode in a loop (The output of one is the input of the other, and viceversa).
The effect works fine, but now I want to create an EchoNode Object that I can just plug-in and connect with the other AudioNode objects.
Something like:
myEchoNode = new EchoNode();
myConvolverNode = context.createConvolver();
myConvolverNode.connect(myEchoNode);
I think that I should make my EchoNode inherit from AudioNode, so that the connect function of every other AudioNode would work, but I don't know how to do that in Javascript with the web Audio API.
Can anyone give me a hint, or if you think that there is a better way to accomplish that I would greatly appreciate it.
Thanks

Oskar's solution should do the trick, but I want to point out that it will require you to connect to your EchoNode in a nonstandard way (using EchoNode.input rather than simply connecting to the EchoNode itself). For simple effects such as feedback delay, this can be avoided by creating the EchoNode via a factory function that returns a native DelayNode mixed with some extra properties. Here's an example from SynthJS:
function FeedbackDelayNode(context, delay, feedback){
this.delayTime.value = delay;
this.gainNode = context.createGainNode();
this.gainNode.gain.value = feedback;
this.connect(this.gainNode);
this.gainNode.connect(this);
}
function FeedbackDelayFactory(context, delayTime, feedback){
var delay = context.createDelayNode(delayTime + 1);
FeedbackDelayNode.call(delay, context, delayTime, feedback);
return delay;
}
AudioContext.prototype.createFeedbackDelay = function(delay, feedback){
return FeedbackDelayFactory(this, delay, feedback);
};
As you can see, the result is a native DelayNode that can be connected to other nodes in the standard fashion, but it has an attached gain node that provides the feedback effect.

Have a look at this article I wrote, it might give you some ideas: http://www.html5rocks.com/en/tutorials/casestudies/jamwithchrome-audio/ (which explains the basic idea behind tuna.js that Taoist recommended).

Related

Detecting net::ERR_FILE_NOT_FOUND with only JS

I have recreated a blueprint, which has 60+ rooms, as an inline SVG.
There are functions that display information, such as pictures, when you select or hover a room. I'm using one div container to display the pictures by setting its background property to url('path-of-image.ext'), as can be seen below.
var cla = document.getElementsByClassName('cla');
for (i = 0; i < cla.length; i++) {
cla[i].addEventListener('mouseenter', fun);
}
function fun(){
var str = 'url("media/' + this.id.slice(4) + '.jpg")';
pictureFrame.style.background = str;
pictureFrame.style.backgroundSize = 'cover';
pictureFrame.style.backgroundPosition = 'center'
}
The reason I'm not using the background property's shorthand is because I plan on animating the background-position property with a transition.
However, not all rooms have pictures. Hence console throws the following error, GET ... net::ERR_FILE_NOT_FOUND, when you select or hover said rooms. The error doesn't cause the script to break, but I would prefer not to run that code every single time a room is hovered, even when a given room doesn't have pictures.
Even though I know this can be done imperatively with if/else statements, I'm trying to do this programmatically since there are so many individual rooms.
I've tried using try/catch, but this doesn't seem to detect this sort of error.
Any ideas?
Is it even possible to detect this kind of error?
You could attempt to read it using FileReader and catch/handle NotFoundError error.
If it were to error, you could assign it to an object or array which you would first check upon hover. If the file was in that array, you could avoid attempting to read it again and just handle however you like.
Here is a good article by Nicholas Zakas on using FileReader
First off I would see if there is a way of checking if the file exists before the document even loads so that you don't make unnecessary requests. If you have a database on the backend which can manage this that would serve you very well in the long term
Since you make it sound like the way you only know a file exists is by requesting it, here's a method that will allow you to try this:
function UrlExists(url)
{
var http = new XMLHttpRequest();
http.open('HEAD', url, false);
http.send();
return http.status!=404;
}
This won't request the image twice because of browser caching. As you can see that method is itself being depricated and overall the best way you can remedy this problem is checking before the page even loads; if you have a database or datastructure of any sort, add a class or property to the element if the image exists or not. Then, in your existing method, you can call something like document.getElementsByClassName('cla-with-image') to get only records that you've determined has an image (much more efficient than trying to load images that don't exist).
If you end up using that UrlExists method, then you can just modify your existing method to be
function fun(){
var url = "media/' + this.id.slice(4) + '.jpg";
if (UrlExists(url)) {
var str = 'url(' + url + ')';
pictureFrame.style.background = str;
pictureFrame.style.backgroundSize = 'cover';
pictureFrame.style.backgroundPosition = 'center'
}
}

How to make Screeps find sources?

In Screeps, I this code doesn't work:
var sources = creep.room.find(Game.FIND_SOURCES_ACTIVE);
It says this:
Cannot read property 'find' of undefined
I have been looking around and cannot find ANY other way to find sources.
Also I've noticed that most of other peoples code doesn't work and even the tutorial's code no longer works when put into the real game.
I can't be completely sure about your issue since I don't have your complete code to go off of but one issue could be that creepis not defined.
You need somewhere in your code to define creep such as a for loop to loop over each of your creeps in the game or room.
var roleMiner = require('role.miner') // role.miner being the module name for miner actions
for(var name in Game.creeps) {
var creep = Game.creeps[name];
//
// do whatever you wish with the current selected creep.
//
// most of the time you will call a module similar to what the tutorials suggest and put your actions for it in there
//
if(creep.memory.role == 'miner'){
roleMiner.run(creep); // passes the current selected creep to the run function in the module
}
}
So, in your roleMiner module you would have something that defines your miners actions.
var roleMiner = {
run: function(creep) {
// this one returns an array of the sources that are in the room with the creep
var sourcesRoom = creep.room.find(FIND_SOURCES);
// this one returns the source object which is closest to the creeps positon
var sourcesClose = creep.pos.findClosestByRange(FIND_SOURCES);
}
}
module.exports = roleMiner;
Hope this helps.
Screeps have some ... mechanism when sharing your data between each game tick.
If you store any thing in global Memory object, your data will lose all its prototype.
to restore your prototype use Object.setPrototypeOf(creep,Creep.prototype) or create new Creep object from your creep id.
I think what you are looking for is:
var sources = creep.pos.findClosestByRange(Game.SOURCES);
or
var sources = creep.pos.findClosestByPath(Game.SOURCES);
im a new player, not sure my code is efficient, i think the find method will be like this:
var sources = creep.room.find(FIND_SOURCES_ACTIVE)
creep will going to the active resource to harvester.

Can Web Workers be used to filter HTML nodes from a list?

I'm trying to do a script that may requiere a heavy filtering of html tags. I thought I could take the chance to learn about web workers but, this may not be the right use for them.
I wanted get every image on a page and filter by size. I know I can't pass an object to the worker and I think they can't have access to the DOM, so I did this:
window.addEventListener("load", init);
function init () {
console.log("init");
var imgs = document.querySelectorAll("img");
var worker = new Worker("worker.js");
console.log(JSON.stringify(imgs));
worker.postMessage(JSON.stringify(imgs));
worker.addEventListener("message", read_message);
}
Unfortunatly, it doesn't look like I can transform a NodeList into an object...
Do you think I should find another way of doing this or is it posible to send that information any other way?

How to use the getLogo function of the Spil API

How would I use the getLogo function to display the Spil Logo on inside my HTML5 game?
Here's the link to their docs
http://developers.spilgames.com/wiki/Developer_Platform_-_Learning_center_-_HTML5_API_getLogo
I don't understand if it's meant to display their logo automatically, or if I'm meant to do something with the object data it returns, and if so how would use it?
We provide basically only two properties: a URL to the image and a function. What you need to do within your game is attach the Javascript link to the image.
A typical logo implementation looks like this for a DOM implementation. But of course this depends on the nature of your game and if you're using a framework:
GameAPI.loadAPI(function (apiInstance) {
// getLogo example
var logoData = apiInstance.Branding.getLogo();
// Create a DOM element and use the values returned by the call
var logo = document.createElement('img');
logo.src = logoData.image;
logo.addEventListener('click', logoData.action);
document.body.appendChild(logo);
});
You can find a tutorial complete with jsFiddle example here: http://developers.spilgames.com/wiki/Developer_Platform_-_Learning_center_-_HTML5_API_-_(Tutorial)_Get_logo
If you run into technical issues, you can always get in touch with the Tech Support team using the "Support" tab on this page: http://developers.spilgames.com/contact
Hopefully this answers your question!

Using Piwik for a Single Page Application

Building a single page / fat client application and I'm wondering what the best practice is for including and tracking using http://piwik.org/
I'd like to use Piwik in a way that is architecturally sound and replacable with a different library in the future.
It seems that there are two basic options for tracking with Piwik:
Fill up a global _paq array with commands, then load the script (it's unclear to me how to record future "page" views or change variables though)
Get and use var myTracker = Piwik.getTracker()
_paq approach:
myApp.loadAnalytics = function() { /* dynamically insert piwik.php script */ }
myApp.track = function(pageName) {
window._paq = window._paq || [];
_paq.push(['setDocumentTitle', pageName]);
_paq.push(["trackPageView"]);
}
myApp.loadAnalytics()
// Then, anywhere in the application, and as many times as I want (I hope :)
myApp.track('reports/eastWing') // Track a "page" change, lightbox event, or anything else
.getTracker() approach:
myApp.loadAnalytics = function() { /* dynamically insert piwik.php script */ }
myApp.track = function(pageName) {
myApp.tracker = myApp.tracker || Piwik.getTracker('https://mysite.com', 1);
myApp.tracker.trackPageView(pageName);
}
myApp.loadAnalytics()
// Then, anywhere in the application, and as many times as I want (I hope :)
myApp.track('reports/eastWing') // Track a "page" change, lightbox event, or anything else
Are these approaches functionally identical? Is one preferred over another for a single page app?
To have the tracking library used (eg. piwik) completely independent from your application, you would need to write a small class that will proxy the functions to the Piwik tracker. Later if you change from Piwik to XYZ you can simply update this proxy class rather than updating multiple files that do some tracking.
The Async code is a must for your app (for example a call to any 'track*' method will send the request)
The full solution using .getTracker looks like this:
https://gist.github.com/SimplGy/5349360
Still not sure if it would be better to use the _paq array instead.

Categories