Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript no exported member 'SMF' #21

Open
fornof opened this issue Jun 5, 2023 · 12 comments
Open

Typescript no exported member 'SMF' #21

fornof opened this issue Jun 5, 2023 · 12 comments

Comments

@fornof
Copy link

fornof commented Jun 5, 2023

I'm getting an error when I copy paste the example :
Module '"jzz-midi-smf"' has no exported member 'SMF'
image
I did 'import JZZ from "jzz" and that gets live audio working.
I could not get the jzz-midi-smf to work though.

I'm using Typescript/ Nodejs, compiling down in react and phaser and rendering to the browser.
I did notice this one: jazz-soft/JZZ#62
I might be able to help out if there is no quick solution to this.

@fornof
Copy link
Author

fornof commented Jun 5, 2023

update: Fixed it.
the ES6/Typescript import is broken somehow. using require works fine. This is my working example for typescript.

import {promises as fs} from 'fs'
var JZZ = require('jzz')
var SMF =  require('jzz-midi-smf')


 let testFile = await fs.readFile("test/data/testScale1.mid", "binary")
  var midiout = JZZ().openMidiOut(); //I think this is just for player.play()

var smf = new JZZ.MIDI.SMF(testFile); 
var player = smf.player();
player.connect(midiout);
//player.play();
fs.writeFile('test/data/out.mid', smf.dump(), 'binary');

@DJthefirst
Copy link

DJthefirst commented Jul 31, 2023

I am using TypeScript in my project and have encountered the same problem. The require() solution however unfortunately does not work for me.

var JZZ = require('jzz') works fine but var SMF = require('jzz-midi-smf') throws Could not find a declaration file for module 'jzz-midi-smf'. I assume because index.d.ts is missing. I know it is a lot of work to convert the js to TS but is there some online generator to do it?

@fornof
Copy link
Author

fornof commented Aug 1, 2023

Use this for smf , rest of the code is above, ignore the smf import
var smf = new JZZ.MIDI.SMF(testFile);

@DJthefirst
Copy link

DJthefirst commented Aug 1, 2023

I now get
Property 'SMF' does not exist on type 'Constructor'. Did you mean 'smf'?
I then tried var smf = JZZ.MIDI.smf();
but the var player = smf.player(); says Property 'player' does not exist on type 'MIDI'

The new keyword also did not work with/without.

@jazz-soft
Copy link
Owner

Use SMF (in capitals) and ignore the warning.

@DJthefirst
Copy link

DJthefirst commented Aug 1, 2023

I am using Svelte Kit and require does not work.

image

the code runs if I comment out var smf = new JZZ.MIDI.SMF();

so it can import jzz just fine. The jzz-midi-smf gives me
image
and SMF(); says
image
I assume because it is not imported correctly.\

The JZZ examples run just fine the problem is in JZZ.MIDI.SMF

@jazz-soft
Copy link
Owner

Call SMF(JZZ); as shown in the example.
That will add the missing member.

@DJthefirst
Copy link

DJthefirst commented Aug 1, 2023

I still get the same error no change. I assume the error is in the import and TS can't find the package to load.

@DJthefirst
Copy link

DJthefirst commented Aug 2, 2023

I was able to get it the typescript errors are just cosmetic.

On a different note is there a way to access the array of available midi in and out ports?

And/Or recreate this function that updates on port change to get a dropdown menu of available ports?

    async initMidiPorts(){
        await navigator.requestMIDIAccess()
        .then((midiAccess) => {
            this.midiAccess = midiAccess;
            this.updateMidiOptions();
            midiAccess.onstatechange = (event) => this.updateMidiOptions();
        });
    }

If not it is no big deal. I appreciate the work you have done on this library. I didn't see it in the docs but could revealing midiAccess.inputs.values() allow this?

@fornof
Copy link
Author

fornof commented Aug 2, 2023 via email

@fornof
Copy link
Author

fornof commented Oct 12, 2024

for getting a list of available outputs you will need to request access to midi, then the browser gives you the inputs and outputs to you:

const midis = await navigator.requestMIDIAccess()
for (let i of midis.outputs.values()){ console.log(i)}

you will want i.name I believe.

I found a solve for in browser typescript react. It is very close to the instructions , except it needs a type.d.ts file

  • it is also forever going to underline SMF as red, but that's because it is imported.
    Step 1 solves the " could not find declaration file" for jzz-midi-smf. It seems to be optional, but there's less underlined.
  1. create a new file jzz-midi-smf.d.ts in src/ or similar , in this file put in:
declare module 'jzz-midi-smf'

This step will give a complete running copy with a save file in the browser. Using react and vite. I wish something was on the main page for quick-start. It took me a few hours to find the docs and put everything together.
2.

import { useEffect, useState } from 'react'
import JZZ from 'jzz'
import SMF from 'jzz-midi-smf'
import './App.css'
SMF(JZZ)
function midiPlay(smfIn: any){
  const midiout = JZZ().openMidiOut([0,1,2,3,4]);
  const player = smfIn.player();
  console.log("dump", smfIn.dump())
  player.connect(midiout);
  player.play()
}
function midiToBase64Save(data: any){
  //https://jazz-soft.net/demo/WriteMidiFile.html
   // MIDI file dumped as a string
  var b64 = JZZ.lib.toBase64(data); // convert to base-64 string
  var uri = 'data:audio/midi;base64,' + b64; // data URI
  //const a = document.createElement('a');
  //a.href = uri;
  //a.download = name||'itWorks.mid';
  //a.click();
  return uri
}
function midiOut(){
  var smf =JZZ.MIDI.SMF(2,96); // type 0, 96 ticks per quarter note
var trk = new JZZ.MIDI.SMF.MTrk();

smf.push(trk);
// add contents:
trk.add(0, JZZ.MIDI.smfSeqName('This is a sequence name'))
   .add(0, JZZ.MIDI.smfBPM(90)) // tempo 90 bpm
   .add(96, JZZ.MIDI.noteOn(0, 'C6', 127))
   .add(96, JZZ.MIDI.noteOn(0, 'Eb6', 127))
   .add(96, JZZ.MIDI.noteOn(0, 'G6', 127))
   .add(192, JZZ.MIDI.noteOff(0, 'C6'))
   .add(192, JZZ.MIDI.noteOff(0, 'Eb6'))
   .add(192, JZZ.MIDI.noteOff(0, 'G6'))
   .add(988, JZZ.MIDI.smfEndOfTrack());
  
   for (var i = 0; i < smf.length; i++) {
    for (var j = 0; j < smf[i].length; j++) {
      console.log('track:', i, 'tick:', smf[i][j].tt, smf[i][j].toString());
      // or do whatever else with the message
    }
  }
  return smf
}
function App() {
  const [fileOut, SetFileOut] = useState("")
 
  
  useEffect(()=>{
    const smf =  midiOut()
    midiPlay(smf)
    SetFileOut(midiToBase64Save(smf.dump()))
    console.log("alldone!")
  },[])
  return (
    <>
      <div>
        <a href={fileOut} target="_blank">
          Click the logo to download the midi file
          <img src="https://opensource.org/wp-content/uploads/2009/06/OSI_Standard_Logo_0.svg" className="logo" alt="Vite logo" />
        </a>

      </div>
  
    </>
  )
}

export default App
function onEffect(arg0: () => void) {
  throw new Error('Function not implemented.')
}


You will need a midi out to hear midiPlay(). The output just asks for the first output it can find in 0,1,2,3,4 - I think that is what https://jazz-soft.net/doc/JZZ/midiout.html#open OpenMidiOut does anyways 🤷

@fornof
Copy link
Author

fornof commented Oct 13, 2024

another issue is that Typescript goes berserk when type at start is not type at end. I resolved with creating a type specifically for SMF which allows testing to continue with jest and not error out:

type Constructor = (typeof JZZ.MIDI)
export interface MidiConstructor extends Constructor  {
    SMF: Function| { MTrk: Function}| any
}
 export function midiOut(){
    var smf =(JZZ.MIDI as MidiConstructor).SMF(2,96); // type 0, 96 ticks per quarter note
  var trk = new (JZZ.MIDI as MidiConstructor).SMF.MTrk();
  ...
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants