Android MIDI sequencer with Processing interface


#43

@chanof
Ok, meanwhile we can code everything rotated by 90 degrees. might be a nice exercise.


#44

haha i was thinking the same :wink:


#45

@chanof @shedMusic

I found a workaround for this. I put all the Midi-code from setup() in an own function called midisetup(), and I call it with a delay from draw(). This does work. I guess another way would be to have a button in draw() and call midisetup() if this button is pushed.
I think the reason for this is that the sketch starts 2 times ( one normal, then restart in orientation mode) and so setup might be called twice, and therefore the mididevice might be blocked.
The button might be called ‘Start shedMusics-MIDI engine’ or something.:smile:


#46

Great solution @sensn I’m sick of thinking oblique…
My question is, if to use less buttons i recall this function with the delay but before recall the sequencer try to send a midi note the app will crash?
I not already implemented play stop buttons for this i ask
May i ask if you could try, thanks!


#47

@chanof
Hm, not sure about this; but in my example the pattern is empty so no event is trying to send a midi out.
so if you have an empty pattern at the start it should work.
I didn’t test how short the delay can be. I tried with 250 ms cause thats the tempo of my sequencer.
Be shure to call midisetup() only once, otherwise there will be the same problem again, i think.
I did this using a boolean set to true at start. then after 250ms check with if statement if its true, then call midisetup and set the boolean to false.
Hope that helps. I can post my code if this doesn’t work for you.


#48

@chanof
Ok, tried it. No crash. Midi works. I actually got pretty nice soundscape from my Korg M1 with hanging notes.:smile:


#49

I use it and work as you say :wink:

if (recall == true){
midiSetup();
recall = false;
}

#50

Hmmm … If the workaround works then good! I still want to know why it stops working on a rotate though! I will investigate further … I am guessing that if the inputPort is already open and connected to the playback device then this causes a lock up when it tries again to connect. Only a maybe, but I’ll see what I can discover.


#51

what do you think of the timestamp: play the notes 20ms in the future to avoid timing and stay below the threshold of the perceivable? I already can’t listen on a machine if it work.


#52

I noticed that it’s enough to call midiSetup(); from inside draw(). There doesn’t need to be a delay at all.
I just tested it with a little control surface sketch for my synth with broken knobs…


#53

Clear! I’m curious to know how this timestamp works and whats about CC massages to control them with sensors for example… May i ask your email sensn, after some test on synth i would like to send you my sequencer version of this amazing topic powered by @shedMusic, would be nice to share each other the final results


#54

long now = System.nanoTime()

Looks like mills() but with nano seconds, tomorrow i will check if we can create a better clock.


#55

@shedMusic @sensn
What you think about this internal clock?

long lasttimecheck;
long timeinterval;

void setup() {
  lasttimecheck = System.nanoTime();
  //step duration 
  timeinterval  = 125000000L;
}
void draw() {
  if (System.nanoTime() > lasttimecheck + timeinterval) {
    lasttimecheck = System.nanoTime();
    println("yeah");
  }
}

#56

thanks. I like simple examples. Will try it out with my sequencer.

I think we need an example for Midi receive too. Might be nice for arpeggiators.


#57

Hi! Im not so interested about receive midi inside android except for midi clock would be nice, but if it’s hard the https://github.com/googlesamples/android-MidiSynth
the example above into android studio could help.

Im not sure to understand, midi receive i think to receive notes or maybe an external clock, if you want build an arpeggiator you already have what you need i presume, or why you want listen an external arpeggiator, i m curious


#58

I am going to be looking at this later today. It’s going to he best not to do timing checks in draw() though … A separate thread probably


#59

Thanks Mark i was thinking it too, but im not sure to dispose the things correctly, do you mean like below?

long lasttimecheck;
long timeinterval;

void setup() {
  lasttimecheck = System.nanoTime();
  //step duration 
  timeinterval  = 125000000L;
}

void clock(){
  if (System.nanoTime() > lasttimecheck + timeinterval) {
    lasttimecheck = System.nanoTime();
    println("yeah" +  lasttimecheck);
  }

}
void draw() {
clock();
}

Take your time, i close with social life these days… :slight_smile: Im so exited about the progress


#60

I want to play a note on the keyboard, send that to my phone, and the phone generates an arp based on that note and sends it back to the synth.

About your example: How would i change the tempo ( with a slider )?
I don’t know what the L means and how i can create such a number?

 timeinterval  = 125000000L;

I guess it is a notation for nanoseconds; but how would I change that with a map() from a slider?

Edit: OK, i can just give it an integer and it is converted to long automatically.
Learning never stops.:smile:


#61

I’ve been testing some drum machines, nice feeling! but i wonder to know how do you deal with the note length:
With drums could be good that the note and when one another have to play, but if i use stop button the note never end, unfortunately i can not test it again before tuesday. I wonder to know how to send note off when stop button is pressed.
Any idea?
Maybe send one another note with 0 velocity?
Thanks


#62

@chanof @sensn

Right ,… timing and sending notes is hopefully coming soon, but for now, a bug fix for the crash on rotate. It’s being cause by the inputPort being reopened whilst it is already open, Don’t know why exactly but that’s the cause . The fix

At top of sketch a new global variable


MidiDevice myOpenDevice ;

and then in setup() use it like this



      m.openDevice(deviceInfo[0], new MidiManager.OnDeviceOpenedListener() {
        @Override
          public void onDeviceOpened(MidiDevice device) {
          if (device == null) {
            println("could not open device");
          } else {
            myOpenDevice = device;
            //Open input port
            inputPort = myOpenDevice.openInputPort(0);
            println("device opened and ready for use");
          }//end else
        }
      } //end m.opendevice
      , new Handler(Looper.getMainLooper())
        );

This is because ‘device’ is unavailable outside this code snippet so using it to open the port means it can’t be closed anywhere, but if you use your new myOpenDevice you can close it … in onPause()


void onPause() {
  try {
    inputPort.close();
  } 
  catch(Exception e) {
  }
}

Much better than doing your setup in draw()!