Coder Social home page Coder Social logo

midi's Introduction

Build Status codecov

Installation

npm install @tonejs/midi

Midi makes it straightforward to read and write MIDI files with Javascript. It uses midi-file for parsing and writing.

Import

Node.js:

const { Midi } = require('@tonejs/midi')

Typescript / ES6

import { Midi } from '@tonejs/midi'

Browser

<script src="https://unpkg.com/@tonejs/midi"></script>
const midi = new Midi()

Basic Example

// load a midi file in the browser
const midi = await Midi.fromUrl("path/to/midi.mid")
//the file name decoded from the first track
const name = midi.name
//get the tracks
midi.tracks.forEach(track => {
  //tracks have notes and controlChanges

  //notes are an array
  const notes = track.notes
  notes.forEach(note => {
    //note.midi, note.time, note.duration, note.name
  })

  //the control changes are an object
  //the keys are the CC number
  track.controlChanges[64]
  //they are also aliased to the CC number's common name (if it has one)
  track.controlChanges.sustain.forEach(cc => {
    // cc.ticks, cc.value, cc.time
  })

  //the track also has a channel and instrument
  //track.instrument.name
})

Format

The data parsed from the midi file looks like this:

{
  // the transport and timing data
  header: {
    name: String,                     // the name of the first empty track, 
                                      // which is usually the song name
    tempos: TempoEvent[],             // the tempo, e.g. 120
    timeSignatures: TimeSignatureEvent[],  // the time signature, e.g. [4, 4],

    PPQ: Number                       // the Pulses Per Quarter of the midi file
                                      // this is read only
  },

  duration: Number,                   // the time until the last note finishes

  // an array of midi tracks
  tracks: [
    {
      name: String,                   // the track name if one was given

      channel: Number,                // channel
                                      // the ID for this channel; 9 and 10 are
                                      // reserved for percussion
      notes: [
        {
          midi: Number,               // midi number, e.g. 60
          time: Number,               // time in seconds
          ticks: Number,              // time in ticks
          name: String,               // note name, e.g. "C4",
          pitch: String,              // the pitch class, e.g. "C",
          octave : Number,            // the octave, e.g. 4
          velocity: Number,           // normalized 0-1 velocity
          duration: Number,           // duration in seconds between noteOn and noteOff
        }
      ],

      // midi control changes
      controlChanges: {
        // if there are control changes in the midi file
        '91': [
          {
            number: Number,           // the cc number
            ticks: Number,            // time in ticks
            time: Number,             // time in seconds
            value: Number,            // normalized 0-1
          }
        ],
      },

      instrument: {                   // and object representing the program change events
        number : Number,              // the instrument number 0-127
        family: String,               // the family of instruments, read only.
        name : String,                // the name of the instrument
        percussion: Boolean,          // if the instrument is a percussion instrument
      },          
    }
  ]
}

Raw Midi Parsing

If you are using Node.js or have the raw binary string from the midi file, just use the parse method:

const midiData = fs.readFileSync("test.mid")
const midi = new Midi(midiData)

Encoding Midi

You can also create midi files from scratch or by modifying an existing file.

// create a new midi file
var midi = new Midi()
// add a track
const track = midi.addTrack()
track.addNote({
  midi : 60,
  time : 0,
  duration: 0.2
})
.addNote({
  name : 'C5',
  time : 0.3,
  duration: 0.1
})
.addCC({
  number : 64,
  value : 127,
  time : 0.2
})
 
// write the output
fs.writeFileSync("output.mid", new Buffer(midi.toArray()))

Acknowledgment

Thank you midi-file!

midi's People

Contributors

adarob avatar appsforartists avatar baparham avatar bartoszbaczek avatar cacalo avatar cghawthorne avatar chrisfeltner avatar cifkao avatar colinfwren avatar dependabot[bot] avatar dirx avatar frankbaele avatar iansimon avatar jackca avatar jeanlazarou avatar kn0ll avatar maximedupre avatar moritzhertler avatar motifn avatar pioug avatar tambien avatar thomasballinger avatar vexcited 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

midi's Issues

Midi.js uses 'window' and this wont work with node.

I swapped this variable out for 'global' in my node script and everything worked just fine.

I know you have this set up for browser usage, but this could be used in node out of the box if this was fixed. :)

Add `scripts: build` to package.json

yarn run build is currently undefined.

Because I see you have a webpack.config.json, I generated the builds in my PR using $( yarn bin )/webpack, but the file sizes are much larger than yours. Please add a build script to package.json, so I can ensure my builds follow the same process as yours. 😃

Could not find a declaration file for module 'midi-file'

When trying to use the package:

import { Midi } from "@tonejs/midi"`

I'm encountering the following error:

ERROR in [at-loader] ./node_modules/@tonejs/midi/dist/Header.d.ts:1:26 
    TS7016: Could not find a declaration file for module 'midi-file'. 'C:/code/motifn/node_modules/midi-file/index.js' implicitly has an 'any' type.
  Try `npm install @types/midi-file` if it exists or add a new declaration (.d.ts) file containing `declare module 'midi-file';`
ERROR in [at-loader] ./node_modules/@tonejs/midi/dist/Instrument.d.ts:1:31 
    TS7016: Could not find a declaration file for module 'midi-file'. 'C:/code/motifn/node_modules/midi-file/index.js' implicitly has an 'any' type.
  Try `npm install @types/midi-file` if it exists or add a new declaration (.d.ts) file containing `declare module 'midi-file';`
ERROR in [at-loader] ./node_modules/@tonejs/midi/dist/Track.d.ts:1:31 
    TS7016: Could not find a declaration file for module 'midi-file'. 'C:/code/motifn/node_modules/midi-file/index.js' implicitly has an 'any' type.
  Try `npm install @types/midi-file` if it exists or add a new declaration (.d.ts) file containing `declare module 'midi-file';`

Interestingly, the package works perfectly from a stackblitz project (was hoping to create a repro), so looks like a minor configuration issue. I'm using a typical Typescript+Webpack setup.

Cheers
Ben

Example fails to run

I am trying to use this library in a project, and it seems to be failing to run at all. Just trying to run the included example, I get the same console error that I do in my own project:

Uncaught (in promise) 0 load.html:1

What could be causing this?

global namespace with requirejs

I am having issues with the anonymous functionality registered as AMD in requirejs:

Uncaught ReferenceError: MidiConvert is not defined

Can't encode tracks with notes that are less than 12 (C0)

Adding a note like this:

track.note(11, time, duration);

Then encoding like this:

Uint8Array.from(midi.toArray())

Throws this:

ERROR TypeError: Cannot read property '1' of null
    at Object.midiPitchFromNote (scripts.bundle.js:12)
    at Object.ensureMidiPitch (scripts.bundle.js:12)
    at a.addNoteOn.a.noteOn (scripts.bundle.js:12)
    at Array.<anonymous> (scripts.bundle.js:12)
    at i (scripts.bundle.js:12)
    at a (scripts.bundle.js:12)
    at t.value (scripts.bundle.js:12)
    at scripts.bundle.js:12
    at Array.forEach (<anonymous>)
    at t.value (scripts.bundle.js:12)

But by doing

    track.note(12, time, duration);

No problems arise when encoding

Possible midi encode bug

I'm using MidiConvert on client side, and export is done with blobs.
Generally it's working fine, but I came up with this minimal example that show the issue.
midi
.track()
.patch(32)
.note(76, 0, 0.66666)
.note(46, 0, 0.66666)
.note(50, 0, 2)
.note(76, 0.66666, 0.66666)
.note(76, 1.33333, 0.66666);
this example will lead to an midi file with length more than 2seconds, and the rhythm is not correct as shown below.
I am curious if this bug will reproduce on server side.
here is the full code
const midi = MidiConvert.create()
midi.track().patch(32).note(76, 0, 0.66666).note(46, 0, 0.66666).note(50, 0, 2).note(76, 0.66666, 0.66666).note(76, 1.33333, 0.66666);
const binaryString = midi.encode();
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); }
var blob = new Blob([bytes], { type: "audio/midi;charset=binary" });
FileSaver.saveAs(blob, "output.mid");
image

midi is not saving correctly on web browser.

so I decided to make a heroku app here so you can see my predicament:
https://demo-for-midi-convert.herokuapp.com/
github for this experiment is at:
https://github.com/fornof/Midi-Keytone

  1. I can get a download of a midi.encode() , but none of my midi players can play it ( see button 1 download).
  2. I can hear a midi/tone.js in the browser, i just cannot export at the moment (play a key or something)
  3. The demo uses fs to write the midi file, but my demo uses a file blob and midi.encode. I don't think midi.encode is working the way it should work. it is a string not a binary object.

This is what a midi file read in looks like.
MThd�����MTrk��X���`����A�Q�����/MTrk���G�Cd�|�Cd��Cd\�Cd��Ed\�Ed��Gd\�Gd��Hd\�Hd��Jd�|�Jd��Jd|�Jd��Jd|�Jd��Jd|�Jd��Od�|�Od��Od\�Od��Qd\�Qd��Sd\�Sd��Td\�Td��Vd�|�Vd��>d\�>d��>d�<�>d��>d\�>d��Cd�<�Cd�/MTrk���G��2d|�2d��2d|�2d��2d|�2d��7d�|�7d��7d\�7d��9d\�9d��;d\�;d��<d\�<d��>d�|�>d��>d|�>d��>d|�>d��>d|�>d��Cd�|�Cd��Cd\�Cd��Ed\�Ed��Gd\�Gd��Hd\�Hd��Jd�|�Jd��6d\�6d��6d�<�6d��6d\�6d��;d�<�;d�/MTrkQ��U�7d�|�7d��5d�|�5d��3d�|�3d��2d�|�2d��2d\�2d��2d�<�2d��2d\�2d��2d�<�2d�/MTrk����Jeffrey M Colletti�/MTrk(�� [email protected]�/MTrk��/MTrk��/MTrk��/MTrk��/MTrk��/

This is what MidiConvert midi.encode() produces from the exact same midi file read in then piped out:
MThd�����MTrk�ÿQ���'ÿ/MTrk¸ÿQ���'ÿ��UntitledÀG�Cd�|�CZ��Cd\�CZ��Ed\�EZ��Gd\�GZ��Hd\�HZ��Jd�|�JZ��Jd|�JZ��Jd|�JZ��Jd|�JZ��Od�|�OZ��Od\�OZ��Qd\�QZ��Sd\�SZ��Td\�TZ��Vd�|�VZ��>d\�>Z��>d�<�>Z��>d\�>Z��Cd�<�CZÿ/MTrkÑÿQ���'ÿ��UntitledÁG��2d|�2Z��2d|�2Z��2d|�2Z��7d�|�7Z��7d\�7Z��9d\�9Z��;d\�;Z��<d\�<Z��>d�|�>Z��>d|�>Z��>d|�>Z��>d|�>Z��Cd�|�CZ��Cd\�CZ��Ed\�EZ��Gd\�GZ��Hd\�HZ��Jd�|�JZ��6d\�6Z��6d�<�6Z��6d\�6Z��;d�<�;Zÿ/MTrk`ÿQ���'ÿ��UntitledÂU�7d�|�7Z��5d�|�5Z��3d�|�3Z��2d�|�2Z��2d\�2Z��2d�<�2Z��2d\�2Z��2d�<�2Zÿ/

I'm guessing it's not getting set to binary correctly, but I've tried "binary" "audio/midi" and "application/octet-stream" and none of them seem to produce the binary format with question marks.
any help on this would be appreciated

typescript fails to compile

Error in MidiConvert.d.sts (7,2): error TS1036: Statements are not allowed in ambient contexts

removing semi-colons from the export declarations fixes the issue for me. using "typescript": "^2.3.4".

Handle Program Change Events

Hey,

I have a lot of MIDI files which are horrible. And by that I mean that all the instruments are merged into one track and the different instrument sounds are made with sending an program change event previously. Is there any plan to support that or at least parse these events?

Update:
I found that there is a code that is supposed to handle program change events, but I'm not sure how right now. I'll spend more time later and investigate that.

Parcel ?? and Decoder is not a function

Hello all.

I'm trying Parcel as packager, and I had just an error when using
MidiConvert.parse(data)

Decoder is not a function

I just had to add 'default' in line 80 of Midi.js
const midiData = Decoder.default(bytes)

I'm not sure where the problem could come from. I feel it could be some babel preset stuff and all that jazz ?

Cannot minify build with Create React APP

When a blank Create React App is created and MidiConvert is a dependency, it is fine for developing. As soon as a build is started it gives the following error:

$ react-scripts build
Creating an optimized production build...
Failed to compile.

Failed to minify the code from this file:

 	./node_modules/midiconvert/src/Util.js:20

Read more here: http://bit.ly/2tRViJ9

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

In the package.json from MidiConvert the following entry triggers the build of the source files.
"module": "src/MidiConvert.js",
When removed, the React project builds.

React project implementing MidiConvert.
Package JSON with erroring line of MidiConvert.

De-sync? w/example

I have run MidiConvert on a certain MIDI file, and the time information reported, after a few seconds, is de-synced from the actual notes times.
The MIDI is from Super Mario World, found here [http://www.ninsheetmusic.org/download/mid/844].
The last chord in the midi sounds at approximately [4m:01s] ("correct").
The last chord in the MidiConvert reports as approximately 277s=[4m:37s] ("de-synced").

I can only guess that tempo changes aren't accounted for in the note times reported by MidiConvert, resulting in de-sync, but I would like to hear what you think could be causing this, as the developer.

Raw Midi Parsing broken - TypeError: Midi is not a constructor

Since version 2.0.5 using Midi as a constructor throws the error TypeError: Midi is not a constructor.
Example using version 2.0.5: https://repl.it/@whitebird/tonejs-midi-error-broken

Last version that was working was version 2.0.4: https://repl.it/@whitebird/tonejs-midi-error-working

It uses this snippet of code:

const fs = require('fs');
const Midi = require('@tonejs/midi');

const midiData = fs.readFileSync('test.mid');
const midi = new Midi(midiData);
console.log(midi);

timeSiganture in the header and all controlChanges in the Tracks are gone after encoding

Hey, great module!
But I have an issue - wehen I read a midi File and directly encode it to a new file, the timeSiganture in the header and all controlChanges in the Tracks are gone. Also the timemal is gone. the sourcefile when imported into my DAW has a timemap and creates the BPM around it, with the encoded file there is no time map.

Can someone help?

Support for xhr

Are you willing to add xhr support for getting the midi files? The file upload api is a little limiting. In my current application im solving this by the following snippet:

    function getMidiStream(url, callback) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.overrideMimeType('text/plain; charset=x-user-defined');
        xhr.onreadystatechange = function () {
            if (this.readyState === 4) {
                if (this.status === 200) {
                    var t = this.responseText || '';
                    var ff = [];
                    var mx = t.length;
                    var scc = String.fromCharCode;
                    for (var z = 0; z < mx; z++) {
                        ff[z] = scc(t.charCodeAt(z) & 255);
                    }
                    callback(ff.join(''));
                } else {
                    onerror && onerror('Unable to load MIDI file');
                }
            }
        };
        xhr.send();
    }

    getMidiStream(url, function (stream) {
           var midi = MidiConvert.parseParts(stream, options);
    })

I wanted to create a pull request but had no idea where to put the code. Btw this code is heavily inspired by how midijs solves this. Its kind of a hack to get a blob.

Frank

bpm and duration not accurate

When I using the parse method, the result JSON header's bpm is a long decimal number,e.g. the bpm is 94, and the result from the JSON is 94.80005877603644.
I am working on changing durations of notes into beats, and it hinder my calculations.
besides, the durations of notes is hard to check as well as the decimal is so long, but I do not really sure if it is due to the bpm accuracy of anyother problems.

Intstrument information

I would be good to get the intstrument information for each track, or would this be out of scope of this project.

can't resolve jsmidgen and midi-file-parser

I get this error when I try to use this library.

ERROR in ./node_modules/midiconvert/src/Midi.js
Module not found: Error: Can't resolve 'jsmidgen' in '/Users/josephweidinger/git/personal/MidiConvertWrapperAdvanced/node_modules/midiconvert/src'
 @ ./node_modules/midiconvert/src/Midi.js 2:0-35
 @ ./node_modules/midiconvert/src/MidiConvert.js
 @ ./src/main.ts

ERROR in ./node_modules/midiconvert/src/Midi.js
Module not found: Error: Can't resolve 'midi-file-parser' in '/Users/josephweidinger/git/personal/MidiConvertWrapperAdvanced/node_modules/midiconvert/src'
 @ ./node_modules/midiconvert/src/Midi.js 1:0-43
 @ ./node_modules/midiconvert/src/MidiConvert.js
 @ ./src/main.ts

Here are 4 methods to make it work... but they all feel wrong...

  1. If I run the commands:
npm install jsmidgen
npm install midi-file-parser

The errors go away.

  1. Looking at the package.json, I notice that these seemingly important dependencies are only devDependencies. If I fork the project and make them dependencies, it installs both of these automatically and everything is good.

  2. Deleting node_modules/midiconvert/src (forces it to use /build)

  3. Deleting in package.json "module": "src/MidiConvert.js",

So it appears the issue is it is using the src dir and not the bundle when you import. It then fails when it tries to compile Midi.js because of the lines:

import * as Decoder from 'midi-file-parser'
import * as Encoder from 'jsmidgen'

In my opinion, it makes sense to list these things as dependencies and not devDependencies. So I'm going to make a PR and you all can decide.

Great library!

I miss one track on each song

Hi,

this is the issue: I miss a track on each song. For example The entertainer has two tracks but (it seems) only one is loaded. I have tested also with other songs, for example, in same folder, A_F_NO7_01.mid has one track and is not loaded.

I have tested in my code with node "@tonejs/midi": "^1.2.0" library version and also I have tried deserializing on your web https://tonejs.github.io/Midi/

Best regards and thanks a lot about to share this great software!

Automatic PPQ detection

I may be misunderstanding ppq, but shouldn't it be present in the header of the midi file we are parsing? Could it hypothetically be included in the returned object from parseTransport?

parsing midi in form of a Uint8Array

I'm curious how I should parse a midi using MidiConvert.parse when it is in Uint8Array. I'm currently getting

Uncaught (in promise) TypeError: t.substr is not a function
    at Object.e [as read] (eval at ./node_modules/midiconvert/build/MidiConvert.js (vendor.js:4028), <anonymous>:1:23388)
    at e (eval at ./node_modules/midiconvert/build/MidiConvert.js (vendor.js:4028), <anonymous>:1:20000)
    at n (eval at ./node_modules/midiconvert/build/MidiConvert.js (vendor.js:4028), <anonymous>:1:22848)
    at t.exports (eval at ./node_modules/midiconvert/build/MidiConvert.js (vendor.js:4028), <anonymous>:1:23890)
    at t.value (eval at ./node_modules/midiconvert/build/MidiConvert.js (vendor.js:4028), <anonymous>:1:7318)
    at Object.parse (eval at ./node_modules/midiconvert/build/MidiConvert.js (vendor.js:4028), <anonymous>:1:604)
    at eval (eval at ../../.cooking/node_modules/buble-loader/index.js?objectAssign=Object.assign&jsx=h!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/app.vue (app.js:7), <anonymous>:102:78)
    at <anonymous>
e @ MidiConvert.js?00db:1
e @ MidiConvert.js?00db:1
n @ MidiConvert.js?00db:1
t.exports @ MidiConvert.js?00db:1
value @ MidiConvert.js?00db:1
parse @ MidiConvert.js?00db:1
(anonymous) @ app.vue?6244:96

Wonder how to resolve this. My current use case is fetching a midi file via aws-sdk from S3, resulting in a Uint8array.

Multiple tempos / BPMs

I have some songs that use multiple BPMs, but when converting using your tool, I only get one BPM as the output.

Can you look into making this tool use multiple BPMs please as an array?

Thanks.

Channels (instruments) merged

Hello!

I'm developing kids piano learning game and i use your library for decoding files. Today we tried to add second instrument to midi. But when i look at data parsed from midi i see that tones from both instruments are merged in one channel. Could you please give me a hint why this happens ? (Maybe i'm using it in wrong way, or midi is not correctly exported).

I did tests with several other (non browser) midi players and they did show two different instruments

thanks

.mrtn

test.midi.zip

Demo code stale? 'sustain' is not an object, not an array

Hello and thanks for the cool project.

I'm parsing this file: https://www.dropbox.com/s/hecoqfrjok5fsjs/KICK1.mid?dl=1

Exported from Ableton 10 via "Export to MIDI file..." or whatever.

It's simple MIDI for a kick drum, all running on a single note w/ velocity changes, but nothing else, I believe.

In your demo code, you've got something like this:

	  //they are also aliased to the CC number's common name (if it has one)
	  track.controlChanges.sustain.forEach(cc => {
	    // cc.ticks, cc.value, cc.time
	  })

But for me, track.controlChanges.sustain is an object (empty, or {}), and not iterable via forEach().

I'm guessing the sample code is simply out of date, but you can inspect the MIDI file I've provided if you want, or feel free to let me know if I can provide more info.

track.notes is an array and forEach() works fine. I can print note data without issue.

Full code:

	const fullPath = ...
	const midiData = fs.readFileSync(fullPath);
	const Midi = require('@tonejs/midi');
	const midi = new Midi(midiData);

	//get the tracks
	midi.tracks.forEach(track => {
	  //tracks have notes and controlChanges

	  //notes are an array
	  const notes = track.notes
	  notes.forEach(note => {
	    //note.midi, note.time, note.duration, note.name
	    console.log(`note: ${json(note)}`);
	  })

	  //they are also aliased to the CC number's common name (if it has one)
	  track.controlChanges.sustain.forEach(cc => { // ** ERROR **
	    // cc.ticks, cc.value, cc.time
	  })

	  //the track also has a channel and instrument
	  console.log(`instrument name: ${track.instrument.name}`)
	})

Error "CreateListFromArrayLike called on non-object" in a electron app

Hi,
first thanks for this lib. I am trying to use it inside an electron app with no success. Maybe I'm doing sthg wrong.

I am getting this error

Uncaught TypeError: CreateListFromArrayLike called on non-object
    at n.readString (/Users/vincentd/projects/samplify/samplify-client/node_modules/@tonejs/midi/build/Midi.js:1)
    at n.readChunk (/Users/vincentd/projects/samplify/samplify-client/node_modules/@tonejs/midi/build/Midi.js:1)
    at t.exports (/Users/vincentd/projects/samplify/samplify-client/node_modules/@tonejs/midi/build/Midi.js:1)
    at new t (/Users/vincentd/projects/samplify/samplify-client/node_modules/@tonejs/midi/build/Midi.js:1)
    at FileReader.reader.onload (Midi.js?ba48:25)

I am importing the lib this way
import * as MidiLib from '@tonejs/midi'
and then calling it with a raw string from a midi file this way
const midiObj = new MidiLib(binaryStr)

Tell me if I'm doing sthg wrong or if I can help somehow.

Thanks!

Vincent

Should tracks have IDs?

Should there be an ID property on each track, which corresponds to its index in the tracks list?

That's the reason I changed types to interfaces, so I could add id as a consumer of MidiConvert, but that seems both useful and lightweight enough that it might belong upstream. It ensures that no matter how the tracks data-structure is transformed for presentation (for instance, sorted by instrument or by channel), or if a track is being passed around independently of tracks, it's still easy to identify which track it represents.

