cawfree / react-native-pure-data

🔈 ⚡ Synthesize algorithmic sound at runtime in React Native.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

react-native-pure-data

code style: prettier

A native wrapper for libpd-ios and libpd-android, which enables you to rapidly prototype DSP algorithms described using Pure Data, an industry standard open source visual programming language capable of synthesising audiovisual effects.

react-native-pure-data enables the synthesis of generative audio, which helps developers achieve dynamic sound at runtime. This is useful for games, music production and communications.

Key Features

  • Patches in Pure Data can be interacted with via React component props.
  • Simultaneous patch execution.
  • Supports hot reloading, so DSP algorithms can be prototyped directly using Pure Data's interface and then executed concurrently on an Android/iOS device or emulator.
  • Loaded patches respect the Component Lifecycle, so they can be mounted or unmounted as expected.

⚠️ Warning

Please be extremely cautious when prototyping using this library.

Pd is capable of generating high amplitude sound waves, which can damage your hearing if you choose to listen using headphones.

Please take care to minimize the risk of hearing damage or loss as much as possible by playing back on external speakers at a reduced volume whenever prototyping with new patches or props. In addition, you must always consider the volume of the end user's device.

And remember,

With great power, comes great responsibility. - Linus Torvalds

🚀 Getting Started

1. Installing

Using npm:

npm install --save react-native-pure-data

Using yarn:

yarn add react-native-pure-data

For versions of React Native less than 0.60, after installation has complete you must execute react-native link to make the native library dependencies visible to your compiled application.

2. Update metro.config.js

Once installed, you'll need to update your metro.config.js to help the Metro Bundler load your patches:

+const metroDefault = require('metro-config/src/defaults/defaults.js');

 module.exports = {
   resolver: {
+    assetExts: metroDefault.assetExts.concat(['pd']),
   },
 };

This will enable hot loading, so you can modify your patches even whilst they're being rendered by the app.

After making this change, you'll need to restart the bundler.

3. Runtime Specific

3.1 iOS

After installing this library, you'll need reinstall the iOS cocoapods. First, enter your app's /ios directory. Then use:

pod install # update cocoapods
cd ..
react-native run-ios

3.2 Android

Android is not yet supported, but will be released this weekend.

✍️ Example

react-native-pure-data exposes just two Components; AudioController and Patch. The former is used for general sound output configuration, and the latter is used to load and interact with a patch written in Pure Data.

The simplest example is a patch which does not rely on any data from your App.js; you'll see here, that all we need to do is define an <AudioController /> at the root of the application, and declare the Patch's file source.

import React from "react";
import {AudioController, Patch} from "react-native-pure-data";

import SomePatch from "./patches/some-patch.pd";

export default () => (
  <AudioController
    active
  >
    <Patch
      source={SomePatch}
    />
  </AudioController>
);

However, Pure Data is uses an asynchronous, message-driven protocol. This normally means that imported patches will need to be either triggered or configured by your runtime logic.

To communicate with a loaded patch from your app, all you have to do is specify additional props on the Patch component. These will be synchronously routed to corresponding receivers in the Pure Data patch whenever the component is re-rendered:

import React, {useState, useEffect} from "react";
import {AudioController, Patch} from "react-native-pure-data";

import SomePatch from "./patches/some-patch.pd";

export default () => {
  const [frequency, setFrequency] = useState(440);
  useEffect(
    () => {
      /* every 1000ms, set a new frequency */
      const i = setInterval(
        () => setFrequency(Math.random() * 1000),
        1000,
      );
      return () => clearInterval(i);
    },
    [],
  );
  return (
    <AudioController
      active
    >
      <Patch
        source={SomePatch}
        nextFrequency={frequency}
      />
    </AudioController>
  );
};

In the example above, a random frequency will be calculated and transmitted to the corresponding receiver on the diagram. In this case, the receiver would be called "nextFrequency", which would be declared using a Pure Data Object with the definition [r nextFrequency]:

The convention used here is that for every numeric prop, the name of that prop corresponds to the message receiver within the patch.

Therefore, if we defined an additional prop named someOtherFrequency={Math.random()}, whenever the component is re-rendered we would send a message to the receiver [r someOtherFrequency] that existed within the patch. If the receiver does not exist, this is a noop.

Please check out the Example App for further details.

✨ Resources

✌️ Licence

MIT

About

🔈 ⚡ Synthesize algorithmic sound at runtime in React Native.

License:MIT License


Languages

Language:JavaScript 43.3%Language:Objective-C 28.7%Language:Java 12.1%Language:Ruby 10.4%Language:Starlark 5.4%