1

I'm loading up a file from the browser and I can see its content starts with MThd followed by plenty of garbbled unreadable characters.

Now, this is a MIDI .mid file and I'd like to parse it with the Tonejs / midi library.

I thus coded the following service method:

import * as ToneMidi from '@tonejs/midi';

public parseRawMidi(rawMidiData: ArrayBuffer): Soundtrack {
  const midi = new ToneMidi.Midi(rawMidiData);
}

But it gives me the error: ypeError: _tonejs_midi__WEBPACK_IMPORTED_MODULE_2__.Midi is not a constructor

I reckon this is because the rawMidiData argument is not of the correct expected type by the constructor.

Indeed the Midi.d.ts file shows:

constructor(midiArray?: (ArrayLike<number> | ArrayBuffer));

Here is my file uploader:

public onUpload(fileList: FileList): void {
  const file = fileList[0];
  const fileReader: FileReader = new FileReader();
  fileReader.onloadend = (event: Event) => {
    this.rawMidi = fileReader.result as ArrayBuffer;
    // var array = new Uint8Array(new ArrayBuffer(rawLength));
    const soundtrack: Soundtrack = this.midiService.parseRawMidi(this.rawMidi);
  };
  fileReader.readAsText(file);
}

UPDATE: A little experiement. I added the following source code:

const buffer = new ArrayBuffer(16);
console.log('Before the call to the constructor');
const midi = new ToneMidi.Midi(buffer);
console.log('and after');

The first logger was displayed, but not the second one, and the same error showed up.

UPDATE: I was using the wrong reader readAsText and when switching to readAsArrayBuffer as in fileReader.readAsArrayBuffer(file); I could get an array buffer passed to the service method. But I still have the same issue of not resolving the constructor call: Midi is not a constructor

UPDATE: After the GitHub issue was resolved, I could upgrade to @tonejs/midi@2.0.5 with the npm install @tonejs/midi command and the constructor then worked fine.

Stephane
  • 11,836
  • 25
  • 112
  • 175
  • That error seems to be more related with how you are importing `ToneMidi`. What import statement are you using? Do you have `esModuleInterop` set in your tsconfig? – Pace Jun 05 '19 at 17:53
  • Here is how I do the import statement `import * as ToneMidi from '@tonejs/midi';` and I have no such `esModuleInterop` in these `tsconfig.json` and `tsconfig-lib.json` files. – Stephane Jun 05 '19 at 20:57
  • Ok, based on that and the examples I think it should be `const midi = new ToneMidi(rawMidiData);`. I'm not 100% certain that it will work with Webpack as it's been a while since I've done TS with Webpack. Let me know if you get other errors. – Pace Jun 05 '19 at 21:27
  • I just tried your suggestion but the compiler complains with `error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature` – Stephane Jun 06 '19 at 05:04
  • 1
    Yes, I just tried a small test app and got this also. Unfortunately it seems the typings do not line up with the way the module is packaged. The typings declare that there is no default export and yet, if I `require` the module, I get a class constructor with a static `fromUrl` method. I can tweak the typings to make it work but this is probably not what you're after. Also, to get it to work I had to make the same `midi-file` hack you had to make or just throw in `--skipLibCheck`. – Pace Jun 06 '19 at 15:55
  • 1
    Looks like the whole library was converted to TS a month ago. My guess is just that there are no TS consumers and the lib is critically broken at the moment. – Pace Jun 06 '19 at 15:59
  • @Pace There is a live example at https://tonejs.github.io/Midi/ that works all right though. Puzzling. – Stephane Jun 30 '19 at 22:28

0 Answers0