Json to midi

Hi, I was searching in your documentation and tests, however I could not find feature I am interested in.

Is it currently possible to generate midi file from json, that was created via MidiConvert?

My use-case is :

  1. translating regualar midi file into JSON via MidiConvert,
  2. tweaking json in some text editor,
  3. translating it back to midi

Implement key signature?

Can we have the key signature of a MIDI file implemented please?

Also, key signatures can change through the music so if it's possible to have it as an array that would be lovely.

Field `timeSignatures[index].measure` sematic

Hello!
Thanks for the awesome library!

I have some difficulties understand the measure field from timeSignatures[index].measure. Is it like the time from which the corresponding time signature changes? The readme API is well documented except for timeSignatures: TimeSignatureEvent[] I think.

Cheers!

midi.toJSON()

Unfortunately, getters like instrumentFamily don't serialize very well. There's a toJSON method on Note already. If we add similar ones to MIDI, Track, and Control, we can make it really easy to serialize/deserialize Tone.js-friendly MIDI.

Pitch Bends

Pitch bends don't appear to be supported. Would expect something like:

addPitchBend (pb: Partial<PitchBendInterface>) {...}

Looking at the underlying midi-file library, it seems pitch bends are encoded with a type of "pitchBend", but apart from that, the pattern is very similar to other midi controller events. So the encoding translation might look something like:

function encodePitchBend (pb: PitchBend, channel: number): MidiPitchBendEvent {
	return {
		absoluteTime: pb.ticks,
		channel,
		deltaTime: 0,
		type: "pitchBend",
		value: pb.value,
	};
}

midi.fromUrl is not a function

I am using the tonejs midi library from a few weeks now and everything was working just fine but suddenly without changing anything i get the error midi.fromUrl is not a function. I use it locally and on a server and in both places i get the same error so i was wondering if somebody knows what is going wrong.

Add instrumentPatchID and instrumentFamilyID

For many tracks, the instrument string isn't set, but there's metadata present in the MIDI file that we can do a better job exposing:

  • There are 15 instrument families, each of which contain 8 instruments. Each track should have a programChange event that provides this data, and its much more likely to be set in an arbitrary MIDI file than the instrument name.

  • Anything on Channel 10 should be percussion.

We could add instrumentTypeID and instrumentFamilyID properties to each track, as well as a table to look up their values:

const instrumentFamilyByID = ['piano', 'chromatic percussion', ]
const instrumentTypeByID = ['acoustic grand piano', 'baby grand piano', ]
const instrumentFamilyIDByTypeID = [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, ]

// example track
{
  controlChanges
  id
  instrument
  instrumentFamilyID: 4,
  instrumentTypeID: 36,
  isPercussion: false,
  name
  notes
  duration
  length
  noteOffs
  noteOns
  startTime
}

