Hacker News new | past | comments | ask | show | jobs | submit login

Wow this is awesome! I'm building something similar with WebMIDI and WebAudio and I've been blocked trying to get recording to work. My current solution is sampling my OscillatorNodes with a MediaRecorder and turning the resulting blob into an .ogg file but it only works in Firefox (Chrome has a bug with decoding ogg with WebAudio). Do you mind elaborating on how you do your wav recording?



I experimented with the MediaRecorder too but couldn't get anything to work. In the end, I used this: https://github.com/mattdiamond/Recorderjs - It has been abandoned by the author and the forceDownload function does not work anymore so I had to replace that. I'll send you a copy of my version if you like?


slightly inefficient, but you can use a ScriptProcessorNode [1]. just copy the buffer right before it reaches your destination and encode it as WAV when you're done recording. (Audio Worker would be the ideal solution but i don't think they're implemented yet).

something like this: http://pastebin.com/UP3F09Wn

[1] https://developer.mozilla.org/en-US/docs/Web/API/ScriptProce...


I tried this but using ScriptProcessorNodes is a pain in practice because of how the events work:

>An event, implementing the AudioProcessingEvent interface, is sent to the object each time the input buffer contains new data, and the event handler terminates when it has filled the output buffer with data.

Events just fire like mad until you put stuff in the output buffer. Couldn't get it to work like I needed it to.


i mean, of course events are going to fire like mad. welcome to the world of audio processing. :)

MediaRecorder works the same way (but for MediaStreamSources, not BufferSources).

the idea is that audio buffers are processed in chunks- an event fires for each chunk that is processed. the act of "recording" is just reassembling these chunks into a single ArrayBuffer.

edit: seems like Recorderjs works exactly this way (but implements features more than just recording, like exporting as WAV).

capturing the chunks: https://github.com/mattdiamond/Recorderjs/blob/master/src/re...

reassembling the chunks: https://github.com/mattdiamond/Recorderjs/blob/master/src/re...


> if (!this.recording) return;

This is the key I was missing in my implementation. Another challenge is wiring this up to multiple OscillatorNodes - the docs say a ScriptProcessorNode can only have one input. In my implementation I create a new OscillatorNode whenever you press a key.


In Acid Machine, I have created a kind of virtual 4 channel mixer, that is the only thing that connects directly to the main destination output. All osc nodes that are generated by an instrument get connected to the instruments master gain node, then that connects to one of the mixer channels. All mixer channels then connect to a master mixer gain, then the output.

If you do it that way, you just need to attach the recorder to the master output of the mixer.


yep--

it's also decent practice to send your oscillators into a mixer anyway so that they can be rerouted at large.

for instance, say you have 4 oscillators, 2 fx buses and an output. you route (4 oscillators) -> mixer -> fx bus 1 -> output. then if you want to switch the fx bus for your oscillators, you can just reroute the mixer instead of each oscillator individually.

in the case of a recorder, you'd want the end of your entire graph to look like this: mixer -> recorder -> output. this way your recorder is capturing all audio (oscillators, effects, etc). (and, as noted above, you have the option to reroute the mixer directly to the output when it's not recording).


Thanks for the advice! What node would be a mixer in WebAudio?


My mixer channels are a gain node (for input), followed by 2 gain nodes - which are used as fx slots and replaced when an effect is added, the last fx slot connects to another gain node (for channel output) - that then connects to the mixer master gain node.

You could have it as simple as 1 gain node for each channel which you use for input and output to the mixer master gain. This would make it difficult to add fx later though.


if all you're trying to do is combine nodes in the graph a gain node is standard. (that is, you can connect any number of oscillators to a single gain).


Great thanks. But throughout this project I've been wondering: why can't I buffer a damn oscillator (or gain) node?


That would be great, here's my code: https://github.com/johnBartos/buffer-oscillator-node/blob/ma...

I wonder if instead of encoding as ogg/opus I could switch the string to WAV instead?


Nice, I like the simplicity. Your download function is almost exactly the same as my modification to recorderJS, so you could just grab a copy of that and swap out the download function for your code.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: