GithubHelp home page GithubHelp logo

rakannimer / react-orchestra Goto Github PK

View Code? Open in Web Editor NEW
75.0 7.0 20.0 16.03 MB

A declarative toolbox to build interactive musical instruments on web and mobile.

Home Page: http://react-orchestra.surge.sh/

JavaScript 95.90% CSS 0.27% Python 0.02% Java 0.02% Objective-C 0.06% HTML 3.72%
react react-native music music-composition orchestra instrument javascript music-theory music-theory-apps

react-orchestra's Introduction

React Orchestra

CircleCI

A toolbox to build interactive and smart instruments on the web and mobile.

Web example can be seen here

Getting Started

React Orchestra can be integrated easily into any project.

Prerequisites

Native

Installing peer dependencies

Under the hood RO uses :

react-native-sound to play mp3 sounds.

react-native-fs to cache sounds in the filesystem.

realm as an offline store for caching and state storage ( might remove this in future versions unless I or someone builds up on realm features to improve react-orchestra functionality )

In your project root :

Install it :

With npm

npm install --save react-native-sound react-native-fs realm
With yarn
yarn add react-native-sound react-native-fs realm

Then link it :

react-native link

Web

IMPORTANT READ THIS:

The sound generation and playback for the web orchestra depends on the WebAudio API. Check support for your platform target here. If your targeted platform is supported you can go ahead and install it.

Install react-orchestra

With npm

npm install --save react-orchestra
With yarn
yarn add react-orchestra

No need to link it ! It's plain JS.

And you're good to go ๐Ÿ’ƒ.

Let's start writing some instruments.

TLDR; I just want to copy paste stuff !

There you go :

Web

yarn add react-orchestra || { npm i -S react-orchestra; }

Native

yarn add react-native-sound react-native-fs realm || { npm i -S react-native-sound react-native-fs realm; }
react-native link react-native-sound react-native-fs realm
yarn add react-orchestra || { npm i -S react-orchestra; }

API + Examples

Let's build a couple of use-cases to get familiar with the API. Or you can directly check out and run the examples :

  • Web example :
git clone [email protected]:RakanNimer/react-orchestra.git
cd  react-orchestra/web/
{yarn && yarn start} || {npm i && npm start}
  • Native example :
git clone [email protected]:RakanNimer/react-orchestra.git
cd  react-orchestra/ReactOrchestraNativeDemo/
yarn || {npm i;}
npm run init-app
react-native run-ios # or run-android

1. A non-interactive instrument that can play notes and sync ui.

import React from 'react';
import { Instrument, Note } from 'react-orchestra/web';
// If you're using react-native then it's :
// import { Instrument, Note } from 'react-orchestra/native';

const delay = ms => new Promise(resolve => setTimeout(ms, resolve));

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      playA: false,
      playC: false,
    };
  }
  componentDidMount() {
    this.playMelody();
  }
  async playMelody() {
    await delay(1000);
    this.setState({ playA: true });
    await delay(1000);
    this.setState({ playB: true, playA: false });
    await delay(1000);
    this.setState({ playB: false });
  }
  render() {
    return (
      <Instrument name={'acoustic_grand_piano'} interactive={false}>
        <Note name={'A3'} play={this.state.playA}>
          {/*
            You can put any react element here native or web.
          */}
          <div> This is what I want my note to look like ! I can put anything in here.
            <img
              alt="Some pic"
              src="https://s-media-cache-ak0.pinimg.com/originals/36/43/e7/3643e7e8dab9b88b3972ee1c9f909dea.jpg"
            />
          </div>
        </Note>
        <Note name={'C3'} play={this.state.playC}><div>Another note</div></Note>
      </Instrument>
    );
  }
}
export default App;

The API aims to be self-explanatory, for example, in the code above we're creating two controlled note components, that we can play and stop using the play prop.

When the component mounts, we start playing a simple melody.

2. An interactive instrument that the end-user controls.

