0

I want to play MIDI files in the browser smoothly (even when the browser tab is not in focus, and be able to get and set the time position).

The readme of timidity says that I should start with

const Timidity = require('timidity')

but I get Uncaught ReferenceError: require is not defined.

I tried many workarounds but all of them yield other errors. For example, import('/127.0.0.1:8887/node_modules/timidity/index.js') while running Web Server for Chrome yields Uncaught (in promise) TypeError: Failed to fetch dynamically imported module (even though opening that URL in the browser works). I tried applying browserify to timidity and bg-sound, adding type="module" to various <script> tags, but I haven't found a combination that allows my script to do something like new Timidity().

browserify index.js -o bundle.js (using index.js from bg-sound after running npm install bg-sound in the directory where that index.js is) allows doing

<script src="bundle.js"></script>
<bg-sound src="https://bitmidi.com/uploads/16752.mid"></bg-sound>
Click somewhere. Until then, there will probably be "The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page."

but then I didn't find a way to access player or timidity in order to use player.seek().

How can I play MIDI files?

root
  • 1,812
  • 1
  • 12
  • 26

1 Answers1

0

Other answers than this self-answer are very welcome. I particularly wonder about the purpose of browserify and whether there's a simpler solution without it.

Anyway, after a cascade of errors and respective workarounds, I've come up with the following modification of the official example:

Run once:

npm install timidity
npm install -g browserify

HTML file:

<script src="myscript-browserified.js"></script>
Click somewhere within the first 5 seconds! Otherwise there will be no sound due to "The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page."

File myscript.js:

const Timidity = require('timidity')

setTimeout(() => {
    baseUrl = 'https://bitmidi.com/timidity/' // for fetching the file libtimidity.wasm
    const player = new Timidity(baseUrl)
    player.load('https://bitmidi.com/uploads/16752.mid')
    player.play()

    player.on('playing', () => {
      console.log(player.duration)
    })
}, 5000);

After modifying myscript.js, run the following command

browserify myscript.js -o myscript-browserified.js
root
  • 1,812
  • 1
  • 12
  • 26