Importing midi file broken

This is connected to an issue filed with tensorflow/magenta-js.


Issue

Importing a midi file (via magenta-js, which is using Tonejs Midi) fails with this error:

Midi.js:86 Uncaught TypeError: Decoder is not a function
    at Midi.decode (Midi.js:86)
    at Object.parse (MidiConvert.js:43)
    at Object.midiToSequenceProto (midi_io.ts:39)
    at FileReader.<anonymous> (....js:14)

Solution

Midi.js within the package midiconvert calls Decoder(bytes) from the midi-file-parser package (expecting it to be a function), except midi-file-parser exports that function within an object.

Changing const midiData = Decoder(bytes) to const midiData = Decoder.default(bytes) within node_modules/midiconvert/src/Midi.js fixes the issue.

New version not working

Hi, I'm using @tonejs/midi, but when I install this package with npm, I have directly this problem while I just try to import it in my file :

error TS2307: Cannot find module './midi-file'

And this, related from the files : Header.d.ts, Instrument.d.ts, & Track.d.ts. The package being in version 2.0.0.

What may I do ? I tried with younger versions and I get problems with typescript syntax (arrays which shall have types of their elements...).

How to identify Piano tracks?

How can I identify this two trakcs?

selection_383

I mean:

piano_left_hand = __some_expression__;
piano_right_hand = __some_expression__;

selection_384

Thanks!

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.