New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

tone-rhythm

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tone-rhythm

Generate an array of Tone.Transport times for use in Tone.Part

  • 2.0.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
20
decreased by-23.08%
Maintainers
1
Weekly downloads
 
Created
Source

tone-rhythm

Generate an array of Tone.Transport times given an array of musical rhythms in various formats that Tone.js understands.

Written for exclusive use with Tone.js.

Features

  • Works with latest version of Tone (v0.12.8 - v13.4.0)
  • Works in-browser (transpiled) or in node (ES6)
  • Light footprint (3.6kB minified)
  • Intuitive for musicians
  • Has a fully-documented API with examples below.

Why use tone-rhythm?

As a musician developing music applications, I wanted an API that would allow me to put rhythms along with a melody into Tone.Part. The example on Tone's docs shows how this is expected:

var synth = new Tone.FMSynth().toMaster()

//schedule a series of notes to play as soon as the page loads
synth.triggerAttackRelease('C4', '4n', '8n')
synth.triggerAttackRelease('E4', '8n', Tone.Time('4n') + Tone.Time('8n'))
synth.triggerAttackRelease('G4', '16n', '2n')
synth.triggerAttackRelease('B4', '16n', Tone.Time('2n') + Tone.Time('8t'))
synth.triggerAttackRelease('G4', '16', Tone.Time('2n') + Tone.Time('8t')*2)
synth.triggerAttackRelease('E4', '2n', '0:3')

The third parameter in triggerAttackRelease is the start time of the note we're triggering. Musicians don't normally consider where a note is in a timeline when composing music. I needed a way to calculate this ahead of time.

I found enlightenment after reading Music Theory using Tone.js - Play Rhythms. Based on the author's work, I created algorithms that accumulate rhythmic values in an array of durations to generate start times. The result feels much more intuitive to me (please see the examples below.)

Getting Started

Prerequisites

Tone.js (v0.12.x or higher)

Installing

npm install tone-rhythm

Or clone the repo and copy dist/tone-rhythm.min.js into your project.

Usage

ES6 / Webpack
// tone is a required peer dependency
import ToneTime from 'tone/Tone/type/Time';

import { toneRhythm } from 'tone-rhythm';
// any or all methods can be used in the instantiated toneRhythm:
const {
    getBarsBeats,
    addTimes,
    getTransportTimes,
    mergeMusicDataPart
} = toneRhythm(ToneTime);
Browser

Via node_modules:

<head>
  <!-- Get tone from unpkg CDN: -->
  <script src="https://unpkg.com/tone@13.4.9/build/Tone.js"></script>
  <!-- Import `tone-rhythm.min.js` from node_modules: -->
  <script src="node_modules/tone-rhythm/dist/tone-rhythm.min.js"></script>
  <!-- OR simply provide your path/to/tone-rhythm.min.js -->
</head>

Via https://unpkg.com/tone-rhythm

<head>
  <!-- Get tone from unpkg CDN: -->
  <script src="https://unpkg.com/tone@13.4.9/build/Tone.js"></script>
  <!-- Get tone-rhythm from unpkg CDN: -->
  <script src="https://unpkg.com/tone-rhythm@2.0.0/dist/tone-rhythm.min.js"></script>
  <!-- OR simply provide your path/to/tone-rhythm.min.js -->
</head>

In your js file(s):

const {
  getBarsBeats,
  addTimes,
  getTransportTimes,
  mergeMusicDataPart
} = toneRhythm.toneRhythm(Tone.Time); // both `toneRhythm` and `Tone.Time` are available globally from imports above
(Legacy) Pre-bundled with Tone 0.12.8

See docs/tone-rhythm@0.0.2.md.

API

Values which can populate a rhythms array:

  • '4n' - a 'notation' value
  • ['4n', '8t'] - an array of 'notation' values which will be added together
  • ['r', '2n'] - an array that has 'r' at first index will be a rest
  • ['r', '2n', '8t'] - (see above about 'r') and the remaining values will be added together