Let's build an instrument that the user can play by clicking or tapping on notes.

import React from 'react';
import { Instrument, Note } from 'react-orchestra/web';
// If you're using react-native then it's :
// import { Instrument, Note } from 'react-orchestra/native';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
    };
    this.onStartPlaying.bind(this);
    this.onStopPlaying.bind(this);
  }
  onStartPlaying(noteName) {
    console.warn(`Note played ${noteName}. Use this function if you want to sync your state with the instrument, dispatch redux action or alter mobx observable or just setting state inside your component`);
  }
  onStopPlaying(noteName) {
    console.warn(`Stopped playing ${noteName}. Use this function if you want to sync your state with the instrument, dispatch redux action or alter mobx observable or just setting state inside your component`);
  }
  render() {
    return (
      <Instrument name={'acoustic_grand_piano'} onStartPlaying={this.onStartPlaying} onStopPlaying={this.onStopPlaying} interactive>
        <Note name={'A3'}>
          <div>
            <div>Click me to play A3</div>
          </div>
        </Note>
        <Note name={'C3'}><div>Click me to play C3</div></Note>
      </Instrument>
    );
  }
}
export default App;

You don't need to listen to clicks or taps setting the interactive prop to true will attach the right events and clean them up for you !

The onPlay handler can be used to manage your state.

3. Playing midi and displaying playback.

As any orchestra, react-orchestra can learn and play music tracks ! For now, it understands MIDI out of the box, more input sources are in the roadmap.

Let's play Beethoven Moonlight's sonata.

import React from 'react';
import { Orchestra } from 'react-orchestra/web';
// If you're using react-native then it's :
// import { Orchestra } from 'react-orchestra/native';
const midiURL = 'https://s3-eu-west-1.amazonaws.com/ut-music-player/assets/midis/beet1track-medium-fast.mid';
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      playSong: false,
    };
    this.onMidiLoaded = this.onMidiLoaded.bind(this);
    this.onInstrumentsReady = this.onInstrumentsReady.bind(this);
  }
  componentDidMount() {

  }
  onMidiLoaded(parsedMidi) {
    console.warn(`Midi loaded ${JSON.stringify(parsedMidi, 2, 2)}. Loading instruments now ...`);
    return parsedMidi;
  }
  onInstrumentsReady(instruments) {
    console.warn(`Instruments ${JSON.stringify(instruments, 2, 2)} are loaded into memory and ready !`);
    this.setState({ play: true });
    return instruments;
  }
  onNotePlayed(noteName) {
    console.warn(`Note ${noteName} was played, optionally handle this event`);
  }
  render() {
    return (
      <Orchestra
        midiURL={midiURL}
        onMidiLoaded={this.onMidiLoaded}
        onInstrumentsReady={this.onInstrumentsReady}
        play={this.state.playSong}
        selectedTracks={[0, 1]}
        onNotePlayed={this.onNotePlayed}
      >
        <div> This is an orchestra it can play complex melodies ! </div>
      </Orchestra>
    );
  }
}
export default App;

**4. Creating a note factory **

This is useful when you want to generate notes that follow a given rule

Example : Render the C Major scale starting at the third octave over 2 octaves

import React from 'react';
import { NoteFactory } from 'react-orchestra/web';

const renderNote = (instrumentName, noteName) => <div style={{ cursor: 'pointer' }}> I am a note : {instrumentName} {noteName} You can click me ! </div>;

class NoteFactoryExample extends React.Component {
  render() {
    return (
      <NoteFactory
        type="scale"
        scaleName="ionian"
        noteName="C"
        instrumentName="acoustic_grand_piano"
        startOctave="3"
        octaveCount="1"
        renderNote={renderNote}
      />
    );
  }
}
export default NoteFactoryExample;

Documentation

Showcase

Did you build something cool with this library ?

Show it off here by submittiing a pull request.

Running the tests

npm test

Tests lint all js files using the js airbnb coding style and runs the jest tests in __tests__ directory.

Contributing

You can contribute by submitting, and responding to issues. If you'd like to add a new feature PRs are very welcome, but please open an issue beforehand so we can discuss the optimal way to go when adding the feature !

Roadmap

  • Create NoteFactory component that takes in a scale name or chord name or Midi URL and creates user-rendered Notes.
  • Add tests that run on browser
  • Add react-orchestra/native jest tests
  • Add more web jest tests

License

This project is licensed under the MIT License - see the LICENSE.md file for details

react-orchestra's People

Contributors

dependabot[bot] avatar keepo12 avatar rakannimer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-orchestra's Issues

breaks with PropTypes

e.g.:

/process.env.NODE_ENV !== "production" ? MidiTrack.propTypes = {
notes: _react.PropTypes.arrayOf(_react.PropTypes.shape({
noteNumber: _react.PropTypes.number,
noteName: _react.PropTypes.string,
startTimeInMS: _react.PropTypes.number,
durationInMS: _react.PropTypes.number,
endTimeInMS: _react.PropTypes.number,
instrumentName: _react.PropTypes.string,
deltaTime: _react.PropTypes.number,
msPerTick: _react.PropTypes.number
}))
} : void 0;
/

How to play Sharp/Flat notes.

Hello!

Is react-orchestra capable of playing flat or sharp notes? I specified in my code Note name={'C#'} but it didn't work. I also tried spelling out the word "sharp" like this Note -name={'C-Sharp'} but to no avail. Does anyone know how to play sharps or flats on react-orchestra?

Compality newer RN version

Hi,
I have not been able to make react orchestra works on RN 0.58 57 and 56 from fresh react-native init install and then I follow the steps on Getting started.
Have react-orchestra been tested on those version ?
Would it be possible to have an updated version of your demo git ?
Regards,

TypeError: Cannot read property 'filter' of undefined

When I build my own version of this repo, everything works fine. I got it working trough docker on a windows machine. However, when I change the url to the .mid file, it fails. I'm not doing anything different, I just changed the url and allowed cross origin on the host. Perhaps you can help me out with this? It could be that something went wrong with my build.

MidiIO.js:111Uncaught (in promise) TypeError: Cannot read property 'filter' of undefined
at http://localhost/demo.5a7d88bb.js:7:17557
at Array.map (native)
at Function.ROpp.e.getAllTracks (http://localhost/demo.5a7d88bb.js:7:17149)
at http://localhost/demo.5a7d88bb.js:7:21947
(anonymous) @ MidiIO.js:111
ROpp.e.getAllTracks @ MidiIO.js:89
(anonymous) @ MidiIO.js:330

Which points to line:

noteOnValid: indexedTrack.channel_noteOn.filter(event => event.deltaTime > 0),

TypeError: undefined is not an object (evaluating '_native.NoteFactory')

Hi,
I'm a beginner with React Native and React Orchestra. I followed every steps for the installation, but I must have missed something because I can't get rid of this error :
IMG_E3B3B0486E70-1

with this code, that i took from the native demo example :

import React from 'react';
import { View, Text } from 'react-native';
import { NoteFactory } from 'react-orchestra/native';

const renderNote = (instrumentName, noteName) =>{
  // console.warn('rendering '+instrumentName, noteName);
  return (<View><Text> I am a note : {instrumentName} {noteName} You can click me ! </Text></View>);
}
class NoteFactoryExample extends React.Component {
  render() {
    // console.warn(JSON.stringify(Object.keys(a), 2, 2));
    return (
      <NoteFactory
        type="scale"
        scaleName="ionian"
        noteName="C"
        instrumentName="acoustic_grand_piano"
        startOctave="3"
        octaveCount="1"
        renderNote={renderNote}
      />
    );
  }
}
export default NoteFactoryExample;

If you have any hint ?
Sorry if this is a silly question :/

Regards

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.