MIDI In module - no midi clock or transport outputs

For discussion of the Voltage Modular synthesis ecosystem.
boonier
Posts: 30
Joined: Thu Apr 21, 2022 1:23 pm

MIDI In module - no midi clock or transport outputs

Post by boonier »

Hi there

Related to my other midi clock query, I'm trying out the other method of running VM as a midi sync slave, but there doesn't seem to be any way to get at the midi sync info from an incoming MIDI stream. The MIDI In module hasn't got any outputs relating to the subject which seems a surprising omission. I guess there is nothing stopping me from writing a new module to do just that, I think I have the chops...however, it appears that for VM in standalone mode (not hosted in a DAW or similar) there is currently no way to synchronise to the outside world using midi. But, please...prove me wrong! :)

Am I just looking at this the wrong way? Is the primary intended use of VM to be in a hosted environment? Plugins loaded in to the Plug-in Host module only get transport info from the host behind the scenes. I could, for example, setup the host to handle all the midi sync and plugin transport sync, but it seems I'll have to burn up some extra cpu to do run the host as well.

cheers
ColinP
Posts: 951
Joined: Mon Aug 03, 2020 7:46 pm

Re: MIDI In module - no midi clock or transport outputs

Post by ColinP »

CA's MIIDI Clock Divider does MIDI Sync to clock conversion...

https://docs.cherryaudio.com/cherry-aud ... ck-divider

Also my Song Control module does MIDI sync input and output and also handles start and stop, or at least it used to!

There might be a recent bug in VMs MIDI sync handling in both directions.

I am too busy to do a test at the moment but will try to look at this later today.
Steve W
Posts: 767
Joined: Thu Jul 16, 2020 5:55 pm

Re: MIDI In module - no midi clock or transport outputs

Post by Steve W »

I am not awake yet but I remember this discussion. Not sure it addresses your issue but it might: viewtopic.php?t=2060

Update: I just duplicated the setup I had here: viewtopic.php?p=8586#p8586. It still works.
Attachments
VM Ext Clock In.png
VM Ext Clock In.png (173.03 KiB) Viewed 1107 times
ColinP
Posts: 951
Joined: Mon Aug 03, 2020 7:46 pm

Re: MIDI In module - no midi clock or transport outputs

Post by ColinP »

Thanks Steve that's good news.

I know you can send MIDI START/STOP out of VM using CA's Sync To MIDI Clock module but is there a CA module that works in the opposite direction receiving START/STOP from the outside world?

Some MIDI modules have odd names and aren't categorised as MIDI so I might be missing something obvious.

I just thought - maybe in standalone mode MIDI START/STOP is available via the TRANSPORT PLAY/STOP signals in the I/O Panel?

I'm going to do some testing....
ColinP
Posts: 951
Joined: Mon Aug 03, 2020 7:46 pm

Re: MIDI In module - no midi clock or transport outputs

Post by ColinP »

Hmmmm...

VM runs without any problems at all on my system usually.

I just tried to replicate Steve's simple test patch as a first step and the ERROR LED lights on the CA MIDI In module. Then as with the MIDI OUT situation last week I got a very odd thing happening with an old preset loading up seemingly at random. I rebooted and got the same result.

I looked in the log file and there's an "Exception opening device USB MIDI Interface" which doesn't really tell me a lot.

Then almost at the end of the log it says

Code: Select all

Could not find multijack Right Input on module 34eab8363c1346ac92f34645699c24bf
15:33:07.559 Failed to connect cable from 34eab8363c1346ac92f34645699c24bf (Right Input) to 61644b1ecda5464291a036f6376a500f (Mix Output Right).
15:33:07.560 LoadPreset() EXIT
15:33:07.582 LoadPreset() Actually done loading - setting preset to not be dirty
Although this last error might just be fallout from the earlier exception.

I'm scratching my head a bit here.

I'm wondering if it's just a problem with my kit rather than anything to do with VM.

Living completely off grid on a boat my mains electricity comes from solar power through a charge controller into a 12 V battery then through an invertor then through a circuitous route to my MIDI outboard. To say my mains is dirty is an understatement as a decent sinewave invertor costs thousands. So my mains is like a ringing square wave but I'm used to dealing with the issues.

I did have earth loop problems with my old laptop when using MIDI and had to disconnect it from the mains to get reliable MIDI but it never caused software exceptions and I haven't noticed the same problem with the new laptop as it's much higher tech. I've unplugged the laptop from the mains and my sound system and the USB/MIDI connection should be going through an opto-isolator so there shouldn't be any possibility of an earth loop.

My MIDI interface is a fairly new thing but seems to have worked OK when I ran a few basic tests. It's a dirt cheap thing though so may be the culprit.

If the recent MIDI Sync Out problem hadn't occurred for other people then I'd immediately put this down to my kit but now I'm uncertain.

I have other work to do so am going to put this on a back burner but I'd love to hear if other people are having any problems as that might help in my trouble-shooting further down the line.
Steve W
Posts: 767
Joined: Thu Jul 16, 2020 5:55 pm

Re: MIDI In module - no midi clock or transport outputs

Post by Steve W »

ColinP wrote: Wed Jun 08, 2022 2:18 pm I know you can send MIDI START/STOP out of VM using CA's Sync To MIDI Clock module but is there a CA module that works in the opposite direction receiving START/STOP from the outside world?
I get them. They show up in MIDI DISPLAY, In fact, I started to test ColinP's Song Control module and it responds to Start and Stop from my external gear (hardware sequencer).

Update: Very pleased to see that ColinP's module also sends out incoming start and stop as state changes via the start out and stop out sockets. :)
Attachments
Ext Song Control Start-Stop.png
Ext Song Control Start-Stop.png (86.37 KiB) Viewed 1085 times
Ext Start-Stop to Song Control.png
Ext Start-Stop to Song Control.png (131.66 KiB) Viewed 1094 times
ColinP
Posts: 951
Joined: Mon Aug 03, 2020 7:46 pm

Re: MIDI In module - no midi clock or transport outputs

Post by ColinP »

Thanks Steve. Also good to know.

But my Song Control module isn't free and is also a bit over the top if all people want is MIDI START/STOP signals. That's why II was wondering if I'd missed a CA module in Core that has gate outputs for MIDI START/STOP. (Much as I would love everyone to buy LSSP!) :D

Your report increases the probability that my USB MIDI device is playing up. But I'm still wondering about other possibilities because of the similarity of the problem to the one uncovered about the CA MIDI Out module and I know that other people (including CA) can replicate that other issue. And even though my USB MIDI port is a cheap thing an exception happening when opening its driver is a pretty weird thing to happen.
Steve W
Posts: 767
Joined: Thu Jul 16, 2020 5:55 pm

Re: MIDI In module - no midi clock or transport outputs

Post by Steve W »

Good points!! If there are no free third-party modules that give access to external start/stop/continue/timing bytes and none of the VM modules at any level do either, that could be a problem. I have had many ideas for additional midi functionality in VM, but since I don't know current programming languages, I have not really gotten into module development.
ColinP
Posts: 951
Joined: Mon Aug 03, 2020 7:46 pm

Re: MIDI In module - no midi clock or transport outputs

Post by ColinP »

Yeah, there ought to be a free (or at least included in Core) comprehensive MIDI transport module.

Here's a little freebie to the VM programming community. It's ProcessSample() from Song Control. It's fairly rough and ready old code from when I first started learning Java and only represents about one or two hours of effort for me so I'm not actually giving much away. Besides details in called methods aren't shown and for it to be of any use you'd already be most of the way there anyway. Still it includes the basics of handling MIDI events so might be useful demo code for someone kind enough to produce a free module that fills the apparent gap.

It's not the most elegant of code and does naughty things like ignoring MIDI exceptions but there's not much useful one could actually do in most cases, so it's fairly typical of professional level coding - which is far messier and produced at a far far faster rate than most people outside of the business realise.

It should be in the VMD section of the forum really but I'm pressed for time. If CA want to move it to the VMD section please feel free.

BTW it uses my own lexical style so might look a bit strange to programmers who write in a style I find cramped and ugly.

Code: Select all

