rserota / wad

Web Audio DAW. Use the Web Audio API for dynamic sound synthesis. It's like jQuery for your ears.
MIT License
1.9k stars 160 forks source link

FX order and FX loop #12

Closed coleww closed 10 years ago

coleww commented 10 years ago

Since we did the thing where a user can pass multiple filters and specify the order, I think i can figure out how to do the same for everything else. Probably maintaining an array of the order things are passed to the constructor, and then using that during setuponplay time.

I'm also interested in making a sort of FX loop so that people could incorporate other libraries, and I think this would have to be a function that is passed the audiocontext and that/this and is overidden by the user. For things like audio visualizers and effect libraries.

rserota commented 10 years ago

What do you mean by 'everything else'? I can't think of other parameters that you would want more than one of.

I'm not sure if I follow what you're saying about an FX loop. Could you explain that more? Maybe with some code snippets?

coleww commented 10 years ago

Oh i meant the order being applied in. For filter, reverb, vibrato, tremolo, etc.

For the FX loop i'm basically thinking like

  function constructExternalFX(that, args){
    //override me
  } 

and function setupExternalFXOnPlay(that, args){ //override me }

Each of these methods would always be called on initialization and play, but would only do something if the user overwrote them. And I could present some code in the readme for how one can add Tuna, web audio analysis, etc. to a Wad app.

rserota commented 10 years ago

The FX loop sounds like a great idea. I had never heard of Tuna before, but it looks pretty cool. It basically just creates webaudio nodes, right? So that shouldn't be too hard to integrate into Wad, using the ExternalFX functions you proposed. Though, you connect to them differently ( node.connect(node.input) vs node.connect(node) ) so the plugEmIn function would need to check for what kind of node it was connecting to.

How were you thinking a user would overwrite these functions? Would they be passing in callbacks to the constructor, or something else? I like all the added flexibility, but I also want it to be simple, where possible.

I noticed that Tuna has not been updated in a while. I know that the web audio standard has been evolving recently, so I'm worried that using Tuna would introduce more cross-browser compatibility issues.

As far as letting users specify the order of all other effects, how would that change the API? I still want there to be a default order, so a user doesn't doesn't have to think about the order of effects if they don't want to. Perhaps, if arguments are passed as an object, effects are applied in the default order (the current behavior), but if arguments are passed as an array of objects, they'll be applied in the specified order. For example, I might do something like this to specify that I want reverb applied before the filter:

var bass = new Wad([
    { source : 'sine' },
    { reverb : { wet : 1 } },
    { filter : { type : 'lowpass', frequency : 700 }
])

Am I making sense? Let me know if we're on the same page, or if you can offer me more clarity on these issues.

Thanks for contributing everything you've done, and thanks for thinking forward with all this cool stuff. I'm excited to see the features you add in the future. Let me know if I can help you in any way.

coleww commented 10 years ago

i like what you are thinking about passing the array.

I'm thinking the user would override those functions in their own script, and it would be passed that/arg/audiocontext etc. to allow for different things. Tuna may be old, but im sure there are newer libraries that could be integrated. Audio analysis/visualization is also interesting to me, but a Wad analyzer might be better.

actually i have a branch somewhere that adds tuna and it seems to work. but i've only tried it on chrome.

rserota commented 10 years ago

Thanks again for contributing. I merged the code because it seems to work, but I have a few questions/comments. First of all, it's not necessary to pass 'this' into setupFxLoopOnPlay. Since that method is actually on the prototype, unlike most of the functions in Wad, you can access 'this' normally without having to pass it in. And I'd say that setupFxLoopOnPlay definitely does belong on the prototype, unlike most of the other functions.

In your example for using tuna, is there a typo? This line looks pretty funky to me: tuna ||= tuna new Tuna(context);

setupfxlooponplay only relies on play() arguments, not constructor arguments. Is that a problem? Might there be some external fx which needs to be set up on the constructor?

I'm also wondering about the name, setupupfxlooponplay. What exactly is the 'loop' part? Maybe a better name would be something like 'setupExternalFxOnPlay', or even just 'setupExFxOnPlay'.

coleww commented 10 years ago

Totally forgot about the prototype/this thing.

the ||= was supposed to be short circuiting or assignment, but I think thats ruby-style. It should actually be tuna = tuna || new Tuna(context).

I can certainly add a constructor function in addition to the above fixes, as well as rename the function.

rserota commented 10 years ago

I've already changed the that/this issue, but if you could do the other changes when you get a moment, I'd appreciate it. You could rename the method to 'setupExternalFxOnPlay' and add a method for 'constructExternalFx'.

rserota commented 10 years ago

This feature looks complete, so I'll close this issue. Feel free to reopen it if you want to discuss any debugging/refactoring or whatever on this feature.