jazz-soft/JZZ-midi-SMF

Can't generate drum midi sound

riffca opened this issue · 2 comments

Hello. Thank you for great library. Convenient api makes me happy.
However I can't get drums work.
I added one more track to existing example and tried to setup bass drum and snare.
https://usermanuals.finalemusic.com/SongWriter2012Win/Content/PercussionMaps.htm
Generated file don't play drums sound(windows midi player) however midi notes exists in DAW(reaper).
Also when piano exists instead of vibraphone it doesn't produce sound. I tried using different channels but got stuck.
Please provide example how to make drums sound together with piano.

CODE:

<!DOCTYPE html>
<html>
<head>
<title>Write MIDI File</title>
<script src="https://cdn.jsdelivr.net/npm/jzz"></script>
<script src="https://cdn.jsdelivr.net/npm/jzz-midi-smf"></script>
<!-- https://github.com/jazz-soft/JZZ-midi-GM -->
<script src="https://cdn.jsdelivr.net/npm/jzz-midi-gm"></script>
<!-- <script src="./tracks.js"></script> -->
</head>

<body>
<h1>Write MIDI File</h1>

<div id=out></div>
<!-- <button onClick="playTrack()">Play</button> -->

<script type="module">

// Create a MIDI file. Type 1; 100 clocks per quarter note.
// Normally, it would rather be 96, but 100 makes it easier to count.
var smf = new JZZ.MIDI.SMF(1, 100);

// Add MIDI file tracks:
var trk0 = new JZZ.MIDI.SMF.MTrk(); smf.push(trk0); // First track in Type 1 MIDI file is normally used for tempo changes
var trk1 = new JZZ.MIDI.SMF.MTrk(); smf.push(trk1); // This one will be for the karaoke lyrics
var trk2 = new JZZ.MIDI.SMF.MTrk(); smf.push(trk2); // This one will be for the music
var trk3 = new JZZ.MIDI.SMF.MTrk(); smf.push(trk3); // This one will be for the music

trk0.smfSeqName('Little Lame') // The name of the first track serves as the file title
    .smfBPM(90); // Tempo. Normally set at clock 0, but can be also changed later

trk1.smfSeqName('Lyrics') // The names of other tracks don't have any particular meaning
    .smfText('@TMary Was A Little Lame') // Karaoke player will recognize this track by the "@T" tag
    .tick(100).smfText('\\Ma') // New verse starts with a backslash "\"
    .tick(75).smfText('ry ')
    .tick(25).smfText('was ')
    .tick(50).smfText('a ')
    .tick(50).smfText('lit')
    .tick(50).smfText('tle ')
    .tick(50).smfText('lame,')
    .tick(100).smfText('/Lit') // New line starts with a slash "/"
    .tick(50).smfText('tle ')
    .tick(50).smfText('lame,')
    .tick(100).smfText('/Lit')
    .tick(50).smfText('tle ')
    .tick(50).smfText('lame,')
    .tick(100).smfText('/Ma')
    .tick(75).smfText('ry ')
    .tick(25).smfText('was ')
    .tick(50).smfText('a ')
    .tick(50).smfText('lit')
    .tick(50).smfText('tle ')
    .tick(50).smfText('lame,')
    .tick(50).smfText('/A ')
    .tick(50).smfText('lit')
    .tick(50).smfText('tle ')
    .tick(50).smfText('lame ')
    .tick(50).smfText('was ')
    .tick(50).smfText('she!');
    

trk2.smfSeqName('Music')
    .ch(0) // all subsequent messahes will go to channel 0
    .program(0x0b) // set channel 0 program to vibraphone
    .tick(50).note('E5', 127, 5).note('E6', 127, 20)  // clock: 100, MIDI channel: 0, note: E5, velocity: 127, duration: 50 clocks
    .tick(50).note('D5', 127, 50)  // etc...
    .tick(50).note('C5', 127, 50)
    .tick(50).note('D5', 127, 50)
    .tick(50).note('E5',127, 25)
    .tick(50).note(64, 127, 50)   // can also use numerical values for the notes
    .tick(50).note(0x40, 127, 50)
    .tick(50).note('D5', 127, 50)
    .tick(50).note('D5', 127, 50)
    .tick(50).note('D5', 127, 50)
    .tick(100).note('E5', 127, 50)
    .tick(50).note('G5', 127, 50)
    .tick(50).note('G5', 127, 90)
    .tick(100).note('E5', 127, 75)
    .tick(75).note('D5', 127, 25)
    .tick(25).note('C5', 127, 50)
    .tick(50).note('D5', 127, 50)
    .tick(50).note('E5', 127, 50)
    .tick(50).note('E5', 127, 50)
    .tick(50).note('E5', 127, 50)
    .tick(75).note('E5', 127, 25)
    .tick(25).note('D5', 127, 50)
    .tick(50).note('D5', 127, 50)
    .tick(50).note('E5', 127, 50)
    .tick(50).note('D5', 127, 50)
    .tick(50).note('C5', 127, 190)
    .tick(100).note('E5', 100, 90).note('G5', 100, 90).note('C6', 127, 90)
    .tick(100).smfEndOfTrack(); // otherwise it will end on clock 1690
    
trk3.smfSeqName('drum')
    .ch(0) // all subsequent messahes will go to channel 0
    .program(JZZ.MIDI.programName(0, 127, 0))
    //.program('Standard Drum Kit') 
    .tick(50).note(0x51, 127, 5)  
    .tick(50).note(0x52, 127, 50)  
    .tick(50).note(0x53, 127, 50)
    .tick(50).note(0x54, 127, 50)
    .tick(50).note(36,127, 25)
    .tick(50).note(64, 127, 50)  
    .tick(50).note(0x40, 127, 50)
    .tick(50).note(36, 127, 50)
    .tick(50).note(20, 127, 50)
    .tick(50).note('C2', 127, 50)
    .tick(50).note('D2', 127, 50)
    .tick(50).note(0x50, 127, 50)
    .tick(50).note(0x60, 127, 50)
    .tick(50).note('C2', 127, 90)
    .tick(50).note(36, 127, 50)
    
    .tick(50).note(37, 127, 90)
    
    .tick(75).note(38, 127, 25)
    .tick(25).note(39, 127, 50)
    .tick(50).note('C2', 127, 50)
    .tick(50).note('D2', 127, 50)
    .tick(50).note(38, 127, 50)
    .tick(50).note('D2', 127, 50)
    .tick(75).note('D2', 127, 25)
    .tick(25).note('D2', 127, 50)
    .tick(50).note('D2', 127, 50)
    .tick(50).note('D2', 127, 50)
    .tick(50).note('C2', 127, 50)
    .tick(50).note('C2', 127, 190)
    .tick(50).note('D2', 100, 90)
    .tick(50).note('C2', 127, 190)
    .tick(50).note(40, 127, 50)
    .tick(50).note(41, 127, 50)
    .tick(50).note(42, 127, 190)
    .tick(50).note(43, 100, 90)
    .tick(50).note('C2', 127, 190)
    .tick(50).note('C2', 127, 190)
    .tick(50).note(50, 127, 190)
    .tick(50).note(50, 127, 190)
    
    .tick(100).smfEndOfTrack(); // otherwise it will end on clock 1690

var str = smf.dump(); // MIDI file dumped as a string
var b64 = JZZ.lib.toBase64(str); // convert to base-64 string
var uri = 'data:audio/midi;base64,' + b64; // data URI


// Finally, write it to the document as a link and as an embedded object:
document.getElementById('out').innerHTML = 'New file: <a download=lame.mid href=' + uri + '>DOWNLOAD</a> <embed src=' + uri + ' autostart=true>';
</script>

</body>
</html>

Currently both tracks are playing on the channel 0.
Change ".ch(0)" in the 3rd track to ".ch(9)", that is the default channel for drums.

Thank you! Channel does job!