Giter Site home page Giter Site logo

react-midi-hooks's Introduction

@react-midi/hooks

This package provides hooks for working with MIDI in your React app.

npm install --save @react-midi/hooks
// or
yarn add @react-midi/hooks

useMIDI()

useMidi() requests midi access using the browser's web midi api. It returns an array of inputs, an array of outputs, and a boolean hasMIDI that is set to true if your browser supports midi. The inputs and outputs are updated anytime a change to their connection is made (for example, if an input or output is disconnected or a connection is opened).

const { inputs, outputs, hasMIDI } = useMIDI(); // Initially returns [[], []]

useMIDINote(input, {note?, channel?}?)

useMIDINote() subscribes to both note on and note off midi messages, optionally filtered by note and/or channel. It returns an object {on, note, velocity, channel} reflecting the received midi message, updating when a new relevant message is received.

  • on will be true for note on, and false for note off
  • note will be a MIDI number (60 = C4)
  • velocity will be an integer between 0 - 127
const App = () => {
  const { inputs, outputs } = useMIDI();
  if (inputs.length < 1) return <div>No MIDI Inputs</div>;
  return <MIDINoteLog input={inputs[0]} />;
};

const MIDINoteLog = ({ input }) => {
  const event = useMIDINote(input, { channel: 1 }); // Intially returns undefined
  if (!event) {
    return <div>Waiting for note...</div>;
  }
  const { on, note, velocity, channel } = event;
  return (
    <div>
      Note {note} {on ? 'on' : 'off'} ({velocity}) on channel {channel}
    </div>
  );
};

useMIDIControl(input, {control?, channel?}?)

useMIDIControl() subscribes to a control change midi message, optionally filtered by control and/or channel. It returns an object {value, control, channel} reflecting the received midi message, updating when a new relevant message is received.

const App = () => {
  const [inputs, outputs] = useMIDI();
  if (inputs.length < 1) return <div>No MIDI Inputs</div>;
  return <MIDIControlLog input={inputs[0]} />;
};

const MIDIControlLog = ({ input }) => {
  const control = useMIDIControl(input, { control: 15, channel: 1 }); // Initially returns {value: 0, control, channel}
  return <div>Value: {control.value}</div>;
};

useMIDIClock(input, division?)

useMIDIClock() subscribes to the midi clock messages of a given input, with the option to specify a division. It returns the number of steps that have occured since the hook began receiving midi clock messages, as well as the play state.

The division argument can be used to update steps only when the number of steps recieved is evenly divisible by given division. A midi clock message is received 24 times for every quarter note, so if you only wanted to count quarter notes, you could use useMIDIClock(input, 24)

The play state is updated when the input receives a midi play or stop message. The steps are reset when the input receives a midi stop message.

const App = () => {
  const [inputs, outputs] = useMIDI();
  if (inputs.length < 1) return <div>No MIDI Inputs</div>;
  return <MIDIClock input={inputs[0]} />;
};

const MIDIClock = ({ input }) => {
  const [step, isPlaying] = useMIDIClock(input, 12); // initially return [0, false]
  return <div>Eighth notes since starting: {step}</div>;
};

useMIDIControls(input, controls, {channel?}?)

useMIDIControls() subscribes to multiple control change midi message, optionally filtered by channel. It returns an array of integers representing the value of controls passed in with the controls argument, updating when a new relevant message is received.

const App = () => {
  const { inputs } = useMIDI();
  if (inputs.length < 1) return <div>No MIDI Inputs</div>;
  return <MIDIControlLog input={inputs[0]} />;
};

const MIDIControlLog = ({ input }) => {
  const controls = [13, 14, 15];
  const values = useMIDIControls(input, controls, { channel: 1 }); // Intially returns [0, 0, 0]
  return (
    <div>
      {controls.map((control) => (
        <div>
          Control {control}: {values[control]}
        </div>
      ))}
    </div>
  );
};

useMIDINotes(input, {channel?}?)

useMIDINotes() subscribes to both note on and note off midi messages, optionally filtered channel. It returns an array of active note objects (see above), updating when notes are played or released.

const App = () => {
  const { inputs } = useMIDI();
  if (inputs.length < 1) return <div>No MIDI Inputs</div>;
  return <MIDINoteLog input={inputs[0]} />;
};

const MIDINoteLog = ({ input }) => {
  const notes = useMIDINotes(input, { channel: 1 }); // Intially returns []
  return (
    <div>
      Playing notes: {notes.map((n) => n.note).join(', ')} // Playing notes: 60,
      72, 80
    </div>
  );
};

useMIDIMessage(input)

useMIDIMessage() subscribes to the general midi message handler of a given input, updating everytime a message is received.

const App = () => {
  const { inputs } = useMIDI();
  if (inputs.length < 1) return <div>No MIDI Inputs</div>;
  return <MIDILog input={inputs[0]} />;
};

const MIDINoteLog = ({ input }) => {
  const message = useMIDIMessage(input); // initially return {}
  return <div>Message Data: {message.data ? message.data.join(', ') : ''}</div>;
};

useMIDIOutput(output)

useMIDIOutput() returns functions that can be used to send messages to the given output.

  • noteOn(note, velocity=127, channel=1): Sends a note on message to the output, defaulting to a velocity of 127 and channel 1.
  • noteOff(note, velocity=127, channel=1): Sends a note of message to the output, defaulting to a velocity of 127 and channel 1.
  • cc(value, control, channel=1): Sends a midi cc (control change) message to the output, defaulting to channel 1.
const App = () => {
  const { outputs } = useMIDI();
  if (outputs.length < 1) return <div>No MIDI Outputs</div>;
  return <MIDIButton output={outputs[0]} />;
};

const MIDIButton = ({ output }) => {
  const { noteOn, noteOff } = useMIDIOutput(output);
  const handleClick = () => {
    noteOn(60); // Play middle C, using velocity and channel defaults
    setTimeout(() => noteOff(60), 200); // Wait 200ms and then trigger note off.
  };
  return <button onClick={handleClick}>Play C3</button>;
};

useMIDIConnectionManager(connections)

Given an array of connections (inputs or outputs), useMIDIConnectionManager() returns the first avaliable connection, as well as a function to change the connection by calling it with a connection id.

If a connection is no longer avaliable, or an unavailable id is given, the first avaliable connection will be returned. The functions returned can be used to create a selection UI, or used with <MIDIConnectionManager /> from @react-midi/components.

const App = () => {
  const { inputs, outputs } = useMIDI();
  const [input, setInputId] = useMIDIConnectionManager(inputs);
  const [output, setOutputId] = useMIDIConnectionManager(outputs);
};

react-midi-hooks's People

Contributors

nicorobo avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.