Sound synth in Node

548 views
Skip to first unread message

Pedro Teixeira

unread,
Oct 28, 2011, 10:35:34 AM10/28/11
to nodejs
Hi all,

I'm looking for the best way to build a simple synth using Node.
It would output the sound to the sound device directly - not using a
browser.
It doesn't have to work anywhere else but MacOS.

I think there are 3 general solutions for this:

1) I can resort to creating the wave in Node and sending it to the
sound device buffer.

or

2) I can use a native binding for an existing C/C++ synth and just
expose the controls in Node.

or

3) I can spawn a child process with an external executable that is a
software synth and control it remotely (if it allows to).

Anyway, I haven't found any solution for any of these 3 approaches.
Any help would be appreciated!

Thanks!

-Pedro

Jorge

unread,
Oct 28, 2011, 11:00:34 AM10/28/11
to nod...@googlegroups.com

There's a wonderful one (disclaimer: I'm biased :-) --> node-sound:

https://github.com/xk/node-sound

One of this days I ought to put it on npm.
--
Jorge.

Ryan Schmidt

unread,
Oct 28, 2011, 4:37:59 PM10/28/11
to nod...@googlegroups.com
On Oct 28, 2011, at 10:00, Jorge wrote:

> On 28/10/2011, at 16:35, Pedro Teixeira wrote:
>
>> I'm looking for the best way to build a simple synth using Node.
>> It would output the sound to the sound device directly - not using a
>> browser.
>> It doesn't have to work anywhere else but MacOS.
>

> There's a wonderful one (disclaimer: I'm biased :-) --> node-sound:
>
> https://github.com/xk/node-sound

Earlier this month when I was looking for the same thing, it took me awhile with various Google queries before I found this module, which worked fine for me on Mac OS X. It comes with dozens of tests (most of which worked for me), which were helpful for figuring out how it works. The one thing I would have wished for that I didn't find was the ability to change the sound buffer as it's being played. Perhaps it's possible, but none of the tests/examples did anything like that (they all fill the buffer, then play it).


George Stagas

unread,
Oct 28, 2011, 6:42:43 PM10/28/11
to nod...@googlegroups.com
You can also send OSC messages (
http://en.wikipedia.org/wiki/Open_Sound_Control ) to something like
SuperCollider ( http://supercollider.sourceforge.net/ )
Here's a very basic lib to get you started:
https://github.com/stagas/node-supercollider

-stagas

2011/10/28 Ryan Schmidt <googl...@ryandesign.com>:

> --
> Job Board: http://jobs.nodejs.org/
> Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
> You received this message because you are subscribed to the Google
> Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com
> To unsubscribe from this group, send email to
> nodejs+un...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/nodejs?hl=en?hl=en
>

Jorge

unread,
Oct 29, 2011, 3:45:01 AM10/29/11
to nod...@googlegroups.com

That would be tricky, because there's double buffering..

The node buffers (which are PCM sounds) are copied (and transformed) by the OSX library into osx sound buffers when you call .play(), so any changes made afterwards are not going to be reproduced.

I'd have to look at it again, but ISTR that even when a sound is playing in a loop, instead of recreating these osx sound buffers again on every loop turn, I just reschedule them.

I think you'd need a play function that accepted a stream of buffers, right ?

That's what the osx sound API looks like.
--
Jorge.

Nicolas Chambrier

unread,
Oct 29, 2011, 6:37:21 PM10/29/11
to nod...@googlegroups.com
Works only on Mac OS X :/ This does not compile at all on Linux, too bad :(

Ryan Schmidt

unread,
Oct 29, 2011, 11:58:43 PM10/29/11
to nod...@googlegroups.com
On Oct 29, 2011, at 02:45, Jorge wrote:
> On 28/10/2011, at 22:37, Ryan Schmidt wrote:
>> Earlier this month when I was looking for the same thing, it took me awhile with various Google queries before I found this module, which worked fine for me on Mac OS X. It comes with dozens of tests (most of which worked for me), which were helpful for figuring out how it works. The one thing I would have wished for that I didn't find was the ability to change the sound buffer as it's being played. Perhaps it's possible, but none of the tests/examples did anything like that (they all fill the buffer, then play it).
>
> That would be tricky, because there's double buffering..

I figured it might not be easy.


> The node buffers (which are PCM sounds) are copied (and transformed) by the OSX library into osx sound buffers when you call .play(), so any changes made afterwards are not going to be reproduced.
>
> I'd have to look at it again, but ISTR that even when a sound is playing in a loop, instead of recreating these osx sound buffers again on every loop turn, I just reschedule them.
>
> I think you'd need a play function that accepted a stream of buffers, right ?
>
> That's what the osx sound API looks like.

I haven't written much sound code before, in any environment, and in this case it was just a quick and dirty experiment to generate a tone whose pitch changed based on some real-time input. I was pleased it was so easy to do with node and node-sound. I made do with the static buffers by stopping the sound, creating a new buffer with a new waveform of the correct pitch, and starting the sound again when the input changed. This results in a slight pause or click between pitch changes, but it didn't really matter for this application.


Pedro Teixeira

unread,
Oct 31, 2011, 8:16:58 PM10/31/11
to nodejs
Thanks everyone for the input!

-Pedro

Jorge

unread,
Oct 31, 2011, 9:48:45 PM10/31/11
to nod...@googlegroups.com
On 30/10/2011, at 00:37, Nicolas Chambrier wrote:

> Works only on Mac OS X :/

On a Mac it's clear what sound API to use, buuut, on linux... ?

> This does not compile at all on Linux, too bad :(

Now yes :-) https://gist.github.com/1329613
--
Jorge

Jorge

unread,
Nov 3, 2011, 3:54:45 PM11/3/11
to nod...@googlegroups.com
By popular demand, here's how to build/synthesize a sound wave in PCM 16bit signed format in node in javascript:

https://github.com/xk/node-sound/blob/master/test-sinewave.js
https://github.com/xk/node-sound/blob/master/test-sinewaves.js
--
Jorge.

Nathan Rajlich

unread,
Nov 3, 2011, 7:17:11 PM11/3/11
to nod...@googlegroups.com
Jorge, the setTimeout() and DONE checks would be unnecessary if you used ev_ref()/uv_ref(). That would keep the process alive while the threads are running. Would fork and send a pull, but lazy ATM :p 

Jorge

unread,
Nov 4, 2011, 2:50:35 AM11/4/11
to nod...@googlegroups.com
On 04/11/2011, at 00:17, Nathan Rajlich wrote:

> Jorge, the setTimeout() and DONE checks would be unnecessary if you used ev_ref()/uv_ref(). That would keep the process alive while the threads are running.

Good to know, thank you.

> Would fork and send a pull, but lazy ATM :p

I can wait :-P
--
Jorge.

Reply all
Reply to author
Forward
0 new messages