Skip to content

Repository files navigation

NPM Version

This is an OPL (IMF, WLF, RAW, DRO, VGM, VGZ) player for the web (and elswhere) based on opl_plr.js by kvee

The main changes I made are to make it lighter & simpler (and more universal) using wasi-sdk instead of emscripten, and to use AudioWorkletProcessor instead of depracated ScriptProcessor for sound-generation. This performs better, and runs in more places. I also added wave-out support, so it can be used in other places.

installation

You can install in your own project (for bundling with vite, etc) with:

npm i @konsumer/nuked

Or, you can add to the web with:

<scripttype="importmap">{"imports": {"@konsumer/nuked": "https://esm.run/@konsumer/nuked","@konsumer/nuked/nuked-player": "https://esm.run/@konsumer/nuked/nuked-player","pako": "https://esm.run/pako"}}</script>

Now you can import from these, if your script-tag has type=module. If you want optional VGZ support (and are using the web-component) add pako.

usage

There are a few ways to use it. The easiest is a quick web-component:

<scripttype="module">import'@konsumer/nuked/nuked-player'</script><nuked-playersrc="song.imf"></nuked-player>

There are a few functions exported:

// these create a "queue" from various files (as Uint8Array or ArrayBuffer, or whatever)imf(imfData,(imfRate=560))raw(rawData)dro(droData)vgm(vgmData,loopRepeat)// this creates an audio-worklet for playbackcreateAudioWorklet(audioContext,queue)// This generates a Uint8Array of bytes for a WAV-file, and can be used offlinecreateWave(queue)

wav

You can generate a WAV (RIFF, uncompressed) file for use in anyhting else:

// create a queue from a fileconstqueue=imf(awaitfetch('mysong.imf').then((r)=>r.arrayBuffer()))// create WAV-bytes from queueconstwav=awaitcreateWave(queue)// create a URL (on web) suitable for a audio-tagconsturl=URL.createObjectURL(newBlob([wav],{type: 'audio/wav'}))

Here is a full nodejs example:

import{imf,createWave}from"@konsumer/nuked";import{readFile,writeFile}from"node:fs/promises";constf=awaitreadFile("break_my_heart.imf");constq=imf(f);constw=awaitcreateWave(q);awaitwriteFile("break_my_heart.wav",w);// or 1-line conversion:awaitwriteFile("break_my_heart.wav",awaitreadFile("break_my_heart.imf").then(imf).then(createWave));

Here is a full bun example (using file built-ins, but you could use node-code, above, too):

import{imf,createWave}from"@konsumer/nuked"constf=awaitBun.file("break_my_heart.imf")constb=awaitf.arrayBuffer()constq=imf(b)constw=awaitcreateWave(q)awaitBun.write("break_my_heart.wav",w)

You can see an example of this, in test.html. It's a bit slower than direct-output, but it works in places where you cannot use the worklet (native node/deno/bun/etc.)

worklet

AudioWorkletProcessor is a hyper-efficient worker (similar to thread) that will run audio-processing in the background. You can use it like this:

import{imf,createAudioWorklet}from'@konsumer/nuked'// create an audio-contextconstctx=newAudioContext()// create a queue from a fileconstqueue=imf(awaitfetch('mysong.imf').then((r)=>r.arrayBuffer()))// create a worklet from a queue/contextconstopl=awaitcreateAudioWorklet(ctx,queue)// connect it to output. you can also use effects see https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Using_Web_Audio_APIopl.connect(ctx.destination)// stuff you can doopl.play()opl.stop()opl.pause()// toggle pause-stateopl.seek(4)// in seconds// respond to time-updatesopl.addEventListener('time',({ current, total })=>{console.log({ current, total })})// you can also get the time right after parsing it (in case you need time, but can't play it through audio-context)consttotal=nuke.getTimeLength(queue)

vgz

VGZ is just gzipped VGM. You can parse it in js like this:

import{vgm}from'@konsumer/nuked'importpakofrom'pako'constqueue=vgm(pako.ungzip(awaitfetch('mysong.vgz').then(r=>r.arrayBuffer())))

I do this in nuked-player web-component.

plans

Eventually, I would like to minimize any js host requirements, so it can run in more places like:

And I need to test to make sure it works in other js AudioContext-hosts like:

About

Yamaha OPL2/3 FM synth chip emulator for javascript (and other things)

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages