Notwithstanding Previous Misdemeanors

    node-libpd

    1.1.0 • Public • Published

    node-libpd

    Node.js bindings for libpd using portaudio as audio backend.

    Install

    npm install [--save] node-libpd
    

    Table of Content

    Basic Usage

    const pd = require('node-libpd');
    // or if you use some transpiler such as babel
    // import pd from 'node-libpd';
    
    // init pd
    const initialized = pd.init({
      numInputChannels: 0,
      numOutputChannels: 2,
      sampleRate: 48000,
      ticks: 1, // a pd block (or tick) is 64 samples, be aware that increasing this value will throttle messages (tbc)
    });
    
    // instantiate a patch
    const patchPathname = path.join(process.cwd(), 'pd', 'my-patch.pd');
    const patch = pd.openPatch(patchPathname);
    
    // subscribe to messages from the patch
    pd.subscribe(`${patch.$0}-output`, msg => {
      console.log(msg);
    });
    
    // send message to the patch
    pd.send(`${patch.$0}-input`, 1234);
    
    // send a scheduled message
    const now = pd.currentTime; // time in sec.
    // send message to the patch in two seconds from `now`, this accuracy of the
    // scheduling will depend on the number of ticks defined at initialization
    pd.send(`${patch.$0}-input`, 1234, now + 2);
    
    // close the patch
    pd.closePatch(`${patch.$0}-input`, 1234);

    Notes / Caveats:

    • The library is meant to be used in a Node.js environment, it cannot run in a browser and never will.
    • The library can only be used with pd-vanilla objects, it does not, and maybe will never, support externals.
    • The audio interface used is the one that is set as default system wise.
    • The bindings are created with N-API, therefore v1 should work on Node.js > 10.x.x, for previous version of Node.js you should install node-libpd v0.2.6 that was created with Nan (be aware that this version won't receive support).
    • The library does not support all the interface of libpd, however the most important ones should be there. The API has also been adapted at particular places to match common JS idiomatisms.

    Tested on MAC OSX 10 and Raspbian Stretch Lite version 9 (raspberry pi 3) - for other platforms, dynamic libraries for libpd and portaudio should probably be built.

    Install on Mac OSX

    xcode-select --install
    

    Install on Raspberry Pi

    apt-get install -y ... ???
    

    API

    Objects

    pd : object

    Singleton that represents an instance of the underlying libpd library

    Patch : object

    Object representing a patch instance.

    pd : object

    Singleton that represents an instance of the underlying libpd library

    Kind: global namespace

    pd.currentTime : Number

    Current audio time in seconds since init as been called.

    Kind: static property of pd
    Read only: true

    pd.init(config) ⇒ Boolean

    Configure and initialize pd instance. You basically want to do that at the startup of the application as the process is blocking and that it can take a long time to have the audio running.

    Kind: static method of pd
    Returns: Boolean - a boolean defining if pd and portaudio have been properly initialized

    Param Type Default Description
    config Object
    [config.numInputChannels] Number 1 num input channels requested
    [config.numOutputChannels] Number 2 num output channels requested
    [config.sampleRate] Number 4800 requested sampleRate
    [config.ticks] Number 1 number of blocks (ticks) processed by pd in one run, a pd tick is 64 samples. Be aware that this value will affect / throttle the messages sent to and received by pd, i.e. more ticks means less precision in the treatement of the messages. A value of 1 or 2 is generally good enough even in constrained platforms such as the RPi.

    pd.destroy()

    Destroy the pd instance. You basically want to do that want your program exists to clean things up, be aware the any call to the pd instance after calliing destroy migth throw a SegFault error.

    Kind: static method of pd

    pd.openPatch(pathname) ⇒ Object

    Open a pd patch instance. As the same patch can be opened several times, think of it as a kind of poly with a nice API, be careful to use patch.$0 in your patches.

    Kind: static method of pd
    Returns: Object - - instance of the patch

    Param Type Description
    pathname String absolute path to the pd patch

    pd.closePatch(patch)

    Close a pd patch instance.

    Kind: static method of pd

    Param Type Description
    patch Patch a patch instance as retrived by openPatch

    pd.addToSearchPath(pathname)

    Add a directory to the pd search paths, for loading libraries etc.

    Kind: static method of pd

    Param Type Description
    pathname String absolute path to the directory

    pd.clearSearchPath()

    Clear the pd search path

    Kind: static method of pd

    pd.send(channel, value, [time])

    Send a named message to the pd backend

    Kind: static method of pd

    Param Type Default Description
    channel String name of the corresponding receive box in the patch the avoid conflict a good practice is the prepend the channel name with patch.$0
    value Any payload of the message, the corresponding mapping is made with pd types: Number -> float, String -> symbol, Array -> list (all value that neither Number nor String are ignored), else -> bang
    [time] Number audio time at which the message should be sent. If null or < currentTime, is sent as fast as possible. (@tbc messages are processed at pd control rate).

    pd.subscribe(channel, callback)

    Subscribe to named events send by a pd patch

    Kind: static method of pd

    Param Type Description
    channel String channel name corresponding to the pd send name
    callback function callback to execute when an event is received

    pd.unsubscribe(channel, [callback])

    Unsubscribe to named events send by a pd patch

    Kind: static method of pd

    Param Type Default Description
    channel String channel name corresponding to the pd send name
    [callback] function callback that should stop receive event. If null, all callbacks of the channel are removed

    pd.writeArray(name, data, [writeLen], [offset]) ⇒ Boolean

    Write values into a pd array. Be carefull with the size of the pd arrays (default to 100) in your patches.

    Kind: static method of pd
    Returns: Boolean - true if the operation succeed, false otherwise

    Param Type Default Description
    name Name name of the pd array
    data Float32Array Float32Array containing the data to be written into the pd array.
    [writeLen] Number data.length @todo confirm behavior
    [offset] Number 0 @todo confirm behavior

    pd.readArray(name, data, [readLen], [offset]) ⇒ Boolean

    Read values into a pd array.

    Kind: static method of pd
    Returns: Boolean - true if the operation succeed, false otherwise

    Param Type Default Description
    name Name name of the pd array
    data Float32Array Float32Array to populate from pd array values
    [readLen] Number data.length @todo confirm behavior
    [offset] Number 0 @todo confirm behavior

    pd.clearArray(name, [value])

    Fill a pd array with a given value.

    Kind: static method of pd

    Param Type Default Description
    name Name name of the pd array
    [value] Number 0 value used to fill the pd array

    pd.arraySize(name) ⇒ Number

    Retrieve the size of a pd array.

    Kind: static method of pd
    Returns: Number - size of the array

    Param Type Description
    name Name name of the pd array

    Patch : object

    Object representing a patch instance.

    Kind: global namespace

    Patch.$0 : Number

    Id of the patch. You should use this value to communicate with a given patch in send and receive channel.

    Kind: static property of Patch
    Read only: true

    Patch.isValid : Boolean

    Validity of the patch instance. False typically means that the given filename does not point to a valid pd patch, or that the patch has been closed.

    Kind: static property of Patch
    Read only: true

    Patch.filename : String

    Name of the the pd patch file

    Kind: static property of Patch
    Read only: true

    Patch.path : String

    Directory of the pd patch file

    Kind: static property of Patch
    Read only: true

    Tests

    To run the tests

    # cf. test/index.js
    npm run test

    Todos

    • list devices and choose device, is a portaudio problem
    • midi event ? is there some real-world use case
    • support pd externals, if only possible...
    • rebuild portaudio without jack on linux

    Credits

    The library has received support from the Ircam's project BeCoMe.

    License

    BSD-3-Clause

    Keywords

    none

    Install

    npm i node-libpd

    DownloadsWeekly Downloads

    4

    Version

    1.1.0

    License

    BSD-3-Clause

    Unpacked Size

    6.72 MB

    Total Files

    42

    Last publish

    Collaborators

    • b-ma