Override
public void ProcessSample()
{
   // add your own code here

   boolean doProcess = playButton.GetValue() == ON_VALUE && linkOut.isConnected();
   
   // need to do some processing for tempo reading and sync out even if not playing
      
   // get timing pulses from MIDI Sync In or Sync In
   // MIDI takes precedence
      
   if( midiSyncIn.IsConnected() )
   {
      // MIDI clocks at 24 ppqn
      ShortMessage message;

      // process MIDI in...
      ArrayList<ShortMessage> inputMessages = midiSyncIn.GetMessages();
      // will be null if no messages to handle
   
      if( inputMessages != null )
      {
         // process input messages one by one...
         int numInputMessages = inputMessages.size();

         for( int i = 0; i < numInputMessages; i++ ) 
         {
            message = inputMessages.get( i );
            switch( message.getStatus() )
            {
            case ShortMessage.TIMING_CLOCK:
               flashMidiLed = true;
               if( doProcess )
                  processPulse( 4 );    // 4 ticks @ 24 ppqn

               // send both MIDI and CV sync out @ 24 ppqn
               midiSyncOutToSend = true;
               syncOutCountdown = SYNC_TRIGGER_LENGTH;
               
               samplesPerBeat = sampleCounter * 24;
               calculateTiming();
               break;
            case ShortMessage.START:
               flashMidiLed = true;
               turnPlayOn();
               break;
            case ShortMessage.CONTINUE:
               flashMidiLed = true;
               turnPlayOn();
               break;
            case ShortMessage.STOP:
               flashMidiLed = true;
               externalStop();
               break;
            }
         }
      }
   }
   else
   {
      // Sync In at 96 ppqn
     
      double input;
      if( syncIn.IsConnected() )
      {
         // sync from socket
         input = syncIn.GetValue();
      }
      else
      {
         // normalise to IO panel sync
         input = GetIOPanelValue( IOPanelValues.IOPanel_Sync );
      }
       // detect rising edge...
      if( input >= TRIGGER_THRESHOLD )
      {
         // sync input is high
         if( syncInDetected == false )
         {
            // rising edge detected
            syncInDetected = true;
            if( doProcess )
               processPulse( 1 );    // 1 tick @ 96 ppqn

               
            // send both MIDI and CV sync out @ 24 ppqn
            if( syncDivider == 0 )
            {
               midiSyncOutToSend = true;
               syncOutCountdown = SYNC_TRIGGER_LENGTH;
            }
            syncDivider++;
            if( syncDivider >= 4 )
               syncDivider = 0;

            samplesPerBeat = sampleCounter * 96;
            calculateTiming();
         }
      }
      else
      {
         // trigger input is low
         syncInDetected = false;   
      }
   }

   
   // note CV start/stop can work in parallel with MIDI sync
   
   if( startIn.IsConnected() )
   {
      // detect rising edge...
      if( startIn.GetValue() >= TRIGGER_THRESHOLD )
      {
         // start input is high
         if( startInDetected == false )
         {
            // rising edge detected
            startInDetected = true;
            turnPlayOn();
         }
      }
      else
      {
         // trigger input is low
         startInDetected = false;   
      }
   }
   else
      startInDetected = false;   
   
   if( stopIn.IsConnected() )
   {
      // detect rising edge...
      if( stopIn.GetValue() >= TRIGGER_THRESHOLD )
      {
         // start input is high
         if( stopInDetected == false )
         {
            // rising edge detected
            stopInDetected = true;
            externalStop();
         }
      }
      else
      {
         // trigger input is low
         stopInDetected = false;   
      }  
   }
   else
      stopInDetected = false;   
   
   
   // inc timing counter each sample for measuring tempo...
   sampleCounter++;
   
   // handle MIDI sync output...
   if( midiSyncOut.IsConnected() )
   {
      if( midiSyncOutToSend )
      {
         try
         {
            midiSyncOut.AddMessage( new ShortMessage( ShortMessage.TIMING_CLOCK ) );
         }
         catch( InvalidMidiDataException e )
         {
         }      
      }
      if( midiStartToSend )
      {
         try
         {
            midiSyncOut.AddMessage( new ShortMessage( ShortMessage.START ) );
         }
         catch( InvalidMidiDataException e )
         {
         }      
      }
      if( midiStopToSend )
      {
         try
         {
            midiSyncOut.AddMessage( new ShortMessage( ShortMessage.STOP ) );
         }
         catch( InvalidMidiDataException e )
         {
         }      
      }
   }
   // always reset even if disconnected...
   midiSyncOutToSend = false;
   midiStartToSend = false;
   midiStopToSend = false;
   
   
   // handle active trigger outputs...
   if( syncOutCountdown > 0 )
   {
      syncOut.SetValue( TRIGGER_VOLTAGE );
      syncOutCountdown--;
   }
   else
      syncOut.SetValue( 0 );

   if( beatOutCountdown > 0 )
   {
      beatOut.SetValue( TRIGGER_VOLTAGE );
      beatOutCountdown--;
   }
   else
      beatOut.SetValue( 0 );

   if( barOutCountdown > 0 )
   {
      barOut.SetValue( TRIGGER_VOLTAGE );
      barOutCountdown--;
   }
   else
      barOut.SetValue( 0 );

   if( startOutCountdown > 0 )
   {
      startOut.SetValue( TRIGGER_VOLTAGE );
      startOutCountdown--;
   }
   else
      startOut.SetValue( 0 );

   if( stopOutCountdown > 0 )
   {
      stopOut.SetValue( TRIGGER_VOLTAGE );
      stopOutCountdown--;
   }
   else
      stopOut.SetValue( 0 );

   if( clockOutCountdown > 0 )
   {
      clockOut.SetValue( TRIGGER_VOLTAGE );
      clockOutCountdown--;
   }
   else
      clockOut.SetValue( 0 );
      
   // output voltage for Key...
   keyOut.SetValue( keyValue );

   // ouput record arm gate/trigger,,,
   if( recordButton.GetValue() == ON_VALUE )
      recordOut.SetValue( TRIGGER_VOLTAGE );
   else
      recordOut.SetValue( 0 );

   // output v/Bar...
   if( playButton.GetValue() == ON_VALUE )
      vBarOut.SetValue( vBarValue );
   else
      vBarOut.SetValue( 0 );
      
   // fade in...
   if( fadeInOut.IsConnected() )
   {
      if( totalBars > 0 )
      {
         if( holdFadeIn )
            fadeInOut.SetValue( TRIGGER_VOLTAGE );
         else
         {
            // t = 0..1
            double t = ( vBarValue - 1.0 ) / totalBars;
            
            // polynomial (cosine like) interpolation...
            double fadeIn = TRIGGER_VOLTAGE * t * t * ( 3 - t - t );
         
            fadeInOut.SetValue( fadeIn );
         }
      }
      else
         fadeInOut.SetValue( 0 );
   }
   
   // communication to first song cell...
   if( linkOut.isConnected() )
   {
      linkOut.resetFudge();
      
      linkOut.setPolyValue( ID_CHANNEL, 1 );
      linkOut.setPolyValue( BAR_OFFSET_CHANNEL, 0 );
      linkOut.setPolyValue( VBAR_CHANNEL, vBarValue );
      linkOut.setPolyValue( PLAYING_CHANNEL, playButton.GetValue() );   
      linkOut.setRestToZero( PLAYING_CHANNEL + 1 );
   }

   // sample level delta
   if( doProcess )
      vBarValue += delta;               
}
Right that's it for me on this thread. I really do need to make progress on the Granular Synth...
boonier
Posts: 30
Joined: Thu Apr 21, 2022 1:23 pm

Re: MIDI In module - no midi clock or transport outputs

Post by boonier »

Sorry coming in a bit late to my own post! I actually rolled my own simple module last night with the sync and transport; parts of it very similar to that what @ColinP just posted. Thanks for posting that btw, plenty to checkout, I will cross reference mine with yours to see if I've done it properly :lol:

Also it includes a MIDI clock divider internally, as I was getting unexpected results when when feeding the midi clock output into a Sync Divider module - I think because that module expects a higher resolution (96ppqn) than the midi clock provides. I don't have a seller's licence (yet) to make it publicly available (for free) but maybe one day it will surface; perhaps Cherry Audio will beat me to it.
Post Reply

Return to “Voltage Modular”