cljs-bach
cljs-bach copied to clipboard
Constant source nodes
I've put together a collection of functions that provide support for inputs* (which are ConstantSourceNodes
in the web audio API: https://developer.mozilla.org/en-US/docs/Web/API/ConstantSourceNode)
This resolves #2, as inputs can be used as source nodes for the parameters of other audio nodes (via the jack
function), and their values can be directly set (via set-input!
, lin-ramp-input!
, and exp-ramp-input!
) by other code (such as MIDI event callbacks).
The following example code demonstrates:
- How to create an input
- How to update the value of an input
- How to use an input to control a parameter of another node.
; Create a constant source node with an initial value of 0
(defonce vol-input (make-input! audio-context 0))
; Update the vol-input's value to 2 (using set-input! from a midi
; event callback can allow you to control a source node with a midi
; device)
(set-input! vol-input 2)
; Ramp the vol-input to a new value gradually over time.
(lin-ramp-input! vol-input 5 5)
(exp-ramp-input! vol-input 10 5)
; Example of using vol-input as the source for the gain value.
(connect->
(sine 180)
(gain (jack vol-input)))
It is also worth noting that the ConstantSourceNode
is relatively new to most web browsers (I believe Chrome and Firefox added support in March), though a polyfill does exist at: https://www.npmjs.com/package/constant-source-node
*I chose the name "input" as I felt that it better reflected the use-case in cljs-bach than ConstantSourceNode
, but am happy to change it to something else.
This also has the potential to fix an annoying hack - if you look at the definition of constant
, you'll see that I had to fake ConstantSourceNodes before they existed by filling a raw buffer with all the same value.
This is a great pull request - you've well understood the original design, you have explained your intent very clearly and you're solving a real problem.
One thought I had - is it worth considering a more minimal API e.g. this branch? Once you have access to the raw node, you can do anything you like to it, so it's not strictly necessary to have them in CLJS Bach itself. Then again, it could be pretty convenient if it's a common use case.
What do you think?
Thanks very much @ctford, apologies for the delayed response.
That's a good point that returning the raw node does allow the users to perform any operations they want without extra functions in the library. However, one downside I can see to removing the ramp functions is that JS interop would be required by the user to make use of the native linear and exponential ramps, and I also found the ramp-end-time
function to be quite useful in practice for controlling the speed of a change without needing to manually calculate an end time relative to context.currentTime
in my compositions. I guess it depends on whether you think the functionality is within the scope of the library, or whether it is better kept in dependent libraries/applications.