It's not recommended to use Tone's seconds format.

See documentation and below for tone-rhythm library usage.

Examples ("Maria" by Leonard Bernstein)

toneRhythm.getTransportTimes

Given an array of durations (see API), return transport times. Array<String|Number>

const mariaDurations = ['8n', '8n', ['2n', '4n'], '8n', '4t', '4t', '4t', '4t', '4t', '4t', '8n', ['2n', '4n'], '8n', '8n', '8n', '8n', '8n', ['4n', '8n'], '8n', '8n', '8n', '8n', '8n', '4n', '4n', ['2n', '4n', '8n'], '8n', '8n', ['2n', '4n'], '8n', '4t', '4t', '4t', '4t', '4t', '4t', '8n', ['2n', '4n'], '8n', '8n', '8n', '8n', '8n', ['4n', '8n'], '8n', '8n', '8n', '8n', '8n', '4n', '4n', ['2n', '4n', '8n']];

const mariaTransportTimes = toneRhythm.getTransportTimes(mariaDurations); /* ->
  Result:
[0, "0:0:2", "0:1:0", "1:0:0", "1:0:2", "1:1:0.667", "1:1:3.334", "1:2:2", "1:3:0.667", "1:3:3.334", "2:0:2", "2:1:0", "3:0:0", "3:0:2", "3:1:0", "3:1:2", "3:2:0", "3:2:2", "4:0:0", "4:0:2", "4:1:0", "4:1:2", "4:2:0", "4:2:2", "4:3:2", "5:0:2", "6:0:0", "6:0:2", "6:1:0", "7:0:0", "7:0:2", "7:1:0.667", "7:1:3.334", "7:2:2", "7:3:0.667", "7:3:3.334", "8:0:2", "8:1:0", "9:0:0", "9:0:2", "9:1:0", "9:1:2", "9:2:0", "9:2:2", "10:0:0", "10:0:2", "10:1:0", "10:1:2", "10:2:0", "10:2:2", "10:3:2", "11:0:2"]
*/

toneRhythm.mergeMusicDataPart

Returns array of objects for consumption by Tone.Part.

const mariaPitches = ["Eb4", "A4", "Bb4", "Eb4", "A4", "Bb4", "C5", "A4", "Bb4", "C5", "A4", "Bb4", "Bb4", "A4", "G4", "F4", "Eb4", "F4", "Bb4", "Ab4", "G4", "F4", "Eb4", "F4", "Eb4", "G4", "Eb4", "A4", "Bb4", "Eb4", "A4", "Bb4", "C5", "A4", "Bb4", "C5", "D5", "Bb4", "D5", "Eb5", "D5", "C5", "Bb4", "D5", "D5", "Eb5", "D5", "C5", "Bb4", "D5", "Eb5", "F5"];

const mergedData = mergeMusicDataPart({
  rhythms: mariaDurations,
  notes: mariaPitches,
  startTime: '0:3:2'
}); /* -> [
  {time: "0:3:2", duration: "8n", note: "Eb4", idx: 0},
  {time: "1:0:0", duration: "8n", note: "A4", idx: 1},
  {time: "1:0:2", duration: "0:3:0", note: "Bb4", idx: 2},
  {time: "1:3:2", duration: "8n", note: "Eb4", idx: 3},
  {time: "2:0:0", duration: "4t", note: "A4", idx: 4},
  {time: "2:0:2.667", duration: "4t", note: "Bb4", idx: 5},
  ...
]
*/

Use in Tone.Part

const melodyPart = new Tone.Part((time, value) => {
  piano.triggerAttackRelease(value.note, value.duration, time);
}, mergedData).start(0);

Contributing

Running the tests:

  • npm run dev - build in dev mode and watch for changes
  • npm run test - opens the tests in-browser

Acknowledgments

Thank you https://www.guitarland.com and the creator of Tone.js.

Documentation created with jsdoc2md

Keywords

FAQs

Package last updated on 01 Sep 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc