Page 1 of 1

Synchronous Loops on Different Channels with SMF

Posted: Mon May 21, 2018 7:02 am
by AndroidProtocol
Hi there,

I have been able to successfully play two midi files simultaneously using the SMF module. However, without looking extensively under the hood, I have struggled to play the files on different channels. I'm using the Novation Circuit, which wants all percussion played on channel 10. Synths are available on channels 1 and 2.

What would be the best JZZ SMF code to create looping of different midi files (same length - 8 bars) on different channels? Here's what I tried for different channels only.

Thanks in advance.

<CODE>

var JZZ = require('jzz');
require('JZZ-midi-SMF')(JZZ);

var dataLead = require('fs').readFileSync('lead.mid').toString('binary');
var smfLead = new JZZ.MIDI.SMF(dataLead);

var dataPerc = require('fs').readFileSync('perc.mid').toString('binary');
var smfPerc = new JZZ.MIDI.SMF(dataPerc);

var playerLead = smfLead.player();
var playerPerc = smfPerc.player();

var portLead = JZZ().openMidiOut(1);
portLead.ch(0).and(function() {
playerLead.connect(this);
playerLead.play();
});

var portPerc = JZZ().openMidiOut(1);
portPerc.ch(9).and(function() {
playerPerc.connect(this);
playerPerc.play();
});

</CODE>

Re: Synchronous Loops on Different Channels with SMF

Posted: Mon May 21, 2018 12:12 pm
by sema
portLead and portPerc refer to the same MIDI port.
MIDI player does not change the channels, it plays messages exactly as they are in the file.
ch() is a convenience function, it does not change channel.

Do you want to change channel for the messages playing from the second file? - I'll post the code later tonight.

Re: Synchronous Loops on Different Channels with SMF

Posted: Mon May 21, 2018 1:27 pm
by AndroidProtocol
Thanks sema! Yes, I'd like perc.mid to play on channel 10 while lead.mid plays on channel 1. These need to play live simultaneously and loop. If we can play an array of files, even better!

Re: Synchronous Loops on Different Channels with SMF

Posted: Mon May 21, 2018 4:38 pm
by sema
You can insert a channel converter between the file player and the output port:

Code: Select all

var smf = new JZZ.MIDI.SMF(data);
var player = smf.player();
var port = JZZ().or('Cannot start MIDI engine!').openMidiOut().or('Cannot open MIDI Out!');
var chan9 = new JZZ.Widget({ _receive: function(msg) { this.emit(msg.setChannel(9)); }});
player.connect(chan9);
chan9.connect(port);
port.and(function() { player.play(); });
Hope that will help :)

Re: Synchronous Loops on Different Channels with SMF

Posted: Mon May 21, 2018 9:24 pm
by AndroidProtocol
Thanks for providing the code so quickly!

A couple observations... There is significant delay in starting the lead. Midi notes in lead.mid are supposed to play immediately. Connecting channel 10 (or chan9 as you named it) would play percussion as a message when the lead would play, but there was no perc.mid file as input.

If we were to pretend that JZZ was a commandline DAW, it would be nice to have something that plays like this:

<- From left to right is time; numbers directly below are pretend measure numbers ->

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20

CH01 - Play immediately and loop 8-bars - source: ch01.mid
CH02 - Play immediately and loop 8-bars - source: ch02.mid
CH10 - Play immediately and loop 8-bars - source: ch03.mid

Re: Synchronous Loops on Different Channels with SMF

Posted: Wed May 23, 2018 7:09 am
by sema
You can synchronize all players by starting them together:
port.and(function() { player1.play(); player2.play(); player3.play(); });

I'll think how to enable measure count in the next player version.