Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/rakannimer/react-orchestra

A declarative toolbox to build interactive musical instruments on web and mobile.
https://github.com/rakannimer/react-orchestra

instrument javascript music music-composition music-theory music-theory-apps orchestra react react-native

Last synced: about 2 months ago
JSON representation

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

Awesome Lists containing this project

README

        

# React Orchestra

[![CircleCI](https://circleci.com/gh/RakanNimer/react-orchestra.svg?style=shield&circle-token=6fe92a6008747c5902e40a5038690d7e0118865d)](https://circleci.com/gh/RakanNimer/react-orchestra)

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

Web example can be seen [here](http://react-orchestra.surge.sh/)

### [Web example repo](https://github.com/RakanNimer/react-orchestra-web-demo)

### [Native example repo](https://github.com/RakanNimer/react-orchestra-native-demo)

## Getting Started

React Orchestra can be integrated easily into any project.

### Prerequisites

#### Native

##### Installing peer dependencies
Under the hood RO uses :

[react-native-sound](https://github.com/zmxv/react-native-sound) to play mp3 sounds.

[react-native-fs](https://github.com/johanneslumpe/react-native-fs) to cache sounds in the filesystem.

[realm](https://github.com/realm/realm-js) 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](http://caniuse.com/#feat=audio-api).
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 :
```sh
git clone [email protected]:RakanNimer/react-orchestra.git
cd react-orchestra/web/
{yarn && yarn start} || {npm i && npm start}
```

- Native example :
```sh
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.**

```javascript
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 (


{/*
You can put any react element here native or web.
*/}

This is what I want my note to look like ! I can put anything in here.
Some pic


Another note


);
}
}
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.

```javascript
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 (



Click me to play A3



Click me to play C3


);
}
}
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.

```javascript
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 (

This is an orchestra it can play complex melodies !


);
}
}
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

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

const renderNote = (instrumentName, noteName) =>

I am a note : {instrumentName} {noteName} You can click me !
;

class NoteFactoryExample extends React.Component {
render() {
return (

);
}
}
export default NoteFactoryExample;

```
## Documentation

- [API](docs/api.md#api)
- [``](docs/api.md#Note)
- [``](docs/api.md#Instrument)
- [``](docs/api.md#Orchestra)
- [``](docs/api.md#NoteFactory)
- [`` (*web only*)](docs/api.md#KeyBinding)

## Showcase

Did you build something cool with this library ?

Show it off here by [submittiing a pull request](https://github.com/RakanNimer/react-orchestra/compare).

## 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

- [x] 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](LICENSE.md) file for details